xref: /aosp_15_r20/frameworks/av/media/libaudioclient/tests/audiotrack_tests.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "AudioTrackTests"
19 
20 #include <binder/ProcessState.h>
21 #include <gtest/gtest.h>
22 
23 #include "audio_test_utils.h"
24 #include "test_execution_tracer.h"
25 
26 using namespace android;
27 
28 // Test that the basic constructor returns an object that doesn't crash
29 // on stop() or destruction.
30 
TEST(AudioTrackTestBasic,EmptyAudioTrack)31 TEST(AudioTrackTestBasic, EmptyAudioTrack) {
32     AttributionSourceState attributionSource;
33     attributionSource.packageName = "AudioTrackTest";
34     attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
35     attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
36     attributionSource.token = sp<BBinder>::make();
37     const auto at = sp<AudioTrack>::make(attributionSource);
38 
39     EXPECT_EQ(NO_INIT, at->initCheck());
40     EXPECT_EQ(true, at->stopped());
41 
42     // ensure we do not crash.
43     at->stop();
44 }
45 
TEST(AudioTrackTest,TestPlayTrack)46 TEST(AudioTrackTest, TestPlayTrack) {
47     const auto ap = sp<AudioPlayback>::make(44100 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
48                                             AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_NONE,
49                                             AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN);
50     ASSERT_NE(nullptr, ap);
51     ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
52             << "Unable to open Resource";
53     EXPECT_EQ(OK, ap->create()) << "track creation failed";
54     EXPECT_EQ(OK, ap->start()) << "audio track start failed";
55     EXPECT_EQ(OK, ap->onProcess());
56     ap->stop();
57 }
58 
TEST(AudioTrackTest,TestSeek)59 TEST(AudioTrackTest, TestSeek) {
60     const auto ap = sp<AudioPlayback>::make(
61             44100 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO);
62     ASSERT_NE(nullptr, ap);
63     ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
64             << "Unable to open Resource";
65     EXPECT_EQ(OK, ap->create()) << "track creation failed";
66     EXPECT_EQ(OK, ap->start()) << "audio track start failed";
67     EXPECT_EQ(OK, ap->onProcess(true));
68     ap->stop();
69 }
70 
TEST(AudioTrackTest,OffloadOrDirectPlayback)71 TEST(AudioTrackTest, OffloadOrDirectPlayback) {
72     audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
73     info.sample_rate = 44100;
74     info.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
75     info.format = AUDIO_FORMAT_MP3;
76     info.stream_type = AUDIO_STREAM_MUSIC;
77     info.bit_rate = 192;
78     info.duration_us = 120 * 1000000;  // 120 sec
79 
80     audio_config_base_t config = {/* .sample_rate = */ info.sample_rate,
81                                   /* .channel_mask = */ info.channel_mask,
82                                   /* .format = */ AUDIO_FORMAT_PCM_16_BIT};
83     audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
84     attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
85     attributes.usage = AUDIO_USAGE_MEDIA;
86     attributes.flags = AUDIO_FLAG_NONE;
87 
88     if (!AudioTrack::isDirectOutputSupported(config, attributes) &&
89         AUDIO_OFFLOAD_NOT_SUPPORTED == AudioSystem::getOffloadSupport(info)) {
90         GTEST_SKIP() << "offload or direct playback is not supported";
91     }
92     sp<AudioPlayback> ap = nullptr;
93     if (AUDIO_OFFLOAD_NOT_SUPPORTED != AudioSystem::getOffloadSupport(info)) {
94         ap = sp<AudioPlayback>::make(info.sample_rate, info.format, info.channel_mask,
95                                      AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD, AUDIO_SESSION_NONE,
96                                      AudioTrack::TRANSFER_OBTAIN, nullptr, &info);
97     } else {
98         ap = sp<AudioPlayback>::make(config.sample_rate, config.format, config.channel_mask,
99                                      AUDIO_OUTPUT_FLAG_DIRECT, AUDIO_SESSION_NONE,
100                                      AudioTrack::TRANSFER_OBTAIN);
101     }
102     ASSERT_NE(nullptr, ap);
103     EXPECT_EQ(OK, ap->create()) << "track creation failed";
104     audio_dual_mono_mode_t mode;
105     if (OK != ap->getAudioTrackHandle()->getDualMonoMode(&mode)) {
106         std::cerr << "no dual mono presentation is available" << std::endl;
107     }
108     if (OK != ap->getAudioTrackHandle()->setDualMonoMode(AUDIO_DUAL_MONO_MODE_LR)) {
109         std::cerr << "no dual mono presentation is available" << std::endl;
110     } else {
111         EXPECT_EQ(OK, ap->getAudioTrackHandle()->getDualMonoMode(&mode));
112         EXPECT_EQ(AUDIO_DUAL_MONO_MODE_LR, mode);
113     }
114     float leveldB;
115     if (OK != ap->getAudioTrackHandle()->getAudioDescriptionMixLevel(&leveldB)) {
116         std::cerr << "Audio Description mixing is unavailable" << std::endl;
117     }
118     if (OK != ap->getAudioTrackHandle()->setAudioDescriptionMixLevel(3.14f)) {
119         std::cerr << "Audio Description mixing is unavailable" << std::endl;
120     } else {
121         EXPECT_EQ(OK, ap->getAudioTrackHandle()->getAudioDescriptionMixLevel(&leveldB));
122         EXPECT_EQ(3.14f, leveldB);
123     }
124     AudioPlaybackRate audioRate;
125     audioRate = ap->getAudioTrackHandle()->getPlaybackRate();
126     std::cerr << "playback speed :: " << audioRate.mSpeed << std::endl
127               << "playback pitch :: " << audioRate.mPitch << std::endl;
128     audioRate.mSpeed = 2.0f;
129     audioRate.mPitch = 2.0f;
130     audioRate.mStretchMode = AUDIO_TIMESTRETCH_STRETCH_VOICE;
131     audioRate.mFallbackMode = AUDIO_TIMESTRETCH_FALLBACK_MUTE;
132     EXPECT_TRUE(isAudioPlaybackRateValid(audioRate));
133     if (OK != ap->getAudioTrackHandle()->setPlaybackRate(audioRate)) {
134         std::cerr << "unable to set playback rate parameters" << std::endl;
135     } else {
136         AudioPlaybackRate audioRateLocal;
137         audioRateLocal = ap->getAudioTrackHandle()->getPlaybackRate();
138         EXPECT_TRUE(isAudioPlaybackRateEqual(audioRate, audioRateLocal));
139     }
140     ap->stop();
141 }
142 
TEST(AudioTrackTest,TestAudioCbNotifier)143 TEST(AudioTrackTest, TestAudioCbNotifier) {
144     const auto ap = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
145                                             AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_FAST,
146                                             AUDIO_SESSION_NONE, AudioTrack::TRANSFER_SHARED);
147     ASSERT_NE(nullptr, ap);
148     ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
149             << "Unable to open Resource";
150     EXPECT_EQ(OK, ap->create()) << "track creation failed";
151     EXPECT_EQ(BAD_VALUE, ap->getAudioTrackHandle()->addAudioDeviceCallback(nullptr));
152     sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
153     sp<OnAudioDeviceUpdateNotifier> cbOld = sp<OnAudioDeviceUpdateNotifier>::make();
154     EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cbOld));
155     EXPECT_EQ(INVALID_OPERATION, ap->getAudioTrackHandle()->addAudioDeviceCallback(cbOld));
156     EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cb));
157     EXPECT_EQ(OK, ap->start()) << "audio track start failed";
158     EXPECT_EQ(OK, ap->onProcess());
159     EXPECT_EQ(OK, cb->waitForAudioDeviceCb());
160     const auto [oldAudioIo, oldDeviceIds] = cbOld->getLastPortAndDevices();
161     EXPECT_EQ(AUDIO_IO_HANDLE_NONE, oldAudioIo);
162     EXPECT_TRUE(oldDeviceIds.empty());
163     const auto [audioIo, deviceIds] = cb->getLastPortAndDevices();
164     EXPECT_NE(AUDIO_IO_HANDLE_NONE, audioIo);
165     EXPECT_FALSE(deviceIds.empty());
166     EXPECT_EQ(audioIo, ap->getAudioTrackHandle()->getOutput());
167     DeviceIdVector routedDeviceIds = ap->getAudioTrackHandle()->getRoutedDeviceIds();
168     EXPECT_TRUE(areDeviceIdsEqual(routedDeviceIds, deviceIds));
169     String8 keys;
170     keys = ap->getAudioTrackHandle()->getParameters(keys);
171     if (!keys.empty()) {
172         std::cerr << "track parameters :: " << keys << std::endl;
173     }
174     EXPECT_TRUE(checkPatchPlayback(audioIo, deviceIds));
175     EXPECT_EQ(BAD_VALUE, ap->getAudioTrackHandle()->removeAudioDeviceCallback(nullptr));
176     EXPECT_EQ(INVALID_OPERATION, ap->getAudioTrackHandle()->removeAudioDeviceCallback(cbOld));
177     EXPECT_EQ(OK, ap->getAudioTrackHandle()->removeAudioDeviceCallback(cb));
178     ap->stop();
179 }
180 
181 class AudioTrackCreateTest
182     : public ::testing::TestWithParam<std::tuple<uint32_t, audio_format_t, audio_channel_mask_t,
183                                                  audio_output_flags_t, audio_session_t>> {
184   public:
AudioTrackCreateTest()185     AudioTrackCreateTest()
186         : mSampleRate(std::get<0>(GetParam())),
187           mFormat(std::get<1>(GetParam())),
188           mChannelMask(std::get<2>(GetParam())),
189           mFlags(std::get<3>(GetParam())),
190           mSessionId(std::get<4>(GetParam())){};
191 
192     const uint32_t mSampleRate;
193     const audio_format_t mFormat;
194     const audio_channel_mask_t mChannelMask;
195     const audio_output_flags_t mFlags;
196     const audio_session_t mSessionId;
197 
198     sp<AudioPlayback> mAP;
199 
SetUp()200     virtual void SetUp() override {
201         mAP = sp<AudioPlayback>::make(mSampleRate, mFormat, mChannelMask, mFlags,
202                                               mSessionId);
203         ASSERT_NE(nullptr, mAP);
204         ASSERT_EQ(OK, mAP->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
205                 << "Unable to open Resource";
206         ASSERT_EQ(OK, mAP->create()) << "track creation failed";
207     }
208 
TearDown()209     virtual void TearDown() override {
210         if (mAP) mAP->stop();
211     }
212 };
213 
TEST_P(AudioTrackCreateTest,TestCreateTrack)214 TEST_P(AudioTrackCreateTest, TestCreateTrack) {
215     EXPECT_EQ(mFormat, mAP->getAudioTrackHandle()->format());
216     EXPECT_EQ(audio_channel_count_from_out_mask(mChannelMask),
217               mAP->getAudioTrackHandle()->channelCount());
218     if (mSampleRate != 0) EXPECT_EQ(mSampleRate, mAP->getAudioTrackHandle()->getSampleRate());
219     if (mSessionId != AUDIO_SESSION_NONE)
220         EXPECT_EQ(mSessionId, mAP->getAudioTrackHandle()->getSessionId());
221     EXPECT_EQ(mSampleRate, mAP->getAudioTrackHandle()->getOriginalSampleRate());
222     EXPECT_EQ(OK, mAP->start()) << "audio track start failed";
223     EXPECT_EQ(OK, mAP->onProcess());
224 }
225 
226 // sampleRate, format, channelMask, flags, sessionId
227 INSTANTIATE_TEST_SUITE_P(
228         AudioTrackParameterizedTest, AudioTrackCreateTest,
229         ::testing::Combine(::testing::Values(48000), ::testing::Values(AUDIO_FORMAT_PCM_16_BIT),
230                            ::testing::Values(AUDIO_CHANNEL_OUT_STEREO),
231                            ::testing::Values(AUDIO_OUTPUT_FLAG_NONE,
232                                              AUDIO_OUTPUT_FLAG_PRIMARY | AUDIO_OUTPUT_FLAG_FAST,
233                                              AUDIO_OUTPUT_FLAG_RAW | AUDIO_OUTPUT_FLAG_FAST,
234                                              AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
235                            ::testing::Values(AUDIO_SESSION_NONE)));
236 
main(int argc,char ** argv)237 int main(int argc, char** argv) {
238     android::ProcessState::self()->startThreadPool();
239     ::testing::InitGoogleTest(&argc, argv);
240     ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
241     return RUN_ALL_TESTS();
242 }
243