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 <sstream>
18
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "AudioRecordTest"
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(AudioRecordTestBasic,EmptyAudioRecord)34 TEST(AudioRecordTestBasic, EmptyAudioRecord) {
35 AttributionSourceState attributionSource;
36 attributionSource.packageName = "AudioRecordTest";
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 ar = sp<AudioRecord>::make(attributionSource);
41
42 // test key commands on an unset AudioRecord.
43 EXPECT_EQ(NO_INIT, ar->initCheck());
44 EXPECT_EQ(true, ar->stopped());
45
46 // just don't crash.
47 ar->stop();
48 }
49
50 class AudioRecordTest : public ::testing::Test {
51 public:
SetUp()52 void SetUp() override {
53 mAC = new AudioCapture(AUDIO_SOURCE_DEFAULT, 44100, AUDIO_FORMAT_PCM_16_BIT,
54 AUDIO_CHANNEL_IN_FRONT);
55 ASSERT_NE(nullptr, mAC);
56 ASSERT_EQ(OK, mAC->create()) << "record creation failed";
57 }
58
TearDown()59 void TearDown() override {
60 if (mAC) ASSERT_EQ(OK, mAC->stop());
61 }
62
63 sp<AudioCapture> mAC;
64 };
65
66 using RecordCreateTestParam = std::tuple<uint32_t, audio_format_t, audio_channel_mask_t,
67 audio_input_flags_t, audio_session_t, audio_source_t>;
68 enum {
69 RECORD_PARAM_SAMPLE_RATE,
70 RECORD_PARAM_FORMAT,
71 RECORD_PARAM_CHANNEL_MASK,
72 RECORD_PARAM_FLAGS,
73 RECORD_PARAM_SESSION_ID,
74 RECORD_PARAM_INPUT_SOURCE
75 };
76
77 class AudioRecordCreateTest : public ::testing::TestWithParam<RecordCreateTestParam> {
78 public:
AudioRecordCreateTest()79 AudioRecordCreateTest()
80 : mSampleRate(std::get<RECORD_PARAM_SAMPLE_RATE>(GetParam())),
81 mFormat(std::get<RECORD_PARAM_FORMAT>(GetParam())),
82 mChannelMask(std::get<RECORD_PARAM_CHANNEL_MASK>(GetParam())),
83 mFlags(std::get<RECORD_PARAM_FLAGS>(GetParam())),
84 mSessionId(std::get<RECORD_PARAM_SESSION_ID>(GetParam())),
85 mInputSource(std::get<RECORD_PARAM_INPUT_SOURCE>(GetParam())){};
86
87 const uint32_t mSampleRate;
88 const audio_format_t mFormat;
89 const audio_channel_mask_t mChannelMask;
90 const audio_input_flags_t mFlags;
91 const audio_session_t mSessionId;
92 const audio_source_t mInputSource;
93 const AudioRecord::transfer_type mTransferType = AudioRecord::TRANSFER_OBTAIN;
94
95 sp<AudioCapture> mAC;
96
SetUp()97 void SetUp() override {
98 mAC = new AudioCapture(mInputSource, mSampleRate, mFormat, mChannelMask, mFlags, mSessionId,
99 mTransferType);
100 ASSERT_NE(nullptr, mAC);
101 ASSERT_EQ(OK, mAC->create()) << "record creation failed";
102 }
103
TearDown()104 void TearDown() override {
105 if (mAC) ASSERT_EQ(OK, mAC->stop());
106 }
107 };
108
TEST_F(AudioRecordTest,TestSimpleRecord)109 TEST_F(AudioRecordTest, TestSimpleRecord) {
110 EXPECT_EQ(OK, mAC->start()) << "start recording failed";
111 EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
112 }
113
TEST_F(AudioRecordTest,TestAudioCbNotifier)114 TEST_F(AudioRecordTest, TestAudioCbNotifier) {
115 EXPECT_EQ(BAD_VALUE, mAC->getAudioRecordHandle()->addAudioDeviceCallback(nullptr));
116 sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
117 sp<OnAudioDeviceUpdateNotifier> cbOld = sp<OnAudioDeviceUpdateNotifier>::make();
118 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->addAudioDeviceCallback(cbOld));
119 EXPECT_EQ(INVALID_OPERATION, mAC->getAudioRecordHandle()->addAudioDeviceCallback(cbOld));
120 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->addAudioDeviceCallback(cb));
121 EXPECT_EQ(OK, mAC->start()) << "record creation failed";
122 EXPECT_EQ(OK, cb->waitForAudioDeviceCb());
123 EXPECT_EQ(AUDIO_IO_HANDLE_NONE, cbOld->mAudioIo);
124 EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, cbOld->mDeviceId);
125 EXPECT_NE(AUDIO_IO_HANDLE_NONE, cb->mAudioIo);
126 EXPECT_NE(AUDIO_PORT_HANDLE_NONE, cb->mDeviceId);
127 EXPECT_EQ(BAD_VALUE, mAC->getAudioRecordHandle()->removeAudioDeviceCallback(nullptr));
128 EXPECT_EQ(INVALID_OPERATION, mAC->getAudioRecordHandle()->removeAudioDeviceCallback(cbOld));
129 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->removeAudioDeviceCallback(cb));
130 mAC->stop();
131 }
132
TEST_F(AudioRecordTest,TestEventRecordTrackPause)133 TEST_F(AudioRecordTest, TestEventRecordTrackPause) {
134 const auto playback = sp<AudioPlayback>::make(
135 8000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_MONO);
136 ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_1ch_8kHz_s16le.raw"))
137 << "Unable to open Resource";
138 EXPECT_EQ(OK, playback->create()) << "AudioTrack Creation failed";
139 audio_session_t audioTrackSession = playback->getAudioTrackHandle()->getSessionId();
140 EXPECT_EQ(OK, mAC->start(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE, audioTrackSession))
141 << "record creation failed";
142 EXPECT_EQ(OK, playback->start());
143 RawBuffer buffer;
144 status_t status = mAC->obtainBufferCb(buffer);
145 EXPECT_EQ(status, TIMED_OUT) << "Not expecting any callbacks until track sends Sync event";
146 playback->getAudioTrackHandle()->pause();
147 EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
148 playback->stop();
149 }
150
TEST_F(AudioRecordTest,TestEventRecordTrackStop)151 TEST_F(AudioRecordTest, TestEventRecordTrackStop) {
152 const auto playback = sp<AudioPlayback>::make(
153 8000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_MONO);
154 ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_1ch_8kHz_s16le.raw"))
155 << "Unable to open Resource";
156 EXPECT_EQ(OK, playback->create()) << "AudioTrack Creation failed";
157 audio_session_t audioTrackSession = playback->getAudioTrackHandle()->getSessionId();
158 EXPECT_EQ(OK, mAC->start(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE, audioTrackSession))
159 << "record creation failed";
160 EXPECT_EQ(OK, playback->start());
161 RawBuffer buffer;
162 status_t status = mAC->obtainBufferCb(buffer);
163 EXPECT_EQ(status, TIMED_OUT) << "Not expecting any callbacks until track sends Sync event";
164 playback->stop();
165 EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
166 }
167
TEST_F(AudioRecordTest,TestGetSetMarker)168 TEST_F(AudioRecordTest, TestGetSetMarker) {
169 mAC->mMarkerPosition = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
170 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setMarkerPosition(mAC->mMarkerPosition))
171 << "setMarkerPosition() failed";
172 uint32_t marker;
173 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getMarkerPosition(&marker))
174 << "getMarkerPosition() failed";
175 EXPECT_EQ(OK, mAC->start()) << "start recording failed";
176 EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
177 EXPECT_EQ(marker, mAC->mMarkerPosition)
178 << "configured marker and received marker are different";
179 EXPECT_EQ(mAC->mReceivedCbMarkerAtPosition, mAC->mMarkerPosition)
180 << "configured marker and received cb marker are different";
181 }
182
TEST_F(AudioRecordTest,TestGetSetMarkerPeriodical)183 TEST_F(AudioRecordTest, TestGetSetMarkerPeriodical) {
184 mAC->mMarkerPeriod = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
185 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->mMarkerPeriod))
186 << "setPositionUpdatePeriod() failed";
187 uint32_t marker;
188 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPositionUpdatePeriod(&marker))
189 << "getPositionUpdatePeriod() failed";
190 EXPECT_EQ(OK, mAC->start()) << "start recording failed";
191 EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
192 EXPECT_EQ(marker, mAC->mMarkerPeriod) << "configured marker and received marker are different";
193 EXPECT_EQ(mAC->mReceivedCbMarkerCount, mAC->mNumFramesToRecord / mAC->mMarkerPeriod)
194 << "configured marker and received cb marker are different";
195 }
196
TEST_F(AudioRecordTest,TestGetPosition)197 TEST_F(AudioRecordTest, TestGetPosition) {
198 uint32_t position;
199 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPosition(&position)) << "getPosition() failed";
200 EXPECT_EQ(0, position);
201 EXPECT_EQ(OK, mAC->start()) << "start recording failed";
202 EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
203 EXPECT_EQ(OK, mAC->stop());
204 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPosition(&position)) << "getPosition() failed";
205 }
206
207 // TODO: Add checkPatchCapture(), verify the information of patch via dumpPort() and dumpPatch()
TEST_P(AudioRecordCreateTest,TestCreateRecord)208 TEST_P(AudioRecordCreateTest, TestCreateRecord) {
209 EXPECT_EQ(mFormat, mAC->getAudioRecordHandle()->format());
210 EXPECT_EQ(audio_channel_count_from_in_mask(mChannelMask),
211 mAC->getAudioRecordHandle()->channelCount());
212 if (mAC->mFrameCount != 0)
213 EXPECT_LE(mAC->mFrameCount, mAC->getAudioRecordHandle()->frameCount());
214 EXPECT_EQ(mInputSource, mAC->getAudioRecordHandle()->inputSource());
215 if (mSampleRate != 0) EXPECT_EQ(mSampleRate, mAC->getAudioRecordHandle()->getSampleRate());
216 if (mSessionId != AUDIO_SESSION_NONE)
217 EXPECT_EQ(mSessionId, mAC->getAudioRecordHandle()->getSessionId());
218 if (mTransferType != AudioRecord::TRANSFER_CALLBACK) {
219 uint32_t marker;
220 mAC->mMarkerPosition = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
221 EXPECT_EQ(INVALID_OPERATION,
222 mAC->getAudioRecordHandle()->setMarkerPosition(mAC->mMarkerPosition));
223 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getMarkerPosition(&marker));
224 EXPECT_EQ(INVALID_OPERATION,
225 mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->mMarkerPosition));
226 EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPositionUpdatePeriod(&marker));
227 }
228 EXPECT_EQ(OK, mAC->start()) << "start recording failed";
229 EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
230 }
231
GetRecordTestName(const testing::TestParamInfo<RecordCreateTestParam> & info)232 static std::string GetRecordTestName(const testing::TestParamInfo<RecordCreateTestParam>& info) {
233 const auto& p = info.param;
234 std::ostringstream s;
235 s << std::get<RECORD_PARAM_SAMPLE_RATE>(p) << "_"
236 << audio_format_to_string(std::get<RECORD_PARAM_FORMAT>(p)) << "__"
237 << audio_channel_mask_to_string(std::get<RECORD_PARAM_CHANNEL_MASK>(p)) << "__"
238 << "Flags_0x" << std::hex << std::get<RECORD_PARAM_FLAGS>(p) << std::dec << "__"
239 << "Session_" << std::get<RECORD_PARAM_SESSION_ID>(p) << "__"
240 << audio_source_to_string(std::get<RECORD_PARAM_INPUT_SOURCE>(p));
241 return s.str();
242 }
243
244 // for port primary input
245 INSTANTIATE_TEST_SUITE_P(AudioRecordPrimaryInput, AudioRecordCreateTest,
246 ::testing::Combine(::testing::Values(8000, 11025, 12000, 16000, 22050,
247 24000, 32000, 44100, 48000),
248 ::testing::Values(AUDIO_FORMAT_PCM_8_24_BIT),
249 ::testing::Values(AUDIO_CHANNEL_IN_MONO,
250 AUDIO_CHANNEL_IN_STEREO,
251 AUDIO_CHANNEL_IN_FRONT_BACK),
252 ::testing::Values(AUDIO_INPUT_FLAG_NONE),
253 ::testing::Values(AUDIO_SESSION_NONE),
254 ::testing::Values(AUDIO_SOURCE_DEFAULT)),
255 GetRecordTestName);
256
257 // for port fast input
258 INSTANTIATE_TEST_SUITE_P(AudioRecordFastInput, AudioRecordCreateTest,
259 ::testing::Combine(::testing::Values(8000, 11025, 12000, 16000, 22050,
260 24000, 32000, 44100, 48000),
261 ::testing::Values(AUDIO_FORMAT_PCM_8_24_BIT),
262 ::testing::Values(AUDIO_CHANNEL_IN_MONO,
263 AUDIO_CHANNEL_IN_STEREO,
264 AUDIO_CHANNEL_IN_FRONT_BACK),
265 ::testing::Values(AUDIO_INPUT_FLAG_FAST),
266 ::testing::Values(AUDIO_SESSION_NONE),
267 ::testing::Values(AUDIO_SOURCE_DEFAULT)),
268 GetRecordTestName);
269
270 // misc
271 INSTANTIATE_TEST_SUITE_P(AudioRecordMiscInput, AudioRecordCreateTest,
272 ::testing::Combine(::testing::Values(48000),
273 ::testing::Values(AUDIO_FORMAT_PCM_16_BIT),
274 ::testing::Values(AUDIO_CHANNEL_IN_MONO),
275 ::testing::Values(AUDIO_INPUT_FLAG_NONE),
276 ::testing::Values(AUDIO_SESSION_NONE),
277 ::testing::Values(AUDIO_SOURCE_MIC,
278 AUDIO_SOURCE_CAMCORDER,
279 AUDIO_SOURCE_VOICE_RECOGNITION,
280 AUDIO_SOURCE_VOICE_COMMUNICATION,
281 AUDIO_SOURCE_UNPROCESSED)),
282 GetRecordTestName);
283
main(int argc,char ** argv)284 int main(int argc, char** argv) {
285 ::testing::InitGoogleTest(&argc, argv);
286 ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
287 android::base::SetMinimumLogSeverity(::android::base::DEBUG);
288 // This is for death handlers instantiated by the framework code.
289 android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
290 android::ProcessState::self()->startThreadPool();
291 return RUN_ALL_TESTS();
292 }
293