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