1 /* 2 * Copyright (C) 2023 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 #pragma once 18 19 #include <atomic> 20 #include <memory> 21 #include <mutex> 22 #include <string_view> 23 24 #include <aidl/android/hardware/audio/common/AudioOffloadMetadata.h> 25 #include <aidl/android/hardware/audio/core/BpStreamCommon.h> 26 #include <aidl/android/hardware/audio/core/BpStreamIn.h> 27 #include <aidl/android/hardware/audio/core/BpStreamOut.h> 28 #include <aidl/android/hardware/audio/core/MmapBufferDescriptor.h> 29 #include <aidl/android/media/audio/IHalAdapterVendorExtension.h> 30 #include <fmq/AidlMessageQueue.h> 31 #include <media/audiohal/EffectHalInterface.h> 32 #include <media/audiohal/StreamHalInterface.h> 33 #include <media/AidlConversionUtil.h> 34 #include <media/AudioParameter.h> 35 #include <mediautils/Synchronization.h> 36 37 #include "ConversionHelperAidl.h" 38 #include "StreamPowerLog.h" 39 40 using ::aidl::android::hardware::audio::common::AudioOffloadMetadata; 41 using ::aidl::android::hardware::audio::core::MmapBufferDescriptor; 42 43 namespace android { 44 45 class StreamContextAidl { 46 public: 47 typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Command, 48 ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> CommandMQ; 49 typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Reply, 50 ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> ReplyMQ; 51 typedef AidlMessageQueue<int8_t, 52 ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ; 53 StreamContextAidl(::aidl::android::hardware::audio::core::StreamDescriptor & descriptor,bool isAsynchronous,int ioHandle)54 StreamContextAidl( 55 ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor, 56 bool isAsynchronous, int ioHandle) 57 : mFrameSizeBytes(descriptor.frameSizeBytes), 58 mCommandMQ(new CommandMQ(descriptor.command)), 59 mReplyMQ(new ReplyMQ(descriptor.reply)), 60 mBufferSizeFrames(descriptor.bufferSizeFrames), 61 mDataMQ(maybeCreateDataMQ(descriptor)), 62 mIsAsynchronous(isAsynchronous), 63 mIsMmapped(isMmapped(descriptor)), 64 mMmapBufferDescriptor(maybeGetMmapBuffer(descriptor)), 65 mIoHandle(ioHandle) {} StreamContextAidl(StreamContextAidl && other)66 StreamContextAidl(StreamContextAidl&& other) : 67 mFrameSizeBytes(other.mFrameSizeBytes), 68 mCommandMQ(std::move(other.mCommandMQ)), 69 mReplyMQ(std::move(other.mReplyMQ)), 70 mBufferSizeFrames(other.mBufferSizeFrames), 71 mDataMQ(std::move(other.mDataMQ)), 72 mIsAsynchronous(other.mIsAsynchronous), 73 mIsMmapped(other.mIsMmapped), 74 mMmapBufferDescriptor(std::move(other.mMmapBufferDescriptor)), 75 mIoHandle(other.mIoHandle) {} 76 StreamContextAidl& operator=(StreamContextAidl&& other) { 77 mFrameSizeBytes = other.mFrameSizeBytes; 78 mCommandMQ = std::move(other.mCommandMQ); 79 mReplyMQ = std::move(other.mReplyMQ); 80 mBufferSizeFrames = other.mBufferSizeFrames; 81 mDataMQ = std::move(other.mDataMQ); 82 mIsAsynchronous = other.mIsAsynchronous; 83 mIsMmapped = other.mIsMmapped; 84 mMmapBufferDescriptor = std::move(other.mMmapBufferDescriptor); 85 mIoHandle = other.mIoHandle; 86 return *this; 87 } isValid()88 bool isValid() const { 89 return mFrameSizeBytes != 0 && 90 mCommandMQ != nullptr && mCommandMQ->isValid() && 91 mReplyMQ != nullptr && mReplyMQ->isValid() && 92 (mDataMQ == nullptr || ( 93 mDataMQ->isValid() && 94 mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() >= 95 mFrameSizeBytes * mBufferSizeFrames)) && 96 (!mIsMmapped || mMmapBufferDescriptor.sharedMemory.fd.get() >= 0); 97 } getBufferSizeBytes()98 size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; } getBufferSizeFrames()99 size_t getBufferSizeFrames() const { return mBufferSizeFrames; } getBufferDurationMs(int32_t sampleRate)100 size_t getBufferDurationMs(int32_t sampleRate) const { 101 auto bufferSize = mIsMmapped ? getMmapBurstSize() : mBufferSizeFrames; 102 return sampleRate != 0 ? bufferSize * MILLIS_PER_SECOND / sampleRate : 0; 103 } getCommandMQ()104 CommandMQ* getCommandMQ() const { return mCommandMQ.get(); } getDataMQ()105 DataMQ* getDataMQ() const { return mDataMQ.get(); } getFrameSizeBytes()106 size_t getFrameSizeBytes() const { return mFrameSizeBytes; } getReplyMQ()107 ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); } isAsynchronous()108 bool isAsynchronous() const { return mIsAsynchronous; } isMmapped()109 bool isMmapped() const { return mIsMmapped; } getMmapBufferDescriptor()110 const MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; } getMmapBurstSize()111 size_t getMmapBurstSize() const { return mMmapBufferDescriptor.burstSizeFrames; } getIoHandle()112 int getIoHandle() const { return mIoHandle; } 113 114 private: maybeCreateDataMQ(const::aidl::android::hardware::audio::core::StreamDescriptor & descriptor)115 static std::unique_ptr<DataMQ> maybeCreateDataMQ( 116 const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) { 117 using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag; 118 if (descriptor.audio.getTag() == Tag::fmq) { 119 return std::make_unique<DataMQ>(descriptor.audio.get<Tag::fmq>()); 120 } 121 return nullptr; 122 } isMmapped(const::aidl::android::hardware::audio::core::StreamDescriptor & descriptor)123 static bool isMmapped( 124 const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) { 125 using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag; 126 return descriptor.audio.getTag() == Tag::mmap; 127 } maybeGetMmapBuffer(::aidl::android::hardware::audio::core::StreamDescriptor & descriptor)128 static MmapBufferDescriptor maybeGetMmapBuffer( 129 ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) { 130 using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag; 131 if (descriptor.audio.getTag() == Tag::mmap) { 132 return std::move(descriptor.audio.get<Tag::mmap>()); 133 } 134 return {}; 135 } 136 137 size_t mFrameSizeBytes; 138 std::unique_ptr<CommandMQ> mCommandMQ; 139 std::unique_ptr<ReplyMQ> mReplyMQ; 140 size_t mBufferSizeFrames; 141 std::unique_ptr<DataMQ> mDataMQ; 142 bool mIsAsynchronous; 143 bool mIsMmapped; 144 MmapBufferDescriptor mMmapBufferDescriptor; 145 int mIoHandle; 146 }; 147 148 class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl { 149 public: 150 // Return size of input/output buffer in bytes for this stream - eg. 4800. 151 status_t getBufferSize(size_t *size) override; 152 153 // Return the base configuration of the stream: 154 // - channel mask; 155 // - format - e.g. AUDIO_FORMAT_PCM_16_BIT; 156 // - sampling rate in Hz - eg. 44100. 157 status_t getAudioProperties(audio_config_base_t *configBase) override; 158 159 // Set audio stream parameters. 160 status_t setParameters(const String8& kvPairs) override; 161 162 // Get audio stream parameters. 163 status_t getParameters(const String8& keys, String8 *values) override; 164 165 // Return the frame size (number of bytes per sample) of a stream. 166 status_t getFrameSize(size_t *size) override; 167 168 // Add or remove the effect on the stream. 169 status_t addEffect(sp<EffectHalInterface> effect) override; 170 status_t removeEffect(sp<EffectHalInterface> effect) override; 171 172 // Put the audio hardware input/output into standby mode. 173 status_t standby() override; 174 175 status_t dump(int fd, const Vector<String16>& args) override; 176 177 // Start a stream operating in mmap mode. 178 status_t start() override; 179 180 // Stop a stream operating in mmap mode. 181 status_t stop() override; 182 183 // Retrieve information on the data buffer in mmap mode. 184 status_t createMmapBuffer(int32_t minSizeFrames, 185 struct audio_mmap_buffer_info *info) override; 186 187 // Get current read/write position in the mmap buffer 188 status_t getMmapPosition(struct audio_mmap_position *position) override; 189 190 // Set the priority of the thread that interacts with the HAL 191 // (must match the priority of the audioflinger's thread that calls 'read' / 'write') 192 status_t setHalThreadPriority(int priority) override; 193 194 status_t legacyCreateAudioPatch(const struct audio_port_config& port, 195 std::optional<audio_source_t> source, 196 audio_devices_t type) override; 197 198 status_t legacyReleaseAudioPatch() override; 199 200 protected: 201 // For tests. 202 friend class sp<StreamHalAidl>; 203 204 struct StatePositions { 205 int64_t framesAtFlushOrDrain; 206 int64_t framesAtStandby; 207 }; 208 209 template<class T> 210 static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon( 211 const std::shared_ptr<T>& stream); 212 213 // Subclasses can not be constructed directly by clients. 214 StreamHalAidl(std::string_view className, 215 bool isInput, 216 const audio_config& config, 217 int32_t nominalLatency, 218 StreamContextAidl&& context, 219 const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream, 220 const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext); 221 222 ~StreamHalAidl() override; 223 getState()224 ::aidl::android::hardware::audio::core::StreamDescriptor::State getState() { 225 std::lock_guard l(mLock); 226 return mLastReply.state; 227 } 228 isInDrainedState(const::aidl::android::hardware::audio::core::StreamDescriptor::State state)229 bool isInDrainedState( 230 const ::aidl::android::hardware::audio::core::StreamDescriptor::State state) { 231 if (state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::IDLE || 232 state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::STANDBY) { 233 // drain equivalent states 234 return true; 235 } 236 return false; 237 } 238 isInPlayOrRecordState(const::aidl::android::hardware::audio::core::StreamDescriptor::State state)239 bool isInPlayOrRecordState( 240 const ::aidl::android::hardware::audio::core::StreamDescriptor::State state) { 241 if (state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::ACTIVE || 242 state == 243 ::aidl::android::hardware::audio::core::StreamDescriptor::State::TRANSFERRING || 244 state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::DRAINING) { 245 // play or record equivalent states 246 return true; 247 } 248 return false; 249 } 250 isInPausedState(const::aidl::android::hardware::audio::core::StreamDescriptor::State & state)251 bool isInPausedState( 252 const ::aidl::android::hardware::audio::core::StreamDescriptor::State& state) { 253 if (state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::PAUSED || 254 state == 255 ::aidl::android::hardware::audio::core::StreamDescriptor::State::DRAIN_PAUSED || 256 state == ::aidl::android::hardware::audio::core::StreamDescriptor::State:: 257 TRANSFER_PAUSED) { 258 // pause equivalent states 259 return true; 260 } 261 return false; 262 } 263 264 status_t getLatency(uint32_t *latency); 265 266 // Always returns non-negative values. 267 status_t getObservablePosition(int64_t* frames, int64_t* timestamp, 268 StatePositions* statePositions = nullptr); 269 270 // Always returns non-negative values. 271 status_t getHardwarePosition(int64_t *frames, int64_t *timestamp); 272 273 // Always returns non-negative values. 274 status_t getXruns(int32_t *frames); 275 276 status_t transfer(void *buffer, size_t bytes, size_t *transferred); 277 278 status_t pause( 279 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr); 280 281 status_t resume( 282 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr); 283 284 status_t drain(bool earlyNotify, 285 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr); 286 287 status_t flush( 288 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr); 289 290 status_t exit(); 291 292 void onAsyncTransferReady(); 293 void onAsyncDrainReady(); 294 void onAsyncError(); 295 296 const bool mIsInput; 297 const audio_config_base_t mConfig; 298 const StreamContextAidl mContext; 299 // This lock is used to make sending of a command and receiving a reply an atomic 300 // operation. Otherwise, when two threads are trying to send a command, they may both advance to 301 // reading of the reply once the HAL has consumed the command from the MQ, and that creates a 302 // race condition between them. 303 // 304 // Note that only access to command and reply MQs needs to be protected because the data MQ is 305 // only accessed by the I/O thread. Also, there is no need to protect lookup operations on the 306 // queues as they are thread-safe, only send/receive operation must be protected. 307 std::mutex mCommandReplyLock; 308 309 private: configToBase(const audio_config & config)310 static audio_config_base_t configToBase(const audio_config& config) { 311 audio_config_base_t result = AUDIO_CONFIG_BASE_INITIALIZER; 312 result.sample_rate = config.sample_rate; 313 result.channel_mask = config.channel_mask; 314 result.format = config.format; 315 return result; 316 } 317 // Note: Since `sendCommand` takes mLock while holding mCommandReplyLock, never call 318 // it with `mLock` being held. 319 status_t sendCommand( 320 const ::aidl::android::hardware::audio::core::StreamDescriptor::Command& command, 321 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr, 322 bool safeFromNonWorkerThread = false, 323 StatePositions* statePositions = nullptr); 324 status_t updateCountersIfNeeded( 325 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr, 326 StatePositions* statePositions = nullptr); 327 328 const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream; 329 const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt; 330 const int64_t mLastReplyLifeTimeNs; 331 std::mutex mLock; 332 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock); 333 int64_t mLastReplyExpirationNs GUARDED_BY(mLock) = 0; 334 // Cached values of observable positions when the stream last entered certain state. 335 // Updated for output streams only. 336 StatePositions mStatePositions GUARDED_BY(mLock) = {}; 337 // mStreamPowerLog is used for audio signal power logging. 338 StreamPowerLog mStreamPowerLog; 339 std::atomic<pid_t> mWorkerTid = -1; 340 }; 341 342 class CallbackBroker; 343 344 class StreamOutHalAidl : public virtual StreamOutHalInterface, 345 public virtual StreamOutHalInterfaceCallback, 346 public StreamHalAidl { 347 public: 348 // Extract the output stream parameters and set by AIDL APIs. 349 status_t setParameters(const String8& kvPairs) override; 350 351 // Return the audio hardware driver estimated latency in milliseconds. 352 status_t getLatency(uint32_t *latency) override; 353 354 // Use this method in situations where audio mixing is done in the hardware. 355 status_t setVolume(float left, float right) override; 356 357 // Selects the audio presentation (if available). 358 status_t selectPresentation(int presentationId, int programId) override; 359 360 // Write audio buffer to driver. 361 status_t write(const void *buffer, size_t bytes, size_t *written) override; 362 363 // Return the number of audio frames written by the audio dsp to DAC since 364 // the output has exited standby. 365 status_t getRenderPosition(uint64_t *dspFrames) override; 366 367 // Set the callback for notifying completion of non-blocking write and drain. 368 status_t setCallback(wp<StreamOutHalInterfaceCallback> callback) override; 369 370 // Returns whether pause and resume operations are supported. 371 status_t supportsPauseAndResume(bool *supportsPause, bool *supportsResume) override; 372 373 // Notifies to the audio driver to resume playback following a pause. 374 status_t pause() override; 375 376 // Notifies to the audio driver to resume playback following a pause. 377 status_t resume() override; 378 379 // Returns whether drain operation is supported. 380 status_t supportsDrain(bool *supportsDrain) override; 381 382 // Requests notification when data buffered by the driver/hardware has been played. 383 status_t drain(bool earlyNotify) override; 384 385 // Notifies to the audio driver to flush (that is, drop) the queued data. Stream must 386 // already be paused before calling 'flush'. 387 status_t flush() override; 388 389 // Return a recent count of the number of audio frames presented to an external observer. 390 // This excludes frames which have been written but are still in the pipeline. See the 391 // table at the start of the 'StreamOutHalInterface' for the specification of the frame 392 // count behavior w.r.t. 'flush', 'drain' and 'standby' operations. 393 status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) override; 394 395 // Notifies the HAL layer that the framework considers the current playback as completed. 396 status_t presentationComplete() override; 397 398 // Called when the metadata of the stream's source has been changed. 399 status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override; 400 401 // Returns the Dual Mono mode presentation setting. 402 status_t getDualMonoMode(audio_dual_mono_mode_t* mode) override; 403 404 // Sets the Dual Mono mode presentation on the output device. 405 status_t setDualMonoMode(audio_dual_mono_mode_t mode) override; 406 407 // Returns the Audio Description Mix level in dB. 408 status_t getAudioDescriptionMixLevel(float* leveldB) override; 409 410 // Sets the Audio Description Mix level in dB. 411 status_t setAudioDescriptionMixLevel(float leveldB) override; 412 413 // Retrieves current playback rate parameters. 414 status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) override; 415 416 // Sets the playback rate parameters that control playback behavior. 417 status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) override; 418 419 status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override; 420 421 status_t setLatencyMode(audio_latency_mode_t mode) override; 422 status_t getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) override; 423 status_t setLatencyModeCallback( 424 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) override; 425 426 status_t exit() override; 427 428 // StreamOutHalInterfaceCallback 429 void onWriteReady() override; 430 void onDrainReady() override; 431 void onError(bool isHardError) override; 432 433 private: 434 friend class sp<StreamOutHalAidl>; 435 436 static ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata> 437 legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy); 438 439 const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut> mStream; 440 const wp<CallbackBroker> mCallbackBroker; 441 mediautils::atomic_wp<StreamOutHalInterfaceCallback> mClientCallback; 442 443 AudioOffloadMetadata mOffloadMetadata; 444 445 // Can not be constructed directly by clients. 446 StreamOutHalAidl( 447 const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency, 448 const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream, 449 const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext, 450 const sp<CallbackBroker>& callbackBroker); 451 452 ~StreamOutHalAidl() override; 453 454 // Filter and update the offload metadata. The parameters which are related to the offload 455 // metadata will be removed after filtering. 456 status_t filterAndUpdateOffloadMetadata(AudioParameter ¶meters); 457 }; 458 459 class MicrophoneInfoProvider; 460 461 class StreamInHalAidl : public StreamInHalInterface, public StreamHalAidl { 462 public: 463 // Set the input gain for the audio driver. 464 status_t setGain(float gain) override; 465 466 // Read audio buffer in from driver. 467 status_t read(void *buffer, size_t bytes, size_t *read) override; 468 469 // Return the amount of input frames lost in the audio driver. 470 status_t getInputFramesLost(uint32_t *framesLost) override; 471 472 // Return a recent count of the number of audio frames received and 473 // the clock time associated with that frame count. 474 // The count must not reset to zero when a PCM input enters standby. 475 status_t getCapturePosition(int64_t *frames, int64_t *time) override; 476 477 // Get active microphones 478 status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) override; 479 480 // Set microphone direction (for processing) 481 status_t setPreferredMicrophoneDirection( 482 audio_microphone_direction_t direction) override; 483 484 // Set microphone zoom (for processing) 485 status_t setPreferredMicrophoneFieldDimension(float zoom) override; 486 487 // Called when the metadata of the stream's sink has been changed. 488 status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override; 489 490 private: 491 friend class sp<StreamInHalAidl>; 492 493 static ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata> 494 legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy); 495 496 const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn> mStream; 497 const wp<MicrophoneInfoProvider> mMicInfoProvider; 498 499 // Can not be constructed directly by clients. 500 StreamInHalAidl( 501 const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency, 502 const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn>& stream, 503 const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext, 504 const sp<MicrophoneInfoProvider>& micInfoProvider); 505 506 ~StreamInHalAidl() override = default; 507 }; 508 509 } // namespace android 510