Loading media/libaudiohal/impl/StreamHalAidl.cpp +57 −12 Original line number Diff line number Diff line Loading @@ -281,11 +281,12 @@ status_t StreamHalAidl::getLatency(uint32_t *latency) { return OK; } status_t StreamHalAidl::getObservablePosition(int64_t *frames, int64_t *timestamp) { status_t StreamHalAidl::getObservablePosition(int64_t* frames, int64_t* timestamp, StatePositions* statePositions) { ALOGV("%p %s::%s", this, getClassName().c_str(), __func__); if (!mStream) return NO_INIT; StreamDescriptor::Reply reply; RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply)); RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply, statePositions)); *frames = std::max<int64_t>(0, reply.observable.frames); *timestamp = std::max<int64_t>(0, reply.observable.timeNs); return OK; Loading Loading @@ -442,8 +443,12 @@ void StreamHalAidl::onAsyncDrainReady() { if (auto state = getState(); state == StreamDescriptor::State::DRAINING) { // Retrieve the current state together with position counters unconditionally // to ensure that the state on our side gets updated. sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), nullptr, true /*safeFromNonWorkerThread */); sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), nullptr, true /*safeFromNonWorkerThread */); // For compatibility with HIDL behavior, apply a "soft" position reset // after receiving the "drain ready" callback. std::lock_guard l(mLock); mStatePositions.framesAtFlushOrDrain = mLastReply.observable.frames; } else { ALOGW("%s: unexpected onDrainReady in the state %s", __func__, toString(state).c_str()); } Loading Loading @@ -512,7 +517,7 @@ status_t StreamHalAidl::legacyReleaseAudioPatch() { status_t StreamHalAidl::sendCommand( const ::aidl::android::hardware::audio::core::StreamDescriptor::Command& command, ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply, bool safeFromNonWorkerThread) { bool safeFromNonWorkerThread, StatePositions* statePositions) { // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized. if (!safeFromNonWorkerThread) { const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire); Loading Loading @@ -544,6 +549,23 @@ status_t StreamHalAidl::sendCommand( } mLastReply = *reply; mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs; if (!mIsInput && reply->status == STATUS_OK) { if (command.getTag() == StreamDescriptor::Command::standby && reply->state == StreamDescriptor::State::STANDBY) { mStatePositions.framesAtStandby = reply->observable.frames; } else if (command.getTag() == StreamDescriptor::Command::flush && reply->state == StreamDescriptor::State::IDLE) { mStatePositions.framesAtFlushOrDrain = reply->observable.frames; } else if (!mContext.isAsynchronous() && command.getTag() == StreamDescriptor::Command::drain && (reply->state == StreamDescriptor::State::IDLE || reply->state == StreamDescriptor::State::DRAINING)) { mStatePositions.framesAtFlushOrDrain = reply->observable.frames; } // for asynchronous drain, the frame count is saved in 'onAsyncDrainReady' } if (statePositions != nullptr) { *statePositions = mStatePositions; } } } switch (reply->status) { Loading @@ -559,7 +581,8 @@ status_t StreamHalAidl::sendCommand( } status_t StreamHalAidl::updateCountersIfNeeded( ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply) { ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply, StatePositions* statePositions) { bool doUpdate = false; { std::lock_guard l(mLock); Loading @@ -569,10 +592,13 @@ status_t StreamHalAidl::updateCountersIfNeeded( // Since updates are paced, it is OK to perform them from any thread, they should // not interfere with I/O operations of the worker. return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), reply, true /*safeFromNonWorkerThread */); reply, true /*safeFromNonWorkerThread */, statePositions); } else if (reply != nullptr) { // provide cached reply std::lock_guard l(mLock); *reply = mLastReply; if (statePositions != nullptr) { *statePositions = mStatePositions; } } return OK; } Loading Loading @@ -664,8 +690,19 @@ status_t StreamOutHalAidl::getRenderPosition(uint64_t *dspFrames) { return BAD_VALUE; } int64_t aidlFrames = 0, aidlTimestamp = 0; RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp)); *dspFrames = aidlFrames; StatePositions statePositions{}; RETURN_STATUS_IF_ERROR( getObservablePosition(&aidlFrames, &aidlTimestamp, &statePositions)); // Number of audio frames since the stream has exited standby. // See the table at the start of 'StreamHalInterface' on when it needs to reset. int64_t mostRecentResetPoint; if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) { mostRecentResetPoint = statePositions.framesAtStandby; } else { mostRecentResetPoint = std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain); } *dspFrames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; return OK; } Loading Loading @@ -722,8 +759,16 @@ status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct time return BAD_VALUE; } int64_t aidlFrames = 0, aidlTimestamp = 0; RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp)); StatePositions statePositions{}; RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp, &statePositions)); // See the table at the start of 'StreamHalInterface'. if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) { *frames = aidlFrames; } else { const int64_t mostRecentResetPoint = std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain); *frames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; } timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND; timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND; return OK; Loading media/libaudiohal/impl/StreamHalAidl.h +21 −5 Original line number Diff line number Diff line Loading @@ -194,6 +194,11 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper // For tests. friend class sp<StreamHalAidl>; struct StatePositions { int64_t framesAtFlushOrDrain; int64_t framesAtStandby; }; template<class T> static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon( const std::shared_ptr<T>& stream); Loading @@ -212,7 +217,8 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper status_t getLatency(uint32_t *latency); // Always returns non-negative values. status_t getObservablePosition(int64_t *frames, int64_t *timestamp); status_t getObservablePosition(int64_t* frames, int64_t* timestamp, StatePositions* statePositions = nullptr); // Always returns non-negative values. status_t getHardwarePosition(int64_t *frames, int64_t *timestamp); Loading Loading @@ -270,9 +276,11 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper status_t sendCommand( const ::aidl::android::hardware::audio::core::StreamDescriptor::Command& command, ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr, bool safeFromNonWorkerThread = false); bool safeFromNonWorkerThread = false, StatePositions* statePositions = nullptr); status_t updateCountersIfNeeded( ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr); ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr, StatePositions* statePositions = nullptr); const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream; const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt; Loading @@ -280,6 +288,9 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper std::mutex mLock; ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock); int64_t mLastReplyExpirationNs GUARDED_BY(mLock) = 0; // Cached values of observable positions when the stream last entered certain state. // Updated for output streams only. StatePositions mStatePositions GUARDED_BY(mLock) = {}; // mStreamPowerLog is used for audio signal power logging. StreamPowerLog mStreamPowerLog; std::atomic<pid_t> mWorkerTid = -1; Loading Loading @@ -328,10 +339,14 @@ class StreamOutHalAidl : public virtual StreamOutHalInterface, // Requests notification when data buffered by the driver/hardware has been played. status_t drain(bool earlyNotify) override; // Notifies to the audio driver to flush the queued data. // Notifies to the audio driver to flush (that is, drop) the queued data. Stream must // already be paused before calling 'flush'. status_t flush() override; // Return a recent count of the number of audio frames presented to an external observer. // This excludes frames which have been written but are still in the pipeline. See the // table at the start of the 'StreamOutHalInterface' for the specification of the frame // count behavior w.r.t. 'flush', 'drain' and 'standby' operations. status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) override; // Notifies the HAL layer that the framework considers the current playback as completed. Loading Loading @@ -413,6 +428,7 @@ class StreamInHalAidl : public StreamInHalInterface, public StreamHalAidl { // Return a recent count of the number of audio frames received and // the clock time associated with that frame count. // The count must not reset to zero when a PCM input enters standby. status_t getCapturePosition(int64_t *frames, int64_t *time) override; // Get active microphones Loading media/libaudiohal/impl/StreamHalHidl.h +6 −1 Original line number Diff line number Diff line Loading @@ -161,10 +161,14 @@ class StreamOutHalHidl : public StreamOutHalInterface, public StreamHalHidl { // Requests notification when data buffered by the driver/hardware has been played. virtual status_t drain(bool earlyNotify); // Notifies to the audio driver to flush the queued data. // Notifies to the audio driver to flush (that is, drop) the queued data. Stream must // already be paused before calling 'flush'. virtual status_t flush(); // Return a recent count of the number of audio frames presented to an external observer. // This excludes frames which have been written but are still in the pipeline. See the // table at the start of the 'StreamOutHalInterface' for the specification of the frame // count behavior w.r.t. 'flush', 'drain' and 'standby' operations. virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp); // Notifies the HAL layer that the framework considers the current playback as completed. Loading Loading @@ -259,6 +263,7 @@ class StreamInHalHidl : public StreamInHalInterface, public StreamHalHidl { // Return a recent count of the number of audio frames received and // the clock time associated with that frame count. // The count must not reset to zero when a PCM input enters standby. virtual status_t getCapturePosition(int64_t *frames, int64_t *time); // Get active microphones Loading media/libaudiohal/include/media/audiohal/StreamHalInterface.h +38 −1 Original line number Diff line number Diff line Loading @@ -135,6 +135,38 @@ protected: virtual ~StreamOutHalInterfaceLatencyModeCallback() = default; }; /** * On position reporting. There are two methods: 'getRenderPosition' and * 'getPresentationPosition'. The first difference is that they may have a * time offset because "render" position relates to what happens between * ADSP and DAC, while "observable" position is relative to the external * observer. The second difference is that 'getRenderPosition' always * resets on standby (for all types of stream data) according to its * definition. Since the original C definition of 'getRenderPosition' used * 32-bit frame counters, and also because in complex playback chains that * include wireless devices the "observable" position has more practical * meaning, 'getRenderPosition' does not exist in the AIDL HAL interface. * The table below summarizes frame count behavior for 'getPresentationPosition': * * | Mixed | Direct | Direct * | | non-offload | offload * ==============|============|==============|============== * PCM and | Continuous | | * encapsulated | | | * bitstream | | | * --------------|------------| Continuous† | * Bitstream | | | Reset on * encapsulated | | | flush, drain * into PCM | | | and standby * | Not | | * --------------| supported |--------------| * Bitstream | | Reset on | * | | flush, drain | * | | and standby | * | | | * * † - on standby, reset of the frame count happens at the framework level. */ class StreamOutHalInterface : public virtual StreamHalInterface { public: // Return the audio hardware driver estimated latency in milliseconds. Loading Loading @@ -173,10 +205,14 @@ class StreamOutHalInterface : public virtual StreamHalInterface { // Requests notification when data buffered by the driver/hardware has been played. virtual status_t drain(bool earlyNotify) = 0; // Notifies to the audio driver to flush the queued data. // Notifies to the audio driver to flush (that is, drop) the queued data. Stream must // already be paused before calling 'flush'. virtual status_t flush() = 0; // Return a recent count of the number of audio frames presented to an external observer. // This excludes frames which have been written but are still in the pipeline. See the // table at the start of the 'StreamOutHalInterface' for the specification of the frame // count behavior w.r.t. 'flush', 'drain' and 'standby' operations. virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0; // Notifies the HAL layer that the framework considers the current playback as completed. Loading Loading @@ -270,6 +306,7 @@ class StreamInHalInterface : public virtual StreamHalInterface { // Return a recent count of the number of audio frames received and // the clock time associated with that frame count. // The count must not reset to zero when a PCM input enters standby. virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0; // Get active microphones Loading Loading
media/libaudiohal/impl/StreamHalAidl.cpp +57 −12 Original line number Diff line number Diff line Loading @@ -281,11 +281,12 @@ status_t StreamHalAidl::getLatency(uint32_t *latency) { return OK; } status_t StreamHalAidl::getObservablePosition(int64_t *frames, int64_t *timestamp) { status_t StreamHalAidl::getObservablePosition(int64_t* frames, int64_t* timestamp, StatePositions* statePositions) { ALOGV("%p %s::%s", this, getClassName().c_str(), __func__); if (!mStream) return NO_INIT; StreamDescriptor::Reply reply; RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply)); RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply, statePositions)); *frames = std::max<int64_t>(0, reply.observable.frames); *timestamp = std::max<int64_t>(0, reply.observable.timeNs); return OK; Loading Loading @@ -442,8 +443,12 @@ void StreamHalAidl::onAsyncDrainReady() { if (auto state = getState(); state == StreamDescriptor::State::DRAINING) { // Retrieve the current state together with position counters unconditionally // to ensure that the state on our side gets updated. sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), nullptr, true /*safeFromNonWorkerThread */); sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), nullptr, true /*safeFromNonWorkerThread */); // For compatibility with HIDL behavior, apply a "soft" position reset // after receiving the "drain ready" callback. std::lock_guard l(mLock); mStatePositions.framesAtFlushOrDrain = mLastReply.observable.frames; } else { ALOGW("%s: unexpected onDrainReady in the state %s", __func__, toString(state).c_str()); } Loading Loading @@ -512,7 +517,7 @@ status_t StreamHalAidl::legacyReleaseAudioPatch() { status_t StreamHalAidl::sendCommand( const ::aidl::android::hardware::audio::core::StreamDescriptor::Command& command, ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply, bool safeFromNonWorkerThread) { bool safeFromNonWorkerThread, StatePositions* statePositions) { // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized. if (!safeFromNonWorkerThread) { const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire); Loading Loading @@ -544,6 +549,23 @@ status_t StreamHalAidl::sendCommand( } mLastReply = *reply; mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs; if (!mIsInput && reply->status == STATUS_OK) { if (command.getTag() == StreamDescriptor::Command::standby && reply->state == StreamDescriptor::State::STANDBY) { mStatePositions.framesAtStandby = reply->observable.frames; } else if (command.getTag() == StreamDescriptor::Command::flush && reply->state == StreamDescriptor::State::IDLE) { mStatePositions.framesAtFlushOrDrain = reply->observable.frames; } else if (!mContext.isAsynchronous() && command.getTag() == StreamDescriptor::Command::drain && (reply->state == StreamDescriptor::State::IDLE || reply->state == StreamDescriptor::State::DRAINING)) { mStatePositions.framesAtFlushOrDrain = reply->observable.frames; } // for asynchronous drain, the frame count is saved in 'onAsyncDrainReady' } if (statePositions != nullptr) { *statePositions = mStatePositions; } } } switch (reply->status) { Loading @@ -559,7 +581,8 @@ status_t StreamHalAidl::sendCommand( } status_t StreamHalAidl::updateCountersIfNeeded( ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply) { ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply, StatePositions* statePositions) { bool doUpdate = false; { std::lock_guard l(mLock); Loading @@ -569,10 +592,13 @@ status_t StreamHalAidl::updateCountersIfNeeded( // Since updates are paced, it is OK to perform them from any thread, they should // not interfere with I/O operations of the worker. return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), reply, true /*safeFromNonWorkerThread */); reply, true /*safeFromNonWorkerThread */, statePositions); } else if (reply != nullptr) { // provide cached reply std::lock_guard l(mLock); *reply = mLastReply; if (statePositions != nullptr) { *statePositions = mStatePositions; } } return OK; } Loading Loading @@ -664,8 +690,19 @@ status_t StreamOutHalAidl::getRenderPosition(uint64_t *dspFrames) { return BAD_VALUE; } int64_t aidlFrames = 0, aidlTimestamp = 0; RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp)); *dspFrames = aidlFrames; StatePositions statePositions{}; RETURN_STATUS_IF_ERROR( getObservablePosition(&aidlFrames, &aidlTimestamp, &statePositions)); // Number of audio frames since the stream has exited standby. // See the table at the start of 'StreamHalInterface' on when it needs to reset. int64_t mostRecentResetPoint; if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) { mostRecentResetPoint = statePositions.framesAtStandby; } else { mostRecentResetPoint = std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain); } *dspFrames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; return OK; } Loading Loading @@ -722,8 +759,16 @@ status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct time return BAD_VALUE; } int64_t aidlFrames = 0, aidlTimestamp = 0; RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp)); StatePositions statePositions{}; RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp, &statePositions)); // See the table at the start of 'StreamHalInterface'. if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) { *frames = aidlFrames; } else { const int64_t mostRecentResetPoint = std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain); *frames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint; } timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND; timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND; return OK; Loading
media/libaudiohal/impl/StreamHalAidl.h +21 −5 Original line number Diff line number Diff line Loading @@ -194,6 +194,11 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper // For tests. friend class sp<StreamHalAidl>; struct StatePositions { int64_t framesAtFlushOrDrain; int64_t framesAtStandby; }; template<class T> static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon( const std::shared_ptr<T>& stream); Loading @@ -212,7 +217,8 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper status_t getLatency(uint32_t *latency); // Always returns non-negative values. status_t getObservablePosition(int64_t *frames, int64_t *timestamp); status_t getObservablePosition(int64_t* frames, int64_t* timestamp, StatePositions* statePositions = nullptr); // Always returns non-negative values. status_t getHardwarePosition(int64_t *frames, int64_t *timestamp); Loading Loading @@ -270,9 +276,11 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper status_t sendCommand( const ::aidl::android::hardware::audio::core::StreamDescriptor::Command& command, ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr, bool safeFromNonWorkerThread = false); bool safeFromNonWorkerThread = false, StatePositions* statePositions = nullptr); status_t updateCountersIfNeeded( ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr); ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr, StatePositions* statePositions = nullptr); const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream; const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt; Loading @@ -280,6 +288,9 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper std::mutex mLock; ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock); int64_t mLastReplyExpirationNs GUARDED_BY(mLock) = 0; // Cached values of observable positions when the stream last entered certain state. // Updated for output streams only. StatePositions mStatePositions GUARDED_BY(mLock) = {}; // mStreamPowerLog is used for audio signal power logging. StreamPowerLog mStreamPowerLog; std::atomic<pid_t> mWorkerTid = -1; Loading Loading @@ -328,10 +339,14 @@ class StreamOutHalAidl : public virtual StreamOutHalInterface, // Requests notification when data buffered by the driver/hardware has been played. status_t drain(bool earlyNotify) override; // Notifies to the audio driver to flush the queued data. // Notifies to the audio driver to flush (that is, drop) the queued data. Stream must // already be paused before calling 'flush'. status_t flush() override; // Return a recent count of the number of audio frames presented to an external observer. // This excludes frames which have been written but are still in the pipeline. See the // table at the start of the 'StreamOutHalInterface' for the specification of the frame // count behavior w.r.t. 'flush', 'drain' and 'standby' operations. status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) override; // Notifies the HAL layer that the framework considers the current playback as completed. Loading Loading @@ -413,6 +428,7 @@ class StreamInHalAidl : public StreamInHalInterface, public StreamHalAidl { // Return a recent count of the number of audio frames received and // the clock time associated with that frame count. // The count must not reset to zero when a PCM input enters standby. status_t getCapturePosition(int64_t *frames, int64_t *time) override; // Get active microphones Loading
media/libaudiohal/impl/StreamHalHidl.h +6 −1 Original line number Diff line number Diff line Loading @@ -161,10 +161,14 @@ class StreamOutHalHidl : public StreamOutHalInterface, public StreamHalHidl { // Requests notification when data buffered by the driver/hardware has been played. virtual status_t drain(bool earlyNotify); // Notifies to the audio driver to flush the queued data. // Notifies to the audio driver to flush (that is, drop) the queued data. Stream must // already be paused before calling 'flush'. virtual status_t flush(); // Return a recent count of the number of audio frames presented to an external observer. // This excludes frames which have been written but are still in the pipeline. See the // table at the start of the 'StreamOutHalInterface' for the specification of the frame // count behavior w.r.t. 'flush', 'drain' and 'standby' operations. virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp); // Notifies the HAL layer that the framework considers the current playback as completed. Loading Loading @@ -259,6 +263,7 @@ class StreamInHalHidl : public StreamInHalInterface, public StreamHalHidl { // Return a recent count of the number of audio frames received and // the clock time associated with that frame count. // The count must not reset to zero when a PCM input enters standby. virtual status_t getCapturePosition(int64_t *frames, int64_t *time); // Get active microphones Loading
media/libaudiohal/include/media/audiohal/StreamHalInterface.h +38 −1 Original line number Diff line number Diff line Loading @@ -135,6 +135,38 @@ protected: virtual ~StreamOutHalInterfaceLatencyModeCallback() = default; }; /** * On position reporting. There are two methods: 'getRenderPosition' and * 'getPresentationPosition'. The first difference is that they may have a * time offset because "render" position relates to what happens between * ADSP and DAC, while "observable" position is relative to the external * observer. The second difference is that 'getRenderPosition' always * resets on standby (for all types of stream data) according to its * definition. Since the original C definition of 'getRenderPosition' used * 32-bit frame counters, and also because in complex playback chains that * include wireless devices the "observable" position has more practical * meaning, 'getRenderPosition' does not exist in the AIDL HAL interface. * The table below summarizes frame count behavior for 'getPresentationPosition': * * | Mixed | Direct | Direct * | | non-offload | offload * ==============|============|==============|============== * PCM and | Continuous | | * encapsulated | | | * bitstream | | | * --------------|------------| Continuous† | * Bitstream | | | Reset on * encapsulated | | | flush, drain * into PCM | | | and standby * | Not | | * --------------| supported |--------------| * Bitstream | | Reset on | * | | flush, drain | * | | and standby | * | | | * * † - on standby, reset of the frame count happens at the framework level. */ class StreamOutHalInterface : public virtual StreamHalInterface { public: // Return the audio hardware driver estimated latency in milliseconds. Loading Loading @@ -173,10 +205,14 @@ class StreamOutHalInterface : public virtual StreamHalInterface { // Requests notification when data buffered by the driver/hardware has been played. virtual status_t drain(bool earlyNotify) = 0; // Notifies to the audio driver to flush the queued data. // Notifies to the audio driver to flush (that is, drop) the queued data. Stream must // already be paused before calling 'flush'. virtual status_t flush() = 0; // Return a recent count of the number of audio frames presented to an external observer. // This excludes frames which have been written but are still in the pipeline. See the // table at the start of the 'StreamOutHalInterface' for the specification of the frame // count behavior w.r.t. 'flush', 'drain' and 'standby' operations. virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0; // Notifies the HAL layer that the framework considers the current playback as completed. Loading Loading @@ -270,6 +306,7 @@ class StreamInHalInterface : public virtual StreamHalInterface { // Return a recent count of the number of audio frames received and // the clock time associated with that frame count. // The count must not reset to zero when a PCM input enters standby. virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0; // Get active microphones Loading