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 #ifndef AUDIO_TEST_UTILS_H_ 18 #define AUDIO_TEST_UTILS_H_ 19 20 #include <sys/stat.h> 21 #include <unistd.h> 22 #include <deque> 23 #include <memory> 24 #include <mutex> 25 #include <utility> 26 27 #include <android-base/thread_annotations.h> 28 #include <binder/MemoryDealer.h> 29 #include <media/AidlConversion.h> 30 #include <media/AudioRecord.h> 31 #include <media/AudioTrack.h> 32 33 using namespace android; 34 35 struct MixPort { 36 std::string name; 37 std::string role; 38 std::string flags; 39 }; 40 41 struct Route { 42 std::string name; 43 std::string sources; 44 std::string sink; 45 }; 46 47 status_t isAutomotivePlatform(bool* isAutomotive); 48 status_t listAudioPorts(std::vector<audio_port_v7>& portsVec); 49 status_t listAudioPatches(std::vector<struct audio_patch>& patchesVec); 50 status_t getAnyPort(audio_port_role_t role, audio_port_type_t type, audio_port_v7& port); 51 status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type, 52 audio_devices_t deviceType, const std::string& address, 53 audio_port_v7& port); 54 status_t getPatchForOutputMix(audio_io_handle_t audioIo, audio_patch& patch); 55 status_t getPatchForInputMix(audio_io_handle_t audioIo, audio_patch& patch); 56 bool patchContainsOutputDevices(DeviceIdVector deviceIds, audio_patch patch); 57 bool patchContainsInputDevice(audio_port_handle_t deviceId, audio_patch patch); 58 bool checkPatchPlayback(audio_io_handle_t audioIo, const DeviceIdVector& deviceIds); 59 bool checkPatchCapture(audio_io_handle_t audioIo, audio_port_handle_t deviceId); 60 std::string dumpPort(const audio_port_v7& port); 61 std::string dumpPortConfig(const audio_port_config& port); 62 std::string dumpPatch(const audio_patch& patch); 63 64 class OnAudioDeviceUpdateNotifier : public AudioSystem::AudioDeviceCallback { 65 public: 66 void onAudioDeviceUpdate(audio_io_handle_t audioIo, const DeviceIdVector& deviceIds) override; 67 status_t waitForAudioDeviceCb(audio_port_handle_t expDeviceId = AUDIO_PORT_HANDLE_NONE); 68 std::pair<audio_io_handle_t, DeviceIdVector> getLastPortAndDevices() const; 69 70 private: 71 audio_io_handle_t mAudioIo GUARDED_BY(mMutex) = AUDIO_IO_HANDLE_NONE; 72 DeviceIdVector mDeviceIds GUARDED_BY(mMutex); 73 mutable std::mutex mMutex; 74 std::condition_variable mCondition; 75 }; 76 77 namespace { 78 79 class TestAudioTrack : public AudioTrack { 80 public: 81 explicit TestAudioTrack(const AttributionSourceState& attributionSourceState = {}) AudioTrack(attributionSourceState)82 : AudioTrack(attributionSourceState) {} 83 TestAudioTrack(audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, 84 audio_channel_mask_t channelMask, const sp<IMemory>& sharedBuffer, 85 audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, 86 const wp<IAudioTrackCallback>& callback = nullptr, 87 int32_t notificationFrames = 0, 88 audio_session_t sessionId = AUDIO_SESSION_ALLOCATE, 89 transfer_type transferType = TRANSFER_DEFAULT, 90 const audio_offload_info_t* offloadInfo = nullptr, 91 const AttributionSourceState& attributionSource = AttributionSourceState(), 92 const audio_attributes_t* pAttributes = nullptr, bool doNotReconnect = false, 93 float maxRequiredSpeed = 1.0f) AudioTrack(streamType,sampleRate,format,channelMask,sharedBuffer,flags,callback,notificationFrames,sessionId,transferType,offloadInfo,attributionSource,pAttributes,doNotReconnect,maxRequiredSpeed)94 : AudioTrack(streamType, sampleRate, format, channelMask, sharedBuffer, flags, callback, 95 notificationFrames, sessionId, transferType, offloadInfo, attributionSource, 96 pAttributes, doNotReconnect, maxRequiredSpeed) {} 97 // The callback thread is normally used for TRANSFER_SYNC_NOTIF_CALLBACK 98 // in order to deliver "more data" callback. However, for offload we are 99 // interested in the "stream end" event which is also served via the same 100 // callback interface. wakeCallbackThread()101 void wakeCallbackThread() { 102 if (sp<AudioTrackThread> t = mAudioTrackThread; t != nullptr) { 103 t->wake(); 104 } 105 } 106 }; 107 108 } // namespace 109 110 // Simple AudioPlayback class. 111 class AudioPlayback : public AudioTrack::IAudioTrackCallback { 112 friend sp<AudioPlayback>; 113 AudioPlayback(uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, 114 audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, 115 audio_session_t sessionId = AUDIO_SESSION_NONE, 116 AudioTrack::transfer_type transferType = AudioTrack::TRANSFER_SHARED, 117 audio_attributes_t* attributes = nullptr, audio_offload_info_t* info = nullptr); 118 119 public: 120 status_t loadResource(const char* name); 121 status_t create(); 122 sp<AudioTrack> getAudioTrackHandle(); 123 status_t start(); 124 status_t waitForConsumption(bool testSeek = false) EXCLUDES(mMutex); 125 status_t fillBuffer(); 126 status_t onProcess(bool testSeek = false); 127 void pause(); 128 void resume(); 129 void stop() EXCLUDES(mMutex); 130 bool waitForStreamEnd(); 131 132 // IAudioTrackCallback 133 void onBufferEnd() override EXCLUDES(mMutex); 134 void onStreamEnd() override EXCLUDES(mMutex); 135 136 bool mStopPlaying GUARDED_BY(mMutex) = false; 137 138 enum State { 139 PLAY_NO_INIT, 140 PLAY_READY, 141 PLAY_STARTED, 142 PLAY_STOPPED, 143 }; 144 145 private: 146 ~AudioPlayback(); 147 const uint32_t mSampleRate; 148 const audio_format_t mFormat; 149 const audio_channel_mask_t mChannelMask; 150 const audio_output_flags_t mFlags; 151 const audio_session_t mSessionId; 152 const AudioTrack::transfer_type mTransferType; 153 const audio_attributes_t* mAttributes; 154 const audio_offload_info_t* mOffloadInfo; 155 156 size_t mBytesUsedSoFar = 0; 157 State mState = PLAY_NO_INIT; 158 size_t mMemCapacity = 0; 159 sp<MemoryDealer> mMemoryDealer; 160 sp<IMemory> mMemory; 161 sp<TestAudioTrack> mTrack; 162 mutable std::mutex mMutex; 163 bool mStreamEndReceived GUARDED_BY(mMutex) = false; 164 std::condition_variable mCondition; 165 }; 166 167 // hold pcm data sent by AudioRecord 168 class RawBuffer { 169 public: 170 RawBuffer(int64_t ptsPipeline = -1, int64_t ptsManual = -1, int32_t capacity = 0); 171 172 std::unique_ptr<uint8_t[]> mData; 173 int64_t mPtsPipeline; 174 int64_t mPtsManual; 175 int32_t mCapacity; 176 }; 177 178 // Simple AudioCapture 179 class AudioCapture : public AudioRecord::IAudioRecordCallback { 180 public: 181 AudioCapture(audio_source_t inputSource, uint32_t sampleRate, audio_format_t format, 182 audio_channel_mask_t channelMask, 183 audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE, 184 audio_session_t sessionId = AUDIO_SESSION_ALLOCATE, 185 AudioRecord::transfer_type transferType = AudioRecord::TRANSFER_CALLBACK, 186 const audio_attributes_t* attributes = nullptr); 187 ~AudioCapture(); 188 size_t onMoreData(const AudioRecord::Buffer& buffer) override EXCLUDES(mMutex); 189 void onOverrun() override; 190 void onMarker(uint32_t markerPosition) override EXCLUDES(mMutex); 191 void onNewPos(uint32_t newPos) override EXCLUDES(mMutex); 192 void onNewIAudioRecord() override; 193 status_t create(); 194 status_t setRecordDuration(float durationInSec); 195 status_t enableRecordDump(); getRecordDumpFileName()196 std::string getRecordDumpFileName() const { return mFileName; } 197 sp<AudioRecord> getAudioRecordHandle(); 198 status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, 199 audio_session_t triggerSession = AUDIO_SESSION_NONE); 200 status_t obtainBufferCb(RawBuffer& buffer) EXCLUDES(mMutex); 201 status_t obtainBuffer(RawBuffer& buffer) EXCLUDES(mMutex); 202 status_t audioProcess() EXCLUDES(mMutex); 203 status_t stop() EXCLUDES(mMutex); 204 uint32_t getMarkerPeriod() const EXCLUDES(mMutex); 205 uint32_t getMarkerPosition() const EXCLUDES(mMutex); 206 void setMarkerPeriod(uint32_t markerPeriod) EXCLUDES(mMutex); 207 void setMarkerPosition(uint32_t markerPosition) EXCLUDES(mMutex); 208 uint32_t waitAndGetReceivedCbMarkerAtPosition() const EXCLUDES(mMutex); 209 uint32_t waitAndGetReceivedCbMarkerCount() const EXCLUDES(mMutex); 210 211 uint32_t mFrameCount = 0; 212 uint32_t mNotificationFrames = 0; 213 int64_t mNumFramesToRecord = 0; 214 215 enum State { 216 REC_NO_INIT, 217 REC_READY, 218 REC_STARTED, 219 REC_STOPPED, 220 }; 221 222 private: 223 const audio_source_t mInputSource; 224 const uint32_t mSampleRate; 225 const audio_format_t mFormat; 226 const audio_channel_mask_t mChannelMask; 227 const audio_input_flags_t mFlags; 228 const audio_session_t mSessionId; 229 const AudioRecord::transfer_type mTransferType; 230 const audio_attributes_t* mAttributes; 231 232 size_t mMaxBytesPerCallback = 2048; 233 sp<AudioRecord> mRecord; 234 State mState = REC_NO_INIT; 235 bool mStopRecording GUARDED_BY(mMutex) = false; 236 std::string mFileName; 237 int mOutFileFd = -1; 238 239 mutable std::mutex mMutex; 240 std::condition_variable mCondition; 241 std::deque<RawBuffer> mBuffersReceived GUARDED_BY(mMutex); 242 243 mutable std::condition_variable mMarkerCondition; 244 uint32_t mMarkerPeriod GUARDED_BY(mMutex) = 0; 245 uint32_t mMarkerPosition GUARDED_BY(mMutex) = 0; 246 std::optional<uint32_t> mReceivedCbMarkerCount GUARDED_BY(mMutex); 247 std::optional<uint32_t> mReceivedCbMarkerAtPosition GUARDED_BY(mMutex); 248 249 int64_t mNumFramesReceived GUARDED_BY(mMutex) = 0; 250 int64_t mNumFramesLost GUARDED_BY(mMutex) = 0; 251 }; 252 253 #endif // AUDIO_TEST_UTILS_H_ 254