From 15816b88b96938b0559518e6e70000668587736f Mon Sep 17 00:00:00 2001 From: Onkar Shinde Date: Wed, 29 May 2024 06:12:46 +0000 Subject: [PATCH 01/17] mediaplayer_fuzzer: Bug Fix Added valid audio-hal-enums instead of random integer to pass VALUE_OR_FATAL() checks in AudioTrack.cpp which was leading to abort. Test: ./mediaplayer_fuzzer Bug: 341858471 Change-Id: I6f38b2378e8b8999e1bbd271d849271b110ba40a --- .../fuzzer/mediaplayer_fuzzer.cpp | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp index 652b1eed3b..15265bffb1 100644 --- a/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp +++ b/media/libmediaplayerservice/fuzzer/mediaplayer_fuzzer.cpp @@ -51,6 +51,69 @@ const char dumpFile[] = "OutputDumpFile"; enum DataSourceType { HTTP, FD, STREAM, FILETYPE, SOCKET, kMaxValue = SOCKET }; +constexpr audio_flags_mask_t kAudioFlagsMasks[] = {AUDIO_FLAG_NONE, + AUDIO_FLAG_AUDIBILITY_ENFORCED, + AUDIO_FLAG_SECURE, + AUDIO_FLAG_SCO, + AUDIO_FLAG_BEACON, + AUDIO_FLAG_HW_AV_SYNC, + AUDIO_FLAG_HW_HOTWORD, + AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY, + AUDIO_FLAG_BYPASS_MUTE, + AUDIO_FLAG_LOW_LATENCY, + AUDIO_FLAG_DEEP_BUFFER, + AUDIO_FLAG_NO_MEDIA_PROJECTION, + AUDIO_FLAG_MUTE_HAPTIC, + AUDIO_FLAG_NO_SYSTEM_CAPTURE, + AUDIO_FLAG_CAPTURE_PRIVATE, + AUDIO_FLAG_CONTENT_SPATIALIZED, + AUDIO_FLAG_NEVER_SPATIALIZE, + AUDIO_FLAG_CALL_REDIRECTION}; + +constexpr audio_content_type_t kAudioContentTypes[] = { + AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_CONTENT_TYPE_SPEECH, AUDIO_CONTENT_TYPE_MUSIC, + AUDIO_CONTENT_TYPE_MOVIE, AUDIO_CONTENT_TYPE_SONIFICATION, AUDIO_CONTENT_TYPE_ULTRASOUND}; + +constexpr audio_source_t kAudioSources[] = {AUDIO_SOURCE_INVALID, + AUDIO_SOURCE_DEFAULT, + AUDIO_SOURCE_MIC, + AUDIO_SOURCE_VOICE_UPLINK, + AUDIO_SOURCE_VOICE_DOWNLINK, + AUDIO_SOURCE_VOICE_CALL, + AUDIO_SOURCE_CAMCORDER, + AUDIO_SOURCE_VOICE_RECOGNITION, + AUDIO_SOURCE_VOICE_COMMUNICATION, + AUDIO_SOURCE_REMOTE_SUBMIX, + AUDIO_SOURCE_UNPROCESSED, + AUDIO_SOURCE_VOICE_PERFORMANCE, + AUDIO_SOURCE_ECHO_REFERENCE, + AUDIO_SOURCE_FM_TUNER, + AUDIO_SOURCE_HOTWORD, + AUDIO_SOURCE_ULTRASOUND}; + +constexpr audio_usage_t kAudioUsages[] = {AUDIO_USAGE_UNKNOWN, + AUDIO_USAGE_MEDIA, + AUDIO_USAGE_VOICE_COMMUNICATION, + AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING, + AUDIO_USAGE_ALARM, + AUDIO_USAGE_NOTIFICATION, + AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE, + AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST, + AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT, + AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED, + AUDIO_USAGE_NOTIFICATION_EVENT, + AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY, + AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, + AUDIO_USAGE_ASSISTANCE_SONIFICATION, + AUDIO_USAGE_GAME, + AUDIO_USAGE_VIRTUAL_SOURCE, + AUDIO_USAGE_ASSISTANT, + AUDIO_USAGE_CALL_ASSISTANT, + AUDIO_USAGE_EMERGENCY, + AUDIO_USAGE_SAFETY, + AUDIO_USAGE_VEHICLE_STATUS, + AUDIO_USAGE_ANNOUNCEMENT}; + constexpr PixelFormat kPixelFormat[] = { PIXEL_FORMAT_UNKNOWN, PIXEL_FORMAT_NONE, PIXEL_FORMAT_CUSTOM, PIXEL_FORMAT_TRANSLUCENT, PIXEL_FORMAT_TRANSPARENT, PIXEL_FORMAT_OPAQUE, @@ -354,7 +417,18 @@ void MediaPlayerServiceFuzzer::invokeMediaPlayer() { [&]() { mMediaPlayer->attachAuxEffect(mFdp.ConsumeIntegral()); }, [&]() { int32_t key = mFdp.PickValueInArray(kMediaParamKeys); - request.writeInt32(mFdp.ConsumeIntegral()); + request.writeInt32((audio_usage_t)mFdp.ConsumeIntegralInRange( + AUDIO_USAGE_UNKNOWN, AUDIO_USAGE_ANNOUNCEMENT) /* usage */); + request.writeInt32((audio_content_type_t)mFdp.ConsumeIntegralInRange( + AUDIO_CONTENT_TYPE_UNKNOWN, + AUDIO_CONTENT_TYPE_ULTRASOUND) /* content_type */); + request.writeInt32((audio_source_t)mFdp.ConsumeIntegralInRange( + AUDIO_SOURCE_INVALID, AUDIO_SOURCE_ULTRASOUND) /* source */); + request.writeInt32((audio_flags_mask_t)mFdp.ConsumeIntegralInRange( + AUDIO_FLAG_NONE, AUDIO_FLAG_CALL_REDIRECTION) /* flags */); + request.writeInt32(mFdp.ConsumeBool() /* hasFlattenedTag */); + request.writeString16( + String16((mFdp.ConsumeRandomLengthString()).c_str()) /* tags */); request.setDataPosition(0); mMediaPlayer->setParameter(key, request); key = mFdp.PickValueInArray(kMediaParamKeys); From 5e38942eb28653da4e7987eb94ddcc23aed35aa8 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 5 Jun 2024 16:53:13 +0000 Subject: [PATCH 02/17] Use the global default cpp_std. Bug: http://b/344590580 Change-Id: Ibbaae662a798ae2919ccb5f0845f6b8956cf5b1d --- camera/ndk/Android.bp | 1 - 1 file changed, 1 deletion(-) diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp index d4dd5464f3..921aab2849 100644 --- a/camera/ndk/Android.bp +++ b/camera/ndk/Android.bp @@ -111,7 +111,6 @@ cc_library_shared { cc_library_shared { name: "libcamera2ndk_vendor", - cpp_std: "gnu++17", vendor: true, srcs: [ "ndk_vendor/impl/ACameraDevice.cpp", From ad434d79398f6493a9d5e14d7f08703d14fe08c8 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 5 Jun 2024 18:41:48 +0000 Subject: [PATCH 03/17] Use the global default cpp_std. Bug: http://b/344590580 Change-Id: I523e556f77e33fbaa6711b9ada7c8646202a2749 --- media/codec2/components/avc/C2SoftAvcDec.h | 2 +- media/codec2/components/dav1d/C2SoftDav1dDec.h | 2 +- media/codec2/components/gav1/C2SoftGav1Dec.h | 2 +- media/codec2/components/hevc/C2SoftHevcDec.h | 2 +- media/codec2/components/mpeg2/C2SoftMpeg2Dec.h | 2 +- media/codec2/vndk/Android.bp | 1 - 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h index 36a463e0e4..6165455761 100644 --- a/media/codec2/components/avc/C2SoftAvcDec.h +++ b/media/codec2/components/avc/C2SoftAvcDec.h @@ -173,7 +173,7 @@ class C2SoftAvcDec : public SimpleC2Component { VuiColorAspects() : primaries(2), transfer(2), coeffs(2), fullRange(0) { } - bool operator==(const VuiColorAspects &o) { + bool operator==(const VuiColorAspects &o) const { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.h b/media/codec2/components/dav1d/C2SoftDav1dDec.h index 6008325bf9..c5c12149c2 100644 --- a/media/codec2/components/dav1d/C2SoftDav1dDec.h +++ b/media/codec2/components/dav1d/C2SoftDav1dDec.h @@ -91,7 +91,7 @@ struct C2SoftDav1dDec : public SimpleC2Component { coeffs(C2Color::MATRIX_UNSPECIFIED), fullRange(C2Color::RANGE_UNSPECIFIED) {} - bool operator==(const VuiColorAspects& o) { + bool operator==(const VuiColorAspects& o) const { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h index 0e09fccfd2..e5d10e0f4c 100644 --- a/media/codec2/components/gav1/C2SoftGav1Dec.h +++ b/media/codec2/components/gav1/C2SoftGav1Dec.h @@ -84,7 +84,7 @@ struct C2SoftGav1Dec : public SimpleC2Component { coeffs(C2Color::MATRIX_UNSPECIFIED), fullRange(C2Color::RANGE_UNSPECIFIED) { } - bool operator==(const VuiColorAspects &o) { + bool operator==(const VuiColorAspects &o) const { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h index 6abf69ed43..ff6d3717c3 100644 --- a/media/codec2/components/hevc/C2SoftHevcDec.h +++ b/media/codec2/components/hevc/C2SoftHevcDec.h @@ -132,7 +132,7 @@ struct C2SoftHevcDec : public SimpleC2Component { VuiColorAspects() : primaries(2), transfer(2), coeffs(2), fullRange(0) { } - bool operator==(const VuiColorAspects &o) { + bool operator==(const VuiColorAspects &o) const { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h index 3965bcc4fc..a7bee90c98 100644 --- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h +++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h @@ -172,7 +172,7 @@ struct C2SoftMpeg2Dec : public SimpleC2Component { VuiColorAspects() : primaries(2), transfer(2), coeffs(2), fullRange(0) { } - bool operator==(const VuiColorAspects &o) { + bool operator==(const VuiColorAspects &o) const { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp index dc06ee6400..327c3fd3a4 100644 --- a/media/codec2/vndk/Android.bp +++ b/media/codec2/vndk/Android.bp @@ -180,7 +180,6 @@ cc_defaults { // public dependency for implementing Codec 2 components cc_defaults { name: "libcodec2-impl-defaults", - cpp_std: "gnu++17", defaults: [ "libcodec2_hal_selection", From 3a81f0d68affdb56e6a4ae813309b6ffc88a7d7d Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Fri, 7 Jun 2024 14:26:40 +0000 Subject: [PATCH 04/17] Add Custom preset for equalizer effect to fix effect STS test case Bug: 340810158 Test: run CtsSecurityTestCases -t android.security.cts.EffectBundleTest Change-Id: I8e8d8d03360a6ef91ed1efa24624c718a1071b0a --- media/libeffects/lvm/wrapper/Aidl/BundleTypes.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h index daabdb7ff6..e5373f36ba 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h +++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h @@ -65,9 +65,9 @@ constexpr inline std::array, MAX_NUM_PRESETS> {5, 3, -1, 3, 5}}}; /* Rock Preset */ static const std::vector kEqPresets = { - {0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"}, - {5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}}; - + {-1, "Custom"}, {0, "Normal"}, {1, "Classical"}, {2, "Dance"}, + {3, "Flat"}, {4, "Folk"}, {5, "Heavy Metal"}, {6, "Hip Hop"}, + {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}}; const std::vector kEqRanges = { MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1), From 18ac32ccb419dfa90d1cfbdebbb53910dd5716ab Mon Sep 17 00:00:00 2001 From: Jan Sebechlebsky Date: Fri, 7 Jun 2024 09:53:53 +0200 Subject: [PATCH 05/17] Trigger texture update on each submission of input buffer. When input queue is full (which will happen if there are no capture requests coming from the camera client), it blocks until there's buffer freed up. This is not desired (for example, it causes video decoder attached to the virtual camera surface to drop frames), and causes that the subsequent capture request received by camera won't get the most recent image from the virtual camera owner. This cl fixes this behavior, by consuming the buffer from the input queue immediatelly after it's submitted. Bug: 344572859 Test: atest VirtualCameraCaptureTest Change-Id: Ic7556921630d56f73bbd861d35c5218351217ee6 --- .../VirtualCameraRenderThread.cc | 78 +++++++++++++++++-- .../virtualcamera/VirtualCameraRenderThread.h | 31 +++++++- .../virtualcamera/util/EglSurfaceTexture.cc | 5 ++ .../virtualcamera/util/EglSurfaceTexture.h | 4 + 4 files changed, 107 insertions(+), 11 deletions(-) diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc index 9a5bd1e5f0..ff09256b1a 100644 --- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc +++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "Exif.h" @@ -78,6 +79,15 @@ using ::android::hardware::camera::common::helper::ExifUtils; namespace { +// helper type for the visitor +template +struct overloaded : Ts... { + using Ts::operator()...; +}; +// explicit deduction guide (not needed as of C++20) +template +overloaded(Ts...) -> overloaded; + using namespace std::chrono_literals; static constexpr std::chrono::milliseconds kAcquireFenceTimeout = 500ms; @@ -89,6 +99,8 @@ static constexpr uint8_t kPipelineDepth = 2; static constexpr size_t kJpegThumbnailBufferSize = 32 * 1024; // 32 KiB +static constexpr UpdateTextureTask kUpdateTextureTask; + CameraMetadata createCaptureResultMetadata( const std::chrono::nanoseconds timestamp, const RequestSettings& requestSettings, @@ -287,6 +299,21 @@ std::chrono::nanoseconds getMaxFrameDuration( static_cast(1e9 / VirtualCameraDevice::kMinFps)); } +class FrameAvailableListenerProxy : public ConsumerBase::FrameAvailableListener { + public: + FrameAvailableListenerProxy(std::function callback) + : mOnFrameAvailableCallback(callback) { + } + + virtual void onFrameAvailable(const BufferItem&) override { + ALOGV("%s: onFrameAvailable", __func__); + mOnFrameAvailableCallback(); + } + + private: + std::function mOnFrameAvailableCallback; +}; + } // namespace CaptureRequestBuffer::CaptureRequestBuffer(int streamId, int bufferId, @@ -345,9 +372,25 @@ const RequestSettings& ProcessCaptureRequestTask::getRequestSettings() const { return mRequestSettings; } +void VirtualCameraRenderThread::requestTextureUpdate() { + std::lock_guard lock(mLock); + // If queue is not empty, we don't need to set the mTextureUpdateRequested + // flag, since the texture will be updated during ProcessCaptureRequestTask + // processing anyway. + if (mQueue.empty()) { + mTextureUpdateRequested = true; + mCondVar.notify_one(); + } +} + void VirtualCameraRenderThread::enqueueTask( std::unique_ptr task) { std::lock_guard lock(mLock); + // When enqueving process capture request task, clear the + // mTextureUpdateRequested flag. If this flag is set, the texture was not yet + // updated and it will be updated when processing ProcessCaptureRequestTask + // anyway. + mTextureUpdateRequested = false; mQueue.emplace_back(std::move(task)); mCondVar.notify_one(); } @@ -377,8 +420,7 @@ sp VirtualCameraRenderThread::getInputSurface() { return mInputSurfaceFuture.get(); } -std::unique_ptr -VirtualCameraRenderThread::dequeueTask() { +RenderThreadTask VirtualCameraRenderThread::dequeueTask() { std::unique_lock lock(mLock); // Clang's thread safety analysis doesn't perform alias analysis, // so it doesn't support moveable std::unique_lock. @@ -389,12 +431,20 @@ VirtualCameraRenderThread::dequeueTask() { ScopedLockAssertion lockAssertion(mLock); mCondVar.wait(lock, [this]() REQUIRES(mLock) { - return mPendingExit || !mQueue.empty(); + return mPendingExit || mTextureUpdateRequested || !mQueue.empty(); }); if (mPendingExit) { - return nullptr; + // Render thread task with null task signals render thread to terminate. + return RenderThreadTask(nullptr); + } + if (mTextureUpdateRequested) { + // If mTextureUpdateRequested, it's guaranteed the queue is empty, return + // kUpdateTextureTask to signal we want render thread to update the texture + // (consume buffer from the queue). + mTextureUpdateRequested = false; + return RenderThreadTask(kUpdateTextureTask); } - std::unique_ptr task = std::move(mQueue.front()); + RenderThreadTask task(std::move(mQueue.front())); mQueue.pop_front(); return task; } @@ -409,11 +459,23 @@ void VirtualCameraRenderThread::threadLoop() { EglTextureProgram::TextureFormat::RGBA); mEglSurfaceTexture = std::make_unique( mInputSurfaceSize.width, mInputSurfaceSize.height); + sp frameAvailableListener = + sp::make( + [this]() { requestTextureUpdate(); }); + mEglSurfaceTexture->setFrameAvailableListener(frameAvailableListener); mInputSurfacePromise.set_value(mEglSurfaceTexture->getSurface()); - while (std::unique_ptr task = dequeueTask()) { - processCaptureRequest(*task); + while (RenderThreadTask task = dequeueTask()) { + std::visit( + overloaded{[this](const std::unique_ptr& t) { + processTask(*t); + }, + [this](const UpdateTextureTask&) { + ALOGV("Idle update of the texture"); + mEglSurfaceTexture->updateTexture(); + }}, + task); } // Destroy EGL utilities still on the render thread. @@ -425,7 +487,7 @@ void VirtualCameraRenderThread::threadLoop() { ALOGV("Render thread exiting"); } -void VirtualCameraRenderThread::processCaptureRequest( +void VirtualCameraRenderThread::processTask( const ProcessCaptureRequestTask& request) { std::chrono::nanoseconds timestamp = std::chrono::duration_cast( diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.h b/services/camera/virtualcamera/VirtualCameraRenderThread.h index b23c30c144..5a5966b635 100644 --- a/services/camera/virtualcamera/VirtualCameraRenderThread.h +++ b/services/camera/virtualcamera/VirtualCameraRenderThread.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "VirtualCameraDevice.h" @@ -34,7 +35,6 @@ #include "util/EglFramebuffer.h" #include "util/EglProgram.h" #include "util/EglSurfaceTexture.h" -#include "util/MetadataUtil.h" #include "util/Util.h" namespace android { @@ -94,6 +94,24 @@ class ProcessCaptureRequestTask { const RequestSettings mRequestSettings; }; +struct UpdateTextureTask {}; + +struct RenderThreadTask + : public std::variant, + UpdateTextureTask> { + // Allow implicit conversion to bool. + // + // Returns false, if the RenderThreadTask consist of null + // ProcessCaptureRequestTask, which signals that the thread should terminate. + operator bool() const { + const bool isExitSignal = + std::holds_alternative>( + *this) && + std::get>(*this) == nullptr; + return !isExitSignal; + } +}; + // Wraps dedicated rendering thread and rendering business with corresponding // input surface. class VirtualCameraRenderThread { @@ -120,6 +138,12 @@ class VirtualCameraRenderThread { // Stop rendering thread. void stop(); + // Send request to render thread to update the texture. + // Currently queued buffers in the input surface will be consumed and the most + // recent buffer in the input surface will be attached to the texture), all + // other buffers will be returned to the buffer queue. + void requestTextureUpdate() EXCLUDES(mLock); + // Equeue capture task for processing on render thread. void enqueueTask(std::unique_ptr task) EXCLUDES(mLock); @@ -131,13 +155,13 @@ class VirtualCameraRenderThread { sp getInputSurface(); private: - std::unique_ptr dequeueTask() EXCLUDES(mLock); + RenderThreadTask dequeueTask() EXCLUDES(mLock); // Rendering thread entry point. void threadLoop(); // Process single capture request task (always called on render thread). - void processCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask); + void processTask(const ProcessCaptureRequestTask& captureRequestTask); // Flush single capture request task returning the error status immediately. void flushCaptureRequest(const ProcessCaptureRequestTask& captureRequestTask); @@ -192,6 +216,7 @@ class VirtualCameraRenderThread { std::mutex mLock; std::deque> mQueue GUARDED_BY(mLock); std::condition_variable mCondVar; + volatile bool mTextureUpdateRequested GUARDED_BY(mLock); volatile bool mPendingExit GUARDED_BY(mLock); // Acquisition timestamp of last frame. diff --git a/services/camera/virtualcamera/util/EglSurfaceTexture.cc b/services/camera/virtualcamera/util/EglSurfaceTexture.cc index 7de5020f95..c81d36d2fb 100644 --- a/services/camera/virtualcamera/util/EglSurfaceTexture.cc +++ b/services/camera/virtualcamera/util/EglSurfaceTexture.cc @@ -64,6 +64,11 @@ sp EglSurfaceTexture::getCurrentBuffer() { return mGlConsumer->getCurrentBuffer(); } +void EglSurfaceTexture::setFrameAvailableListener( + const wp& listener) { + mGlConsumer->setFrameAvailableListener(listener); +} + bool EglSurfaceTexture::waitForNextFrame(const std::chrono::nanoseconds timeout) { return mSurface->waitForNextFrame(mGlConsumer->getFrameNumber(), static_cast(timeout.count())); diff --git a/services/camera/virtualcamera/util/EglSurfaceTexture.h b/services/camera/virtualcamera/util/EglSurfaceTexture.h index b9c5126851..ac3cf7d352 100644 --- a/services/camera/virtualcamera/util/EglSurfaceTexture.h +++ b/services/camera/virtualcamera/util/EglSurfaceTexture.h @@ -21,6 +21,7 @@ #include #include "GLES/gl.h" +#include "gui/ConsumerBase.h" #include "gui/Surface.h" #include "utils/RefBase.h" @@ -58,6 +59,9 @@ class EglSurfaceTexture { // Returns false on timeout, true if new frame was received before timeout. bool waitForNextFrame(std::chrono::nanoseconds timeout); + void setFrameAvailableListener( + const wp& listener); + // Update the texture with the most recent submitted buffer. // Most be called on thread with EGL context. // From 9cc4545fd602c2a99e7ca44d3affeabf0b6914b6 Mon Sep 17 00:00:00 2001 From: Priyanka Advani Date: Mon, 10 Jun 2024 22:22:01 +0000 Subject: [PATCH 06/17] Revert "Use the global default cpp_std." This reverts commit 5e38942eb28653da4e7987eb94ddcc23aed35aa8. Reason for revert: Droidmonitor created revert due to b/346410836. Change-Id: I4ca7520e0cc6b0fb6474a66393b3b359c6946866 --- camera/ndk/Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp index 921aab2849..d4dd5464f3 100644 --- a/camera/ndk/Android.bp +++ b/camera/ndk/Android.bp @@ -111,6 +111,7 @@ cc_library_shared { cc_library_shared { name: "libcamera2ndk_vendor", + cpp_std: "gnu++17", vendor: true, srcs: [ "ndk_vendor/impl/ACameraDevice.cpp", From 700f152a809562872535d8bfff6b5ad0f014fb97 Mon Sep 17 00:00:00 2001 From: Wonsik Kim Date: Mon, 10 Jun 2024 22:50:06 +0000 Subject: [PATCH 07/17] FilterWrapper: propagate ParamReflectors to the wrapper component FilterWrapper to query param reflectors from both the component and the filter, so that if the filter defines a parameter that the component does not describe, the framework can still recognize the parameter. In addition, add a vendor control parameter to the sample plugin as a demonstration. Bug: 330287140 Test: atest MediaCodecTest#testVendorParameters Change-Id: Ie4bbf9056925ccb3334e6e730f4ac313cc8f4dec --- media/codec2/hal/aidl/ComponentStore.cpp | 43 +++++++--- .../aidl/include/codec2/aidl/ComponentStore.h | 5 +- .../hal/hidl/1.0/utils/ComponentStore.cpp | 29 +++++-- .../include/codec2/hidl/1.0/ComponentStore.h | 5 +- .../hal/hidl/1.1/utils/ComponentStore.cpp | 29 +++++-- .../include/codec2/hidl/1.1/ComponentStore.h | 5 +- .../hal/hidl/1.2/utils/ComponentStore.cpp | 29 +++++-- .../include/codec2/hidl/1.2/ComponentStore.h | 5 +- media/codec2/hal/plugin/FilterWrapper.cpp | 7 ++ media/codec2/hal/plugin/FilterWrapperStub.cpp | 4 + .../hal/plugin/internal/FilterWrapper.h | 4 + .../hal/plugin/samples/SampleFilterPlugin.cpp | 78 +++++++++++++++---- 12 files changed, 193 insertions(+), 50 deletions(-) diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp index b95c09efd6..ea4d045780 100644 --- a/media/codec2/hal/aidl/ComponentStore.cpp +++ b/media/codec2/hal/aidl/ComponentStore.cpp @@ -36,7 +36,7 @@ #include #include -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules #include #include #include @@ -51,7 +51,7 @@ namespace media { namespace c2 { namespace utils { -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules using ::android::DefaultFilterPlugin; using ::android::FilterWrapper; #endif @@ -144,7 +144,15 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) ::android::SetPreferredCodec2ComponentStore(store); // Retrieve struct descriptors - mParamReflector = mStore->getParamReflector(); + mParamReflectors.push_back(mStore->getParamReflector()); +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules + std::shared_ptr paramReflector = + GetFilterWrapper()->getParamReflector(); + if (paramReflector != nullptr) { + ALOGD("[%s] added param reflector from filter wrapper", mStore->getName().c_str()); + mParamReflectors.push_back(paramReflector); + } +#endif // Retrieve supported parameters from store using namespace std::placeholders; @@ -173,8 +181,7 @@ c2_status_t ComponentStore::validateSupportedParams( std::lock_guard lock(mStructDescriptorsMutex); auto it = mStructDescriptors.find(coreIndex); if (it == mStructDescriptors.end()) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { // All supported params must be described res = C2_BAD_INDEX; @@ -189,7 +196,7 @@ std::shared_ptr ComponentStore::getParameterCache() const { return mParameterCache; } -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules // static std::shared_ptr ComponentStore::GetFilterWrapper() { constexpr const char kPluginPath[] = "libc2filterplugin.so"; @@ -221,8 +228,13 @@ std::shared_ptr ComponentStore::tryCreateMultiAccessUn } } if (!isComponentSupportsLargeAudioFrame) { + // TODO - b/342269852: MultiAccessUnitInterface also needs to take multiple + // param reflectors. Currently filters work on video domain only, + // and the MultiAccessUnitHelper is only enabled on audio domain; + // thus we pass the component's param reflector, which is mParamReflectors[0]. multiAccessUnitIntf = std::make_shared( - c2interface, std::static_pointer_cast(mParamReflector)); + c2interface, + std::static_pointer_cast(mParamReflectors[0])); } } } @@ -250,7 +262,7 @@ ScopedAStatus ComponentStore::createComponent( mStore->createComponent(name, &c2component); if (status == C2_OK) { -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules c2component = GetFilterWrapper()->maybeWrapComponent(c2component); #endif onInterfaceLoaded(c2component->intf()); @@ -284,7 +296,7 @@ ScopedAStatus ComponentStore::createInterface( std::shared_ptr c2interface; c2_status_t res = mStore->createInterface(name, &c2interface); if (res == C2_OK) { -#ifndef __ANDROID_APEX__ +#ifndef __ANDROID_APEX__ // Filters are not supported for APEX modules c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface); #endif onInterfaceLoaded(c2interface); @@ -347,8 +359,7 @@ ScopedAStatus ComponentStore::getStructDescriptors( if (item == mStructDescriptors.end()) { // not in the cache, and not known to be unsupported, query local reflector if (!mUnsupportedStructDescriptors.count(coreIndex)) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { mUnsupportedStructDescriptors.emplace(coreIndex); } else { @@ -401,6 +412,16 @@ ScopedAStatus ComponentStore::getConfigurable( return ScopedAStatus::ok(); } +std::shared_ptr ComponentStore::describe(const C2Param::CoreIndex &index) { + for (const std::shared_ptr &reflector : mParamReflectors) { + std::shared_ptr desc = reflector->describe(index); + if (desc) { + return desc; + } + } + return nullptr; +} + // Called from createComponent() after a successful creation of `component`. void ComponentStore::reportComponentBirth(Component* component) { ComponentStatus componentStatus; diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h index 746e1bfc5c..b2158a61a5 100644 --- a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h +++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h @@ -118,7 +118,7 @@ struct ComponentStore : public BnComponentStore { c2_status_t mInit; std::shared_ptr mStore; - std::shared_ptr mParamReflector; + std::vector> mParamReflectors; std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; @@ -135,6 +135,9 @@ struct ComponentStore : public BnComponentStore { mutable std::mutex mComponentRosterMutex; std::map mComponentRoster; + // describe from mParamReflectors + std::shared_ptr describe(const C2Param::CoreIndex &index); + // Called whenever Component is created. void reportComponentBirth(Component* component); // Called only from the destructor of Component. diff --git a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp index 988ab6f9eb..1ba1889681 100644 --- a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp +++ b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp @@ -139,7 +139,15 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) SetPreferredCodec2ComponentStore(store); // Retrieve struct descriptors - mParamReflector = mStore->getParamReflector(); + mParamReflectors.push_back(mStore->getParamReflector()); +#ifndef __ANDROID_APEX__ + std::shared_ptr paramReflector = + GetFilterWrapper()->getParamReflector(); + if (paramReflector != nullptr) { + ALOGD("[%s] added param reflector from filter wrapper", mStore->getName().c_str()); + mParamReflectors.push_back(paramReflector); + } +#endif // Retrieve supported parameters from store using namespace std::placeholders; @@ -168,8 +176,7 @@ c2_status_t ComponentStore::validateSupportedParams( std::lock_guard lock(mStructDescriptorsMutex); auto it = mStructDescriptors.find(coreIndex); if (it == mStructDescriptors.end()) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { // All supported params must be described res = C2_BAD_INDEX; @@ -217,7 +224,8 @@ std::shared_ptr ComponentStore::tryCreateMultiAccessUn } if (!isComponentSupportsLargeAudioFrame) { multiAccessUnitIntf = std::make_shared( - c2interface, std::static_pointer_cast(mParamReflector)); + c2interface, + std::static_pointer_cast(mParamReflectors[0])); } } } @@ -339,8 +347,7 @@ Return ComponentStore::getStructDescriptors( if (item == mStructDescriptors.end()) { // not in the cache, and not known to be unsupported, query local reflector if (!mUnsupportedStructDescriptors.count(coreIndex)) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { mUnsupportedStructDescriptors.emplace(coreIndex); } else { @@ -386,6 +393,16 @@ Return> ComponentStore::getConfigurable() { return mConfigurable; } +std::shared_ptr ComponentStore::describe(const C2Param::CoreIndex &index) { + for (const std::shared_ptr &reflector : mParamReflectors) { + std::shared_ptr desc = reflector->describe(index); + if (desc) { + return desc; + } + } + return nullptr; +} + // Called from createComponent() after a successful creation of `component`. void ComponentStore::reportComponentBirth(Component* component) { ComponentStatus componentStatus; diff --git a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h index b5d85da239..44b8ec1956 100644 --- a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h +++ b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h @@ -117,9 +117,12 @@ struct ComponentStore : public IComponentStore { // Does bookkeeping for an interface that has been loaded. void onInterfaceLoaded(const std::shared_ptr &intf); + // describe from mParamReflectors + std::shared_ptr describe(const C2Param::CoreIndex &index); + c2_status_t mInit; std::shared_ptr mStore; - std::shared_ptr mParamReflector; + std::vector> mParamReflectors; std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; diff --git a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp index 46af809831..1b869581d6 100644 --- a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp +++ b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp @@ -139,7 +139,15 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) SetPreferredCodec2ComponentStore(store); // Retrieve struct descriptors - mParamReflector = mStore->getParamReflector(); + mParamReflectors.push_back(mStore->getParamReflector()); +#ifndef __ANDROID_APEX__ + std::shared_ptr paramReflector = + GetFilterWrapper()->getParamReflector(); + if (paramReflector != nullptr) { + ALOGD("[%s] added param reflector from filter wrapper", mStore->getName().c_str()); + mParamReflectors.push_back(paramReflector); + } +#endif // Retrieve supported parameters from store using namespace std::placeholders; @@ -168,8 +176,7 @@ c2_status_t ComponentStore::validateSupportedParams( std::lock_guard lock(mStructDescriptorsMutex); auto it = mStructDescriptors.find(coreIndex); if (it == mStructDescriptors.end()) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { // All supported params must be described res = C2_BAD_INDEX; @@ -218,7 +225,8 @@ std::shared_ptr ComponentStore::tryCreateMultiAccessUn if (!isComponentSupportsLargeAudioFrame) { multiAccessUnitIntf = std::make_shared( - c2interface, std::static_pointer_cast(mParamReflector)); + c2interface, + std::static_pointer_cast(mParamReflectors[0])); } } } @@ -340,8 +348,7 @@ Return ComponentStore::getStructDescriptors( if (item == mStructDescriptors.end()) { // not in the cache, and not known to be unsupported, query local reflector if (!mUnsupportedStructDescriptors.count(coreIndex)) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { mUnsupportedStructDescriptors.emplace(coreIndex); } else { @@ -423,6 +430,16 @@ Return ComponentStore::createComponent_1_1( return Void(); } +std::shared_ptr ComponentStore::describe(const C2Param::CoreIndex &index) { + for (const std::shared_ptr &reflector : mParamReflectors) { + std::shared_ptr desc = reflector->describe(index); + if (desc) { + return desc; + } + } + return nullptr; +} + // Called from createComponent() after a successful creation of `component`. void ComponentStore::reportComponentBirth(Component* component) { ComponentStatus componentStatus; diff --git a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h index 85862a9f61..52d2945874 100644 --- a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h +++ b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h @@ -125,9 +125,12 @@ struct ComponentStore : public IComponentStore { // Does bookkeeping for an interface that has been loaded. void onInterfaceLoaded(const std::shared_ptr &intf); + // describe from mParamReflectors + std::shared_ptr describe(const C2Param::CoreIndex &index); + c2_status_t mInit; std::shared_ptr mStore; - std::shared_ptr mParamReflector; + std::vector> mParamReflectors; std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; diff --git a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp index f89c83586f..2e0386f485 100644 --- a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp +++ b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp @@ -139,7 +139,15 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) SetPreferredCodec2ComponentStore(store); // Retrieve struct descriptors - mParamReflector = mStore->getParamReflector(); + mParamReflectors.push_back(mStore->getParamReflector()); +#ifndef __ANDROID_APEX__ + std::shared_ptr paramReflector = + GetFilterWrapper()->getParamReflector(); + if (paramReflector != nullptr) { + ALOGD("[%s] added param reflector from filter wrapper", mStore->getName().c_str()); + mParamReflectors.push_back(paramReflector); + } +#endif // Retrieve supported parameters from store using namespace std::placeholders; @@ -168,8 +176,7 @@ c2_status_t ComponentStore::validateSupportedParams( std::lock_guard lock(mStructDescriptorsMutex); auto it = mStructDescriptors.find(coreIndex); if (it == mStructDescriptors.end()) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { // All supported params must be described res = C2_BAD_INDEX; @@ -217,7 +224,8 @@ std::shared_ptr ComponentStore::tryCreateMultiAccessUn } if (!isComponentSupportsLargeAudioFrame) { multiAccessUnitIntf = std::make_shared( - c2interface, std::static_pointer_cast(mParamReflector)); + c2interface, + std::static_pointer_cast(mParamReflectors[0])); } } } @@ -338,8 +346,7 @@ Return ComponentStore::getStructDescriptors( if (item == mStructDescriptors.end()) { // not in the cache, and not known to be unsupported, query local reflector if (!mUnsupportedStructDescriptors.count(coreIndex)) { - std::shared_ptr structDesc = - mParamReflector->describe(coreIndex); + std::shared_ptr structDesc = describe(coreIndex); if (!structDesc) { mUnsupportedStructDescriptors.emplace(coreIndex); } else { @@ -457,6 +464,16 @@ Return ComponentStore::createComponent_1_2( return Void(); } +std::shared_ptr ComponentStore::describe(const C2Param::CoreIndex &index) { + for (const std::shared_ptr &reflector : mParamReflectors) { + std::shared_ptr desc = reflector->describe(index); + if (desc) { + return desc; + } + } + return nullptr; +} + // Called from createComponent() after a successful creation of `component`. void ComponentStore::reportComponentBirth(Component* component) { ComponentStatus componentStatus; diff --git a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h index c08fce4c67..1b209e27fd 100644 --- a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h +++ b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h @@ -132,9 +132,12 @@ struct ComponentStore : public IComponentStore { // Does bookkeeping for an interface that has been loaded. void onInterfaceLoaded(const std::shared_ptr &intf); + // describe from mParamReflectors + std::shared_ptr describe(const C2Param::CoreIndex &index); + c2_status_t mInit; std::shared_ptr mStore; - std::shared_ptr mParamReflector; + std::vector> mParamReflectors; std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; diff --git a/media/codec2/hal/plugin/FilterWrapper.cpp b/media/codec2/hal/plugin/FilterWrapper.cpp index 197d6e7086..4e03dbbcb3 100644 --- a/media/codec2/hal/plugin/FilterWrapper.cpp +++ b/media/codec2/hal/plugin/FilterWrapper.cpp @@ -1011,4 +1011,11 @@ c2_status_t FilterWrapper::queryParamsForPreviousComponent( return mPlugin->queryParamsForPreviousComponent(intf, params); } +std::shared_ptr FilterWrapper::getParamReflector() { + if (mInit != OK) { + return nullptr; + } + return mStore->getParamReflector(); +} + } // namespace android diff --git a/media/codec2/hal/plugin/FilterWrapperStub.cpp b/media/codec2/hal/plugin/FilterWrapperStub.cpp index 3fd54095ae..a21f6d0735 100644 --- a/media/codec2/hal/plugin/FilterWrapperStub.cpp +++ b/media/codec2/hal/plugin/FilterWrapperStub.cpp @@ -57,4 +57,8 @@ c2_status_t FilterWrapper::createBlockPool( return CreateCodec2BlockPool(allocatorParam, component, pool); } +std::shared_ptr FilterWrapper::getParamReflector() { + return nullptr; +} + } // namespace android diff --git a/media/codec2/hal/plugin/internal/FilterWrapper.h b/media/codec2/hal/plugin/internal/FilterWrapper.h index dcffb5cd30..c27901e4ff 100644 --- a/media/codec2/hal/plugin/internal/FilterWrapper.h +++ b/media/codec2/hal/plugin/internal/FilterWrapper.h @@ -104,6 +104,10 @@ class FilterWrapper : public std::enable_shared_from_this { const std::shared_ptr &intf, std::vector> *params); + /** + * Return the param reflector of the filter plugin store. + */ + std::shared_ptr getParamReflector(); private: status_t mInit; std::unique_ptr mPlugin; diff --git a/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp b/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp index b5383ad584..47412b7868 100644 --- a/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp +++ b/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp @@ -37,6 +37,19 @@ typedef C2StreamParam C2StreamColorAspectsRequestInfo; +// In practice the vendor parameters will be defined in a separate header file, +// but for the purpose of this sample, we just define it here. + +// Vendor-specific type index for filters start from this value. 0x7000 is added to +// avoid conflict with existing vendor type indices. +constexpr uint32_t kTypeIndexFilterStart = C2Param::TYPE_INDEX_VENDOR_START + 0x7000; +// Answer to the Ultimate Question of Life, the Universe, and Everything +// (Reference to The Hitchhiker's Guide to the Galaxy by Douglas Adams) +constexpr uint32_t kParamIndexVendorUltimateAnswer = kTypeIndexFilterStart + 0; +typedef C2StreamParam + C2StreamVendorUltimateAnswerInfo; +constexpr char C2_PARAMKEY_VENDOR_ULTIMATE_ANSWER[] = "ultimate-answer"; + namespace android { using namespace std::literals::chrono_literals; @@ -49,10 +62,9 @@ class SampleToneMappingFilter static const std::string NAME; static const FilterPlugin_V1::Descriptor DESCRIPTOR; - explicit Interface(c2_node_id_t id) + Interface(c2_node_id_t id, const std::shared_ptr &reflector) : mId(id), - mReflector(std::make_shared()), - mHelper(mReflector) { + mHelper(reflector) { } ~Interface() override = default; C2String getName() const override { return NAME; } @@ -126,7 +138,6 @@ class SampleToneMappingFilter } private: const c2_node_id_t mId; - std::shared_ptr mReflector; struct Helper : public C2InterfaceHelper { explicit Helper(std::shared_ptr reflector) : C2InterfaceHelper(reflector) { @@ -265,6 +276,15 @@ class SampleToneMappingFilter .withSetter(ColorAspectsRequestSetter) .build()); + addParameter( + DefineParam(mVendorUltimateAnswerInfo, C2_PARAMKEY_VENDOR_ULTIMATE_ANSWER) + .withDefault(new C2StreamVendorUltimateAnswerInfo::input(0u)) + .withFields({ + C2F(mVendorUltimateAnswerInfo, value).any(), + }) + .withSetter(VendorUltimateAnswerSetter) + .build()); + addParameter( DefineParam(mOutputColorAspectInfo, C2_PARAMKEY_COLOR_ASPECTS) .withDefault(new C2StreamColorAspectsInfo::output(0u)) @@ -336,6 +356,15 @@ class SampleToneMappingFilter return C2R::Ok(); } + static C2R VendorUltimateAnswerSetter( + bool mayBlock, + C2P &me) { + (void)mayBlock; + ALOGI("Answer to the Ultimate Question of Life, the Universe, and Everything " + "set to %d", me.v.value); + return C2R::Ok(); + } + std::shared_ptr mApiFeatures; std::shared_ptr mName; @@ -362,11 +391,13 @@ class SampleToneMappingFilter std::shared_ptr mInputColorAspectInfo; std::shared_ptr mOutputColorAspectInfo; std::shared_ptr mColorAspectRequestInfo; + + std::shared_ptr mVendorUltimateAnswerInfo; } mHelper; }; - explicit SampleToneMappingFilter(c2_node_id_t id) - : mIntf(std::make_shared(id)) { + SampleToneMappingFilter(c2_node_id_t id, const std::shared_ptr &reflector) + : mIntf(std::make_shared(id, reflector)) { } ~SampleToneMappingFilter() override { if (mProcessingThread.joinable()) { @@ -802,7 +833,10 @@ const std::string SampleToneMappingFilter::Interface::NAME = "c2.sample.tone-map // static const FilterPlugin_V1::Descriptor SampleToneMappingFilter::Interface::DESCRIPTOR = { // controlParams - { C2StreamColorAspectsRequestInfo::output::PARAM_TYPE }, + { + C2StreamColorAspectsRequestInfo::output::PARAM_TYPE, + C2StreamVendorUltimateAnswerInfo::input::PARAM_TYPE, + }, // affectedParams { C2StreamHdrStaticInfo::output::PARAM_TYPE, @@ -815,7 +849,7 @@ class SampleC2ComponentStore : public C2ComponentStore { SampleC2ComponentStore() : mReflector(std::make_shared()), mIntf(mReflector), - mFactories(CreateFactories()) { + mFactories(CreateFactories(mReflector)) { } ~SampleC2ComponentStore() = default; @@ -892,36 +926,46 @@ class SampleC2ComponentStore : public C2ComponentStore { template struct ComponentFactoryImpl : public ComponentFactory { public: - ComponentFactoryImpl(const std::shared_ptr &traits) - : ComponentFactory(traits) { + ComponentFactoryImpl( + const std::shared_ptr &traits, + const std::shared_ptr &reflector) + : ComponentFactory(traits), + mReflector(reflector) { } ~ComponentFactoryImpl() override = default; c2_status_t createComponent( c2_node_id_t id, std::shared_ptr* const component) const override { - *component = std::make_shared(id); + *component = std::make_shared(id, mReflector); return C2_OK; } c2_status_t createInterface( c2_node_id_t id, std::shared_ptr* const interface) const override { - *interface = std::make_shared(id); + *interface = std::make_shared(id, mReflector); return C2_OK; } + private: + std::shared_ptr mReflector; }; template - static void AddFactory(std::map> *factories) { - std::shared_ptr intf{new typename T::Interface(0)}; + static void AddFactory( + std::map> *factories, + const std::shared_ptr &reflector) { + std::shared_ptr intf{new typename T::Interface(0, reflector)}; std::shared_ptr traits(new (std::nothrow) C2Component::Traits); CHECK(C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) << "Failed to fill traits from interface"; - factories->emplace(traits->name, new ComponentFactoryImpl(traits)); + factories->emplace( + traits->name, + new ComponentFactoryImpl(traits, reflector)); } - static std::map> CreateFactories() { + static std::map> CreateFactories( + const std::shared_ptr &reflector) { std::map> factories; - AddFactory(&factories); + AddFactory(&factories, reflector); return factories; } From 23f8162d8ac8aef024be3d02e85ca0efd7efa689 Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Fri, 7 Jun 2024 18:48:49 -0700 Subject: [PATCH 08/17] VolumeShaper: Log to mediametrics Test: atest VolumeShaperTests Test: adb shell dumpsys media.metrics | grep VolumeShaper Bug: 346405585 Change-Id: Ica5d750684e602d14dff490904b27fd11ff82554 --- include/media/Interpolator.h | 2 +- include/media/VolumeShaper.h | 51 +++++++++++++++++-- media/libaudioclient/AudioTrack.cpp | 13 +++++ .../include/MediaMetricsConstants.h | 2 + 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/include/media/Interpolator.h b/include/media/Interpolator.h index e26290fc94..5a2ab27118 100644 --- a/include/media/Interpolator.h +++ b/include/media/Interpolator.h @@ -289,7 +289,7 @@ class Interpolator : public std::map { std::string toString() const { std::stringstream ss; - ss << "Interpolator{mInterpolatorType=" << static_cast(mInterpolatorType); + ss << "Interpolator{mInterpolatorType=" << media::toString(mInterpolatorType); ss << ", mFirstSlope=" << mFirstSlope; ss << ", mLastSlope=" << mLastSlope; ss << ", {"; diff --git a/include/media/VolumeShaper.h b/include/media/VolumeShaper.h index 6208db313e..26da3634c8 100644 --- a/include/media/VolumeShaper.h +++ b/include/media/VolumeShaper.h @@ -116,6 +116,16 @@ class VolumeShaper { TYPE_SCALE, }; + static std::string toString(Type type) { + switch (type) { + case TYPE_ID: return "TYPE_ID"; + case TYPE_SCALE: return "TYPE_SCALE"; + default: + return std::string("Unknown Type: ") + .append(std::to_string(static_cast(type))); + } + } + // Must match with VolumeShaper.java in frameworks/base. enum OptionFlag : int32_t { OPTION_FLAG_NONE = 0, @@ -125,6 +135,22 @@ class VolumeShaper { OPTION_FLAG_ALL = (OPTION_FLAG_VOLUME_IN_DBFS | OPTION_FLAG_CLOCK_TIME), }; + static std::string toString(OptionFlag flag) { + std::string s; + for (const auto& flagPair : std::initializer_list>{ + {OPTION_FLAG_VOLUME_IN_DBFS, "OPTION_FLAG_VOLUME_IN_DBFS"}, + {OPTION_FLAG_CLOCK_TIME, "OPTION_FLAG_CLOCK_TIME"}, + }) { + if (flag & flagPair.first) { + if (!s.empty()) { + s.append("|"); + } + s.append(flagPair.second); + } + } + return s; + } + // Bring from base class; must match with VolumeShaper.java in frameworks/base. using InterpolatorType = Interpolator::InterpolatorType; @@ -329,10 +355,10 @@ class VolumeShaper { // Returns a string for debug printing. std::string toString() const { std::stringstream ss; - ss << "VolumeShaper::Configuration{mType=" << static_cast(mType); + ss << "VolumeShaper::Configuration{mType=" << toString(mType); ss << ", mId=" << mId; if (mType != TYPE_ID) { - ss << ", mOptionFlags=" << static_cast(mOptionFlags); + ss << ", mOptionFlags=" << toString(mOptionFlags); ss << ", mDurationMs=" << mDurationMs; ss << ", " << Interpolator::toString().c_str(); } @@ -414,6 +440,25 @@ class VolumeShaper { | FLAG_CREATE_IF_NECESSARY), }; + static std::string toString(Flag flag) { + std::string s; + for (const auto& flagPair : std::initializer_list>{ + {FLAG_REVERSE, "FLAG_REVERSE"}, + {FLAG_TERMINATE, "FLAG_TERMINATE"}, + {FLAG_JOIN, "FLAG_JOIN"}, + {FLAG_DELAY, "FLAG_DELAY"}, + {FLAG_CREATE_IF_NECESSARY, "FLAG_CREATE_IF_NECESSARY"}, + }) { + if (flag & flagPair.first) { + if (!s.empty()) { + s.append("|"); + } + s.append(flagPair.second); + } + } + return s; + } + Operation() : Operation(FLAG_NONE, -1 /* replaceId */) { } @@ -508,7 +553,7 @@ class VolumeShaper { std::string toString() const { std::stringstream ss; - ss << "VolumeShaper::Operation{mFlags=" << static_cast(mFlags) ; + ss << "VolumeShaper::Operation{mFlags=" << toString(mFlags); ss << ", mReplaceId=" << mReplaceId; ss << ", mXOffset=" << mXOffset; ss << "}"; diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp index 6772201073..58e492041f 100644 --- a/media/libaudioclient/AudioTrack.cpp +++ b/media/libaudioclient/AudioTrack.cpp @@ -3035,6 +3035,7 @@ VolumeShaper::Status AudioTrack::applyVolumeShaper( const sp& configuration, const sp& operation) { + const int64_t beginNs = systemTime(); AutoMutex lock(mLock); mVolumeHandler->setIdIfNecessary(configuration); media::VolumeShaperConfiguration config; @@ -3042,6 +3043,18 @@ VolumeShaper::Status AudioTrack::applyVolumeShaper( media::VolumeShaperOperation op; operation->writeToParcelable(&op); VolumeShaper::Status status; + + mediametrics::Defer defer([&] { + mediametrics::LogItem(mMetricsId) + .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_APPLYVOLUMESHAPER) + .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs)) + .set(AMEDIAMETRICS_PROP_STATE, stateToString(mState)) + .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status) + .set(AMEDIAMETRICS_PROP_TOSTRING, configuration->toString() + .append(" ") + .append(operation->toString())) + .record(); }); + mAudioTrack->applyVolumeShaper(config, op, &status); if (status == DEAD_OBJECT) { diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h index 26aa3755d9..e60a6784eb 100644 --- a/media/libmediametrics/include/MediaMetricsConstants.h +++ b/media/libmediametrics/include/MediaMetricsConstants.h @@ -213,6 +213,7 @@ // format to transport packets. // Raw byte streams are used if this // is false. +#define AMEDIAMETRICS_PROP_TOSTRING "toString" // string #define AMEDIAMETRICS_PROP_TOTALINPUTBYTES "totalInputBytes" // int32 (MIDI) #define AMEDIAMETRICS_PROP_TOTALOUTPUTBYTES "totalOutputBytes" // int32 (MIDI) #define AMEDIAMETRICS_PROP_THREADID "threadId" // int32 value io handle @@ -243,6 +244,7 @@ // Values are strings accepted for a given property. // An event is a general description, which often is a function name. +#define AMEDIAMETRICS_PROP_EVENT_VALUE_APPLYVOLUMESHAPER "applyVolumeShaper" #define AMEDIAMETRICS_PROP_EVENT_VALUE_BEGINAUDIOINTERVALGROUP "beginAudioIntervalGroup" #define AMEDIAMETRICS_PROP_EVENT_VALUE_CLOSE "close" #define AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE "create" From f478aa16824c0de2cb4cdac8387d2f9047b98191 Mon Sep 17 00:00:00 2001 From: Sungtak Lee Date: Thu, 6 Jun 2024 22:29:06 +0000 Subject: [PATCH 09/17] bufferpool@2.0: Ensure uniqueness of connection id Currently same connection id can be given to different connections if they don't belong to the same bufferpool. Ensure uniqueness of connection id for each connection. Bug: 323793249 Change-Id: I7ab772dedcb1d6cc4dff204b845ded206efabc73 --- media/module/bufferpool/2.0/AccessorImpl.cpp | 30 +++++++++++++++----- media/module/bufferpool/2.0/AccessorImpl.h | 9 +++++- media/module/bufferpool/2.0/Android.bp | 3 ++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/media/module/bufferpool/2.0/AccessorImpl.cpp b/media/module/bufferpool/2.0/AccessorImpl.cpp index 202d8030a7..b9483bfc19 100644 --- a/media/module/bufferpool/2.0/AccessorImpl.cpp +++ b/media/module/bufferpool/2.0/AccessorImpl.cpp @@ -17,6 +17,8 @@ #define LOG_TAG "BufferPoolAccessor2.0" //#define LOG_NDEBUG 0 +#include + #include #include #include @@ -147,7 +149,25 @@ static constexpr uint32_t kSeqIdVndkBit = 0; #endif static constexpr uint32_t kSeqIdMax = 0x7fffffff; -uint32_t Accessor::Impl::sSeqId = time(nullptr) & kSeqIdMax; + +Accessor::Impl::ConnectionIdGenerator::ConnectionIdGenerator() { + mSeqId = static_cast(time(nullptr) & kSeqIdMax); + mPid = static_cast(getpid()); +} + +ConnectionId Accessor::Impl::ConnectionIdGenerator::getConnectionId() { + uint32_t seq; + { + std::lock_guard l(mLock); + seq = mSeqId; + if (mSeqId == kSeqIdMax) { + mSeqId = 0; + } else { + ++mSeqId; + } + } + return (int64_t)mPid << 32 | seq | kSeqIdVndkBit; +} Accessor::Impl::Impl( const std::shared_ptr &allocator) @@ -163,13 +183,14 @@ ResultStatus Accessor::Impl::connect( uint32_t *pMsgId, const StatusDescriptor** statusDescPtr, const InvalidationDescriptor** invDescPtr) { + static ::android::base::NoDestructor sConIdGenerator; sp newConnection = new Connection(); ResultStatus status = ResultStatus::CRITICAL_ERROR; { std::lock_guard lock(mBufferPool.mMutex); if (newConnection) { int32_t pid = getpid(); - ConnectionId id = (int64_t)pid << 32 | sSeqId | kSeqIdVndkBit; + ConnectionId id = sConIdGenerator->getConnectionId(); status = mBufferPool.mObserver.open(id, statusDescPtr); if (status == ResultStatus::OK) { newConnection->initialize(accessor, id); @@ -179,11 +200,6 @@ ResultStatus Accessor::Impl::connect( mBufferPool.mConnectionIds.insert(id); mBufferPool.mInvalidationChannel.getDesc(invDescPtr); mBufferPool.mInvalidation.onConnect(id, observer); - if (sSeqId == kSeqIdMax) { - sSeqId = 0; - } else { - ++sSeqId; - } } } diff --git a/media/module/bufferpool/2.0/AccessorImpl.h b/media/module/bufferpool/2.0/AccessorImpl.h index 3d39941337..2366177135 100644 --- a/media/module/bufferpool/2.0/AccessorImpl.h +++ b/media/module/bufferpool/2.0/AccessorImpl.h @@ -77,7 +77,14 @@ class Accessor::Impl private: // ConnectionId = pid : (timestamp_created + seqId) // in order to guarantee uniqueness for each connection - static uint32_t sSeqId; + struct ConnectionIdGenerator { + int32_t mPid; + uint32_t mSeqId; + std::mutex mLock; + + ConnectionIdGenerator(); + ConnectionId getConnectionId(); + }; const std::shared_ptr mAllocator; diff --git a/media/module/bufferpool/2.0/Android.bp b/media/module/bufferpool/2.0/Android.bp index bdab103311..c40603c0e2 100644 --- a/media/module/bufferpool/2.0/Android.bp +++ b/media/module/bufferpool/2.0/Android.bp @@ -21,6 +21,9 @@ cc_defaults { export_include_dirs: [ "include", ], + header_libs: [ + "libbase_headers", + ], shared_libs: [ "libcutils", "libfmq", From 2720defd5349622115cadeda12a9e91121e89b95 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Tue, 11 Jun 2024 00:47:43 +0000 Subject: [PATCH 10/17] Add flag for MusicFx edge to edge enablement Flag: com.android.media.audio.music_fx_edge_to_edge Test: m com.android.media.audio-aconfig-java Bug: 336204940 Change-Id: If9428c1882994487428c606362c5dd52b08bfb68 --- media/audio/aconfig/audio.aconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/media/audio/aconfig/audio.aconfig b/media/audio/aconfig/audio.aconfig index 4c3e25a428..c3ae59c880 100644 --- a/media/audio/aconfig/audio.aconfig +++ b/media/audio/aconfig/audio.aconfig @@ -59,6 +59,13 @@ flag { bug: "307588546" } +flag { + name: "music_fx_edge_to_edge" + namespace: "media_audio" + description: "Enable Edge-to-edge feature for MusicFx and handle insets" + bug: "336204940" +} + flag { name: "port_to_piid_simplification" namespace: "media_audio" From 8daea2e138d27059f25e7d0471acce4bc35e7e65 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Tue, 11 Jun 2024 00:49:57 +0000 Subject: [PATCH 11/17] Camera: Update LowLightBoost Documentation If supported, low light boost state is expected to be present at all times in the capture results. Test: Successful build Bug: 346182281 Change-Id: I7fcd235ce57cc3c2eec469a2e41650c3f0e02c7a --- camera/ndk/include/camera/NdkCameraMetadataTags.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index 645a3d45f4..7129428c76 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -2287,12 +2287,11 @@ typedef enum acamera_metadata_tag { *

When low light boost is enabled by setting the AE mode to * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY', it can dynamically apply a low light * boost when the light level threshold is exceeded.

- *

This field is present in the CaptureResult when the AE mode is set to - * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY'. Otherwise, the field is not present.

*

This state indicates when low light boost is 'ACTIVE' and applied. Similarly, it can * indicate when it is not being applied by returning 'INACTIVE'.

*

This key will be absent from the CaptureResult if AE mode is not set to * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY.

+ *

The default value will always be 'INACTIVE'.

*/ ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE = // byte (acamera_metadata_enum_android_control_low_light_boost_state_t) ACAMERA_CONTROL_START + 59, @@ -8305,11 +8304,8 @@ typedef enum acamera_metadata_enum_acamera_control_ae_mode { *

If the session configuration is not supported, the AE mode reported in the * CaptureResult will be 'ON' instead of 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY'.

*

When this AE mode is enabled, the CaptureResult field - * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE will be present and not null. Otherwise, the - * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE field will not be present in the CaptureResult.

- *

The application can observe the CaptureResult field - * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE to determine when low light boost is 'ACTIVE' or - * 'INACTIVE'.

+ * ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE will indicate when low light boost is 'ACTIVE' + * or 'INACTIVE'. By default ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE will be 'INACTIVE'.

*

The low light boost is 'ACTIVE' once the scene lighting condition is less than the * upper bound lux value defined by ACAMERA_CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE. * This mode will be 'INACTIVE' once the scene lighting condition is greater than the From 892344af93a48ae8fe0461d2a9a245798e4018e6 Mon Sep 17 00:00:00 2001 From: Satish Yalla Date: Tue, 11 Jun 2024 01:36:45 +0000 Subject: [PATCH 12/17] Revert "Use the global default cpp_std." This reverts commit ad434d79398f6493a9d5e14d7f08703d14fe08c8. Reason for revert: Droidmonitor triggered revert due to build breakage in b/346434347. Will be verifying through ABTD before submission. Change-Id: I3fc1e2d82ad291b8aecfb6d1cc13b63200251edc --- media/codec2/components/avc/C2SoftAvcDec.h | 2 +- media/codec2/components/dav1d/C2SoftDav1dDec.h | 2 +- media/codec2/components/gav1/C2SoftGav1Dec.h | 2 +- media/codec2/components/hevc/C2SoftHevcDec.h | 2 +- media/codec2/components/mpeg2/C2SoftMpeg2Dec.h | 2 +- media/codec2/vndk/Android.bp | 1 + 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h index 6165455761..36a463e0e4 100644 --- a/media/codec2/components/avc/C2SoftAvcDec.h +++ b/media/codec2/components/avc/C2SoftAvcDec.h @@ -173,7 +173,7 @@ class C2SoftAvcDec : public SimpleC2Component { VuiColorAspects() : primaries(2), transfer(2), coeffs(2), fullRange(0) { } - bool operator==(const VuiColorAspects &o) const { + bool operator==(const VuiColorAspects &o) { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.h b/media/codec2/components/dav1d/C2SoftDav1dDec.h index c5c12149c2..6008325bf9 100644 --- a/media/codec2/components/dav1d/C2SoftDav1dDec.h +++ b/media/codec2/components/dav1d/C2SoftDav1dDec.h @@ -91,7 +91,7 @@ struct C2SoftDav1dDec : public SimpleC2Component { coeffs(C2Color::MATRIX_UNSPECIFIED), fullRange(C2Color::RANGE_UNSPECIFIED) {} - bool operator==(const VuiColorAspects& o) const { + bool operator==(const VuiColorAspects& o) { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h index e5d10e0f4c..0e09fccfd2 100644 --- a/media/codec2/components/gav1/C2SoftGav1Dec.h +++ b/media/codec2/components/gav1/C2SoftGav1Dec.h @@ -84,7 +84,7 @@ struct C2SoftGav1Dec : public SimpleC2Component { coeffs(C2Color::MATRIX_UNSPECIFIED), fullRange(C2Color::RANGE_UNSPECIFIED) { } - bool operator==(const VuiColorAspects &o) const { + bool operator==(const VuiColorAspects &o) { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h index ff6d3717c3..6abf69ed43 100644 --- a/media/codec2/components/hevc/C2SoftHevcDec.h +++ b/media/codec2/components/hevc/C2SoftHevcDec.h @@ -132,7 +132,7 @@ struct C2SoftHevcDec : public SimpleC2Component { VuiColorAspects() : primaries(2), transfer(2), coeffs(2), fullRange(0) { } - bool operator==(const VuiColorAspects &o) const { + bool operator==(const VuiColorAspects &o) { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h index a7bee90c98..3965bcc4fc 100644 --- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h +++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h @@ -172,7 +172,7 @@ struct C2SoftMpeg2Dec : public SimpleC2Component { VuiColorAspects() : primaries(2), transfer(2), coeffs(2), fullRange(0) { } - bool operator==(const VuiColorAspects &o) const { + bool operator==(const VuiColorAspects &o) { return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs && fullRange == o.fullRange; } diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp index 327c3fd3a4..dc06ee6400 100644 --- a/media/codec2/vndk/Android.bp +++ b/media/codec2/vndk/Android.bp @@ -180,6 +180,7 @@ cc_defaults { // public dependency for implementing Codec 2 components cc_defaults { name: "libcodec2-impl-defaults", + cpp_std: "gnu++17", defaults: [ "libcodec2_hal_selection", From 0532bad48cedebc32daad97659185f47f6afd72e Mon Sep 17 00:00:00 2001 From: Jan Sebechlebsky Date: Tue, 11 Jun 2024 10:52:01 +0200 Subject: [PATCH 13/17] Lock BLOB buffer for USAGE_CPU_WRITE_OFTEN Bug: 301023410 Test: atest virtual_camera_tests CtsVirtualDevicesCameraTestCases CtsVirtualDevicesCameraCtsTestCases Change-Id: I91056eb6a796c1169e31283e48375ae239176b8b --- services/camera/virtualcamera/VirtualCameraRenderThread.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc index ff09256b1a..ad2844359e 100644 --- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc +++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc @@ -750,7 +750,7 @@ ndk::ScopedAStatus VirtualCameraRenderThread::renderIntoBlobStreamBuffer( return status; } - PlanesLockGuard planesLock(hwBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, + PlanesLockGuard planesLock(hwBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, fence); if (planesLock.getStatus() != OK) { return cameraStatus(Status::INTERNAL_ERROR); From 07258629e38293b07e1b4314cf7988fc2f1b2b28 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Mon, 10 Jun 2024 16:56:41 +0000 Subject: [PATCH 14/17] Revert "Revert "Revert "Revert^2 "Audio policy: anonymize Bluetooth MAC ..."" Bug: 303552947 Bug: 285588444 Test: make This reverts commit 624967539ea7a6dfde618a3c9f828d6ac68251b4. Change-Id: I1a082f431e2abb9db73472707272cfedb50458cf --- .../AidlConversionCppNdk.cpp | 20 +--- .../audio_aidl_legacy_conversion_tests.cpp | 20 ---- media/utils/ServiceUtilities.cpp | 43 --------- .../include/mediautils/ServiceUtilities.h | 4 - .../service/AudioPolicyInterfaceImpl.cpp | 94 ++++--------------- 5 files changed, 21 insertions(+), 160 deletions(-) diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp index 77418ebab1..9eaddced8c 100644 --- a/media/audioaidlconversion/AidlConversionCppNdk.cpp +++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp @@ -1069,13 +1069,6 @@ ::android::status_t aidl2legacy_AudioDevice_audio_device( if (mac.size() != 6) return BAD_VALUE; snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - // special case for anonymized mac address: - // change anonymized bytes back from FD:FF:FF:FF to XX:XX:XX:XX - std::string address(addressBuffer); - if (address.compare(0, strlen("FD:FF:FF:FF"), "FD:FF:FF:FF") == 0) { - address.replace(0, strlen("FD:FF:FF:FF"), "XX:XX:XX:XX"); - } - strcpy(addressBuffer, address.c_str()); } break; case Tag::ipv4: { const std::vector& ipv4 = aidl.address.get(); @@ -1136,20 +1129,11 @@ legacy2aidl_audio_device_AudioDevice( if (!legacyAddress.empty()) { switch (suggestDeviceAddressTag(aidl.type)) { case Tag::mac: { - // special case for anonymized mac address: - // change anonymized bytes so that they can be scanned as HEX bytes - // Use '01' for LSB bits 0 and 1 as Bluetooth MAC addresses are never multicast - // and universaly administered - std::string address = legacyAddress; - if (address.compare(0, strlen("XX:XX:XX:XX"), "XX:XX:XX:XX") == 0) { - address.replace(0, strlen("XX:XX:XX:XX"), "FD:FF:FF:FF"); - } - std::vector mac(6); - int status = sscanf(address.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", + int status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); if (status != mac.size()) { - ALOGE("%s: malformed MAC address: \"%s\"", __func__, address.c_str()); + ALOGE("%s: malformed MAC address: \"%s\"", __func__, legacyAddress.c_str()); return unexpected(BAD_VALUE); } aidl.address = AudioDeviceAddress::make(std::move(mac)); diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp index 0be1d7e25c..7f55e48b21 100644 --- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp +++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp @@ -483,28 +483,8 @@ INSTANTIATE_TEST_SUITE_P( AudioDeviceAddress::make( std::vector{1, 2})))); -TEST(AnonymizedBluetoothAddressRoundTripTest, Legacy2Aidl2Legacy) { - const std::vector sAnonymizedAidlAddress = - std::vector{0xFD, 0xFF, 0xFF, 0xFF, 0xAB, 0xCD}; - const std::string sAnonymizedLegacyAddress = std::string("XX:XX:XX:XX:AB:CD"); - auto device = legacy2aidl_audio_device_AudioDevice(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, - sAnonymizedLegacyAddress); - ASSERT_TRUE(device.ok()); - ASSERT_EQ(AudioDeviceAddress::Tag::mac, device.value().address.getTag()); - ASSERT_EQ(sAnonymizedAidlAddress, device.value().address.get()); - - audio_devices_t legacyType; - std::string legacyAddress; - status_t status = - aidl2legacy_AudioDevice_audio_device(device.value(), &legacyType, &legacyAddress); - ASSERT_EQ(OK, status); - EXPECT_EQ(legacyType, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP); - EXPECT_EQ(sAnonymizedLegacyAddress, legacyAddress); -} - class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam { }; - TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) { const auto initial = GetParam(); auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial); diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp index 4b0192a22b..7bec8cf616 100644 --- a/media/utils/ServiceUtilities.cpp +++ b/media/utils/ServiceUtilities.cpp @@ -47,7 +47,6 @@ static const String16 sAndroidPermissionRecordAudio("android.permission.RECORD_A static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE"); static const String16 sModifyAudioRouting("android.permission.MODIFY_AUDIO_ROUTING"); static const String16 sCallAudioInterception("android.permission.CALL_AUDIO_INTERCEPTION"); -static const String16 sAndroidPermissionBluetoothConnect("android.permission.BLUETOOTH_CONNECT"); static String16 resolveCallingPackage(PermissionController& permissionController, const std::optional opPackageName, uid_t uid) { @@ -393,48 +392,6 @@ status_t checkIMemory(const sp& iMemory) return NO_ERROR; } -/** - * Determines if the MAC address in Bluetooth device descriptors returned by APIs of - * a native audio service (audio flinger, audio policy) must be anonymized. - * MAC addresses returned to system server or apps with BLUETOOTH_CONNECT permission - * are not anonymized. - * - * @param attributionSource The attribution source of the calling app. - * @param caller string identifying the caller for logging. - * @return true if the MAC addresses must be anonymized, false otherwise. - */ -bool mustAnonymizeBluetoothAddress( - const AttributionSourceState& attributionSource, const String16& caller) { - uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); - if (isAudioServerOrSystemServerUid(uid)) { - return false; - } - const std::optional resolvedAttributionSource = - resolveAttributionSource(attributionSource, DEVICE_ID_DEFAULT); - if (!resolvedAttributionSource.has_value()) { - return true; - } - permission::PermissionChecker permissionChecker; - return permissionChecker.checkPermissionForPreflightFromDatasource( - sAndroidPermissionBluetoothConnect, resolvedAttributionSource.value(), caller, - AppOpsManager::OP_BLUETOOTH_CONNECT) - != permission::PermissionChecker::PERMISSION_GRANTED; -} - -/** - * Modifies the passed MAC address string in place for consumption by unprivileged clients. - * the string is assumed to have a valid MAC address format. - * the anonymzation must be kept in sync with toAnonymizedAddress() in BluetoothUtils.java - * - * @param address input/output the char string contining the MAC address to anonymize. - */ -void anonymizeBluetoothAddress(char *address) { - if (address == nullptr || strlen(address) != strlen("AA:BB:CC:DD:EE:FF")) { - return; - } - memcpy(address, "XX:XX:XX:XX", strlen("XX:XX:XX:XX")); -} - sp MediaPackageManager::retrievePackageManager() { const sp sm = defaultServiceManager(); if (sm == nullptr) { diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h index 9c02cd41f5..e0fabfdb22 100644 --- a/media/utils/include/mediautils/ServiceUtilities.h +++ b/media/utils/include/mediautils/ServiceUtilities.h @@ -113,10 +113,6 @@ bool modifyPhoneStateAllowed(const AttributionSourceState& attributionSource); bool bypassInterruptionPolicyAllowed(const AttributionSourceState& attributionSource); bool callAudioInterceptionAllowed(const AttributionSourceState& attributionSource); void purgePermissionCache(); -bool mustAnonymizeBluetoothAddress( - const AttributionSourceState& attributionSource, const String16& caller); -void anonymizeBluetoothAddress(char *address); - int32_t getOpForSource(audio_source_t source); AttributionSourceState getCallingAttributionSource(); diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 8ba281426a..768cd07d15 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -1576,19 +1576,6 @@ Status AudioPolicyService::isDirectOutputSupported( return Status::ok(); } -template -void anonymizePortBluetoothAddress(Port *port) { - if (port->type != AUDIO_PORT_TYPE_DEVICE) { - return; - } - if (!(audio_is_a2dp_device(port->ext.device.type) - || audio_is_ble_device(port->ext.device.type) - || audio_is_bluetooth_sco_device(port->ext.device.type) - || audio_is_hearing_aid_out_device(port->ext.device.type))) { - return; - } - anonymizeBluetoothAddress(port->ext.device.address); -} Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl, media::AudioPortType typeAidl, Int* count, @@ -1607,27 +1594,14 @@ Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl, std::unique_ptr ports(new audio_port_v7[num_ports]); unsigned int generation; - const AttributionSourceState attributionSource = getCallingAttributionSource(); - AutoCallerClear acc; - { - audio_utils::lock_guard _l(mMutex); - if (mAudioPolicyManager == NULL) { - return binderStatusFromStatusT(NO_INIT); - } - // AudioPolicyManager->listAudioPorts makes a deep copy of port structs into ports - // so it is safe to access after releasing the mutex - RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( - mAudioPolicyManager->listAudioPorts( - role, type, &num_ports, ports.get(), &generation))); - numPortsReq = std::min(numPortsReq, num_ports); - } - - if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) { - for (size_t i = 0; i < numPortsReq; ++i) { - anonymizePortBluetoothAddress(&ports[i]); - } + audio_utils::lock_guard _l(mMutex); + if (mAudioPolicyManager == NULL) { + return binderStatusFromStatusT(NO_INIT); } - + AutoCallerClear acc; + RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( + mAudioPolicyManager->listAudioPorts(role, type, &num_ports, ports.get(), &generation))); + numPortsReq = std::min(numPortsReq, num_ports); RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( convertRange(ports.get(), ports.get() + numPortsReq, std::back_inserter(*portsAidl), legacy2aidl_audio_port_v7_AudioPortFw))); @@ -1650,24 +1624,12 @@ Status AudioPolicyService::listDeclaredDevicePorts(media::AudioPortRole role, Status AudioPolicyService::getAudioPort(int portId, media::AudioPortFw* _aidl_return) { audio_port_v7 port{ .id = portId }; - - const AttributionSourceState attributionSource = getCallingAttributionSource(); - AutoCallerClear acc; - - { - audio_utils::lock_guard _l(mMutex); - if (mAudioPolicyManager == NULL) { - return binderStatusFromStatusT(NO_INIT); - } - // AudioPolicyManager->getAudioPort makes a deep copy of the port struct into port - // so it is safe to access after releasing the mutex - RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port))); - } - - if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) { - anonymizePortBluetoothAddress(&port); + audio_utils::lock_guard _l(mMutex); + if (mAudioPolicyManager == NULL) { + return binderStatusFromStatusT(NO_INIT); } - + AutoCallerClear acc; + RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port))); *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_port_v7_AudioPortFw(port)); return Status::ok(); } @@ -1725,32 +1687,14 @@ Status AudioPolicyService::listAudioPatches(Int* count, std::unique_ptr patches(new audio_patch[num_patches]); unsigned int generation; - const AttributionSourceState attributionSource = getCallingAttributionSource(); - AutoCallerClear acc; - - { - audio_utils::lock_guard _l(mMutex); - if (mAudioPolicyManager == NULL) { - return binderStatusFromStatusT(NO_INIT); - } - // AudioPolicyManager->listAudioPatches makes a deep copy of patches structs into patches - // so it is safe to access after releasing the mutex - RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( - mAudioPolicyManager->listAudioPatches(&num_patches, patches.get(), &generation))); - numPatchesReq = std::min(numPatchesReq, num_patches); - } - - if (mustAnonymizeBluetoothAddress(attributionSource, String16(__func__))) { - for (size_t i = 0; i < numPatchesReq; ++i) { - for (size_t j = 0; j < patches[i].num_sources; ++j) { - anonymizePortBluetoothAddress(&patches[i].sources[j]); - } - for (size_t j = 0; j < patches[i].num_sinks; ++j) { - anonymizePortBluetoothAddress(&patches[i].sinks[j]); - } - } + audio_utils::lock_guard _l(mMutex); + if (mAudioPolicyManager == NULL) { + return binderStatusFromStatusT(NO_INIT); } - + AutoCallerClear acc; + RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( + mAudioPolicyManager->listAudioPatches(&num_patches, patches.get(), &generation))); + numPatchesReq = std::min(numPatchesReq, num_patches); RETURN_IF_BINDER_ERROR(binderStatusFromStatusT( convertRange(patches.get(), patches.get() + numPatchesReq, std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatchFw))); From 391001579a1b35f023731aec7e5e15d3c3320d4d Mon Sep 17 00:00:00 2001 From: Vadim Caen Date: Tue, 11 Jun 2024 15:24:15 +0200 Subject: [PATCH 15/17] Add sensor rotation option to the test camera Add a option to set the sensor rotation for the test camera Bug: N/A Test: Manulally, creating a test camera Change-Id: I931a54b492b519d016316ab0d09358b34e26fc11 --- .../virtualcamera/VirtualCameraService.cc | 29 +++++++++++++++++++ .../tests/VirtualCameraServiceTest.cc | 29 +++++++++++++++++++ .../camera/virtualcamera/util/MetadataUtil.cc | 14 +++++++++ .../camera/virtualcamera/util/MetadataUtil.h | 5 ++++ 4 files changed, 77 insertions(+) diff --git a/services/camera/virtualcamera/VirtualCameraService.cc b/services/camera/virtualcamera/VirtualCameraService.cc index 705af86ec0..7466089e89 100644 --- a/services/camera/virtualcamera/VirtualCameraService.cc +++ b/services/camera/virtualcamera/VirtualCameraService.cc @@ -76,6 +76,8 @@ Available commands: --camera_id=(ID) - override numerical ID for test camera instance --lens_facing=(front|back|external) - specifies lens facing for test camera instance --input_fps=(fps) - specify input fps for test camera, valid values are from 1 to 1000 + --sensor_orientation=(0|90|180|270) - Clockwise angle through which the output image + needs to be rotated to be upright on the device screen in its native orientation * disable_test_camera )"; constexpr char kCreateVirtualDevicePermission[] = @@ -439,6 +441,31 @@ binder_status_t VirtualCameraService::enableTestCameraCmd( } } + std::optional sensorOrientation; + std::optional sensorOrientationInt; + it = options.find("sensor_orientation"); + if (it != options.end()) { + sensorOrientationInt = parseInt(it->second); + switch (sensorOrientationInt.value_or(0)) { + case 0: + sensorOrientation = SensorOrientation::ORIENTATION_0; + break; + case 90: + sensorOrientation = SensorOrientation::ORIENTATION_90; + break; + case 180: + sensorOrientation = SensorOrientation::ORIENTATION_180; + break; + case 270: + sensorOrientation = SensorOrientation::ORIENTATION_270; + break; + default: + dprintf(err, "Invalid sensor rotation: %s\n, must be 0, 90, 180 or 270.", + it->second.c_str()); + return STATUS_BAD_VALUE; + } + } + sp token = sp::make(); mTestCameraToken.set(AIBinder_fromPlatformBinder(token)); @@ -449,6 +476,8 @@ binder_status_t VirtualCameraService::enableTestCameraCmd( Format::RGBA_8888, .maxFps = kMaxFps}); configuration.lensFacing = lensFacing.value_or(LensFacing::EXTERNAL); + configuration.sensorOrientation = + sensorOrientation.value_or(SensorOrientation::ORIENTATION_0); configuration.virtualCameraCallback = ndk::SharedRefBase::make( inputFps.value_or(kTestCameraDefaultInputFps)); diff --git a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc index 752d3908c4..719f64d53b 100644 --- a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc +++ b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "VirtualCameraService.h" @@ -191,6 +192,16 @@ class VirtualCameraServiceTest : public ::testing::Test { return getLensFacing(metadata); } + std::optional getCameraSensorOrienation(const std::string& id) { + std::shared_ptr camera = mCameraProvider->getCamera(id); + if (camera == nullptr) { + return std::nullopt; + } + CameraMetadata metadata; + camera->getCameraCharacteristics(&metadata); + return getSensorOrientation(metadata); + } + protected: std::shared_ptr mCameraService; std::shared_ptr mCameraProvider; @@ -506,6 +517,24 @@ TEST_F(VirtualCameraServiceTest, TestCameraShellCmdWithInvalidInputFps) { Eq(STATUS_BAD_VALUE)); } +TEST_F(VirtualCameraServiceTest, TestCameraShellCmdWithSensorOrientation90) { + EXPECT_THAT( + execute_shell_command("enable_test_camera --sensor_orientation=90"), + Eq(NO_ERROR)); + + std::vector cameraIds = getCameraIds(); + ASSERT_THAT(cameraIds, SizeIs(1)); + EXPECT_THAT(getCameraSensorOrienation(cameraIds[0]), Optional(Eq(90))); +} + +TEST_F(VirtualCameraServiceTest, TestCameraShellCmdWithSensorOrientationNoArgs) { + EXPECT_THAT(execute_shell_command("enable_test_camera"), Eq(NO_ERROR)); + + std::vector cameraIds = getCameraIds(); + ASSERT_THAT(cameraIds, SizeIs(1)); + EXPECT_THAT(getCameraSensorOrienation(cameraIds[0]), Optional(Eq(0))); +} + } // namespace } // namespace virtualcamera } // namespace companion diff --git a/services/camera/virtualcamera/util/MetadataUtil.cc b/services/camera/virtualcamera/util/MetadataUtil.cc index 31a8776bfe..4889830a64 100644 --- a/services/camera/virtualcamera/util/MetadataUtil.cc +++ b/services/camera/virtualcamera/util/MetadataUtil.cc @@ -961,6 +961,20 @@ std::optional getDeviceId( return static_cast(entry.data.i32[0]); } +std::optional getSensorOrientation( + const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata) { + auto metadata = + reinterpret_cast(cameraMetadata.metadata.data()); + + camera_metadata_ro_entry_t entry; + if (find_camera_metadata_ro_entry(metadata, ANDROID_SENSOR_ORIENTATION, + &entry) != OK) { + return std::nullopt; + } + + return static_cast(entry.data.i32[0]); +} + } // namespace virtualcamera } // namespace companion } // namespace android diff --git a/services/camera/virtualcamera/util/MetadataUtil.h b/services/camera/virtualcamera/util/MetadataUtil.h index ca6f332cdb..22d3657a4a 100644 --- a/services/camera/virtualcamera/util/MetadataUtil.h +++ b/services/camera/virtualcamera/util/MetadataUtil.h @@ -488,6 +488,11 @@ getPrecaptureTrigger( std::optional getDeviceId( const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata); +// Return the value of ANDROID_SENSOR_ORIENTATION or nullopt if the key is not +// present (which is equivalent to a orientation of 0). +std::optional getSensorOrientation( + const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata); + } // namespace virtualcamera } // namespace companion } // namespace android From ecf24859c9e07e9a313acb744754854fb35dd451 Mon Sep 17 00:00:00 2001 From: Vadim Caen Date: Tue, 11 Jun 2024 15:25:10 +0200 Subject: [PATCH 16/17] Simple code clarity changes Test: N/A Bug: N/A Change-Id: I2c11ef703856c158b48329dbef6485196cfc1d43 --- .../camera/virtualcamera/VirtualCameraRenderThread.cc | 4 ++-- .../camera/virtualcamera/VirtualCameraSessionContext.cc | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc index ff09256b1a..08b8e17abb 100644 --- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc +++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc @@ -833,8 +833,8 @@ ndk::ScopedAStatus VirtualCameraRenderThread::renderIntoEglFramebuffer( Rect viewportRect = viewport.value_or(Rect(framebuffer.getWidth(), framebuffer.getHeight())); - glViewport(viewportRect.leftTop().x, viewportRect.leftTop().y, - viewportRect.getWidth(), viewportRect.getHeight()); + glViewport(viewportRect.left, viewportRect.top, viewportRect.getWidth(), + viewportRect.getHeight()); sp textureBuffer = mEglSurfaceTexture->getCurrentBuffer(); if (textureBuffer == nullptr) { diff --git a/services/camera/virtualcamera/VirtualCameraSessionContext.cc b/services/camera/virtualcamera/VirtualCameraSessionContext.cc index 284ad05b23..aab2d0dc88 100644 --- a/services/camera/virtualcamera/VirtualCameraSessionContext.cc +++ b/services/camera/virtualcamera/VirtualCameraSessionContext.cc @@ -129,7 +129,8 @@ std::optional VirtualCameraSessionContext::getStreamConfig( streamId); return std::optional(); } - return {it->second->getStreamConfig()}; + VirtualCameraStream& stream = *it->second; + return {stream.getStreamConfig()}; } std::shared_ptr VirtualCameraSessionContext::fetchHardwareBuffer( @@ -141,7 +142,8 @@ std::shared_ptr VirtualCameraSessionContext::fetchHardwareBuffe streamId); return nullptr; } - return it->second->getHardwareBuffer(bufferId); + VirtualCameraStream& stream = *it->second; + return stream.getHardwareBuffer(bufferId); } std::shared_ptr @@ -154,7 +156,8 @@ VirtualCameraSessionContext::fetchOrCreateEglFramebuffer( streamId); return nullptr; } - return it->second->getEglFrameBuffer(eglDisplay, bufferId); + VirtualCameraStream& stream = *it->second; + return stream.getEglFrameBuffer(eglDisplay, bufferId); } std::set VirtualCameraSessionContext::getStreamIds() const { From 6742a969bc7e20f5e7c4e1dcf0edb8be9e4575e5 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Tue, 11 Jun 2024 01:08:36 +0000 Subject: [PATCH 17/17] Add flag for EffectChain callback mutex improvement aconfig flags: Flag: com.android.media.audio.effect_chain_callback_improve Test: m com.android.media.audio-aconfig-cc Bug: 342413767 Change-Id: I1559227d2073ac165b142ec95764390ddab3fb03 --- media/audio/aconfig/audioserver.aconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/media/audio/aconfig/audioserver.aconfig b/media/audio/aconfig/audioserver.aconfig index 94b60e2034..5e701688b6 100644 --- a/media/audio/aconfig/audioserver.aconfig +++ b/media/audio/aconfig/audioserver.aconfig @@ -14,6 +14,13 @@ flag { bug: "294525897" } +flag { + name: "effect_chain_callback_improve" + namespace: "media_audio" + description: "Improve effect chain callback mutex logic." + bug: "342413767" +} + flag { name: "fdtostring_timeout_fix" namespace: "media_audio"