1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // pull in all the <= 5.0 tests
18 #include "5.0/AudioPrimaryHidlHalTest.cpp"
19 
getOutputDeviceConfigParameters()20 const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
21     static std::vector<DeviceConfigParameter> parameters = [] {
22         std::vector<DeviceConfigParameter> result;
23         for (const auto& device : getDeviceParameters()) {
24             auto module =
25                     getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
26             for (const auto& ioProfile : module->getOutputProfiles()) {
27                 for (const auto& profile : ioProfile->getAudioProfiles()) {
28                     const auto& channels = profile->getChannels();
29                     const auto& sampleRates = profile->getSampleRates();
30                     auto configs = ConfigHelper::combineAudioConfig(
31                             vector<audio_channel_mask_t>(channels.begin(), channels.end()),
32                             vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
33                             profile->getFormat());
34                     auto flags = ioProfile->getFlags();
35                     for (auto& config : configs) {
36                         // Some combinations of flags declared in the config file require special
37                         // treatment.
38                         if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
39                             config.offloadInfo.sampleRateHz = config.sampleRateHz;
40                             config.offloadInfo.channelMask = config.channelMask;
41                             config.offloadInfo.format = config.format;
42                             config.offloadInfo.streamType = AudioStreamType::MUSIC;
43                             config.offloadInfo.bitRatePerSecond = 320;
44                             config.offloadInfo.durationMicroseconds = -1;
45                             config.offloadInfo.bitWidth = 16;
46                             config.offloadInfo.bufferSize = 256;  // arbitrary value
47                             config.offloadInfo.usage = AudioUsage::MEDIA;
48                             result.emplace_back(device, config,
49                                                 AudioOutputFlag(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
50                                                                 AUDIO_OUTPUT_FLAG_DIRECT));
51                         } else {
52                             if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {  // ignore the flag
53                                 flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY;
54                             }
55                             result.emplace_back(device, config, AudioOutputFlag(flags));
56                         }
57                     }
58                 }
59             }
60         }
61         return result;
62     }();
63     return parameters;
64 }
65 
getInputDeviceConfigParameters()66 const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters() {
67     static std::vector<DeviceConfigParameter> parameters = [] {
68         std::vector<DeviceConfigParameter> result;
69         for (const auto& device : getDeviceParameters()) {
70             auto module =
71                     getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
72             for (const auto& ioProfile : module->getInputProfiles()) {
73                 for (const auto& profile : ioProfile->getAudioProfiles()) {
74                     const auto& channels = profile->getChannels();
75                     const auto& sampleRates = profile->getSampleRates();
76                     auto configs = ConfigHelper::combineAudioConfig(
77                             vector<audio_channel_mask_t>(channels.begin(), channels.end()),
78                             vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
79                             profile->getFormat());
80                     for (const auto& config : configs) {
81                         result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags()));
82                     }
83                 }
84             }
85         }
86         return result;
87     }();
88     return parameters;
89 }
90 
TEST_P(AudioHidlDeviceTest,CloseDeviceWithOpenedOutputStreams)91 TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) {
92     doc::test("Verify that a device can't be closed if there are streams opened");
93     DeviceAddress address{.device = AudioDevice::OUT_DEFAULT};
94     AudioConfig config{};
95     auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
96     SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}};
97     sp<IStreamOut> stream;
98     StreamHelper<IStreamOut> helper(stream);
99     AudioConfig suggestedConfig{};
100     ASSERT_NO_FATAL_FAILURE(helper.open(
101             [&](AudioIoHandle handle, AudioConfig config, auto cb) {
102                 return getDevice()->openOutputStream(handle, address, config, flags, initMetadata,
103                                                      cb);
104             },
105             config, &res, &suggestedConfig));
106     ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close());
107     ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res));
108     ASSERT_OK(getDevice()->close());
109     ASSERT_TRUE(resetDevice());
110 }
111 
TEST_P(AudioHidlDeviceTest,CloseDeviceWithOpenedInputStreams)112 TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) {
113     doc::test("Verify that a device can't be closed if there are streams opened");
114     auto module = getCachedPolicyConfig().getModuleFromName(getDeviceName());
115     if (module->getInputProfiles().empty()) {
116         GTEST_SKIP() << "Device doesn't have input profiles";
117     }
118     DeviceAddress address{.device = AudioDevice::IN_DEFAULT};
119     AudioConfig config{};
120     auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
121     SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
122     sp<IStreamIn> stream;
123     StreamHelper<IStreamIn> helper(stream);
124     AudioConfig suggestedConfig{};
125     ASSERT_NO_FATAL_FAILURE(helper.open(
126             [&](AudioIoHandle handle, AudioConfig config, auto cb) {
127                 return getDevice()->openInputStream(handle, address, config, flags, initMetadata,
128                                                     cb);
129             },
130             config, &res, &suggestedConfig));
131     ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close());
132     ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res));
133     ASSERT_OK(getDevice()->close());
134     ASSERT_TRUE(resetDevice());
135 }
136 
TEST_P(AudioPatchHidlTest,UpdatePatchInvalidHandle)137 TEST_P(AudioPatchHidlTest, UpdatePatchInvalidHandle) {
138     doc::test("Verify that passing an invalid handle to updateAudioPatch is checked");
139     AudioPatchHandle ignored;
140     ASSERT_OK(getDevice()->updateAudioPatch(
141             static_cast<int32_t>(AudioHandleConsts::AUDIO_PATCH_HANDLE_NONE),
142             hidl_vec<AudioPortConfig>(), hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
143     ASSERT_RESULT(Result::INVALID_ARGUMENTS, res);
144 }
145 
146 using DualMonoModeAccessorHidlTest = AccessorHidlTest<DualMonoMode, OutputStreamTest>;
TEST_P(DualMonoModeAccessorHidlTest,DualMonoModeTest)147 TEST_P(DualMonoModeAccessorHidlTest, DualMonoModeTest) {
148     doc::test("Check that dual mono mode can be set and retrieved");
149     testAccessors<OPTIONAL>(&OutputStreamTest::getStream, "dual mono mode",
150                             Initial{DualMonoMode::OFF},
151                             {DualMonoMode::LR, DualMonoMode::LL, DualMonoMode::RR},
152                             &IStreamOut::setDualMonoMode, &IStreamOut::getDualMonoMode);
153 }
154 
155 INSTANTIATE_TEST_CASE_P(DualMonoModeHidl, DualMonoModeAccessorHidlTest,
156                         ::testing::ValuesIn(getOutputDeviceConfigParameters()),
157                         &DeviceConfigParameterToString);
158 
159 using AudioDescriptionMixLevelHidlTest = AccessorHidlTest<float, OutputStreamTest>;
TEST_P(AudioDescriptionMixLevelHidlTest,AudioDescriptionMixLevelTest)160 TEST_P(AudioDescriptionMixLevelHidlTest, AudioDescriptionMixLevelTest) {
161     doc::test("Check that audio description mix level can be set and retrieved");
162     testAccessors<OPTIONAL>(
163             &OutputStreamTest::getStream, "audio description mix level",
164             Initial{-std::numeric_limits<float>::infinity()}, {-48.0f, -1.0f, 0.0f, 1.0f, 48.0f},
165             &IStreamOut::setAudioDescriptionMixLevel, &IStreamOut::getAudioDescriptionMixLevel,
166             {48.5f, 1000.0f, std::numeric_limits<float>::infinity()});
167 }
168 
169 INSTANTIATE_TEST_CASE_P(AudioDescriptionMixLevelHidl, AudioDescriptionMixLevelHidlTest,
170                         ::testing::ValuesIn(getOutputDeviceConfigParameters()),
171                         &DeviceConfigParameterToString);
172 
173 using PlaybackRateParametersHidlTest = AccessorHidlTest<PlaybackRate, OutputStreamTest>;
TEST_P(PlaybackRateParametersHidlTest,PlaybackRateParametersTest)174 TEST_P(PlaybackRateParametersHidlTest, PlaybackRateParametersTest) {
175     doc::test("Check that playback rate parameters can be set and retrieved");
176     testAccessors<OPTIONAL>(
177             &OutputStreamTest::getStream, "playback rate parameters",
178             Initial{PlaybackRate{1.0f, 1.0f, TimestretchMode::DEFAULT,
179                                  TimestretchFallbackMode::FAIL}},
180             {// Speed and pitch values in the range from 0.5f to 2.0f must be supported
181              // (see the definition of IStreamOut::setPlaybackRateParameters).
182              PlaybackRate{1.0f, 1.0f, TimestretchMode::DEFAULT, TimestretchFallbackMode::MUTE},
183              PlaybackRate{2.0f, 2.0f, TimestretchMode::DEFAULT, TimestretchFallbackMode::MUTE},
184              PlaybackRate{0.5f, 0.5f, TimestretchMode::DEFAULT, TimestretchFallbackMode::MUTE},
185              // Gross speed / pitch values must not be rejected if the fallback mode is "mute"
186              PlaybackRate{1000.0f, 1000.0f, TimestretchMode::DEFAULT,
187                           TimestretchFallbackMode::MUTE},
188              // Default speed / pitch values must not be rejected in "fail" fallback mode
189              PlaybackRate{1.0f, 1.0f, TimestretchMode::DEFAULT, TimestretchFallbackMode::FAIL},
190              // Same for "voice" mode
191              PlaybackRate{1.0f, 1.0f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
192              PlaybackRate{2.0f, 2.0f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
193              PlaybackRate{0.5f, 0.5f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
194              PlaybackRate{1000.0f, 1000.0f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
195              PlaybackRate{1.0f, 1.0f, TimestretchMode::VOICE, TimestretchFallbackMode::FAIL}},
196             &IStreamOut::setPlaybackRateParameters, &IStreamOut::getPlaybackRateParameters,
197             {PlaybackRate{1000.0f, 1000.0f, TimestretchMode::DEFAULT,
198                           TimestretchFallbackMode::FAIL},
199              PlaybackRate{1000.0f, 1000.0f, TimestretchMode::VOICE,
200                           TimestretchFallbackMode::FAIL}});
201 }
202 
203 INSTANTIATE_TEST_CASE_P(PlaybackRateParametersHidl, PlaybackRateParametersHidlTest,
204                         ::testing::ValuesIn(getOutputDeviceConfigParameters()),
205                         &DeviceConfigParameterToString);
206 
207 /** Stub implementation of IStreamOutEventCallback **/
208 class MockOutEventCallbacks : public IStreamOutEventCallback {
onCodecFormatChanged(const hidl_vec<uint8_t> & audioMetadata __unused)209     Return<void> onCodecFormatChanged(const hidl_vec<uint8_t>& audioMetadata __unused) override {
210         return {};
211     }
212 };
213 
TEST_P(OutputStreamTest,SetEventCallback)214 TEST_P(OutputStreamTest, SetEventCallback) {
215     doc::test("If supported, set event callback for output stream should never fail");
216     auto res = stream->setEventCallback(new MockOutEventCallbacks);
217     EXPECT_RESULT(okOrNotSupported, res);
218     if (res == Result::OK) {
219         ASSERT_OK(stream->setEventCallback(nullptr));
220     } else {
221         doc::partialTest("The stream does not support event callback");
222     }
223 }
224