• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include <thread>
18 
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "AudioTrackTests"
21 
22 #include <android-base/logging.h>
23 #include <binder/ProcessState.h>
24 #include <gtest/gtest.h>
25 
26 #include "audio_test_utils.h"
27 #include "test_execution_tracer.h"
28 
29 using namespace android;
30 
31 // Test that the basic constructor returns an object that doesn't crash
32 // on stop() or destruction.
33 
TEST(AudioTrackTestBasic,EmptyAudioTrack)34 TEST(AudioTrackTestBasic, EmptyAudioTrack) {
35     AttributionSourceState attributionSource;
36     attributionSource.packageName = "AudioTrackTest";
37     attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
38     attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
39     attributionSource.token = sp<BBinder>::make();
40     const auto at = sp<AudioTrack>::make(attributionSource);
41 
42     EXPECT_EQ(NO_INIT, at->initCheck());
43     EXPECT_EQ(true, at->stopped());
44 
45     // ensure we do not crash.
46     at->stop();
47 }
48 
TEST(AudioTrackTest,TestPlayTrack)49 TEST(AudioTrackTest, TestPlayTrack) {
50     const auto ap = sp<AudioPlayback>::make(44100 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
51                                             AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_NONE,
52                                             AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN);
53     ASSERT_NE(nullptr, ap);
54     ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
55             << "Unable to open Resource";
56     EXPECT_EQ(OK, ap->create()) << "track creation failed";
57     EXPECT_EQ(OK, ap->start()) << "audio track start failed";
58     EXPECT_EQ(OK, ap->onProcess());
59     ap->stop();
60 }
61 
TEST(AudioTrackTest,TestSeek)62 TEST(AudioTrackTest, TestSeek) {
63     const auto ap = sp<AudioPlayback>::make(
64             44100 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO);
65     ASSERT_NE(nullptr, ap);
66     ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
67             << "Unable to open Resource";
68     EXPECT_EQ(OK, ap->create()) << "track creation failed";
69     EXPECT_EQ(OK, ap->start()) << "audio track start failed";
70     EXPECT_EQ(OK, ap->onProcess(true));
71     ap->stop();
72 }
73 
TEST(AudioTrackTest,OffloadOrDirectPlayback)74 TEST(AudioTrackTest, OffloadOrDirectPlayback) {
75     audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
76     info.sample_rate = 44100;
77     info.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
78     info.format = AUDIO_FORMAT_MP3;
79     info.stream_type = AUDIO_STREAM_MUSIC;
80     info.bit_rate = 192;
81     info.duration_us = 120 * 1000000;  // 120 sec
82 
83     audio_config_base_t config = {/* .sample_rate = */ info.sample_rate,
84                                   /* .channel_mask = */ info.channel_mask,
85                                   /* .format = */ AUDIO_FORMAT_PCM_16_BIT};
86     audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
87     attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
88     attributes.usage = AUDIO_USAGE_MEDIA;
89     attributes.flags = AUDIO_FLAG_NONE;
90 
91     if (!AudioTrack::isDirectOutputSupported(config, attributes) &&
92         AUDIO_OFFLOAD_NOT_SUPPORTED == AudioSystem::getOffloadSupport(info)) {
93         GTEST_SKIP() << "offload or direct playback is not supported";
94     }
95     sp<AudioPlayback> ap = nullptr;
96     if (AUDIO_OFFLOAD_NOT_SUPPORTED != AudioSystem::getOffloadSupport(info)) {
97         ap = sp<AudioPlayback>::make(info.sample_rate, info.format, info.channel_mask,
98                                      AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD, AUDIO_SESSION_NONE,
99                                      AudioTrack::TRANSFER_OBTAIN, nullptr, &info);
100     } else {
101         ap = sp<AudioPlayback>::make(config.sample_rate, config.format, config.channel_mask,
102                                      AUDIO_OUTPUT_FLAG_DIRECT, AUDIO_SESSION_NONE,
103                                      AudioTrack::TRANSFER_OBTAIN);
104     }
105     ASSERT_NE(nullptr, ap);
106     EXPECT_EQ(OK, ap->create()) << "track creation failed";
107     audio_dual_mono_mode_t mode;
108     if (OK != ap->getAudioTrackHandle()->getDualMonoMode(&mode)) {
109         std::cerr << "no dual mono presentation is available" << std::endl;
110     }
111     if (OK != ap->getAudioTrackHandle()->setDualMonoMode(AUDIO_DUAL_MONO_MODE_LR)) {
112         std::cerr << "no dual mono presentation is available" << std::endl;
113     } else {
114         EXPECT_EQ(OK, ap->getAudioTrackHandle()->getDualMonoMode(&mode));
115         EXPECT_EQ(AUDIO_DUAL_MONO_MODE_LR, mode);
116     }
117     float leveldB;
118     if (OK != ap->getAudioTrackHandle()->getAudioDescriptionMixLevel(&leveldB)) {
119         std::cerr << "Audio Description mixing is unavailable" << std::endl;
120     }
121     if (OK != ap->getAudioTrackHandle()->setAudioDescriptionMixLevel(3.14f)) {
122         std::cerr << "Audio Description mixing is unavailable" << std::endl;
123     } else {
124         EXPECT_EQ(OK, ap->getAudioTrackHandle()->getAudioDescriptionMixLevel(&leveldB));
125         EXPECT_EQ(3.14f, leveldB);
126     }
127     AudioPlaybackRate audioRate;
128     audioRate = ap->getAudioTrackHandle()->getPlaybackRate();
129     std::cerr << "playback speed :: " << audioRate.mSpeed << std::endl
130               << "playback pitch :: " << audioRate.mPitch << std::endl;
131     audioRate.mSpeed = 2.0f;
132     audioRate.mPitch = 2.0f;
133     audioRate.mStretchMode = AUDIO_TIMESTRETCH_STRETCH_VOICE;
134     audioRate.mFallbackMode = AUDIO_TIMESTRETCH_FALLBACK_MUTE;
135     EXPECT_TRUE(isAudioPlaybackRateValid(audioRate));
136     if (OK != ap->getAudioTrackHandle()->setPlaybackRate(audioRate)) {
137         std::cerr << "unable to set playback rate parameters" << std::endl;
138     } else {
139         AudioPlaybackRate audioRateLocal;
140         audioRateLocal = ap->getAudioTrackHandle()->getPlaybackRate();
141         EXPECT_TRUE(isAudioPlaybackRateEqual(audioRate, audioRateLocal));
142     }
143     ap->stop();
144 }
145 
TEST(AudioTrackTest,TestAudioCbNotifier)146 TEST(AudioTrackTest, TestAudioCbNotifier) {
147     const auto ap = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
148                                             AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_FAST,
149                                             AUDIO_SESSION_NONE, AudioTrack::TRANSFER_SHARED);
150     ASSERT_NE(nullptr, ap);
151     ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
152             << "Unable to open Resource";
153     EXPECT_EQ(OK, ap->create()) << "track creation failed";
154     EXPECT_EQ(BAD_VALUE, ap->getAudioTrackHandle()->addAudioDeviceCallback(nullptr));
155     sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
156     sp<OnAudioDeviceUpdateNotifier> cbOld = sp<OnAudioDeviceUpdateNotifier>::make();
157     EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cbOld));
158     EXPECT_EQ(INVALID_OPERATION, ap->getAudioTrackHandle()->addAudioDeviceCallback(cbOld));
159     EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cb));
160     EXPECT_EQ(OK, ap->start()) << "audio track start failed";
161     EXPECT_EQ(OK, ap->onProcess());
162     EXPECT_EQ(OK, cb->waitForAudioDeviceCb());
163     const auto [oldAudioIo, oldDeviceIds] = cbOld->getLastPortAndDevices();
164     EXPECT_EQ(AUDIO_IO_HANDLE_NONE, oldAudioIo);
165     EXPECT_TRUE(oldDeviceIds.empty());
166     const auto [audioIo, deviceIds] = cb->getLastPortAndDevices();
167     EXPECT_NE(AUDIO_IO_HANDLE_NONE, audioIo);
168     EXPECT_FALSE(deviceIds.empty());
169     EXPECT_EQ(audioIo, ap->getAudioTrackHandle()->getOutput());
170     DeviceIdVector routedDeviceIds = ap->getAudioTrackHandle()->getRoutedDeviceIds();
171     EXPECT_TRUE(areDeviceIdsEqual(routedDeviceIds, deviceIds));
172     String8 keys;
173     keys = ap->getAudioTrackHandle()->getParameters(keys);
174     if (!keys.empty()) {
175         std::cerr << "track parameters :: " << keys << std::endl;
176     }
177     EXPECT_TRUE(checkPatchPlayback(audioIo, deviceIds));
178     EXPECT_EQ(BAD_VALUE, ap->getAudioTrackHandle()->removeAudioDeviceCallback(nullptr));
179     EXPECT_EQ(INVALID_OPERATION, ap->getAudioTrackHandle()->removeAudioDeviceCallback(cbOld));
180     EXPECT_EQ(OK, ap->getAudioTrackHandle()->removeAudioDeviceCallback(cb));
181     ap->stop();
182 }
183 
184 class AudioTrackOffloadTest : public ::testing::Test {
185   protected:
TearDown()186     void TearDown() override {
187         if (!IsSkipped()) {
188             // Let the offload AF stream to exit to avoid interfering with other tests.
189             std::this_thread::sleep_for(std::chrono::milliseconds(750));
190         }
191     }
192     bool halSupportsClipTransition() const;
193     void testPlayback(bool testDrainPause, sp<AudioPlayback>* outPlayback = nullptr);
194 };
195 
halSupportsClipTransition() const196 bool AudioTrackOffloadTest::halSupportsClipTransition() const {
197     // TODO: Check for the HAL type (HIDL/AIDL) and version. HIDL and AIDL V4 should also
198     //       support this.
199     AudioParameter param;
200     param.addKey(String8(AudioParameter::keyClipTransitionSupport));
201     String8 values = AudioSystem::getParameters(AUDIO_IO_HANDLE_NONE, param.keysToString());
202     LOG(DEBUG) << __func__ << ": values \"" << values << "\"";
203     return !values.empty();
204 }
205 
testPlayback(bool testDrainPause,sp<AudioPlayback> * outPlayback)206 void AudioTrackOffloadTest::testPlayback(bool testDrainPause, sp<AudioPlayback>* outPlayback) {
207     audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
208     info.sample_rate = 48000;
209     info.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
210     info.format = AUDIO_FORMAT_APE;
211     info.stream_type = AUDIO_STREAM_MUSIC;
212     info.bit_rate = 236256;
213     info.duration_us = 120 * 1000000;  // 120 sec to ensure the offloading choice
214 
215     if (AUDIO_OFFLOAD_NOT_SUPPORTED == AudioSystem::getOffloadSupport(info)) {
216         GTEST_SKIP() << "offload playback is not supported for "
217                      << audio_format_to_string(info.format);
218     }
219     auto ap = sp<AudioPlayback>::make(info.sample_rate, info.format, info.channel_mask,
220                                       AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD, AUDIO_SESSION_NONE,
221                                       AudioTrack::TRANSFER_OBTAIN, nullptr, &info);
222     ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/sine960hz_48000_3s.ape"))
223             << "unable to open the media file";
224     ASSERT_EQ(OK, ap->create()) << "track creation failed";
225     ASSERT_EQ(OK, ap->start()) << "audio track start failed";
226     LOG(INFO) << __func__ << ": Started track";
227     EXPECT_EQ(OK, ap->onProcess());
228     LOG(INFO) << __func__ << ": onProcess done";
229     if (!outPlayback) {
230         ap->stop();
231         LOG(INFO) << __func__ << ": Stopped track";
232     }
233     if (testDrainPause) {
234         // Wait for draining to start, no event for this.
235         std::this_thread::sleep_for(std::chrono::milliseconds(200));
236         LOG(INFO) << __func__ << ": Pausing drain";
237         ap->pause();
238         LOG(INFO) << __func__ << ": Resuming drain";
239         ap->resume();
240     }
241     if (!outPlayback) {
242         LOG(INFO) << __func__ << ": Waiting for stream end";
243         EXPECT_TRUE(ap->waitForStreamEnd()) << "Did not receive onStreamEnd";
244     } else {
245         *outPlayback = std::move(ap);
246     }
247 }
248 
TEST_F(AudioTrackOffloadTest,Completion)249 TEST_F(AudioTrackOffloadTest, Completion) {
250     testPlayback(false /*testDrainPause*/);
251 }
252 
TEST_F(AudioTrackOffloadTest,DrainPause)253 TEST_F(AudioTrackOffloadTest, DrainPause) {
254     if (!halSupportsClipTransition()) {
255         // TODO: In theory, this should also work w/o having the proper clip transition
256         //       support, but as a fact it was not. Need to figure out why.
257         GTEST_SKIP() << "Proper indication of clip transition is not supported";
258     }
259     testPlayback(true /*testDrainPause*/);
260 }
261 
262 // Similar to AudioTrackOffloadTest.testMultipleAudioTrackOffloadPreemption
TEST_F(AudioTrackOffloadTest,ClipPreemption)263 TEST_F(AudioTrackOffloadTest, ClipPreemption) {
264     if (!halSupportsClipTransition()) {
265         GTEST_SKIP() << "Proper indication of clip transition is not supported";
266     }
267     sp<AudioPlayback> trackOne, trackTwo;
268     {
269         SCOPED_TRACE("track 1");
270         LOG(INFO) << __func__ << ": Creating and starting track 1";
271         ASSERT_NO_FATAL_FAILURE(testPlayback(false /*testDrainPause*/, &trackOne));
272     }
273     {
274         SCOPED_TRACE("track 2");
275         // Wait for track 1 to start playing, no event for this.
276         std::this_thread::sleep_for(std::chrono::milliseconds(300));
277         LOG(INFO) << __func__ << ": Creating and starting track 2";
278         ASSERT_NO_FATAL_FAILURE(testPlayback(false /*testDrainPause*/, &trackTwo));
279         std::this_thread::sleep_for(std::chrono::milliseconds(200));
280         trackTwo->stop();
281     }
282     LOG(INFO) << __func__ << ": Waiting for stream end on track 2";
283     EXPECT_TRUE(trackTwo->waitForStreamEnd()) << "Did not receive onStreamEnd on track 2";
284 }
285 
286 class AudioTrackCreateTest
287     : public ::testing::TestWithParam<std::tuple<uint32_t, audio_format_t, audio_channel_mask_t,
288                                                  audio_output_flags_t, audio_session_t>> {
289   public:
AudioTrackCreateTest()290     AudioTrackCreateTest()
291         : mSampleRate(std::get<0>(GetParam())),
292           mFormat(std::get<1>(GetParam())),
293           mChannelMask(std::get<2>(GetParam())),
294           mFlags(std::get<3>(GetParam())),
295           mSessionId(std::get<4>(GetParam())){};
296 
297     const uint32_t mSampleRate;
298     const audio_format_t mFormat;
299     const audio_channel_mask_t mChannelMask;
300     const audio_output_flags_t mFlags;
301     const audio_session_t mSessionId;
302 
303     sp<AudioPlayback> mAP;
304 
SetUp()305     virtual void SetUp() override {
306         mAP = sp<AudioPlayback>::make(mSampleRate, mFormat, mChannelMask, mFlags,
307                                               mSessionId);
308         ASSERT_NE(nullptr, mAP);
309         ASSERT_EQ(OK, mAP->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
310                 << "Unable to open Resource";
311         ASSERT_EQ(OK, mAP->create()) << "track creation failed";
312     }
313 
TearDown()314     virtual void TearDown() override {
315         if (mAP) mAP->stop();
316     }
317 };
318 
TEST_P(AudioTrackCreateTest,TestCreateTrack)319 TEST_P(AudioTrackCreateTest, TestCreateTrack) {
320     EXPECT_EQ(mFormat, mAP->getAudioTrackHandle()->format());
321     EXPECT_EQ(audio_channel_count_from_out_mask(mChannelMask),
322               mAP->getAudioTrackHandle()->channelCount());
323     if (mSampleRate != 0) EXPECT_EQ(mSampleRate, mAP->getAudioTrackHandle()->getSampleRate());
324     if (mSessionId != AUDIO_SESSION_NONE)
325         EXPECT_EQ(mSessionId, mAP->getAudioTrackHandle()->getSessionId());
326     EXPECT_EQ(mSampleRate, mAP->getAudioTrackHandle()->getOriginalSampleRate());
327     EXPECT_EQ(OK, mAP->start()) << "audio track start failed";
328     EXPECT_EQ(OK, mAP->onProcess());
329 }
330 
331 // sampleRate, format, channelMask, flags, sessionId
332 INSTANTIATE_TEST_SUITE_P(
333         AudioTrackParameterizedTest, AudioTrackCreateTest,
334         ::testing::Combine(::testing::Values(48000), ::testing::Values(AUDIO_FORMAT_PCM_16_BIT),
335                            ::testing::Values(AUDIO_CHANNEL_OUT_STEREO),
336                            ::testing::Values(AUDIO_OUTPUT_FLAG_NONE,
337                                              AUDIO_OUTPUT_FLAG_PRIMARY | AUDIO_OUTPUT_FLAG_FAST,
338                                              AUDIO_OUTPUT_FLAG_RAW | AUDIO_OUTPUT_FLAG_FAST,
339                                              AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
340                            ::testing::Values(AUDIO_SESSION_NONE)));
341 
main(int argc,char ** argv)342 int main(int argc, char** argv) {
343     android::ProcessState::self()->startThreadPool();
344     ::testing::InitGoogleTest(&argc, argv);
345     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
346     return RUN_ALL_TESTS();
347 }
348