Merge "Camera: Add support for composite stream combination queries" into main
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index ab161d6..fe10e12 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -237,3 +237,13 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ namespace: "camera_platform"
+ name: "multi_res_raw_reprocessing"
+ description: "Allow multi-resolution raw reprocessing without reprocessing capability"
+ bug: "336922859"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 28670b1..03c765a 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -362,8 +362,8 @@
const ui::DisplayState& displayState,
const sp<IGraphicBufferProducer>& bufferProducer,
sp<IBinder>* pDisplayHandle, sp<SurfaceControl>* mirrorRoot) {
- sp<IBinder> dpy = SurfaceComposerClient::createDisplay(
- String8("ScreenRecorder"), gSecureDisplay);
+ static const std::string kDisplayName("ScreenRecorder");
+ sp<IBinder> dpy = SurfaceComposerClient::createVirtualDisplay(kDisplayName, gSecureDisplay);
SurfaceComposerClient::Transaction t;
t.setDisplaySurface(dpy, bufferProducer);
setDisplayProjection(t, dpy, displayState);
@@ -797,7 +797,7 @@
sp<Overlay> overlay;
~RecordingData() {
- if (dpy != nullptr) SurfaceComposerClient::destroyDisplay(dpy);
+ if (dpy != nullptr) SurfaceComposerClient::destroyVirtualDisplay(dpy);
if (overlay != nullptr) overlay->stop();
if (encoder != nullptr) {
encoder->stop();
diff --git a/media/codec2/hal/plugin/FilterWrapper.cpp b/media/codec2/hal/plugin/FilterWrapper.cpp
index 197d6e7..b926150 100644
--- a/media/codec2/hal/plugin/FilterWrapper.cpp
+++ b/media/codec2/hal/plugin/FilterWrapper.cpp
@@ -49,11 +49,6 @@
std::weak_ptr<FilterWrapper> filterWrapper)
: mIntf(intf), mFilterWrapper(filterWrapper) {
takeFilters(std::move(filters));
- for (size_t i = 0; i < mFilters.size(); ++i) {
- mControlParamTypes.insert(
- mFilters[i].desc.controlParams.begin(),
- mFilters[i].desc.controlParams.end());
- }
}
~WrappedDecoderInterface() override = default;
@@ -91,6 +86,12 @@
// TODO: documentation
mFilters = std::move(filters);
+ mControlParamTypes.clear();
+ for (size_t i = 0; i < mFilters.size(); ++i) {
+ mControlParamTypes.insert(
+ mFilters[i].desc.controlParams.begin(),
+ mFilters[i].desc.controlParams.end());
+ }
mTypeToIndexForQuery.clear();
mTypeToIndexForConfig.clear();
for (size_t i = 0; i < mFilters.size(); ++i) {
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 20b6d7f..a897fa0 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -2229,9 +2229,15 @@
// See also b/300350761.
//
// The workaround is no longer needed with fetchGraphicBlock & C2Fence changes.
- // so we are reverting back to the logical sequence of the operations.
+ // so we are reverting back to the logical sequence of the operations when
+ // AIDL HALs are selected.
+ // When the HIDL HALs are selected, we retained workaround(the reversed
+ // order) as default in order to keep legacy behavior.
+ bool stopHalBeforeSurface =
+ Codec2Client::IsAidlSelected() ||
+ property_get_bool("debug.codec2.stop_hal_before_surface", false);
status_t err = C2_OK;
- if (android::media::codec::provider_->stop_hal_before_surface()) {
+ if (stopHalBeforeSurface && android::media::codec::provider_->stop_hal_before_surface()) {
err = comp->stop();
mChannel->stopUseOutputSurface(pushBlankBuffer);
} else {
@@ -2334,8 +2340,14 @@
// See also b/300350761.
//
// The workaround is no longer needed with fetchGraphicBlock & C2Fence changes.
- // so we are reverting back to the logical sequence of the operations.
- if (android::media::codec::provider_->stop_hal_before_surface()) {
+ // so we are reverting back to the logical sequence of the operations when
+ // AIDL HALs are selected.
+ // When the HIDL HALs are selected, we retained workaround(the reversed
+ // order) as default in order to keep legacy behavior.
+ bool stopHalBeforeSurface =
+ Codec2Client::IsAidlSelected() ||
+ property_get_bool("debug.codec2.stop_hal_before_surface", false);
+ if (stopHalBeforeSurface && android::media::codec::provider_->stop_hal_before_surface()) {
comp->release();
mChannel->stopUseOutputSurface(pushBlankBuffer);
} else {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 3984b83..c7ab82f 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -2784,7 +2784,16 @@
}
void CCodecBufferChannel::setInfoBuffer(const std::shared_ptr<C2InfoBuffer> &buffer) {
- mInfoBuffers.push_back(buffer);
+ if (mInputSurface == nullptr) {
+ mInfoBuffers.push_back(buffer);
+ } else {
+ std::list<std::unique_ptr<C2Work>> items;
+ std::unique_ptr<C2Work> work(new C2Work);
+ work->input.infoBuffers.emplace_back(*buffer);
+ work->worklets.emplace_back(new C2Worklet);
+ items.push_back(std::move(work));
+ c2_status_t err = mComponent->queue(&items);
+ }
}
status_t toStatusT(c2_status_t c2s, c2_operation_t c2op) {
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 5aff5f2..84c1a8a 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -285,11 +285,12 @@
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;
@@ -446,8 +447,12 @@
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());
}
@@ -455,15 +460,8 @@
void StreamHalAidl::onAsyncError() {
std::lock_guard l(mLock);
- if (mLastReply.state == StreamDescriptor::State::IDLE ||
- mLastReply.state == StreamDescriptor::State::DRAINING ||
- mLastReply.state == StreamDescriptor::State::TRANSFERRING) {
- mLastReply.state = StreamDescriptor::State::ERROR;
- ALOGW("%s: onError received", __func__);
- } else {
- ALOGW("%s: unexpected onError in the state %s", __func__,
- toString(mLastReply.state).c_str());
- }
+ ALOGW("%s: received in the state %s", __func__, toString(mLastReply.state).c_str());
+ mLastReply.state = StreamDescriptor::State::ERROR;
}
status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
@@ -514,9 +512,9 @@
}
status_t StreamHalAidl::sendCommand(
- const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
+ 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);
@@ -548,6 +546,23 @@
}
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) {
@@ -563,7 +578,8 @@
}
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);
@@ -573,10 +589,13 @@
// 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;
}
@@ -668,8 +687,19 @@
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;
}
@@ -726,8 +756,16 @@
return BAD_VALUE;
}
int64_t aidlFrames = 0, aidlTimestamp = 0;
- RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp));
- *frames = aidlFrames;
+ 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;
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 8a398d8..fff7a92 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -194,6 +194,11 @@
// 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);
@@ -212,7 +217,8 @@
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);
@@ -268,11 +274,13 @@
// Note: Since `sendCommand` takes mLock while holding mCommandReplyLock, never call
// it with `mLock` being held.
status_t sendCommand(
- const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
+ 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;
@@ -280,6 +288,9 @@
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;
@@ -328,10 +339,14 @@
// 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.
@@ -413,6 +428,7 @@
// 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
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index 80379d0..433e0a3 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -161,10 +161,14 @@
// 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.
@@ -259,6 +263,7 @@
// 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
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index eb14f6b..585a895 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -135,6 +135,38 @@
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.
@@ -173,10 +205,14 @@
// 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.
@@ -270,6 +306,7 @@
// 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
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index 7a1411d..0031855 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -44,7 +44,7 @@
],
fuzz_config: {
cc: [
- "android-media-fuzzing-reports@google.com",
+ "android-media-playback+bugs@google.com",
],
componentid: 155276,
hotlists: [
diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp
index eb9ac0f..bf29b1d 100644
--- a/media/libstagefright/VideoRenderQualityTracker.cpp
+++ b/media/libstagefright/VideoRenderQualityTracker.cpp
@@ -302,13 +302,6 @@
mRenderDurationMs += (actualRenderTimeUs - mLastRenderTimeUs) / 1000;
}
- // Now that a frame has been rendered, the previously skipped frames can be processed as skipped
- // frames since the app is not skipping them to terminate playback.
- for (int64_t contentTimeUs : mPendingSkippedFrameContentTimeUsList) {
- processMetricsForSkippedFrame(contentTimeUs);
- }
- mPendingSkippedFrameContentTimeUsList = {};
-
// We can render a pending queued frame if it's the last frame of the video, so release it
// immediately.
if (contentTimeUs == mTunnelFrameQueuedContentTimeUs && mTunnelFrameQueuedContentTimeUs != -1) {
@@ -332,9 +325,25 @@
(long long) contentTimeUs, (long long) nextExpectedFrame.contentTimeUs);
break;
}
+ // Process all skipped frames before the dropped frame.
+ while (!mPendingSkippedFrameContentTimeUsList.empty()) {
+ if (mPendingSkippedFrameContentTimeUsList.front() >= nextExpectedFrame.contentTimeUs) {
+ break;
+ }
+ processMetricsForSkippedFrame(mPendingSkippedFrameContentTimeUsList.front());
+ mPendingSkippedFrameContentTimeUsList.pop_front();
+ }
processMetricsForDroppedFrame(nextExpectedFrame.contentTimeUs,
nextExpectedFrame.desiredRenderTimeUs);
}
+ // Process all skipped frames before the rendered frame.
+ while (!mPendingSkippedFrameContentTimeUsList.empty()) {
+ if (mPendingSkippedFrameContentTimeUsList.front() >= nextExpectedFrame.contentTimeUs) {
+ break;
+ }
+ processMetricsForSkippedFrame(mPendingSkippedFrameContentTimeUsList.front());
+ mPendingSkippedFrameContentTimeUsList.pop_front();
+ }
processMetricsForRenderedFrame(nextExpectedFrame.contentTimeUs,
nextExpectedFrame.desiredRenderTimeUs, actualRenderTimeUs,
freezeEventOut, judderEventOut);
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index cb2994e..b3707c8 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -1615,6 +1615,39 @@
mLastTrack->timescale = ntohl(timescale);
+ // 14496-12 says all ones means indeterminate, but some files seem to use
+ // 0 instead. We treat both the same.
+ int64_t duration = 0;
+ if (version == 1) {
+ if (mDataSource->readAt(
+ timescale_offset + 4, &duration, sizeof(duration))
+ < (ssize_t)sizeof(duration)) {
+ return ERROR_IO;
+ }
+ if (duration != -1) {
+ duration = ntoh64(duration);
+ }
+ } else {
+ uint32_t duration32;
+ if (mDataSource->readAt(
+ timescale_offset + 4, &duration32, sizeof(duration32))
+ < (ssize_t)sizeof(duration32)) {
+ return ERROR_IO;
+ }
+ if (duration32 != 0xffffffff) {
+ duration = ntohl(duration32);
+ }
+ }
+ if (duration != 0 && mLastTrack->timescale != 0) {
+ long double durationUs = ((long double)duration * 1000000) / mLastTrack->timescale;
+ if (durationUs < 0 || durationUs > INT64_MAX) {
+ ALOGE("cannot represent %lld * 1000000 / %lld in 64 bits",
+ (long long) duration, (long long) mLastTrack->timescale);
+ return ERROR_MALFORMED;
+ }
+ AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs);
+ }
+
uint8_t lang[2];
off64_t lang_offset;
if (version == 1) {
@@ -3874,18 +3907,17 @@
}
int32_t id;
- int64_t duration;
if (version == 1) {
// we can get ctime value from U64_AT(&buffer[4])
// we can get mtime value from U64_AT(&buffer[12])
id = U32_AT(&buffer[20]);
- duration = U64_AT(&buffer[28]);
+ // we can get duration value from U64_AT(&buffer[28])
} else if (version == 0) {
// we can get ctime value from U32_AT(&buffer[4])
// we can get mtime value from U32_AT(&buffer[8])
id = U32_AT(&buffer[12]);
- duration = U32_AT(&buffer[20]);
+ // we can get duration value from U32_AT(&buffer[20])
} else {
return ERROR_UNSUPPORTED;
}
@@ -3894,15 +3926,6 @@
return ERROR_MALFORMED;
AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_TRACK_ID, id);
- if (duration != 0 && mHeaderTimescale != 0) {
- long double durationUs = ((long double)duration * 1000000) / mHeaderTimescale;
- if (durationUs < 0 || durationUs > INT64_MAX) {
- ALOGE("cannot represent %lld * 1000000 / %lld in 64 bits",
- (long long) duration, (long long) mHeaderTimescale);
- return ERROR_MALFORMED;
- }
- AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs);
- }
size_t matrixOffset = dynSize + 16;
int32_t a00 = U32_AT(&buffer[matrixOffset]);
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 9ec7700..3d873df 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -192,7 +192,6 @@
header_libs: [
"libstagefright_headers",
"libmedia_headers",
- "libstagefright_headers",
],
shared_libs: [
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d5d778f..e8da710 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1935,10 +1935,11 @@
if (mPrimaryHardwareDev == nullptr) {
return 0;
}
+ if (mInputBufferSizeOrderedDevs.empty()) {
+ return 0;
+ }
mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
- sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
-
std::vector<audio_channel_mask_t> channelMasks = {channelMask};
if (channelMask != AUDIO_CHANNEL_IN_MONO) {
channelMasks.push_back(AUDIO_CHANNEL_IN_MONO);
@@ -1968,6 +1969,22 @@
mHardwareStatus = AUDIO_HW_IDLE;
+ auto getInputBufferSize = [](const sp<DeviceHalInterface>& dev, audio_config_t config,
+ size_t* bytes) -> status_t {
+ if (!dev) {
+ return BAD_VALUE;
+ }
+ status_t result = dev->getInputBufferSize(&config, bytes);
+ if (result == BAD_VALUE) {
+ // Retry with the config suggested by the HAL.
+ result = dev->getInputBufferSize(&config, bytes);
+ }
+ if (result != OK || *bytes == 0) {
+ return BAD_VALUE;
+ }
+ return result;
+ };
+
// Change parameters of the configuration each iteration until we find a
// configuration that the device will support, or HAL suggests what it supports.
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -1979,16 +1996,15 @@
config.sample_rate = testSampleRate;
size_t bytes = 0;
- audio_config_t loopConfig = config;
- status_t result = dev->getInputBufferSize(&config, &bytes);
- if (result == BAD_VALUE) {
- // Retry with the config suggested by the HAL.
- result = dev->getInputBufferSize(&config, &bytes);
+ ret = BAD_VALUE;
+ for (const AudioHwDevice* dev : mInputBufferSizeOrderedDevs) {
+ ret = getInputBufferSize(dev->hwDevice(), config, &bytes);
+ if (ret == OK) {
+ break;
+ }
}
- if (result != OK || bytes == 0) {
- config = loopConfig;
- continue;
- }
+ if (ret == BAD_VALUE) continue;
+
if (config.sample_rate != sampleRate || config.channel_mask != channelMask ||
config.format != format) {
uint32_t dstChannelCount = audio_channel_count_from_in_mask(channelMask);
@@ -2610,12 +2626,43 @@
}
mAudioHwDevs.add(handle, audioDevice);
+ if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_STUB) != 0) {
+ mInputBufferSizeOrderedDevs.insert(audioDevice);
+ }
ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
return audioDevice;
}
+// Sort AudioHwDevice to be traversed in the getInputBufferSize call in the following order:
+// Primary, Usb, Bluetooth, A2DP, other modules, remote submix.
+/* static */
+bool AudioFlinger::inputBufferSizeDevsCmp(const AudioHwDevice* lhs, const AudioHwDevice* rhs) {
+ static const std::map<std::string_view, int> kPriorities = {
+ { AUDIO_HARDWARE_MODULE_ID_PRIMARY, 0 }, { AUDIO_HARDWARE_MODULE_ID_USB, 1 },
+ { AUDIO_HARDWARE_MODULE_ID_BLUETOOTH, 2 }, { AUDIO_HARDWARE_MODULE_ID_A2DP, 3 },
+ { AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, std::numeric_limits<int>::max() }
+ };
+
+ const std::string_view lhsName = lhs->moduleName();
+ const std::string_view rhsName = rhs->moduleName();
+
+ auto lhsPriority = std::numeric_limits<int>::max() - 1;
+ if (const auto lhsIt = kPriorities.find(lhsName); lhsIt != kPriorities.end()) {
+ lhsPriority = lhsIt->second;
+ }
+ auto rhsPriority = std::numeric_limits<int>::max() - 1;
+ if (const auto rhsIt = kPriorities.find(rhsName); rhsIt != kPriorities.end()) {
+ rhsPriority = rhsIt->second;
+ }
+
+ if (lhsPriority != rhsPriority) {
+ return lhsPriority < rhsPriority;
+ }
+ return lhsName < rhsName;
+}
+
// ----------------------------------------------------------------------------
uint32_t AudioFlinger::getPrimaryOutputSamplingRate() const
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 4e46bea..6acd194 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -630,6 +630,10 @@
DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs
GUARDED_BY(hardwareMutex()) {nullptr /* defValue */};
+ static bool inputBufferSizeDevsCmp(const AudioHwDevice* lhs, const AudioHwDevice* rhs);
+ std::set<AudioHwDevice*, decltype(&inputBufferSizeDevsCmp)>
+ mInputBufferSizeOrderedDevs GUARDED_BY(hardwareMutex()) {inputBufferSizeDevsCmp};
+
const sp<DevicesFactoryHalInterface> mDevicesFactoryHal =
DevicesFactoryHalInterface::create();
/* const */ sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback; // set onFirstRef().
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 7c248dc..d45fca1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2696,14 +2696,17 @@
}
}
- // Set DIRECT flag if current thread is DirectOutputThread. This can
- // happen when the playback is rerouted to direct output thread by
+ // Set DIRECT/OFFLOAD flag if current thread is DirectOutputThread/OffloadThread.
+ // This can happen when the playback is rerouted to direct output/offload thread by
// dynamic audio policy.
// Do NOT report the flag changes back to client, since the client
- // doesn't explicitly request a direct flag.
+ // doesn't explicitly request a direct/offload flag.
audio_output_flags_t trackFlags = *flags;
if (mType == DIRECT) {
trackFlags = static_cast<audio_output_flags_t>(trackFlags | AUDIO_OUTPUT_FLAG_DIRECT);
+ } else if (mType == OFFLOAD) {
+ trackFlags = static_cast<audio_output_flags_t>(trackFlags |
+ AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT);
}
*afTrackFlags = trackFlags;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 6537a00..acd0ff5 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -561,6 +561,7 @@
audio_port_config config = {};
devicePort->toAudioPortConfig(&config);
config.config_mask = AUDIO_PORT_CONFIG_GAIN;
+ config.gain.mode = gains[0]->getMode();
config.gain.values[0] = gainValueMb;
return mClientInterface->setAudioPortConfig(&config, 0) == NO_ERROR;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 784f2b9..7f4be79 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1577,6 +1577,11 @@
outputDesc->mDirectClientSession = session;
addOutput(*output, outputDesc);
+ setOutputDevices(__func__, outputDesc,
+ devices,
+ true,
+ 0,
+ NULL);
mPreviousOutputs = mOutputs;
ALOGV("%s returns new direct output %d", __func__, *output);
mpClientInterface->onAudioPortListUpdate();
@@ -8608,7 +8613,11 @@
}
addOutput(output, desc);
-
+ setOutputDevices(__func__, desc,
+ devices,
+ true,
+ 0,
+ NULL);
sp<DeviceDescriptor> speaker = mAvailableOutputDevices.getDevice(
AUDIO_DEVICE_OUT_SPEAKER, String8(""), AUDIO_FORMAT_DEFAULT);
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index f40a7d0..5dc039c 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -478,8 +478,8 @@
MsdAudioPatchCount,
AudioPolicyManagerTestMsd,
::testing::Values(
- MsdAudioPatchCountSpecification(1u, "single"),
- MsdAudioPatchCountSpecification(2u, "dual")
+ MsdAudioPatchCountSpecification(2u, "single"),
+ MsdAudioPatchCountSpecification(3u, "dual")
),
[](const ::testing::TestParamInfo<MsdAudioPatchCountSpecification> &info) {
return std::get<MSD_AUDIO_PATCH_COUNT_NAME_INDEX>(info.param); }
@@ -506,7 +506,7 @@
mConfig->addDevice(mMsdOutputDevice);
mConfig->addDevice(mMsdInputDevice);
- if (mExpectedAudioPatchCount == 2) {
+ if (mExpectedAudioPatchCount == 3) {
// Add SPDIF device with PCM output profile as a second device for dual MSD audio patching.
mSpdifDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPDIF);
mSpdifDevice->addAudioProfile(pcmOutputProfile);
@@ -559,7 +559,7 @@
addOutputProfile(primaryEncodedOutputProfile);
mDefaultOutputDevice = mConfig->getDefaultOutputDevice();
- if (mExpectedAudioPatchCount == 2) {
+ if (mExpectedAudioPatchCount == 3) {
mSpdifDevice->addAudioProfile(dtsOutputProfile);
primaryEncodedOutputProfile->addSupportedDevice(mSpdifDevice);
}
@@ -608,7 +608,7 @@
const PatchCountCheck patchCount = snapshotPatchCount();
mManager->setForceUse(AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,
AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
- ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount -1 , patchCount.deltaFromSnapshot());
}
TEST_P(AudioPolicyManagerTestMsd, PatchCreationSetReleaseMsdOutputPatches) {
@@ -616,15 +616,15 @@
DeviceVector devices = mManager->getAvailableOutputDevices();
// Remove MSD output device to avoid patching to itself
devices.remove(mMsdOutputDevice);
- ASSERT_EQ(mExpectedAudioPatchCount, devices.size());
+ ASSERT_EQ(mExpectedAudioPatchCount -1 , devices.size());
mManager->setMsdOutputPatches(&devices);
- ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount - 1, patchCount.deltaFromSnapshot());
// Dual patch: exercise creating one new audio patch and reusing another existing audio patch.
DeviceVector singleDevice(devices[0]);
mManager->releaseMsdOutputPatches(singleDevice);
- ASSERT_EQ(mExpectedAudioPatchCount - 1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount - 2, patchCount.deltaFromSnapshot());
mManager->setMsdOutputPatches(&devices);
- ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount - 1, patchCount.deltaFromSnapshot());
mManager->releaseMsdOutputPatches(devices);
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
@@ -644,7 +644,7 @@
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount - 1, patchCount.deltaFromSnapshot());
}
TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
@@ -667,7 +667,7 @@
getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1,
k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(0, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(1, patchCount.deltaFromSnapshot());
}
TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrFormatSwitching) {
@@ -681,7 +681,7 @@
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
- ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount - 1, patchCount.deltaFromSnapshot());
}
{
const PatchCountCheck patchCount = snapshotPatchCount();
@@ -690,7 +690,7 @@
getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1,
k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT, nullptr /*output*/, &portId);
ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(-static_cast<int>(mExpectedAudioPatchCount), patchCount.deltaFromSnapshot());
+ ASSERT_EQ(-static_cast<int>(mExpectedAudioPatchCount) + 2, patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
@@ -700,7 +700,7 @@
getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1,
k48000SamplingRate, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(0, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(1, patchCount.deltaFromSnapshot());
}
}
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
index afc432d..165dece 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.h
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -26,7 +26,7 @@
* and single call monitoring differently. See function documentation for
* more details.
* To disable/enable:
- * - adb shell cmd media.camera set-cameraservice-watchdog [0/1]
+ * - adb shell cmd media.camera set-watchdog [0/1]
*/
#pragma once
#include <chrono>
diff --git a/services/mediaresourcemanager/fuzzer/Android.bp b/services/mediaresourcemanager/fuzzer/Android.bp
index 5bac062..3f04f69 100644
--- a/services/mediaresourcemanager/fuzzer/Android.bp
+++ b/services/mediaresourcemanager/fuzzer/Android.bp
@@ -47,7 +47,7 @@
],
fuzz_config: {
cc: [
- "android-media-fuzzing-reports@google.com",
+ "girishshetty@google.com",
],
componentid: 155276,
hotlists: [