From 4cdb851766ef1f68843e545d3e3c6d3ad5468a05 Mon Sep 17 00:00:00 2001 From: rmp22 <195054967+rmp22@users.noreply.github.com> Date: Thu, 6 Mar 2025 07:54:12 +0800 Subject: [PATCH 01/68] Effects: Do not allow ViperFx effect to be supsended Change-Id: I2438a0d511daeddd1cc076d61566f332137f10c1 Signed-off-by: rmp22 <195054967+rmp22@users.noreply.github.com> Signed-off-by: Pranav Vashi --- services/audioflinger/Effects.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index 4af8f06d9c0..fae1501e787 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -2976,6 +2976,11 @@ static const effect_uuid_t SL_IID_DAP_ = { 0x46d279d9, 0x9be7, 0x453d, 0x9d7c, { 0xef, 0x93, 0x7f, 0x67, 0x55, 0x87 } }; const effect_uuid_t * const SL_IID_DAP = &SL_IID_DAP_; +// ViperFx +static const effect_uuid_t SL_V4A_RE_ = // 90380da3-8536-4744-a6a3-5731970e640f +{ 0x90380da3, 0x8536, 0x4744, 0xa6a3, {0x57, 0x31, 0x97, 0x0e, 0x64, 0x0f} }; +const effect_uuid_t * const SL_V4A_RE = &SL_V4A_RE_; + /* static */ bool EffectChain::isEffectEligibleForBtNrecSuspend_l(const effect_uuid_t* type) { // Only NS and AEC are suspended when BtNRec is off @@ -2994,6 +2999,7 @@ bool EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc) (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) || (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0) || (memcmp(&desc.type, SL_IID_DAP, sizeof(effect_uuid_t)) == 0) || + (memcmp(&desc.type, SL_V4A_RE, sizeof(effect_uuid_t)) == 0) || (memcmp(&desc.type, SL_IID_DYNAMICSPROCESSING, sizeof(effect_uuid_t)) == 0))) { return false; } From f6932628a9a17df7fc2f6fc7cfcca24794d688bd Mon Sep 17 00:00:00 2001 From: Ghosuto Date: Sun, 4 May 2025 16:35:59 +0000 Subject: [PATCH 02/68] Effects: Do not allow SW dolby effect to be supsended Signed-off-by: Pranav Vashi --- services/audioflinger/Effects.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index fae1501e787..6d2abd46fdf 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -2976,6 +2976,11 @@ static const effect_uuid_t SL_IID_DAP_ = { 0x46d279d9, 0x9be7, 0x453d, 0x9d7c, { 0xef, 0x93, 0x7f, 0x67, 0x55, 0x87 } }; const effect_uuid_t * const SL_IID_DAP = &SL_IID_DAP_; +// Dolby Atmos SW +static const effect_uuid_t SL_IID_DAP_SW_ = // 9d4921da-8225-4f29-aefa-39537a04bcaa +{ 0x9d4921da, 0x8225, 0x4f29, 0xaefa, {0x39, 0x53, 0x7a, 0x04, 0xbc, 0xaa} }; +const effect_uuid_t * const SL_IID_DAP_SW = &SL_IID_DAP_SW_; + // ViperFx static const effect_uuid_t SL_V4A_RE_ = // 90380da3-8536-4744-a6a3-5731970e640f { 0x90380da3, 0x8536, 0x4744, 0xa6a3, {0x57, 0x31, 0x97, 0x0e, 0x64, 0x0f} }; @@ -2999,6 +3004,7 @@ bool EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc) (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) || (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0) || (memcmp(&desc.type, SL_IID_DAP, sizeof(effect_uuid_t)) == 0) || + (memcmp(&desc.type, SL_IID_DAP_SW, sizeof(effect_uuid_t)) == 0) || (memcmp(&desc.type, SL_V4A_RE, sizeof(effect_uuid_t)) == 0) || (memcmp(&desc.type, SL_IID_DYNAMICSPROCESSING, sizeof(effect_uuid_t)) == 0))) { return false; From 0ef14e5ab222ea4c4aaa52c0aaed3116adbd5c07 Mon Sep 17 00:00:00 2001 From: Arian Date: Mon, 30 Jan 2023 09:31:15 +0000 Subject: [PATCH 03/68] fixup! Camera: Skip stream size check for whitelisted apps Signed-off-by: Pranav Vashi --- .../camera/libcameraservice/utils/SessionConfigurationUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp index a989ab1c004..81c1089e22f 100644 --- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp +++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp @@ -514,7 +514,7 @@ binder::Status createConfiguredSurface( uint64_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK | GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_HW_COMPOSER; - bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 && + bool flexibleConsumer = !isPriviledgedClient && (consumerUsage & disallowedFlags) == 0 && (consumerUsage & allowedFlags) != 0; out_surface = new Surface(flagtools::surfaceTypeToIGBP(surface), useAsync); From 969d880e03ca3dac66ba274475ef43951a354492 Mon Sep 17 00:00:00 2001 From: Susmitha Gummalla Date: Tue, 29 Apr 2014 12:18:30 -0700 Subject: [PATCH 04/68] Camera: Add support for preview frame fd -Add support for receiving dataCallback with fd/buffer as frame buffer CRs-fixed: 654901 Change-Id: I5c16e560f1e209a6ab4afa4f3437602b02992b9b Signed-off-by: Pranav Vashi --- camera/ICameraClient.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp index bef2ea0acdd..f4212b7726e 100644 --- a/camera/ICameraClient.cpp +++ b/camera/ICameraClient.cpp @@ -51,7 +51,12 @@ class BpCameraClient: public BpInterface data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); data.writeInt32(msgType); data.writeInt32(ext1); - data.writeInt32(ext2); + if ((msgType == CAMERA_MSG_PREVIEW_FRAME) && (ext1 == CAMERA_FRAME_DATA_FD)) { + ALOGD("notifyCallback: CAMERA_MSG_PREVIEW_FRAME fd = %d", ext2); + data.writeFileDescriptor(ext2); + } else { + data.writeInt32(ext2); + } remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } @@ -129,8 +134,14 @@ status_t BnCameraClient::onTransact( ALOGV("NOTIFY_CALLBACK"); CHECK_INTERFACE(ICameraClient, data, reply); int32_t msgType = data.readInt32(); - int32_t ext1 = data.readInt32(); - int32_t ext2 = data.readInt32(); + int32_t ext1 = data.readInt32(); + int32_t ext2 = 0; + if ((msgType == CAMERA_MSG_PREVIEW_FRAME) && (ext1 == CAMERA_FRAME_DATA_FD)) { + ext2 = data.readFileDescriptor(); + ALOGD("onTransact: CAMERA_MSG_PREVIEW_FRAME fd = %d", ext2); + } else { + ext2 = data.readInt32(); + } notifyCallback(msgType, ext1, ext2); return NO_ERROR; } break; From 94457ff3918aaeaf0e2aa306e8d401e1ee7909e5 Mon Sep 17 00:00:00 2001 From: jhenrique09 Date: Tue, 24 Mar 2020 16:36:07 -0300 Subject: [PATCH 05/68] av: Remove restrictions for system audio record * Give freedom to screen recorder apps Change-Id: I726bde4f44bba6fc8cd771ae90c8864b26cdd919 Signed-off-by: Pranav Vashi --- .../libaaudio/src/utility/AAudioUtilities.cpp | 4 ++-- .../managerdefinitions/src/AudioPolicyMix.cpp | 24 ------------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp index 98e4ee21ca2..443d3a2b1fc 100644 --- a/media/libaaudio/src/utility/AAudioUtilities.cpp +++ b/media/libaaudio/src/utility/AAudioUtilities.cpp @@ -303,7 +303,7 @@ audio_flags_mask_t AAudio_computeAudioFlagsMask( bool isContentSpatialized, audio_output_flags_t outputFlags) { audio_flags_mask_t flagsMask = AUDIO_FLAG_NONE; - switch (policy) { + /*switch (policy) { case AAUDIO_UNSPECIFIED: case AAUDIO_ALLOW_CAPTURE_BY_ALL: // flagsMask is not modified @@ -318,7 +318,7 @@ audio_flags_mask_t AAudio_computeAudioFlagsMask( default: ALOGE("%s() 0x%08X unrecognized capture policy", __func__, policy); // flagsMask is not modified - } + }*/ switch (spatializationBehavior) { case AAUDIO_UNSPECIFIED: diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp index 3e9ef25e91f..5cf20baafb5 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp @@ -416,30 +416,6 @@ bool AudioPolicyMixCollection::mixMatch(const AudioMix* mix, size_t mixIndex, const audio_config_base_t& config, uid_t uid, audio_session_t session) { if (mix->mMixType == MIX_TYPE_PLAYERS) { - // Loopback render mixes are created from a public API and thus restricted - // to non sensible audio that have not opted out. - if (is_mix_loopback_render(mix->mRouteFlags)) { - if (!(attributes.usage == AUDIO_USAGE_UNKNOWN || - attributes.usage == AUDIO_USAGE_MEDIA || - attributes.usage == AUDIO_USAGE_GAME || - attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION)) { - return false; - } - auto hasFlag = [](auto flags, auto flag) { return (flags & flag) == flag; }; - if (hasFlag(attributes.flags, AUDIO_FLAG_NO_SYSTEM_CAPTURE)) { - return false; - } - - if (attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION) { - if (!mix->mVoiceCommunicationCaptureAllowed) { - return false; - } - } else if (!mix->mAllowPrivilegedMediaPlaybackCapture && - hasFlag(attributes.flags, AUDIO_FLAG_NO_MEDIA_PROJECTION)) { - return false; - } - } - // Permit match only if requested format and mix format are PCM and can be format // adapted by the mixer, or are the same format on direct output. if (!is_mix_loopback(mix->mRouteFlags) && From 111a8846b34028240fb87870c364a4e11a5eadbb Mon Sep 17 00:00:00 2001 From: Mounika Reddy Tangirala Date: Tue, 22 May 2018 17:41:52 +0530 Subject: [PATCH 06/68] CameraService: Fix deadlock in binder death cleanup In the event of a binder death, there is a chance of deadlock due to recursive lock acquisition in the death handling sequence. Fix: Clear evicted client list before acquiring service lock. Change-Id: I6fc5fa6e01c002bc46be058fcd977be14cae0270 Signed-off-by: Pranav Vashi --- services/camera/libcameraservice/CameraService.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 988803b6ea2..3a8b79fe79c 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -3870,7 +3870,8 @@ bool CameraService::evictClientIdByRemote(const wp& remote) { ret = true; } } - + //clear the evicted client list before acquring service lock again. + evicted.clear(); // Reacquire mServiceLock mServiceLock.lock(); From f9ca543d9e1564660a33d042fa540b6cda0bf93a Mon Sep 17 00:00:00 2001 From: Susmitha Gummalla Date: Tue, 27 Aug 2019 16:38:37 -0800 Subject: [PATCH 07/68] Camera: Flush Improvements - Result drain optimization -Avoid waiting on results once flush is completed -Help improve camera switch KPI CRs-Fixed: 2525025 Change-Id: I0db7877b6582c281a178035d4c202a5bd6aaaca8 Signed-off-by: Pranav Vashi --- .../camera/libcameraservice/device3/Camera3Device.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 86efe37f9ad..5b9e76bd331 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -3424,9 +3424,15 @@ status_t Camera3Device::RequestThread::clear( status_t Camera3Device::RequestThread::flush() { ATRACE_CALL(); + status_t flush_status; Mutex::Autolock l(mFlushLock); - return mInterface->flush(); + flush_status = mInterface->flush(); + // We have completed flush, signal RequestThread::waitForNextRequestLocked() to no longer wait for + // new requests + mRequestSignal.signal(); + + return flush_status; } void Camera3Device::RequestThread::setPaused(bool paused) { From cf90455ed22fbae9269d53c28dc1666df36e2e35 Mon Sep 17 00:00:00 2001 From: Venugopal Nadipalli Date: Tue, 26 Jul 2022 12:05:31 +0530 Subject: [PATCH 08/68] Camera: Removing cachedump call to miminimize delay during close. - The cacheDump() call was added for better debugging by always dumping the state of the last camera session. Since LT/VT chipsets it is adding significant delay during camera close. Hence we are removing cachedump call during disconnect. https://partnerissuetracker.corp.google.com/issues/237992867 CRs-Fixed: 3228616 Change-Id: Ibba2a51f08c592bf15b046642101e11d890ed248 Signed-off-by: Pranav Vashi --- .../camera/libcameraservice/common/Camera2ClientBase.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp index 5766b5584aa..3c75d45c76d 100644 --- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp +++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp @@ -290,14 +290,6 @@ binder::Status Camera2ClientBase::disconnectImpl() { ALOGD("Camera %s: Shutting down", TClientBase::mCameraIdStr.c_str()); - // Before detaching the device, cache the info from current open session. - // The disconnected check avoids duplication of info and also prevents - // deadlock while acquiring service lock in cacheDump. - if (!TClientBase::mDisconnected) { - ALOGV("Camera %s: start to cacheDump", TClientBase::mCameraIdStr.c_str()); - Camera2ClientBase::getCameraService()->cacheDump(TClientBase::mCameraIdStr); - } - detachDevice(); CameraService::BasicClient::disconnect(); From 55e8541453b6717053f2cfdde148090129e7e6c0 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Wed, 1 May 2013 02:58:11 -0700 Subject: [PATCH 09/68] camera: Don't segfault if we get a NULL parameter * Values end up NULL on some drivers, don't crash. Change-Id: Ic897dbd4629cf3af98c85f93be202c382dde806b Signed-off-by: Pranav Vashi --- camera/CameraParameters.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp index cd58d019293..afc9ddeb537 100644 --- a/camera/CameraParameters.cpp +++ b/camera/CameraParameters.cpp @@ -238,6 +238,9 @@ void CameraParameters::unflatten(const String8 ¶ms) void CameraParameters::set(const char *key, const char *value) { + if (key == NULL || value == NULL) + return; + // XXX i think i can do this with strspn() if (strchr(key, '=') || strchr(key, ';')) { //XXX ALOGE("Key \"%s\"contains invalid character (= or ;)", key); From 56b70315bd7ae5b33f13930c9e384e38e7f307ec Mon Sep 17 00:00:00 2001 From: Paras Nagda Date: Fri, 4 May 2018 16:13:15 +0530 Subject: [PATCH 10/68] stagefright: add changes related to high-framerates in CameraSource Below changes are squashed with this change. Stagefright: Allow setting high-framerates in CameraSource ChangeId: If66211dd81b2a08d4df4c6f23e87304e9e7013f4 Stagefright: Allow setting of high-framerates in CameraSource for HSR ChangeId: I30cb3b656570de1b615d55c20c0b4f98ae6e0c12 Stagefright: Create CameraSource for HSR ChangeId: I7f420f5b15fb3c05bb7f918430ca9b7a630ed18e Stagefright: Do not skip frames in time-lapse-source for high-speed ChangeId: I8420e44ab96484f0d6301c366a24eefc8efeaf0f media : Changing time stamp manipulation in HFR recording. ChangeId: I98cdb14bb2b9c86013df9b2c8f2e558f184b633e media: Modify timestamps for HFR use case ChangeId: I3faf7294f743b1031ccc6624c3348f7e12b339b8 CRs-Fixed: 2226740 Change-Id: I079d880252992b94bd78ac43aed732f5000175d3 Signed-off-by: Pranav Vashi --- .../libmediaplayerservice/StagefrightRecorder.cpp | 3 ++- media/libstagefright/CameraSource.cpp | 14 +++++++++++++- media/libstagefright/CameraSourceTimeLapse.cpp | 9 ++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 2aba3261e79..12472c402b4 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -1941,7 +1941,7 @@ status_t StagefrightRecorder::setupCameraSource( pid_t pid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(mAttributionSource.pid)); String16 clientName = VALUE_OR_RETURN_STATUS( aidl2legacy_string_view_String16(mAttributionSource.packageName.value_or(""))); - if (mCaptureFpsEnable) { + if (mCaptureFpsEnable && mCaptureFps != mFrameRate) { if (!(mCaptureFps > 0.)) { ALOGE("Invalid mCaptureFps value: %lf", mCaptureFps); return BAD_VALUE; @@ -2111,6 +2111,7 @@ status_t StagefrightRecorder::setupVideoEncoder( preferBFrames = false; tsLayers = 2; // use at least two layers as resulting video will likely be sped up } else if (mCaptureFps > maxPlaybackFps) { // slow-mo + format->setInt32("high-frame-rate", 1); maxPlaybackFps = mCaptureFps; // assume video will be played back at full capture speed preferBFrames = false; } diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index f0ef6e5d640..012a05414cb 100644 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -254,6 +254,12 @@ status_t CameraSource::isCameraColorFormatSupported( return OK; } +static int32_t getHighSpeedFrameRate(const CameraParameters& params) { + const char* hsr = params.get("video-hsr"); + int32_t rate = (hsr != NULL && strncmp(hsr, "off", 3)) ? strtol(hsr, NULL, 10) : 0; + return std::min(rate, 240); +} + /* * Configure the camera to use the requested video size * (width and height) and/or frame rate. If both width and @@ -301,11 +307,15 @@ status_t CameraSource::configureCamera( } if (frameRate != -1) { - CHECK(frameRate > 0 && frameRate <= 120); + CHECK(frameRate > 0 && frameRate <= 240); const char* supportedFrameRates = params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES); CHECK(supportedFrameRates != NULL); ALOGV("Supported frame rates: %s", supportedFrameRates); + if (getHighSpeedFrameRate(*params)) { + ALOGI("Use default 30fps for HighSpeed %dfps", frameRate); + frameRate = 30; + } char buf[4]; snprintf(buf, 4, "%d", frameRate); if (strstr(supportedFrameRates, buf) == NULL) { @@ -407,6 +417,8 @@ status_t CameraSource::checkFrameRate( ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual); return UNKNOWN_ERROR; } + int32_t highSpeedRate = getHighSpeedFrameRate(params); + frameRateActual = highSpeedRate ? highSpeedRate : frameRateActual; // Check the actual video frame rate against the target/requested // video frame rate. diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp index b1a005b59dc..4b03371ca51 100644 --- a/media/libstagefright/CameraSourceTimeLapse.cpp +++ b/media/libstagefright/CameraSourceTimeLapse.cpp @@ -277,7 +277,8 @@ bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) { // The first 2 output frames from the encoder are: decoder specific info and // the compressed video frame data for the first input video frame. if (mNumFramesEncoded >= 1 && *timestampUs < - (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs)) { + (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs) && + (mTimeBetweenFrameCaptureUs > mTimeBetweenTimeLapseVideoFramesUs + 1)) { // Skip all frames from last encoded frame until // sufficient time (mTimeBetweenFrameCaptureUs) has passed. // Tell the camera to release its recording frame and return. @@ -292,6 +293,12 @@ bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) { mLastTimeLapseFrameRealTimestampUs = *timestampUs; *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs; + // Update start-time once the captured-time reaches the expected start-time. + // Not doing so will result in CameraSource always dropping frames since + // updated-timestamp will never intersect start-timestamp + if ((mNumFramesReceived == 0 && mLastTimeLapseFrameRealTimestampUs >= mStartTimeUs)) { + mStartTimeUs = *timestampUs; + } return false; } return false; From d6eff73cd7055116b72e3bc727ae8df941fccc92 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Sun, 3 Jan 2016 14:09:23 -0800 Subject: [PATCH 11/68] libstagefright: Support YVU420SemiPlanar camera format Change-Id: I631ba6267b3769d9da498329a39ac89c609be6d8 Signed-off-by: Pranav Vashi --- media/libstagefright/CameraSource.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index 012a05414cb..ddcce6cc794 100644 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -84,6 +84,10 @@ static int32_t getColorFormat(const char* colorFormat) { return OMX_COLOR_FormatAndroidOpaque; } + if (!strcmp(colorFormat, "YVU420SemiPlanar")) { + return OMX_QCOM_COLOR_FormatYVU420SemiPlanar; + } + ALOGE("Uknown color format (%s), please add it to " "CameraSource::getColorFormat", colorFormat); From 5b36b24c815248c144b5964b1ff76e7d9232a060 Mon Sep 17 00:00:00 2001 From: cjh1249131356 Date: Sun, 9 Oct 2022 14:45:25 +0800 Subject: [PATCH 12/68] StagefrightRecorder: Add "set-title" parameter * Required by OnePlus / Oplus Camera. * Unused by others. Signed-off-by: cjh1249131356 Signed-off-by: Pranav Vashi --- media/libmediaplayerservice/StagefrightRecorder.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 12472c402b4..48281c0e708 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -1127,6 +1127,8 @@ status_t StagefrightRecorder::setParameter( } } else if (key == "log-session-id") { return setLogSessionId(value); + } else if (key == "set-title") { + return OK; } else { ALOGE("setParameter: failed to find key %s", key.c_str()); } From 95d20e3532cf3d0a8c1cf82414965540ebbb28fb Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Tue, 15 Dec 2015 05:44:18 -0500 Subject: [PATCH 13/68] nuplayer: Avoid crash when codec fails to load * Remove unnecessary check condition. Change-Id: Ia5055195f1a74cdba96ad0b7598da321c25fe27c Signed-off-by: Pranav Vashi --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 65de591bf09..dcd79a9d1fd 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -2410,9 +2410,6 @@ void NuPlayer::performDecoderFlush(FlushCommand audio, FlushCommand video) { void NuPlayer::performReset() { ALOGV("performReset"); - CHECK(mAudioDecoder == NULL); - CHECK(mVideoDecoder == NULL); - updatePlaybackTimer(true /* stopping */, "performReset"); updateRebufferingTimer(true /* stopping */, true /* exiting */); From 05d89b104ed6cfb6b146ca78dc9a9b0fa5a52888 Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Thu, 2 Jun 2022 18:23:53 +0530 Subject: [PATCH 14/68] av: Initial support for 24bit encoding and 6 channels * From CAF. Change-Id: I32bb7470c2abede313d6392dede4873270d720cc Signed-off-by: Pranav Vashi --- media/libmediaplayerservice/StagefrightRecorder.cpp | 2 +- media/libstagefright/ACodec.cpp | 7 +++++++ media/libstagefright/AudioSource.cpp | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 48281c0e708..eb4d05d5415 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -555,7 +555,7 @@ status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) { status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { ALOGV("setParamAudioNumberOfChannels: %d", channels); - if (channels <= 0 || channels >= 3) { + if (channels <= 0 || channels > 6) { ALOGE("Invalid number of audio channels: %d", channels); return BAD_VALUE; } diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 282212343f3..c3146545c72 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -3353,6 +3353,10 @@ status_t ACodec::setupRawAudioFormat( pcmParams.eNumData = OMX_NumericalDataSigned; pcmParams.nBitPerSample = 16; break; + case kAudioEncodingPcm24bitPacked: + pcmParams.eNumData = OMX_NumericalDataSigned; + pcmParams.nBitPerSample = 24; + break; default: return BAD_VALUE; } @@ -5462,6 +5466,9 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp ¬ify) { } else if (params.eNumData == OMX_NumericalDataFloat && params.nBitPerSample == 32u) { encoding = kAudioEncodingPcmFloat; + } else if (params.eNumData == OMX_NumericalDataSigned + && params.nBitPerSample == 24u) { + encoding = kAudioEncodingPcm24bitPacked; } else if (params.nBitPerSample != 16u || params.eNumData != OMX_NumericalDataSigned) { ALOGE("unsupported PCM port: %s(%d), %s(%d) mode ", diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index f658d846c4e..1e9c040ee3d 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -93,7 +93,7 @@ void AudioSource::set( mNoMoreFramesToRead = false; ALOGV("sampleRate: %u, outSampleRate: %u, channelCount: %u", sampleRate, outSampleRate, channelCount); - CHECK(channelCount == 1 || channelCount == 2); + CHECK(channelCount == 1 || channelCount == 2 || channelCount == 6); CHECK(sampleRate > 0); size_t minFrameCount; From 80ee8f514382d2804539c09a713b9a33df1bbab9 Mon Sep 17 00:00:00 2001 From: johnmart19 Date: Tue, 30 May 2023 21:41:31 +0300 Subject: [PATCH 15/68] frameworks/av: Import Xiaomi Image Tags defenitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Hưng Phan Signed-off-by: Pranav Vashi --- .../include/img_utils/TagDefinitions.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/media/img_utils/include/img_utils/TagDefinitions.h b/media/img_utils/include/img_utils/TagDefinitions.h index 1cc98669cb8..4f481f4e940 100644 --- a/media/img_utils/include/img_utils/TagDefinitions.h +++ b/media/img_utils/include/img_utils/TagDefinitions.h @@ -181,6 +181,8 @@ enum { TAG_EXPOSURETIME = 0x829Au, TAG_ISOSPEEDRATINGS = 0x8827u, TAG_FOCALLENGTH = 0x920Au, + TAG_FOCALLLENGTHIN35MMFILM = 0xA405u, + TAG_XIAOMI_PRODUCT = 0x9A00u, TAG_FNUMBER = 0x829Du, TAG_GPSINFO = 0x8825u, TAG_GPSVERSIONID = 0x0u, @@ -280,6 +282,14 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = { 0, UNDEFINED_ENDIAN }, + { // FocalLengthIn35mmFilm + "FocalLengthIn35mmFilm", + 0xA405u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, { // FNumber "FNumber", 0x829Du, @@ -1396,6 +1406,14 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = { 1, UNDEFINED_ENDIAN }, + { // Product + "Product", + 0x9A00u, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, }; } /*namespace img_utils*/ From 1a0bdc94681ff8ad239d169945981d13c0525308 Mon Sep 17 00:00:00 2001 From: Paul Keith Date: Fri, 6 May 2022 10:41:52 +0530 Subject: [PATCH 16/68] libstagefright: omx: Add support for loading prebuilt ddp and ac4 decoder lib [HELLBOY017]: Also allow to load dolby codec in MediaCodecList Change-Id: I3b85c15889c9e3aef152e726a83936234103254e --- media/libstagefright/MediaCodecList.cpp | 1 + media/libstagefright/omx/SoftOMXPlugin.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp index daad2c648c1..447dc23b235 100644 --- a/media/libstagefright/MediaCodecList.cpp +++ b/media/libstagefright/MediaCodecList.cpp @@ -363,6 +363,7 @@ const sp MediaCodecList::getGlobalSettings() const { //static bool MediaCodecList::isSoftwareCodec(const AString &componentName) { return componentName.startsWithIgnoreCase("OMX.google.") + || componentName.startsWithIgnoreCase("OMX.dolby.") || componentName.startsWithIgnoreCase("c2.android.") || (!componentName.startsWithIgnoreCase("OMX.") && !componentName.startsWithIgnoreCase("c2.")); diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp index 8c186c90f8b..25b36cb7b66 100644 --- a/media/libstagefright/omx/SoftOMXPlugin.cpp +++ b/media/libstagefright/omx/SoftOMXPlugin.cpp @@ -61,6 +61,10 @@ static const struct { { "OMX.google.flac.decoder", "flacdec", "audio_decoder.flac" }, { "OMX.google.flac.encoder", "flacenc", "audio_encoder.flac" }, { "OMX.google.gsm.decoder", "gsmdec", "audio_decoder.gsm" }, + { "OMX.dolby.ac3.decoder", "ddpdec", "audio_decoder.ac3" }, + { "OMX.dolby.eac3-joc.decoder", "ddpdec", "audio_decoder.eac3_joc" }, + { "OMX.dolby.eac3.decoder", "ddpdec", "audio_decoder.eac3" }, + { "OMX.dolby.ac4.decoder", "ac4dec", "audio_decoder.ac4" }, }; static const size_t kNumComponents = From cda1373ea5c8be33f7c91d6cbcfa01e6bb334307 Mon Sep 17 00:00:00 2001 From: Adithya R Date: Tue, 26 Sep 2023 21:29:52 +0530 Subject: [PATCH 17/68] OMX: Remove support for prebuilt ac4 decoder Requires proprietary Dolby changes in libstagefright. This partially reverts commit 01090fa125c2993654e18e024ddf7cef87bca30e. Change-Id: Ifdf36ad253155e77ba14d0624612bf6be6711ca6 --- media/libstagefright/omx/SoftOMXPlugin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp index 25b36cb7b66..6258ee08d73 100644 --- a/media/libstagefright/omx/SoftOMXPlugin.cpp +++ b/media/libstagefright/omx/SoftOMXPlugin.cpp @@ -64,7 +64,6 @@ static const struct { { "OMX.dolby.ac3.decoder", "ddpdec", "audio_decoder.ac3" }, { "OMX.dolby.eac3-joc.decoder", "ddpdec", "audio_decoder.eac3_joc" }, { "OMX.dolby.eac3.decoder", "ddpdec", "audio_decoder.eac3" }, - { "OMX.dolby.ac4.decoder", "ac4dec", "audio_decoder.ac4" }, }; static const size_t kNumComponents = From fb822ffcc47c9fbbfb366b1cfb6494727f01cbf9 Mon Sep 17 00:00:00 2001 From: johnmart19 Date: Sat, 24 Dec 2022 16:34:00 +0200 Subject: [PATCH 18/68] media: OMXStore: Import loading libstagefrightdolby - Imported from Xiaomi Android 13 Changes Change-Id: Ia7da9da19bfa10c64a82eb68eef3857a78e12469 --- media/libstagefright/omx/OMXStore.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/media/libstagefright/omx/OMXStore.cpp b/media/libstagefright/omx/OMXStore.cpp index b2d5a70ffa9..0f9a7ec3d09 100644 --- a/media/libstagefright/omx/OMXStore.cpp +++ b/media/libstagefright/omx/OMXStore.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "OMXStore" #include #include +#include #include #include @@ -63,6 +64,21 @@ OMXStore::~OMXStore() { void OMXStore::addVendorPlugin() { addPlugin("libstagefrighthw.so"); + + // MIUI ADD: DOLBY_ENABLE + // NOTE: We do not use FeatureManager::isFeatureEnable here because we can not add shared lib + // libmediautils to this module due to this module is vendor_avaiable and vndk is set as true + // but libmediautils is not. + bool isDolbyEnable = property_get_bool("ro.vendor.audio.dolby.dax.support", false); + if (isDolbyEnable) { + // !IMPORTANT: + // Dolby OMX plugin manages all the Dolby codec components. Customer needs to manage Dolby + // codec components in its own OMX plugin (e.g. above libstagefrighthw.so) then removes + // all Dolby's modifications in this file to pass Goolge VTS. + ALOGD("%s(): Loading Dolby OMX plugin...", __FUNCTION__); + addPlugin("libstagefrightdolby.so"); + } + // MIUI END } void OMXStore::addPlatformPlugin() { From 3ecb19b77ac9efa028f2a0e0c8663878592b0263 Mon Sep 17 00:00:00 2001 From: Uma Mehta Date: Tue, 8 May 2018 18:41:23 +0530 Subject: [PATCH 19/68] media: Add changes to pick target specific media xml's Add changes to pick the right media xml's from vendor/etc of the target based on target specific system property CRs-Fixed: 2083569 [neobuddy89: Squashed similar commits] Change-Id: I18d89821e765e8cd1b6003f99bc21dcd87a1458c Signed-off-by: tejas101k --- media/libmedia/MediaProfiles.cpp | 42 ++++++++++++ media/libstagefright/xmlparser/Android.bp | 7 ++ .../xmlparser/MediaCodecsXmlParser.cpp | 65 +++++++++++++++++-- 3 files changed, 109 insertions(+), 5 deletions(-) diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index 04388067c39..d4a8714e846 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -973,6 +973,7 @@ void MediaProfiles::checkAndAddRequiredProfilesIfNecessary() { /*static*/ MediaProfiles* MediaProfiles::getInstance() { + char platform[PROPERTY_VALUE_MAX] = {0}; ALOGV("getInstance"); Mutex::Autolock lock(sLock); if (!sIsInitialized) { @@ -993,6 +994,47 @@ MediaProfiles::getInstance() sInstance = createInstanceFromXmlFile(xmlFile); } } else { + if (!strncmp(value, "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/vendor/etc", strlen("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/vendor/etc"))) { + property_get("ro.board.platform", platform, NULL); + if (!strcmp(platform, "msm8953")){ + if (property_get("vendor.media.target.version", value, "0") && + (atoi(value) == 1)){ + strlcpy(value, "/vendor/etc/media_profiles_8953_v1.xml", + PROPERTY_VALUE_MAX); + } else { + strlcpy(value, "/vendor/etc/media_profiles_vendor.xml", + PROPERTY_VALUE_MAX); + } + } else if (!strcmp(platform, "sdm660")) { + property_get("vendor.media.target.version", value, "0"); + if (atoi(value) == 1) { + strlcpy(value, "/vendor/etc/media_profiles_sdm660_v1.xml", + PROPERTY_VALUE_MAX); + } else { + strlcpy(value, "/vendor/etc/media_profiles_vendor.xml", + PROPERTY_VALUE_MAX); + } + } else if (!strcmp(platform, "bengal")) { + property_get("vendor.sys.media.target.version", value, "0"); + if (atoi(value) == 3) { + strlcpy(value, "/vendor/etc/media_profiles_khaje.xml", + PROPERTY_VALUE_MAX); + } else if (atoi(value) == 2) { + strlcpy(value, "/vendor/etc/media_profiles_scuba.xml", + PROPERTY_VALUE_MAX); + } else { + strlcpy(value, "/vendor/etc/media_profiles_vendor.xml", + PROPERTY_VALUE_MAX); + } + } + char variant[PROPERTY_VALUE_MAX]; + if (property_get("ro.media.xml_variant.codecs", variant, NULL) > 0) { + std::string xmlPath = std::string("/vendor/etc/media_profiles") + + std::string(variant) + std::string(".xml"); + strlcpy(value, xmlPath.c_str(), PROPERTY_VALUE_MAX); + ALOGI("Profiles xml path: %s", value); + } + } sInstance = createInstanceFromXmlFile(value); } CHECK(sInstance != NULL); diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp index 2c5e81a8191..c1fca4f4350 100644 --- a/media/libstagefright/xmlparser/Android.bp +++ b/media/libstagefright/xmlparser/Android.bp @@ -31,8 +31,15 @@ cc_library_shared { "libexpat", "liblog", "libstagefright_omx_utils", + "libcutils" ], + target: { + vendor: { + cflags: ["-D__ANDROID_VNDK__"], + }, + }, + cflags: [ "-Werror", "-Wall", diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp index ae7147c1612..0281427b481 100644 --- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp +++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp @@ -14,7 +14,8 @@ * limitations under the License. */ -//#define LOG_NDEBUG 0 +#define LOG_NDEBUG 0 +#define PROP_VALUE_MAX 92 #define LOG_TAG "MediaCodecsXmlParser" #include @@ -42,6 +43,7 @@ #include #include #include +#include namespace android { @@ -123,6 +125,57 @@ status_t combineStatus(status_t a, status_t b) { } } +std::string getVendorXmlPath(const std::string &path) { + std::string vendorPath; + std::string result = path; + + if (!strncmp(path.c_str(), "/vendor/etc/media_codecs.xml", + strlen("/vendor/etc/media_codecs.xml"))) { + vendorPath = "/vendor/etc/media_codecs_vendor"; + } else if (!strncmp(path.c_str(), "/vendor/etc/media_codecs_performance.xml", + strlen("/vendor/etc/media_codecs_performance.xml"))) { + vendorPath = "/vendor/etc/media_codecs_performance"; + } + + if (!vendorPath.empty()) { + if (fileExists(vendorPath + std::string(".xml"))) { + char version[PROP_VALUE_MAX] = {0}; + result = vendorPath + std::string(".xml"); +#ifdef __ANDROID_VNDK__ + property_get("vendor.media.target.version", version, "0"); +#else + property_get("vendor.sys.media.target.version", version, "0"); +#endif + if (atoi(version) > 0) { + std::string versionedXml = vendorPath + std::string("_v") + + std::string(version) + std::string(".xml"); + if(fileExists(versionedXml)) { + result = versionedXml; + } + } + } + ALOGI("getVendorXmlPath (%s)", result.c_str()); + } + + // Choose different xmls based on system (if needed) + if (!android::base::GetProperty("ro.media.xml_variant.codecs", "").empty()){ + const std::vector &xmlFiles = MediaCodecsXmlParser::getDefaultXmlNames(); + for (const std::string &xmlName : xmlFiles) { + vendorPath = "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/vendor/etc/" + xmlName; + if (!strncmp(path.c_str(), vendorPath.c_str(), vendorPath.size())) { + vendorPath = vendorPath.substr(0,vendorPath.size()-4) + "_vendor.xml"; + if (fileExists(vendorPath)) { + result = vendorPath; + } + ALOGI("getVendorXmlPath %s", result.c_str()); + break; + } + } + } + + return result; +} + MediaCodecsXmlParser::StringSet parseCommaSeparatedStringSet(const char *s) { MediaCodecsXmlParser::StringSet result; for (const char *ptr = s ? : ""; *ptr; ) { @@ -448,20 +501,22 @@ status_t MediaCodecsXmlParser::Impl::parseXmlFilesInSearchDirs( status_t MediaCodecsXmlParser::Impl::parseXmlPath(const std::string &path) { std::lock_guard guard(mLock); - if (!fileExists(path)) { - ALOGV("Cannot find %s", path.c_str()); + std::string vendorPath = getVendorXmlPath(path); + + if (!fileExists(vendorPath)) { + ALOGV("Cannot find %s", vendorPath.c_str()); mParsingStatus = combineStatus(mParsingStatus, NAME_NOT_FOUND); return NAME_NOT_FOUND; } // save state (even though we should always be at toplevel here) State::RestorePoint rp = mState.createRestorePoint(); - Parser parser(&mState, path); + Parser parser(&mState, vendorPath); parser.parseXmlFile(); mState.restore(rp); if (parser.getStatus() != OK) { - ALOGD("parseXmlPath(%s) failed with %s", path.c_str(), asString(parser.getStatus())); + ALOGD("parseXmlPath(%s) failed with %s", vendorPath.c_str(), asString(parser.getStatus())); } mParsingStatus = combineStatus(mParsingStatus, parser.getStatus()); return parser.getStatus(); From 325389e78bad50fd11ffcbc1356768f5ea23c3fc Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Sat, 1 Apr 2023 19:50:59 +0530 Subject: [PATCH 20/68] MediaProfiles: Check before overriding media settings xml * Some devices copy init.qti.media.rc or such qcom scripts which makes MediaProfiles to select platform specific xml without checking if that xml is present. * Issue highlighted by [Electimon] Change-Id: If1e27a77298fea75a4f1c22e49fa078b1b14c1d7 Signed-off-by: Pranav Vashi Signed-off-by: tejas101k --- media/libmedia/MediaProfiles.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index d4a8714e846..1246fb32a32 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -998,7 +998,8 @@ MediaProfiles::getInstance() property_get("ro.board.platform", platform, NULL); if (!strcmp(platform, "msm8953")){ if (property_get("vendor.media.target.version", value, "0") && - (atoi(value) == 1)){ + (atoi(value) == 1) && + checkXmlFile("/vendor/etc/media_profiles_8953_v1.xml")){ strlcpy(value, "/vendor/etc/media_profiles_8953_v1.xml", PROPERTY_VALUE_MAX); } else { @@ -1007,7 +1008,8 @@ MediaProfiles::getInstance() } } else if (!strcmp(platform, "sdm660")) { property_get("vendor.media.target.version", value, "0"); - if (atoi(value) == 1) { + if (atoi(value) == 1 && + checkXmlFile("/vendor/etc/media_profiles_sdm660_v1.xml")) { strlcpy(value, "/vendor/etc/media_profiles_sdm660_v1.xml", PROPERTY_VALUE_MAX); } else { @@ -1016,10 +1018,12 @@ MediaProfiles::getInstance() } } else if (!strcmp(platform, "bengal")) { property_get("vendor.sys.media.target.version", value, "0"); - if (atoi(value) == 3) { + if (atoi(value) == 3 && + checkXmlFile("/vendor/etc/media_profiles_khaje.xml")) { strlcpy(value, "/vendor/etc/media_profiles_khaje.xml", PROPERTY_VALUE_MAX); - } else if (atoi(value) == 2) { + } else if (atoi(value) == 2 && + checkXmlFile("/vendor/etc/media_profiles_scuba.xml")) { strlcpy(value, "/vendor/etc/media_profiles_scuba.xml", PROPERTY_VALUE_MAX); } else { @@ -1031,8 +1035,10 @@ MediaProfiles::getInstance() if (property_get("ro.media.xml_variant.codecs", variant, NULL) > 0) { std::string xmlPath = std::string("/vendor/etc/media_profiles") + std::string(variant) + std::string(".xml"); - strlcpy(value, xmlPath.c_str(), PROPERTY_VALUE_MAX); - ALOGI("Profiles xml path: %s", value); + if (checkXmlFile(xmlPath.c_str())) { + strlcpy(value, xmlPath.c_str(), PROPERTY_VALUE_MAX); + ALOGI("Profiles xml path: %s", value); + } } } sInstance = createInstanceFromXmlFile(value); From 6c5d53a6305f06458983a0ba5444833bc290f41c Mon Sep 17 00:00:00 2001 From: yifeng Cao Date: Wed, 4 Jun 2025 05:07:51 -0700 Subject: [PATCH 21/68] MediaHTTP: resolve mName race condition issue b/422390714 HTTPBase::toString will get mName MediaHTTP::disconnect will do nName assignment different thread do HTTPBase::toString and MediaHTTP::disconnect() may cause mName's race condition issue, and occur mediaserver NE. Google: 3652570 Change-Id: I05b1adc4d2bf212e1a7159627117257f56f72841 --- media/libdatasource/MediaHTTP.cpp | 11 ++++++++++- media/libdatasource/include/datasource/MediaHTTP.h | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/media/libdatasource/MediaHTTP.cpp b/media/libdatasource/MediaHTTP.cpp index b1f214096fb..99c34e6a0f3 100644 --- a/media/libdatasource/MediaHTTP.cpp +++ b/media/libdatasource/MediaHTTP.cpp @@ -68,6 +68,7 @@ status_t MediaHTTP::connect( if (success) { AString sanitized = uriDebugString(mLastURI); + Mutex::Autolock autoLock(mLock); mName = String8::format("MediaHTTP(%s)", sanitized.c_str()); } @@ -79,7 +80,10 @@ void MediaHTTP::close() { } void MediaHTTP::disconnect() { - mName = String8("MediaHTTP()"); + { + Mutex::Autolock autoLock(mLock); + mName = String8("MediaHTTP()"); + } if (mInitCheck != OK) { return; } @@ -87,6 +91,11 @@ void MediaHTTP::disconnect() { mHTTPConnection->disconnect(); } +String8 MediaHTTP::toString() { + Mutex::Autolock autoLock(mLock); + return mName; +} + status_t MediaHTTP::initCheck() const { return mInitCheck; } diff --git a/media/libdatasource/include/datasource/MediaHTTP.h b/media/libdatasource/include/datasource/MediaHTTP.h index a8d203b2454..2591905e3b1 100644 --- a/media/libdatasource/include/datasource/MediaHTTP.h +++ b/media/libdatasource/include/datasource/MediaHTTP.h @@ -38,6 +38,8 @@ struct MediaHTTP : public HTTPBase { virtual void disconnect(); + virtual String8 toString(); + virtual status_t initCheck() const; virtual ssize_t readAt(off64_t offset, void *data, size_t size); @@ -65,6 +67,8 @@ struct MediaHTTP : public HTTPBase { bool mCachedSizeValid; off64_t mCachedSize; + Mutex mLock; + DISALLOW_EVIL_CONSTRUCTORS(MediaHTTP); }; From f332fc5350498913128ef4344defede9ff192987 Mon Sep 17 00:00:00 2001 From: fengxiaoshuang Date: Tue, 22 Apr 2025 14:12:16 +0800 Subject: [PATCH 22/68] issue: After connecting the Bluetooth earphones and projecting the screen, music will play from the earphones. At this point, disconnect the earphones, click play, and the projection will be silent Analysis: The screen projection device is remote_stubmix, and the output: deepubuffer does not support this device. If the Bluetooth earphones in the testing steps are replaced with wired earphones, restoreTrack_1 will be called after disconnecting the earphones because hasCurrentEncodedFFormat returns true. When the Bluetooth earphones are disconnected, the mCurrentEncodedFFormat is set to AUDIO-FORMAT-DEFAULT in setDeviceConnectionStateInt, so the return value of hasCurrentEncodedFFormat remains false Solution: Add a true judgment when Bluetooth earphones are disconnected in hasCurrentEncodedFFormat issue ID: 405883200 Google: 3598871 Change-Id: I1e3237109cf5f59137e44ccafc706dc50894742c Signed-off-by: fengxiaoshuang --- .../common/managerdefinitions/include/DeviceDescriptor.h | 5 +++++ .../common/managerdefinitions/src/DeviceDescriptor.cpp | 4 ++++ services/audiopolicy/managerdefault/AudioPolicyManager.cpp | 2 ++ 3 files changed, 11 insertions(+) diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h index 9e4a735894e..c1c57f3a2df 100644 --- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h @@ -58,6 +58,10 @@ class DeviceDescriptor : public DeviceDescriptorBase, mCurrentEncodedFormat = format; } + void setDeviceConnectState(bool connected){ + mIsConnected = connected; + } + bool equals(const sp& other) const; bool hasCurrentEncodedFormat() const; @@ -107,6 +111,7 @@ class DeviceDescriptor : public DeviceDescriptorBase, } std::string mTagName; // Unique human readable identifier for a device port found in conf file. + bool mIsConnected = false; audio_format_t mCurrentEncodedFormat; bool mIsDynamic = false; std::string mDeclaredAddress; // Original device address diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp index 9523c73abf8..cac0bd43f06 100644 --- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp @@ -106,6 +106,10 @@ bool DeviceDescriptor::hasCurrentEncodedFormat() const if (mEncodedFormats.empty()) { return true; } + if(device_has_encoding_capability(type()) && !mIsConnected) { + ALOGD("%s: mIsConnected is false", __func__); + return true; + } return (mCurrentEncodedFormat != AUDIO_FORMAT_DEFAULT); } diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index abf76554703..bf303e0ce69 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -271,6 +271,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const spsetEncapsulationInfoFromHal(mpClientInterface); + device->setDeviceConnectState(true); // outputs should never be empty here ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():" @@ -303,6 +304,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const spsetEncodedFormat(AUDIO_FORMAT_DEFAULT); + device->setDeviceConnectState(false); // remove device from mReportedFormatsMap cache mReportedFormatsMap.erase(device); From 009a143810306fdcfdbe0ee55d134fd5e2d36c09 Mon Sep 17 00:00:00 2001 From: rmp22 <195054967+rmp22@users.noreply.github.com> Date: Sun, 5 Oct 2025 14:27:37 +0800 Subject: [PATCH 23/68] skip mediametrics when statsd is not available Change-Id: I23a25f11eab0126d0dab3c200af8934de734d54b Signed-off-by: rmp22 <195054967+rmp22@users.noreply.github.com> Signed-off-by: Pranav Vashi --- services/mediametrics/statsd_codec.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp index 256ce8b9f33..bcc2a828ae3 100644 --- a/services/mediametrics/statsd_codec.cpp +++ b/services/mediametrics/statsd_codec.cpp @@ -180,7 +180,8 @@ static void parseVector(const std::string &str, std::vector *vector) { bool statsd_codec(const std::shared_ptr& item, const std::shared_ptr& statsdLog) { - if (item == nullptr) return false; + bool statsd_enabled = false; + if (item == nullptr || !statsd_enabled) return false; AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, stats::media_metrics::MEDIA_CODEC_REPORTED); From 50afbb72abe8593cf289fad5db9c1676cec1240f Mon Sep 17 00:00:00 2001 From: cjh1249131356 Date: Fri, 22 Jul 2022 22:55:18 +0800 Subject: [PATCH 24/68] libcameraservice: Add support to set vendor tag with client package name * OEMs like OnePlus and Nothing detect camera package name to unlock features like 48mp. [PA Edit: Make this generic by defining the package name rather than the OEM] Change-Id: Ic0b537820ef1874647911379bcf142f0768a7a76 Co-Authored-By: Jake Weinstein Co-Authored-By: Pranav Vashi Signed-off-by: cjh1249131356 Signed-off-by: Pranav Vashi --- services/camera/libcameraservice/Android.bp | 5 ++++- .../camera/libcameraservice/CameraService.cpp | 9 ++++++++ .../camera/libcameraservice/CameraService.h | 2 ++ .../device3/Camera3Device.cpp | 21 +++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index f9cbc0e6d8b..9e6ab8a26a5 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -241,7 +241,10 @@ cc_library { "-Wextra", "-Werror", "-Wno-ignored-qualifiers", - ], + ] + select(soong_config_variable("camera", "package_name"), { + any @ flag_val: ["-DTARGET_CAMERA_PACKAGE_NAME=" + flag_val], + default: [], + }), } cc_library_static { diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 3a8b79fe79c..c64621270b2 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -186,6 +186,9 @@ constexpr int32_t kInvalidDeviceId = -1; // Set to keep track of logged service error events. static std::set sServiceErrorEventSet; +// Current camera package name +static std::string sCurrPackageName; + CameraService::CameraService( std::shared_ptr cameraServiceProxyWrapper, std::shared_ptr attributionAndPermissionUtils) : @@ -1520,6 +1523,10 @@ Status CameraService::filterGetInfoErrorCode(status_t err) { } } +std::string CameraService::getCurrPackageName() { + return sCurrPackageName; +} + Status CameraService::makeClient( const sp& cameraService, const sp& cameraCb, const AttributionSourceState& clientAttribution, int callingPid, bool systemNativeClient, @@ -2542,6 +2549,8 @@ Status CameraService::connectHelper(const sp& cameraCb, const std::str const std::string clientPackageName = clientAttribution.packageName.value_or(kUnknownPackageName); + sCurrPackageName = clientPackageName; + { // Acquire mServiceLock and prevent other clients from connecting std::unique_ptr lock = diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index e2d2e5437d5..fe64b7ce65c 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -345,6 +345,8 @@ class CameraService : */ bool isAutomotiveExteriorSystemCamera(const std::string& cameraId) const; + static std::string getCurrPackageName(); + ///////////////////////////////////////////////////////////////////// // CameraClient functionality diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 5b9e76bd331..565963920e9 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -2492,6 +2492,27 @@ status_t Camera3Device::configureStreamsLocked(int operatingMode, return BAD_VALUE; } +#ifdef CAMERA_PACKAGE_NAME + sp vTags; + sp vCache = VendorTagDescriptorCache::getGlobalVendorTagCache(); + if (vCache.get()) { + const camera_metadata_t *metaBuffer = sessionParams.getAndLock(); + metadata_vendor_id_t vendorId = get_camera_metadata_vendor_id(metaBuffer); + sessionParams.unlock(metaBuffer); + vCache->getVendorTagDescriptor(vendorId, &vTags); + uint32_t tag; + if (CameraMetadata::getTagFromName(CAMERA_PACKAGE_NAME, vTags.get(), &tag)) { + ALOGE("%s: Unable to get %s tag", __FUNCTION__, CAMERA_PACKAGE_NAME); + } else { + std::string pkgName = CameraService::getCurrPackageName(); + status_t res = const_cast(sessionParams).update(tag, String8(pkgName.c_str())); + if (res) { + ALOGE("%s: metadata update failed, res = %d", __FUNCTION__, res); + } + } + } +#endif + bool isConstrainedHighSpeed = CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE == operatingMode; From 76c842668a72001607f3bcd4624dfcebbdde1b92 Mon Sep 17 00:00:00 2001 From: Terminator-J Date: Mon, 2 Jun 2025 08:59:46 -0700 Subject: [PATCH 25/68] libcameraservice: Fixup! Add support to set vendor tag with client package name Match prior cc_defaults implementation: * Fix libcameraservice cflags to use correct #ifdef variable (vital, fixes issues) * Add cflags to cameraserver as before (probably not needed but it seems to be working this way & doesn't impact those not using this config) * Add escaped double quotes for passing variable name to match previous behavior * Whitespace cleanup (always!) --- camera/cameraserver/Android.bp | 8 +++++++- services/camera/libcameraservice/Android.bp | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp index d0df90b8334..5636aac7435 100644 --- a/camera/cameraserver/Android.bp +++ b/camera/cameraserver/Android.bp @@ -53,16 +53,22 @@ cc_binary { "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.4", ], + static_libs: [ "libcameraservice", ], + compile_multilib: "first", + cflags: [ "-Wall", "-Wextra", "-Werror", "-Wno-unused-parameter", - ], + ] + select(soong_config_variable("camera", "package_name"), { + any @ flag_val: ["-DCAMERA_PACKAGE_NAME=\"" + flag_val + "\""], + default: [], + }), init_rc: ["cameraserver.rc"], diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index 9e6ab8a26a5..f3777e9d76f 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -242,7 +242,7 @@ cc_library { "-Werror", "-Wno-ignored-qualifiers", ] + select(soong_config_variable("camera", "package_name"), { - any @ flag_val: ["-DTARGET_CAMERA_PACKAGE_NAME=" + flag_val], + any @ flag_val: ["-DCAMERA_PACKAGE_NAME=\"" + flag_val + "\""], default: [], }), } From 17c02c75e00d06c6d142a0a3cf5cab99d29525a4 Mon Sep 17 00:00:00 2001 From: Hikari-no-Tenshi Date: Tue, 9 Nov 2021 19:49:41 +0200 Subject: [PATCH 26/68] libcameraservice: add TARGET_CAMERA_NEEDS_CLIENT_INFO_LIB Directly set camera package name by using OnePlusCameraProvider service. Co-authored-by: Pranav Vashi Signed-off-by: Pranav Vashi --- services/camera/libcameraservice/Android.bp | 8 +++++++ .../camera/libcameraservice/CameraService.cpp | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index f3777e9d76f..19d5fd621a2 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -244,6 +244,14 @@ cc_library { ] + select(soong_config_variable("camera", "package_name"), { any @ flag_val: ["-DCAMERA_PACKAGE_NAME=\"" + flag_val + "\""], default: [], + }) + select(soong_config_variable("camera", "needs_client_info_lib"), { + true: ["-DTARGET_CAMERA_NEEDS_CLIENT_INFO_LIB"], + false: [], + default: [], + }) + select(soong_config_variable("camera", "needs_client_info_lib_oplus"), { + true: ["-DTARGET_CAMERA_NEEDS_CLIENT_INFO_LIB_OPLUS"], + false: [], + default: [], }), } diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index c64621270b2..85578ccddf5 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -90,6 +90,14 @@ #include "utils/TagMonitor.h" #include "utils/Utils.h" +#ifdef CAMERA_NEEDS_CLIENT_INFO_LIB +#include +#endif + +#ifdef CAMERA_NEEDS_CLIENT_INFO_LIB_OPLUS +#include +#endif + namespace { const char* kActivityServiceName = "activity"; const char* kSensorPrivacyServiceName = "sensor_privacy"; @@ -138,6 +146,12 @@ using hardware::camera2::ICameraInjectionCallback; using hardware::camera2::ICameraInjectionSession; using hardware::camera2::utils::CameraIdAndSessionConfiguration; using hardware::camera2::utils::ConcurrentCameraIdCombination; +#ifdef CAMERA_NEEDS_CLIENT_INFO_LIB +using ::vendor::oneplus::hardware::camera::V1_0::IOnePlusCameraProvider; +#endif +#ifdef CAMERA_NEEDS_CLIENT_INFO_LIB_OPLUS +using ::vendor::oplus::hardware::cameraMDM::V2_0::IOPlusCameraMDM; +#endif namespace flags = com::android::internal::camera::flags; namespace vd_flags = android::companion::virtualdevice::flags; @@ -173,6 +187,12 @@ static const std::string &sCameraInjectExternalCameraPermission = // Constant integer for FGS Logging, used to denote the API type for logger static const int LOG_FGS_CAMERA_API = 1; const char *sFileName = "lastOpenSessionDumpFile"; +#ifdef CAMERA_NEEDS_CLIENT_INFO_LIB +static const sp gVendorCameraProviderService = IOnePlusCameraProvider::getService(); +#endif +#ifdef CAMERA_NEEDS_CLIENT_INFO_LIB_OPLUS +static const sp gVendorCameraProviderService = IOPlusCameraMDM::getService(); +#endif static constexpr int32_t kSystemNativeClientScore = resource_policy::PERCEPTIBLE_APP_ADJ; static constexpr int32_t kSystemNativeClientState = ActivityManager::PROCESS_STATE_PERSISTENT_UI; @@ -4480,6 +4500,10 @@ status_t CameraService::BasicClient::notifyCameraOpening() { sCameraService->updateOpenCloseStatus(mCameraIdStr, true /*open*/, getPackageName(), mSharedMode); +#if defined (CAMERA_NEEDS_CLIENT_INFO_LIB) || defined (CAMERA_NEEDS_CLIENT_INFO_LIB_OPLUS) + gVendorCameraProviderService->setPackageName(getPackageName().c_str()); +#endif + return OK; } From 29f0a178abd74468aa907859e80124bd31192182 Mon Sep 17 00:00:00 2001 From: Terminator-J Date: Mon, 2 Jun 2025 09:17:09 -0700 Subject: [PATCH 27/68] libcameraservice: Fixup! add TARGET_CAMERA_NEEDS_CLIENT_INFO_LIB Match prior cc_defaults implementation: * Fix libcameraservice cflags to use correct #ifdef variable (vital, fixes issues) * Add shared libs to both cameraserver & libcameraservice as before (probably not needed for cameraserver but it doesn't seem to hurt & won't affect those not using this config) --- camera/cameraserver/Android.bp | 10 +++++++++- services/camera/libcameraservice/Android.bp | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp index 5636aac7435..d6b7b159a1f 100644 --- a/camera/cameraserver/Android.bp +++ b/camera/cameraserver/Android.bp @@ -52,7 +52,15 @@ cc_binary { "android.hardware.camera.device@1.0", "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.4", - ], + ] + select(soong_config_variable("camera", "needs_client_info_lib"), { + true: ["//hardware/oneplus:vendor.oneplus.hardware.camera@1.0"], + false: [], + default: [], + }) + select(soong_config_variable("camera", "needs_client_info_lib_oplus"), { + true: ["vendor.oplus.hardware.cameraMDM@2.0"], + false: [], + default: [], + }), static_libs: [ "libcameraservice", diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index 19d5fd621a2..b38e505e3d4 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -219,6 +219,17 @@ cc_library { "libmediametrics_headers", ], + shared_libs: [ + ] + select(soong_config_variable("camera", "needs_client_info_lib"), { + true: ["//hardware/oneplus:vendor.oneplus.hardware.camera@1.0"], + false: [], + default: [], + }) + select(soong_config_variable("camera", "needs_client_info_lib_oplus"), { + true: ["vendor.oplus.hardware.cameraMDM@2.0"], + false: [], + default: [], + }), + export_shared_lib_headers: [ "libbinder", "libactivitymanager_aidl", @@ -245,11 +256,11 @@ cc_library { any @ flag_val: ["-DCAMERA_PACKAGE_NAME=\"" + flag_val + "\""], default: [], }) + select(soong_config_variable("camera", "needs_client_info_lib"), { - true: ["-DTARGET_CAMERA_NEEDS_CLIENT_INFO_LIB"], + true: ["-DCAMERA_NEEDS_CLIENT_INFO_LIB"], false: [], default: [], }) + select(soong_config_variable("camera", "needs_client_info_lib_oplus"), { - true: ["-DTARGET_CAMERA_NEEDS_CLIENT_INFO_LIB_OPLUS"], + true: ["-DCAMERA_NEEDS_CLIENT_INFO_LIB_OPLUS"], false: [], default: [], }), From 0b0ac66d6780ef51d99473fa4c244b4c301e1c1b Mon Sep 17 00:00:00 2001 From: John Galt Date: Wed, 6 Aug 2025 12:02:37 -0400 Subject: [PATCH 28/68] libcameraservice: support disabling torch control support On some devices such as OnePlus 12, newer blobs have a strange crash which is entirely proprietary stacktraced with torch control support, and Oplus stock disables in platform. We previously had a hack to manually implement it in an extension, but this device was also the only one that had other issues with it. Additionally, >2.3 aidl isn't expected to lack this support. So this hack simply always uses the same strength (legacy path), and does not use torch control. Signed-off-by: Pranav Vashi --- services/camera/libcameraservice/Android.bp | 4 ++++ services/camera/libcameraservice/CameraService.cpp | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index b38e505e3d4..82c5164e053 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -263,6 +263,10 @@ cc_library { true: ["-DCAMERA_NEEDS_CLIENT_INFO_LIB_OPLUS"], false: [], default: [], + }) + select(soong_config_variable("camera", "disable_torch_control"), { + true: ["-DDISABLE_TORCH_CONTROL"], + false: [], + default: [], }), } diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 85578ccddf5..71df74ac5dd 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -3040,11 +3040,15 @@ Status CameraService::turnOnTorchWithStrengthLevel(const std::string& unresolved Mutex::Autolock al(mTorchUidMapMutex); updateTorchUidMapLocked(cameraId, uid); } +#ifdef DISABLE_TORCH_CONTROL + bool shouldSkipTorchStrengthUpdates = false; + status_t err = mFlashlight->setTorchMode(cameraId, (torchStrength > 0) ? 1 : 0); +#else // Check if the current torch strength level is same as the new one. bool shouldSkipTorchStrengthUpdates = mCameraProviderManager->shouldSkipTorchStrengthUpdate( cameraId, torchStrength); - status_t err = mFlashlight->turnOnTorchWithStrengthLevel(cameraId, torchStrength); +#endif if (err != OK) { int32_t errorCode; From f0f0d28e5c93d0211f42a714a6c631b0c052f6a8 Mon Sep 17 00:00:00 2001 From: xialei6 Date: Thu, 21 Aug 2025 11:22:29 +0800 Subject: [PATCH 29/68] updatePolicyState after updating all EffectHandle state. Maybe updatePolicyState after updating all EffectHandle state makes more sense than before Change-Id: I9ed3e25eede842000c56865af3193711d8485980 Signed-off-by: xialei6 --- services/audioflinger/Effects.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index 6d2abd46fdf..e7ff0a8356a 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -171,6 +171,9 @@ status_t EffectBase::setEnabled(bool enabled, bool fromHandle) getCallback()->onEffectDisable(this); } } + if (status != NO_ERROR) { + status = updatePolicyState(); + } return status; } @@ -1913,12 +1916,6 @@ Status EffectHandle::enable(int32_t* _aidl_return) mEnabled = true; - status_t status = effect->updatePolicyState(); - if (status != NO_ERROR) { - mEnabled = false; - RETURN(status); - } - effect->checkSuspendOnEffectEnabled(true, false /*threadLocked*/); // checkSuspendOnEffectEnabled() can suspend this same effect when enabled @@ -1926,7 +1923,7 @@ Status EffectHandle::enable(int32_t* _aidl_return) RETURN(NO_ERROR); } - status = effect->setEnabled(true, true /*fromHandle*/); + status_t status = effect->setEnabled(true, true /*fromHandle*/); if (status != NO_ERROR) { mEnabled = false; } @@ -1950,8 +1947,6 @@ Status EffectHandle::disable(int32_t* _aidl_return) } mEnabled = false; - effect->updatePolicyState(); - if (effect->suspended()) { RETURN(NO_ERROR); } From a50528b204215bb5aad9ad7e1542e7810ee4fd00 Mon Sep 17 00:00:00 2001 From: Dhina17 Date: Sun, 26 May 2024 15:29:14 +0530 Subject: [PATCH 30/68] camera: Add extension to control torch light strength Some devices are capable of doing this but not their camera HAL. Squashed: From: Hridaya Prajapati Date: Mon, 28 Apr 2025 10:32:05 +0545 Subject: services: Move libcameraservice_ext_lib_defaults to select() Change-Id: I9c961215d0cffefa0c3507f6c097fa41e88177cf Change-Id: Ib154aa4a1e6137a6b8ecab9245905f72b951db16 Signed-off-by: Pranav Vashi --- services/camera/libcameraservice/Android.bp | 17 +++++++ .../common/CameraProviderExtension.cpp | 41 +++++++++++++++++ .../common/CameraProviderExtension.h | 23 ++++++++++ .../common/CameraProviderManager.cpp | 46 +++++++++++++++++-- 4 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 services/camera/libcameraservice/common/CameraProviderExtension.cpp create mode 100644 services/camera/libcameraservice/common/CameraProviderExtension.h diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index 82c5164e053..5062e4c6731 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -141,6 +141,7 @@ cc_library { "common/Camera2ClientBase.cpp", "common/CameraDeviceBase.cpp", "common/CameraOfflineSessionBase.cpp", + "common/CameraProviderExtension.cpp", "common/CameraProviderManager.cpp", "common/FrameProcessorBase.cpp", "common/hidl/HidlProviderInfo.cpp", @@ -267,6 +268,14 @@ cc_library { true: ["-DDISABLE_TORCH_CONTROL"], false: [], default: [], + }) + select(soong_config_variable("camera", "ext_lib"), { + any @ flag_val: ["-DTARGET_PROVIDES_CAMERA_PROVIDER_EXT_LIB"], + default: [], + }), + + whole_static_libs: select(soong_config_variable("libcameraservice", "ext_lib"), { + any @ flag_val: [flag_val], + default: ["libcameraservice_ext_lib"], }), } @@ -331,3 +340,11 @@ cc_library_static { "-Wno-ignored-qualifiers", ], } + +cc_library_static { + name: "libcameraservice_ext_lib", + srcs: [ + "common/CameraProviderExtension.cpp", + ], + export_include_dirs: ["."], +} diff --git a/services/camera/libcameraservice/common/CameraProviderExtension.cpp b/services/camera/libcameraservice/common/CameraProviderExtension.cpp new file mode 100644 index 00000000000..fe7b9f31607 --- /dev/null +++ b/services/camera/libcameraservice/common/CameraProviderExtension.cpp @@ -0,0 +1,41 @@ +/* + * Copyright 2024 The LibreMobileOS Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TARGET_PROVIDES_CAMERA_PROVIDER_EXT_LIB + +#include "common/CameraProviderExtension.h" + +bool supportsTorchStrengthControlExt() { + return false; +} + +int32_t getTorchDefaultStrengthLevelExt() { + return 0; +} + +int32_t getTorchMaxStrengthLevelExt() { + return 0; +} + +int32_t getTorchStrengthLevelExt() { + return 0; +} + +void setTorchStrengthLevelExt(__unused int32_t torchStrength) { + // Nothing +} + +#endif diff --git a/services/camera/libcameraservice/common/CameraProviderExtension.h b/services/camera/libcameraservice/common/CameraProviderExtension.h new file mode 100644 index 00000000000..ae17a2fc00f --- /dev/null +++ b/services/camera/libcameraservice/common/CameraProviderExtension.h @@ -0,0 +1,23 @@ +/* + * Copyright 2024 The LibreMobileOS Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +extern bool supportsTorchStrengthControlExt(); +extern int32_t getTorchDefaultStrengthLevelExt(); +extern int32_t getTorchMaxStrengthLevelExt(); +extern int32_t getTorchStrengthLevelExt(); +extern void setTorchStrengthLevelExt(int32_t torchStrength); diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index 7032db04aa7..c6515e9720a 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -57,6 +57,8 @@ #include "device3/ZoomRatioMapper.h" #include "utils/Utils.h" +#include "common/CameraProviderExtension.h" + namespace android { using namespace ::android::hardware::camera; @@ -581,7 +583,15 @@ status_t CameraProviderManager::getTorchStrengthLevel(const std::string &id, auto deviceInfo = findDeviceInfoLocked(id); if (deviceInfo == nullptr) return NAME_NOT_FOUND; - return deviceInfo->getTorchStrengthLevel(torchStrength); + // Use the extension only for the camera that has flash unit + // Otherwise fallback to the default impl. + if (deviceInfo->hasFlashUnit() && supportsTorchStrengthControlExt()) { + int32_t strength = getTorchStrengthLevelExt(); + *torchStrength = strength; + return OK; + } else { + return deviceInfo->getTorchStrengthLevel(torchStrength); + } } status_t CameraProviderManager::turnOnTorchWithStrengthLevel(const std::string &id, @@ -591,7 +601,16 @@ status_t CameraProviderManager::turnOnTorchWithStrengthLevel(const std::string & auto deviceInfo = findDeviceInfoLocked(id); if (deviceInfo == nullptr) return NAME_NOT_FOUND; - return deviceInfo->turnOnTorchWithStrengthLevel(torchStrength); + // Use the extension only for the camera that has flash unit + // Otherwise fallback to the default impl. + if (deviceInfo->hasFlashUnit() && supportsTorchStrengthControlExt()) { + // Turn on the torch if level > 0. + deviceInfo->setTorchMode(torchStrength > 0); + setTorchStrengthLevelExt(torchStrength); + return OK; + } else { + return deviceInfo->turnOnTorchWithStrengthLevel(torchStrength); + } } bool CameraProviderManager::shouldSkipTorchStrengthUpdate(const std::string &id, @@ -615,7 +634,13 @@ int32_t CameraProviderManager::getTorchDefaultStrengthLevel(const std::string &i auto deviceInfo = findDeviceInfoLocked(id); if (deviceInfo == nullptr) return NAME_NOT_FOUND; - return deviceInfo->mTorchDefaultStrengthLevel; + // Use the extension only for the camera that has flash unit + // Otherwise fallback to the default impl. + if (deviceInfo->hasFlashUnit() && supportsTorchStrengthControlExt()) { + return getTorchDefaultStrengthLevelExt(); + } else { + return deviceInfo->mTorchDefaultStrengthLevel; + } } bool CameraProviderManager::supportSetTorchMode(const std::string &id) const { @@ -3562,8 +3587,21 @@ status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string const CameraCompatibilityInfo& compatInfo) const { auto deviceInfo = findDeviceInfoLocked(id); if (deviceInfo != nullptr) { - return deviceInfo->getCameraCharacteristics(overrideForPerfClass, characteristics, + status_t res = deviceInfo->getCameraCharacteristics(overrideForPerfClass, characteristics, compatInfo); + if (deviceInfo->hasFlashUnit() && supportsTorchStrengthControlExt()) { + int32_t maxTorchStrength = getTorchMaxStrengthLevelExt(); + int32_t defaultTorchStrength = getTorchDefaultStrengthLevelExt(); + // if max strength level > 0, means the device supports + // strength level controllable torch. + if (maxTorchStrength > 0) { + characteristics->update(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL, + &maxTorchStrength, 1); + characteristics->update(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL, + &defaultTorchStrength, 1); + } + } + return res; } // Find hidden physical camera characteristics From 041e3191883f19915a050d3d722f041a3c4ff03a Mon Sep 17 00:00:00 2001 From: "eric_kuang.rs" Date: Thu, 30 May 2024 09:39:54 +0800 Subject: [PATCH 31/68] Fix usb camera number is not correct after plug out. Test: manual test Bug: 343508677 Change-Id: I95c124ce96f8d96cd0bbb5bb7b0daefe36681064 --- .../camera/libcameraservice/common/CameraProviderManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index c6515e9720a..916443bd587 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -752,7 +752,11 @@ status_t CameraProviderManager::notifyUsbDeviceEvent(int32_t eventId, } } else if (eventId == android::hardware::ICameraService::EVENT_USB_DEVICE_DETACHED) { + size_t usbNum = mExternalUsbDevicesForProvider.first.size(); usbDeviceDetached(usbDeviceId); + if (usbNum > 1) { + startExternalLazyProvider(); + } } return OK; From 39e7783a4b64a628f9a09f0a3027530bdf0ca827 Mon Sep 17 00:00:00 2001 From: someone5678 <59456192+someone5678@users.noreply.github.com> Date: Sun, 5 Jan 2025 18:48:37 +0900 Subject: [PATCH 32/68] Extends "Camera: Skip stream size check for whitelisted apps" Squashed commits: cameraserver: Let multiple cameras opened by stock camera application Let conflicting camera devices list be empty and let the camera hal manage it. Old camera hals mark camera device as conflicting if the new camera device is opened. Fixes dual video camera mode for old devices Change-Id: I2043dee762ddcef96432e440cc6017181950a4c3 Signed-off-by: Lostark13 cameraserver: Allow google camera to access multiple cameras Change-Id: I99a735d7bbe2ab4650f40294cf8b776bbb3a8f03 Signed-off-by: minaripenguin Co-authored-by: Lostark13 Co-authored-by: minaripenguin Change-Id: I4348bb5d82721cbd7a922cd32a66502d6dda68c9 Signed-off-by: someone5678 <59456192+someone5678@users.noreply.github.com> Signed-off-by: Pranav Vashi --- .../camera/libcameraservice/CameraService.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 71df74ac5dd..ae4e98453e9 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -1957,6 +1958,14 @@ status_t CameraService::checkIfDeviceIsUsable(const std::string& cameraId) const return NO_ERROR; } +bool isPrivilegedClient(const std::string &packageName) { + std::vector privilegedClientList = android::base::Split( + android::base::GetProperty("persist.vendor.camera.privapp.list", ""), ","); + auto it = std::find(privilegedClientList.begin(), privilegedClientList.end(), + packageName); + return it != privilegedClientList.end(); +} + void CameraService::finishConnectLocked(const sp& client, const CameraService::DescriptorPtr& desc, int oomScoreOffset, bool systemNativeClient) { @@ -1966,6 +1975,10 @@ void CameraService::finishConnectLocked(const sp& client, oomScoreOffset, systemNativeClient); auto evicted = mActiveClientManager.addAndEvict(clientDescriptor); + if (isPrivilegedClient(client->getPackageName())) { + evicted.clear(); + } + logConnected(desc->getKey(), static_cast(desc->getOwnerId()), client->getPackageName()); @@ -2113,6 +2126,10 @@ status_t CameraService::handleEvictionsLocked(const std::string& cameraId, int c // Find clients that would be evicted auto evicted = mActiveClientManager.wouldEvict(clientDescriptor); + if (isPrivilegedClient(packageName)) { + evicted.clear(); + } + // If the incoming client was 'evicted,' higher priority clients have the camera in the // background, so we cannot do evictions if (std::find(evicted.begin(), evicted.end(), clientDescriptor) != evicted.end()) { From 9b91f6760eb0de6f69f0346a10557e241209b820 Mon Sep 17 00:00:00 2001 From: bengris32 Date: Sat, 7 Dec 2024 14:20:58 +0000 Subject: [PATCH 33/68] CameraProviderExtension: Inject strength in fixupTorchStrengthTags Change-Id: Ic56c0896aed0788980e48efb3f7aefa31ff444f7 Signed-off-by: bengris32 Signed-off-by: Pranav Vashi --- .../common/CameraProviderExtension.cpp | 6 +++-- .../common/CameraProviderManager.cpp | 23 ++++--------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/services/camera/libcameraservice/common/CameraProviderExtension.cpp b/services/camera/libcameraservice/common/CameraProviderExtension.cpp index fe7b9f31607..8bb171e7c25 100644 --- a/services/camera/libcameraservice/common/CameraProviderExtension.cpp +++ b/services/camera/libcameraservice/common/CameraProviderExtension.cpp @@ -23,11 +23,13 @@ bool supportsTorchStrengthControlExt() { } int32_t getTorchDefaultStrengthLevelExt() { - return 0; + // Without extension, assume only one level of torch strength + return 1; } int32_t getTorchMaxStrengthLevelExt() { - return 0; + // Without extension, assume only one level of torch strength + return 1; } int32_t getTorchStrengthLevelExt() { diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index 916443bd587..28236e53e1c 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -1761,8 +1761,8 @@ status_t CameraProviderManager::ProviderInfo::DeviceInfo3::fixupTorchStrengthTag status_t res = OK; auto& c = mCameraCharacteristics; auto flashInfoStrengthDefaultLevelEntry = c.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL); - if (flashInfoStrengthDefaultLevelEntry.count == 0) { - int32_t flashInfoStrengthDefaultLevel = 1; + if (flashInfoStrengthDefaultLevelEntry.count == 0 || supportsTorchStrengthControlExt()) { + int32_t flashInfoStrengthDefaultLevel = getTorchDefaultStrengthLevelExt(); res = c.update(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL, &flashInfoStrengthDefaultLevel, 1); if (res != OK) { @@ -1772,8 +1772,8 @@ status_t CameraProviderManager::ProviderInfo::DeviceInfo3::fixupTorchStrengthTag } } auto flashInfoStrengthMaximumLevelEntry = c.find(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL); - if (flashInfoStrengthMaximumLevelEntry.count == 0) { - int32_t flashInfoStrengthMaximumLevel = 1; + if (flashInfoStrengthMaximumLevelEntry.count == 0 || supportsTorchStrengthControlExt()) { + int32_t flashInfoStrengthMaximumLevel = getTorchMaxStrengthLevelExt(); res = c.update(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL, &flashInfoStrengthMaximumLevel, 1); if (res != OK) { @@ -3591,21 +3591,8 @@ status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string const CameraCompatibilityInfo& compatInfo) const { auto deviceInfo = findDeviceInfoLocked(id); if (deviceInfo != nullptr) { - status_t res = deviceInfo->getCameraCharacteristics(overrideForPerfClass, characteristics, + return deviceInfo->getCameraCharacteristics(overrideForPerfClass, characteristics, compatInfo); - if (deviceInfo->hasFlashUnit() && supportsTorchStrengthControlExt()) { - int32_t maxTorchStrength = getTorchMaxStrengthLevelExt(); - int32_t defaultTorchStrength = getTorchDefaultStrengthLevelExt(); - // if max strength level > 0, means the device supports - // strength level controllable torch. - if (maxTorchStrength > 0) { - characteristics->update(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL, - &maxTorchStrength, 1); - characteristics->update(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL, - &defaultTorchStrength, 1); - } - } - return res; } // Find hidden physical camera characteristics From e6deda50e1cfa7be40185caa2145677cf400f955 Mon Sep 17 00:00:00 2001 From: bengris32 Date: Tue, 8 Oct 2024 11:13:21 +0100 Subject: [PATCH 34/68] CameraProviderExtension: Use weak linkage for default implementations Change-Id: I0a8744c1318caf38c4c9e3db2ed498e9c287f4f2 Signed-off-by: bengris32 Signed-off-by: Pranav Vashi --- .../common/CameraProviderExtension.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/services/camera/libcameraservice/common/CameraProviderExtension.cpp b/services/camera/libcameraservice/common/CameraProviderExtension.cpp index 8bb171e7c25..6dbabbad8d0 100644 --- a/services/camera/libcameraservice/common/CameraProviderExtension.cpp +++ b/services/camera/libcameraservice/common/CameraProviderExtension.cpp @@ -14,30 +14,26 @@ * limitations under the License. */ -#ifndef TARGET_PROVIDES_CAMERA_PROVIDER_EXT_LIB - #include "common/CameraProviderExtension.h" -bool supportsTorchStrengthControlExt() { +__attribute__((weak)) bool supportsTorchStrengthControlExt() { return false; } -int32_t getTorchDefaultStrengthLevelExt() { +__attribute__((weak)) int32_t getTorchDefaultStrengthLevelExt() { // Without extension, assume only one level of torch strength return 1; } -int32_t getTorchMaxStrengthLevelExt() { +__attribute__((weak)) int32_t getTorchMaxStrengthLevelExt() { // Without extension, assume only one level of torch strength return 1; } -int32_t getTorchStrengthLevelExt() { +__attribute__((weak)) int32_t getTorchStrengthLevelExt() { return 0; } -void setTorchStrengthLevelExt(__unused int32_t torchStrength) { +__attribute__((weak)) void setTorchStrengthLevelExt(__unused int32_t torchStrength) { // Nothing } - -#endif From afb40c4a0f0a98c92e531af03162f648faecb801 Mon Sep 17 00:00:00 2001 From: bengris32 Date: Sat, 7 Dec 2024 14:12:05 +0000 Subject: [PATCH 35/68] CameraProviderExtension: Return BAD_VALUE for invalid strength level Change-Id: If53c41a80752a37ff273333b75ef5d1066cecb94 Signed-off-by: bengris32 Signed-off-by: Pranav Vashi --- .../libcameraservice/common/CameraProviderManager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index 28236e53e1c..844cef9c473 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -604,7 +604,13 @@ status_t CameraProviderManager::turnOnTorchWithStrengthLevel(const std::string & // Use the extension only for the camera that has flash unit // Otherwise fallback to the default impl. if (deviceInfo->hasFlashUnit() && supportsTorchStrengthControlExt()) { - // Turn on the torch if level > 0. + // Return BAD_VALUE if the strength is not in the supported + // range. + if (torchStrength <= 0 || torchStrength > getTorchMaxStrengthLevelExt()) { + ALOGE("%s: Invalid torch strength level %d", __FUNCTION__, torchStrength); + return BAD_VALUE; + } + deviceInfo->setTorchMode(torchStrength > 0); setTorchStrengthLevelExt(torchStrength); return OK; From 717e909d6272f8344c87c9f30de6c45e50020a3a Mon Sep 17 00:00:00 2001 From: bengris32 Date: Sat, 7 Dec 2024 14:13:21 +0000 Subject: [PATCH 36/68] CameraProviderExtension: Update mTorchStrengthLevel with new level Change-Id: Ia6a5cbec9aa16d5ba36a5a3a9c090769c13aa587 Signed-off-by: bengris32 Signed-off-by: Pranav Vashi --- .../camera/libcameraservice/common/CameraProviderManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index 844cef9c473..f4284c87c05 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -613,6 +613,7 @@ status_t CameraProviderManager::turnOnTorchWithStrengthLevel(const std::string & deviceInfo->setTorchMode(torchStrength > 0); setTorchStrengthLevelExt(torchStrength); + deviceInfo->mTorchStrengthLevel = torchStrength; return OK; } else { return deviceInfo->turnOnTorchWithStrengthLevel(torchStrength); From 9a8fee1ffcff2f57bc118b5e25c93cb97e6d31aa Mon Sep 17 00:00:00 2001 From: bengris32 Date: Sat, 7 Dec 2024 14:16:32 +0000 Subject: [PATCH 37/68] CameraProviderExtension: Reset strength level on torch off Change-Id: Ie96d5d62786023d1179529daeca24242dfcd0413 Signed-off-by: bengris32 Signed-off-by: Pranav Vashi --- .../libcameraservice/common/CameraProviderManager.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index f4284c87c05..2ef8408cd35 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -711,7 +711,15 @@ status_t CameraProviderManager::setTorchMode(const std::string &id, bool enabled } saveRef(DeviceMode::TORCH, deviceInfo->mId, halCameraProvider); - return deviceInfo->setTorchMode(enabled); + res = deviceInfo->setTorchMode(enabled); + if (!enabled && + deviceInfo->hasFlashUnit() && supportsTorchStrengthControlExt()) { + // Need to reset torch strength back to default when torch is turned off + int32_t defaultLevel = getTorchDefaultStrengthLevelExt(); + setTorchStrengthLevelExt(defaultLevel); + deviceInfo->mTorchStrengthLevel = defaultLevel; + } + return res; } status_t CameraProviderManager::setUpVendorTags() { From fae9ab2150adf230a8a4c8a573aaa89c6aba6340 Mon Sep 17 00:00:00 2001 From: John Galt Date: Tue, 28 Jan 2025 13:01:49 -0500 Subject: [PATCH 38/68] CameraProviderExtension: add enabled bool and always set torch This has two changes for two reasons: - Enabled bool is for device side workarounds (such as switches which must be reset, etc). - Always setting torch strength in this path fixes normal flash usage (camera flash, screen off torch gestures, etc). Signed-off-by: Pranav Vashi --- .../libcameraservice/common/CameraProviderExtension.cpp | 2 +- .../libcameraservice/common/CameraProviderExtension.h | 2 +- .../libcameraservice/common/CameraProviderManager.cpp | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/services/camera/libcameraservice/common/CameraProviderExtension.cpp b/services/camera/libcameraservice/common/CameraProviderExtension.cpp index 6dbabbad8d0..65435a4d23f 100644 --- a/services/camera/libcameraservice/common/CameraProviderExtension.cpp +++ b/services/camera/libcameraservice/common/CameraProviderExtension.cpp @@ -34,6 +34,6 @@ __attribute__((weak)) int32_t getTorchStrengthLevelExt() { return 0; } -__attribute__((weak)) void setTorchStrengthLevelExt(__unused int32_t torchStrength) { +__attribute__((weak)) void setTorchStrengthLevelExt(__unused int32_t torchStrength, __unused bool enabled) { // Nothing } diff --git a/services/camera/libcameraservice/common/CameraProviderExtension.h b/services/camera/libcameraservice/common/CameraProviderExtension.h index ae17a2fc00f..693400b7592 100644 --- a/services/camera/libcameraservice/common/CameraProviderExtension.h +++ b/services/camera/libcameraservice/common/CameraProviderExtension.h @@ -20,4 +20,4 @@ extern bool supportsTorchStrengthControlExt(); extern int32_t getTorchDefaultStrengthLevelExt(); extern int32_t getTorchMaxStrengthLevelExt(); extern int32_t getTorchStrengthLevelExt(); -extern void setTorchStrengthLevelExt(int32_t torchStrength); +extern void setTorchStrengthLevelExt(int32_t torchStrength, bool enabled); diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index 2ef8408cd35..8d8f0e21217 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -612,7 +612,7 @@ status_t CameraProviderManager::turnOnTorchWithStrengthLevel(const std::string & } deviceInfo->setTorchMode(torchStrength > 0); - setTorchStrengthLevelExt(torchStrength); + setTorchStrengthLevelExt(torchStrength, true); deviceInfo->mTorchStrengthLevel = torchStrength; return OK; } else { @@ -712,11 +712,10 @@ status_t CameraProviderManager::setTorchMode(const std::string &id, bool enabled saveRef(DeviceMode::TORCH, deviceInfo->mId, halCameraProvider); res = deviceInfo->setTorchMode(enabled); - if (!enabled && - deviceInfo->hasFlashUnit() && supportsTorchStrengthControlExt()) { + if (deviceInfo->hasFlashUnit() && supportsTorchStrengthControlExt()) { // Need to reset torch strength back to default when torch is turned off int32_t defaultLevel = getTorchDefaultStrengthLevelExt(); - setTorchStrengthLevelExt(defaultLevel); + setTorchStrengthLevelExt(defaultLevel, enabled); deviceInfo->mTorchStrengthLevel = defaultLevel; } return res; From d85f7dea997ba0f193feaa65e25da862777f2ec4 Mon Sep 17 00:00:00 2001 From: Phoenix wang Date: Wed, 5 Nov 2025 11:09:32 +0800 Subject: [PATCH 39/68] Null Pointer Exception in CameraServer during user switch A Null Pointer Exception (NPE) occurs in Camera3Device::setNotifyCallback when switching users. The crash happens upon accessing mRequestThread, which has already been destroyed. The root cause is a race condition: the UidPolicy callback, triggered by the user switch, disconnects the device and nullifies mRequestThread. If setNotifyCallback is called after this, it leads to the NPE. The issue is 100% reproducible by adding a delay in setNotifyCallback to simulate the race. Bug:457793937 Change-Id: I6d0bd5488ae773c4db1e87f7dc4813fe4d6636ab Signed-off-by: Phoenix wang --- .../device3/Camera3Device.cpp | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 565963920e9..91dae4a38b3 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -1746,14 +1746,23 @@ status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout, status_t Camera3Device::setNotifyCallback(wp listener) { ATRACE_CALL(); - std::lock_guard l(mOutputLock); + { + std::lock_guard l(mOutputLock); - if (listener != NULL && mListener != NULL) { - ALOGW("%s: Replacing old callback listener", __FUNCTION__); + if (listener != NULL && mListener != NULL) { + ALOGW("%s: Replacing old callback listener", __FUNCTION__); + } + mListener = listener; + } + { + Mutex::Autolock l(mLock); + if (mRequestThread) { + mRequestThread->setNotificationListener(listener); + } + if (mPreparerThread) { + mPreparerThread->setNotificationListener(listener); + } } - mListener = listener; - mRequestThread->setNotificationListener(listener); - mPreparerThread->setNotificationListener(listener); return OK; } From 913fe378de5632f4dc28e40dd494f5868e6b1e6e Mon Sep 17 00:00:00 2001 From: "kuowei.li" Date: Mon, 15 Dec 2025 14:34:46 +0800 Subject: [PATCH 40/68] audio: fix incorrect eos in sync offload output case. Mixer status set incorrectly when async write is not used, causing test failure. Adjust mixer status to MIXER_DRAIN_ALL when async write is disabled. Test: atest CtsMediaPlayerTestCases:android.media.player.cts.MediaPlayerTest#testPositionAtEnd Change-Id: I4b4338a1f57e79750c9c02e90391ea7089a180a6 --- services/audioflinger/Threads.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 2cd715ccda0..a8234475618 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -7593,7 +7593,11 @@ PlaybackThread::mixer_state OffloadThread::prepareTracks_l( if ((mDrainSequence & 1) == 0) { mSleepTimeUs = 0; mStandbyTimeNs = systemTime() + mStandbyDelayNs; - mixerStatus = MIXER_DRAIN_TRACK; + if (!mUseAsyncWrite) { + mixerStatus = MIXER_DRAIN_ALL; + } else { + mixerStatus = MIXER_DRAIN_TRACK; + } mDrainSequence += 2; } if (mHwPaused) { From 89971ead9967a085c7fe938b7c37f4c775905c6e Mon Sep 17 00:00:00 2001 From: "shipeng.sun" Date: Mon, 15 Dec 2025 11:05:43 +0800 Subject: [PATCH 41/68] MediaCodec: Improve mediacrypto async priorty The decryption priority of MediaCrypto is determined by the priority of the Client's Binder call. For asynchronous decryption threads, the priority needs to be increased to ANDROID_PRIORITY_AUDIO. Bug: 468888713 Change-Id: I5069a79c9f313d2c761c433aff8bd202e171502f Signed-off-by: shipeng.sun --- media/libstagefright/MediaCodec.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 87c2cfff40a..e66ccba42eb 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -5616,7 +5616,8 @@ void MediaCodec::onMessageReceived(const sp &msg) { mCryptoLooper = new ALooper(); mCryptoLooper->setName("CryptoAsyncLooper"); mCryptoLooper->registerHandler(mCryptoAsync); - status_t err = mCryptoLooper->start(); + status_t err = mCryptoLooper->start(false /* runOnCallingThread */, + false /* canCallJava */, ANDROID_PRIORITY_AUDIO); if (err != OK) { ALOGE("Crypto Looper failed to start"); mCryptoAsync = nullptr; From f93f378468cc97bf84894900ac6e6e3a82234a5f Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Tue, 3 Feb 2026 20:53:38 +0530 Subject: [PATCH 42/68] Revert "codec2,aom/Android.bp: add libcodec2_soft_sanitize_cfi" This reverts commit ae2576a6004a961e2c625252424f23c8da0c4951. --- media/codec2/components/aom/Android.bp | 2 -- 1 file changed, 2 deletions(-) diff --git a/media/codec2/components/aom/Android.bp b/media/codec2/components/aom/Android.bp index 83066c74bd5..257cf4ea95d 100644 --- a/media/codec2/components/aom/Android.bp +++ b/media/codec2/components/aom/Android.bp @@ -12,7 +12,6 @@ cc_library { defaults: [ "libcodec2_soft-defaults", "libcodec2_soft_sanitize_all-defaults", - "libcodec2_soft_sanitize_cfi-defaults", ], // coordinated with frameworks/av/media/codec2/components/gav1/Android.bp @@ -30,7 +29,6 @@ cc_library { defaults: [ "libcodec2_soft-defaults", "libcodec2_soft_sanitize_all-defaults", - "libcodec2_soft_sanitize_cfi-defaults", ], static_libs: ["libaom"], From eb913ff3a39de133ad19f946f6fc47612e590e48 Mon Sep 17 00:00:00 2001 From: HELLBOY017 Date: Tue, 24 May 2022 10:46:29 +0530 Subject: [PATCH 43/68] Add AC4Tbl params for dolby AC4 decoder [1/2] Signed-off-by: Pranav Vashi --- media/libstagefright/ACodec.cpp | 65 ++++ media/libstagefright/Android.bp | 1 + media/libstagefright/TableXInit.cpp | 100 ++++++ media/libstagefright/include/TableXInit.h | 186 ++++++++++ media/libstagefright/omx/Android.bp | 1 + media/libstagefright/omx/generic_header.h | 161 +++++++++ media/libstagefright/omx/generic_source.c | 392 ++++++++++++++++++++++ 7 files changed, 906 insertions(+) create mode 100755 media/libstagefright/TableXInit.cpp create mode 100755 media/libstagefright/include/TableXInit.h create mode 100755 media/libstagefright/omx/generic_header.h create mode 100755 media/libstagefright/omx/generic_source.c diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index c3146545c72..d42fc5acf48 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -66,6 +66,7 @@ #include "include/SecureBuffer.h" #include "include/SharedMemoryBuffer.h" #include +#include "TableXInit.h" #include @@ -3143,6 +3144,27 @@ status_t ACodec::setupEAC3Codec( (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3, &def, sizeof(def)); } + +template +static void InitTblOMXParams(T *params) { + params->nSize = sizeof(T); + params->seedA = 0; + params->seedB = 0; + params->seedC = 0; + + params->idA = 0; + params->idB = 0; + params->idC = 0; + + params->maskA = 0; + params->maskB = 0; + params->maskC = 0; + + params->sizeA = 0; + params->sizeB = 0; + params->sizeC = 0; +} + status_t ACodec::setupAC4Codec( bool encoder, int32_t numChannels, int32_t sampleRate) { status_t err = setupRawAudioFormat( @@ -3170,6 +3192,49 @@ status_t ACodec::setupAC4Codec( def.nChannels = numChannels; def.nSampleRate = sampleRate; + + OMX_AUDIO_PARAM_ANDROID_AC4TBL tbl; + InitTblOMXParams(&tbl); + + TableXInit *A_OBJ = new TableXInit(AC4_TABLE_SEC_FRS_CODE, + AC4_TABLE_SEC_FRS_MASK_VAL); + + TableXInit *B_OBJ = new TableXInit(AC4_TABLE_SEC_MDD_MAX_FRAM, + AC4_TABLE_SEC_MMF_MASK_VAL); + + TableXInit *C_OBJ = new TableXInit(AC4_TABLE_SEC_MDD_MAX_INST, + AC4_TABLE_SEC_MMI_MASK_VAL); + + A_OBJ->init(); + B_OBJ->init(); + C_OBJ->init(); + + tbl.seedA = A_OBJ->getSeed(); + tbl.seedB = B_OBJ->getSeed(); + tbl.seedC = C_OBJ->getSeed(); + + tbl.sizeA = A_OBJ->getSize(); + tbl.sizeB = B_OBJ->getSize(); + tbl.sizeC = C_OBJ->getSize(); + + tbl.idA = A_OBJ->getTableID(); + tbl.idB = B_OBJ->getTableID(); + tbl.idC = C_OBJ->getTableID(); + + tbl.maskA = A_OBJ->getMaskVal(); + tbl.maskB = B_OBJ->getMaskVal(); + tbl.maskC = C_OBJ->getMaskVal(); + + memcpy (tbl.bufferA, A_OBJ->getBuffer(), LUT_BUFFER_SIZE); + memcpy (tbl.bufferB, B_OBJ->getBuffer(), TABLE_B_C_U8_SZ); + memcpy (tbl.bufferC, C_OBJ->getBuffer(), TABLE_B_C_U8_SZ); + + mOMXNode->setParameter( + (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc4Tbl, &tbl, sizeof(tbl)); + + delete A_OBJ; + delete B_OBJ; + delete C_OBJ; return mOMXNode->setParameter( (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc4, &def, sizeof(def)); diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp index af00aedccca..3bbcc3f50a1 100644 --- a/media/libstagefright/Android.bp +++ b/media/libstagefright/Android.bp @@ -274,6 +274,7 @@ cc_library { "StagefrightMediaScanner.cpp", "SurfaceMediaSource.cpp", "SurfaceUtils.cpp", + "TableXInit.cpp" , "ThrottledSource.cpp", "Utils.cpp", "VideoFrameScheduler.cpp", diff --git a/media/libstagefright/TableXInit.cpp b/media/libstagefright/TableXInit.cpp new file mode 100755 index 00000000000..f29bce9095f --- /dev/null +++ b/media/libstagefright/TableXInit.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * This program is protected under international and U.S. copyright laws as + * an unpublished work. This program is confidential and proprietary to the + * copyright owners. Reproduction or disclosure, in whole or in part, or the + * production of derivative works therefrom without the express permission of + * the copyright owners is prohibited. + * + * Copyright (C) 2017 by Dolby International AB. + * All rights reserved. + ******************************************************************************/ + +#include +#include + +#include "include/TableXInit.h" + +namespace android { + +TableXInit::TableXInit(uint8_t table_id, uint8_t mask_val) + :_table_id(table_id), + _mask_val(mask_val), + _session_seed(rand()), + _buffer_size(0), + _isTableXInitialized(0) +{ + for (unsigned int i = 0; i < MAX_BUFFER_SIZE; i++) { + _buffer[i] = 0; + } +} + +void +TableXInit::init() +{ + union SCRAMBLED_TABLE_PT + { + unsigned char *ui8; + unsigned int *ui32; + } scramble_table_pt; + + scramble_table_pt.ui32 = scrambled_table; + + if ( _table_id == AC4_TABLE_SEC_FRS_CODE + && _isTableXInitialized == 0 ) + { + + _buffer_size = LUT_BUFFER_SIZE; + + for(unsigned int i = 0; i < _buffer_size; i++) + { + _buffer[i] = _table_a_u8[i] ^ ( scramble_table_pt.ui8[ ( i + _session_seed ) % LUT_BUFFER_SIZE] + ^ scramble_table_pt.ui8[ ( i + _session_seed + _mask_val) % LUT_BUFFER_SIZE] ); + } + _isTableXInitialized = 1; + } + else + if ( _table_id == AC4_TABLE_SEC_MDD_MAX_FRAM + && _isTableXInitialized == 0 ) + { + _buffer_size = TABLE_B_C_U8_SZ; + + for(unsigned int i = 0; i < _buffer_size; i++) + { + _buffer[i] = _table_b_u8[i] ^ ( scramble_table_pt.ui8[ ( i + _session_seed ) % LUT_BUFFER_SIZE] + ^ scramble_table_pt.ui8[ ( i + _session_seed + _mask_val ) % LUT_BUFFER_SIZE] ); + } + _isTableXInitialized = 1; + } + else + if ( _table_id == AC4_TABLE_SEC_MDD_MAX_INST + && _isTableXInitialized == 0 ) + { + + _buffer_size = TABLE_B_C_U8_SZ; + + for(unsigned int i = 0; i < _buffer_size; i++) + { + _buffer[i] = _table_c_u8[i] ^ ( scramble_table_pt.ui8[ ( i + _session_seed ) % LUT_BUFFER_SIZE] + ^ scramble_table_pt.ui8[ ( i + _session_seed + _mask_val ) % LUT_BUFFER_SIZE] ); + } + _isTableXInitialized = 1; + } +} + +TableXInit::~TableXInit() +{ + _session_seed = 0; + _table_id = 0; + _mask_val = 0; + _buffer_size = 0; + + _isTableXInitialized = 0; + + for (int i = 0; i < MAX_BUFFER_SIZE; i++) + { + _buffer[i] = 0; + } +} + +}; // namespace + diff --git a/media/libstagefright/include/TableXInit.h b/media/libstagefright/include/TableXInit.h new file mode 100755 index 00000000000..4b832aafb62 --- /dev/null +++ b/media/libstagefright/include/TableXInit.h @@ -0,0 +1,186 @@ +/****************************************************************************** + * This program is protected under international and U.S. copyright laws as + * an unpublished work. This program is confidential and proprietary to the + * copyright owners. Reproduction or disclosure, in whole or in part, or the + * production of derivative works therefrom without the express permission of + * the copyright owners is prohibited. + * + * Copyright (C) 2017 by Dolby International AB. + * All rights reserved. + ******************************************************************************/ + +/** + * @brief For the AC-4 Split Security solution, setup the session + * parameters for table retrieval + * + * @return DLB_AC4DEC_OK on success + */ + +#ifndef TABLEXINIT_H +#define TABLEXINIT_H + +#include +#include + +/* Put in macro here */ + +#define LUT_BUFFER_SIZE (256) +#define MAX_BUFFER_SIZE LUT_BUFFER_SIZE + +#define TABLE_B_C_U8_SZ (80) +#define TABLE_A_U32_SZ (64) + +/* Table Identifiers */ +#define AC4_TABLE_SEC_FRS_CODE 0x09 +#define AC4_TABLE_SEC_MDD_MAX_FRAM 0x0A +#define AC4_TABLE_SEC_MDD_MAX_INST 0x0B + +/* Session Mask Parameters */ +#define AC4_TABLE_SEC_FRS_MASK_VAL 0x0 +#define AC4_TABLE_SEC_MMF_MASK_VAL 0x4 +#define AC4_TABLE_SEC_MMI_MASK_VAL 0x8 + +static unsigned char _table_a_u8[LUT_BUFFER_SIZE] = { + +/*0*/ 0x7F,0xF8,0xFF,0xFF, 0xFC,0xFF,0xFF,0xFF, 0xF5,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF, +/*1*/ 0x7F,0xF8,0xFF,0xFF, 0xFC,0xFF,0xFF,0xFF, 0xF5,0xFF,0xFF,0xFF, 0xFE,0xFF,0xFF,0xFF, +/*2*/ 0xFF,0xF7,0xFF,0xFF, 0xFB,0xFF,0xFF,0xFF, 0xF7,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, +/*3*/ 0xFF,0xF9,0xFF,0xFF, 0xF9,0xFF,0xFF,0xFF, 0xFB,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF, +/*4*/ 0xFF,0xF9,0xFF,0xFF, 0xF9,0xFF,0xFF,0xFF, 0xFB,0xFF,0xFF,0xFF, 0xFE,0xFF,0xFF,0xFF, +/*5*/ 0x3F,0xFC,0xFF,0xFF, 0xFC,0xFF,0xFF,0xFF, 0xFA,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF, +/*6*/ 0x3F,0xFC,0xFF,0xFF, 0xFC,0xFF,0xFF,0xFF, 0xFA,0xFF,0xFF,0xFF, 0xFE,0xFF,0xFF,0xFF, +/*7*/ 0xFF,0xFB,0xFF,0xFF, 0xFB,0xFF,0xFF,0xFF, 0xFB,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, +/*8*/ 0xFF,0xFC,0xFF,0xFF, 0xF9,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF, +/*9*/ 0xFF,0xFC,0xFF,0xFF, 0xF9,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF, 0xFE,0xFF,0xFF,0xFF, +/*10*/ 0xFF,0xFD,0xFF,0xFF, 0xFB,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, +/*11*/ 0x7F,0xFE,0xFF,0xFF, 0xF9,0xFF,0xFF,0xFF, 0xFE,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF, +/*12*/ 0x7F,0xFE,0xFF,0xFF, 0xF9,0xFF,0xFF,0xFF, 0xFE,0xFF,0xFF,0xFF, 0xFE,0xFF,0xFF,0xFF, +/*13*/ 0xFF,0xF7,0xFF,0xFF, 0xFB,0xFF,0xFF,0xFF, 0xF7,0xFF,0xFF,0xFF, 0xF9,0xFF,0xFF,0xFF, +/*14*/ 0xFF,0xF7,0xFF,0xFF, 0xFB,0xFF,0xFF,0xFF, 0xF7,0xFF,0xFF,0xFF, 0xFC,0xFF,0xFF,0xFF, +/*15*/ 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF, 0xFA,0xFF,0xFF,0xFF +}; + +static unsigned char _table_b_u8[LUT_BUFFER_SIZE] = { +/*0*/ 0xF7,0xFF,0xFF,0xFF, +/*1*/ 0xFA,0xFF,0xFF,0xFF, +/*2*/ 0xFA,0xFF,0xFF,0xFF, +/*3*/ 0xFA,0xFF,0xFF,0xFF, +/*4*/ 0xFA,0xFF,0xFF,0xFF, +/*5*/ 0xFA,0xFF,0xFF,0xFF, +/*6*/ 0xFA,0xFF,0xFF,0xFF, +/*7*/ 0xFA,0xFF,0xFF,0xFF, +/*8*/ 0xFA,0xFF,0xFF,0xFF, +/*9*/ 0xFA,0xFF,0xFF,0xFF, +/*10*/ 0xFA,0xFF,0xFF,0xFF, +/*11*/ 0xFA,0xFF,0xFF,0xFF, +/*12*/ 0xFA,0xFF,0xFF,0xFF, +/*13*/ 0xFA,0xFF,0xFF,0xFF, +/*14*/ 0xFA,0xFF,0xFF,0xFF, +/*15*/ 0xFA,0xFF,0xFF,0xFF, +/*16*/ 0xFA,0xFF,0xFF,0xFF, +/*17*/ 0xF7,0xFF,0xFF,0xFF, +/*18*/ 0xF7,0xFF,0xFF,0xFF, +/*19*/ 0xFA,0xFF,0xFF,0xFF, +}; + +static unsigned char _table_c_u8[TABLE_B_C_U8_SZ] = { +/*0*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*1*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*2*/ 0xF4, 0xFF, 0xFF, 0xFF, +/*3*/ 0xF4, 0xFF, 0xFF, 0xFF, +/*4*/ 0xF4, 0xFF, 0xFF, 0xFF, +/*5*/ 0xFA, 0xFF, 0xFF, 0xFF, +/*6*/ 0xFA, 0xFF, 0xFF, 0xFF, +/*7*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*8*/ 0xFC, 0xFF, 0xFF, 0xFF, +/*9*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*10*/ 0xFD, 0xFF, 0xFF, 0xFF, +/*11*/ 0xFD, 0xFF, 0xFF, 0xFF, +/*12*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*13*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*14*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*15*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*16*/ 0xF4, 0xFF, 0xFF, 0xFF, +/*17*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*18*/ 0xFE, 0xFF, 0xFF, 0xFF, +/*19*/ 0xFE, 0xFF, 0xFF, 0xFF +}; + +static unsigned int scrambled_table[TABLE_A_U32_SZ] = { + 0x18aa9205,0xb9953de4,0x6fc38e9e,0x6c44fe69, + 0x2dcf9356,0x0755aed1,0xf994015f,0x28dc5d10, + 0x0efc3170,0x2486ce80,0x1a4f683a,0xda7ea9bf, + 0xba6747ab,0x65cc8474,0x1b3049af,0xd89d380f, + 0x1535e9e3,0xb4d4ace6,0xbce2eb58,0xa7627839, + 0x21cb3cf3,0x2b52bd11,0x9023a173,0xd9793f51, + 0x22d3767f,0xf487f17a,0x40b02606,0x97d25c0d, + 0x2a6e4de7,0xb699dbb3,0xb15a64a8,0x539f00e0, + 0x43ea19cd,0x6dc24617,0x0298c027,0x50c13ed6, + 0x6b2c16d5,0xdf13710b,0xbee575ad,0x964863f5, + 0xfb29917c,0xec3461b5,0xca36b74a,0x5466a2bb, + 0x088104f6,0x2f8f7bb2,0x9c0cf233,0x208b7d8c, + 0x881d4ea5,0x6077144c,0xff0aa4ef,0x25de45e8, + 0xddb85985,0x5ed009a6,0xc8c5c6ed,0x2e82f7d7, + 0x4172a3fa,0x576ac4f0,0x37e18d1e,0xfd12034b, + 0x5bf8421c,0x9b1f9a83,0x3ba0c7c9,0x32898aee +}; + +// --------------------------------------------------------------------------- + +namespace android { + +class TableXInit +{ +public: + /*! + * Constructors and destructors + */ + TableXInit(unsigned char table_id, unsigned char mask_val = 0); + ~TableXInit(); + + unsigned char getSeed() + { + return _session_seed; + } + + unsigned char * getBuffer() + { + return _buffer; + } + + unsigned char getTableID() + { + return _table_id; + } + + unsigned char getMaskVal() + { + return _mask_val; + } + + unsigned int getSize() + { + return _buffer_size; + } + + unsigned char isInit() + { + return _isTableXInitialized; + } + + void init(); + +private: + unsigned char _table_id; + unsigned char _mask_val; + unsigned char _session_seed; + unsigned int _buffer_size; + + unsigned char _isTableXInitialized; + + unsigned char _buffer[MAX_BUFFER_SIZE]; +}; + +}; //namespace + +#endif //TABLEXINIT_H diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp index 6ba7896ba81..cb32954a5d7 100644 --- a/media/libstagefright/omx/Android.bp +++ b/media/libstagefright/omx/Android.bp @@ -33,6 +33,7 @@ cc_library_shared { "1.0/WOmxNode.cpp", "1.0/WOmxObserver.cpp", "1.0/WOmxBufferSource.cpp", + "generic_source.c" ], export_include_dirs: [ diff --git a/media/libstagefright/omx/generic_header.h b/media/libstagefright/omx/generic_header.h new file mode 100755 index 00000000000..e5b49defc09 --- /dev/null +++ b/media/libstagefright/omx/generic_header.h @@ -0,0 +1,161 @@ +/****************************************************************************** + * This program is protected under international and U.S. copyright laws as + * an unpublished work. This program is confidential and proprietary to the + * copyright owners. Reproduction or disclosure, in whole or in part, or the + * production of derivative works therefrom without the express permission of + * the copyright owners is prohibited. + * + * Copyright (C) 2017 by Dolby International AB. + * All rights reserved. + ******************************************************************************/ + +/** + * @addtogroup ac4dec_lib_cch Configuration Change Handler (CCH) + * + * @brief This module implements Part 2 of the AC-4 Split Security Architecture + * This module implements the three functions that were identified as + * part of the original TEE Architecture. All function names have been + * renamed as generic_function_X + */ + +/** + * @file + * + * @ingroup generic_shared_library + * + * @brief AC-4 Split Security Architecture Shared Library Implementation. + * + */ + +#ifndef GENERIC_HEADER_H +#define GENERIC_HEADER_H + +#include +#include +#include +#include + +#define LOG_DUALIS_TABLE_SIZE 65 /**< Number of entries for ld(x) lookup table used by DLB_logDualisDiv8(x) */ + +static float get_num_octaves_div8(unsigned int a, unsigned int b); +unsigned int function_a (unsigned int sbx, unsigned int sbz); + +#define MAX_NUM_ASPX_INST_CHANNELS 2 /**< Maximum number of A-SPX channels per instance. */ +#define MAX_NUM_ATSG_SIG 5 /**< Maximum number of signal time slot groups (signal envelopes) per A-SPX frame */ +#define MAX_NUM_ATSG_NOISE 2 /**< Maximum number of noise time slot groups (noise envelopes) per A-SPX frame */ +#define MAX_NUM_SBG_SIG_HIRES 22 /**< Maximum number of signal QMF subband groups (scale factor bands) for high resolution */ +#define MAX_NUM_SBG_SIG_LORES 11 /**< Maximum number of signal QMF subband groups (scale factor bands) for low resolution */ +#define MAX_NUM_SBG_NOISE 5 /**< Maximum number of noise QMF subband groups (scale factor bands) */ +#define MAX_NUM_SB_ASPX 44 /**< Maximum number of QMF subbands in the A-SPX range */ +/** @brief Macro to retrieve the add harmonic flag for a specific A-SPX subband group from the respective bit field. */ +#define ADD_HARMONIC(bitfield, sbg) ((bitfield) & (0x1UL << ((sizeof(unsigned long)*CHAR_BIT-1)-(sbg)))) + +/** + * @brief Calculate sine start envelopes. + * + * The values in p_sine_start_env indicate the envelope numbers where sines have to start (per subband group). + * A value of MAX_NUM_ATSG_SIG indicates that no sine is present. + * + */ +void +function_b + (unsigned int num_sbg_sig_highres /**< [in] Number high resolution subband groups. */ + ,unsigned int aspx_sbg_start /**< [in] A-SPX start subband group. */ + ,signed int aspx_tsg_ptr /**< [in] Pointer to envelope border signalling sine start + envelope */ + ,unsigned long aspx_add_harmonic /**< [in] Sinusoid insertion flags (one bit per sbg). */ + ,unsigned int *p_sine_start_env /**< [in,out] An array indicating the sine start envelope per + subband group. */ + ); + + +#define GET_CONFIG_EVENT(config_change) \ + (cch_config_change_t)((config_change) & 0x0F) + +#define GET_FRAME_EVENT(config_change) \ + (cch_config_change_t)((config_change) & 0xF0) +#define SET_CONFIG_EVENT(config_change, config_event) \ + (config_change = (cch_config_change_t)(((config_change) & 0xF0) | config_event)) + +#define SET_FRAME_EVENT(config_change, frame_event) \ + (config_change = (cch_config_change_t)(((config_change) & 0x0F) | frame_event)) + +/** + * @brief Configuration change information. + * + * Please note, that the order of the messages does matter. + */ +typedef enum +{ + UNDEFINED = -1 + + /* lower nibble reserved for configuration event messages */ + ,NO_CHANGE = 0x00 /* Nothing changed, normal processing. */ + ,SEAMLESS = 0x01 /* Perfect transition, only used in combination with frame rate switches between multiples. */ + ,GAPLESS = 0x02 /* No silence gap in between. */ + ,CLEAN = 0x03 /* Something better than GAPLESS but not as good as SEAMLESS, still needs to be defined. */ + ,SPLICE = 0x04 /* A SPLICE always introduces silence gaps. */ + + /* upper nibble reserved for frame event messages */ + ,FRAME_DROP = 0x10 + ,FRAME_REPETITION = 0x20 +} cch_config_change_t; + +/** + * @brief Determines the slice index within an EHFR frame sequence. + * + * @return The slice index within an EHFR frame sequence. + */ +static inline unsigned int +cch_get_slice_index + (unsigned int sequence_counter /**< [in] Sequence counter. */ + ,unsigned int frame_rate_fraction /**< [in] Frame rate fraction. */ + ) +{ + return sequence_counter & (frame_rate_fraction - 1); +} + +typedef struct cch_frame_data_s +{ + cch_config_change_t config_change; /**< Configuration change. + Can be of types: NO_CHANGE, SEAMLESS, GAPLESS, + CLEAN, SPLICE, FRAME_DROP, FRAME_REPETITION */ + int b_frame_complete; /**< Flag indicating if the frame is complete and can be decoded. */ + int b_collection_frame; /**< Flag indicating a collection frame, i.e. the frame is not + processed but collected. */ +} cch_frame_data_t; + +/* + * Determines and assigns data to the frame data structure which exists for every single frame and is stored in the internal FIFO + * buffer. Moreover, the config_change message is complemented with a frame event (FRAME_DROP or FRAME_REPETITION). + * Note that short frame equivalents - as used for frame length information - means, that e.g. a long frame has the length of 4. + */ +int +function_c + (int b_collection_frame_previous /* [in] Flag indicating if the previous frame was a collection + frame. */ + ,unsigned int sequence_counter_current /* [in] Sequence counter of current frame. */ + ,unsigned int frame_rate_fraction_previous /* [in] Frame rate fraction of previous frame. */ + ,unsigned int frame_rate_fraction_current /* [in] Frame rate fraction of current frame. */ + ,unsigned int length_frame_delayed /* [in] Length of the delayed frame in units of short frame + equivalents. */ + ,unsigned int length_frame_current /* [in] Length of the current frame in units of short frame + equivalents. */ + ,cch_config_change_t *p_config_change /* [in,out] Configuration change. */ + ,unsigned int *p_length_frames_collected /* [in,out] Stores the overall length of collected frames in units of + short frame equivalents. + This variable is updated within this function. */ + ,unsigned int *p_num_frames_collected /* [in,out] Stores the number of collected frames during a + collection phase. + This variable is updated within this function. */ + ,unsigned int *p_num_slices_available /* [in,out] Slice counter holding the number of available slices. + This variable is updated within this function. */ + ,cch_config_change_t *p_config_change_previous /* [out] Config change of previous frame. */ + ,cch_frame_data_t *p_frame_data_current /* [out] Frame data structure to be filled. */ + ); + +#else + +//#error "libstagefright: AC4 Split Security Architecture unsupported" + +#endif // GENERIC_HEADER_H diff --git a/media/libstagefright/omx/generic_source.c b/media/libstagefright/omx/generic_source.c new file mode 100755 index 00000000000..7b91dfd6480 --- /dev/null +++ b/media/libstagefright/omx/generic_source.c @@ -0,0 +1,392 @@ +/****************************************************************************** + * This program is protected under international and U.S. copyright laws as + * an unpublished work. This program is confidential and proprietary to the + * copyright owners. Reproduction or disclosure, in whole or in part, or the + * production of derivative works therefrom without the express permission of + * the copyright owners is prohibited. + * + * Copyright (C) 2017 by Dolby International AB. + * All rights reserved. + ******************************************************************************/ + +/** + * @file + * + * @ingroup security_split + * + * @brief A-SPX frequency scale calculation + */ + +#include + +#include "generic_header.h" + +#define LOG_TAG "generic_source" + +#define DLB_ScF(a) ((float)(a)) +static const float Q15 = 32768.0f; + +union float_long + { + float f; + long l; + }; + +static long lmax(long a, long b) { return a < b ? b : a; } +static long lmin(long a, long b) { return a < b ? a : b; } +static long lclip(long a, long lo, long hi) { return lmin( lmax(a, lo), hi); } + +static int16_t +DLB_16srndS(float a) { + return (int16_t)lclip(lrintf(Q15 * a), INT16_MIN, INT16_MAX); } + +static float +DLB_SsubSS(float a, float b) { + return a - b; } + +#define shru(a, shift) ldexpf((a), -(int)(shift)) +static float +DLB_SshrSU(float a, unsigned sh) { + return shru(a, sh); } + +static const float a_log_dualis[LOG_DUALIS_TABLE_SIZE] = { + DLB_ScF(-1.00000000000), /* actually, ld 0 is not defined */ + DLB_ScF(0.000000000000), /* ld(1) / 8 */ + DLB_ScF(0.125000000000), /* ld(2) / 8 */ + DLB_ScF(0.198120312590), /* ld(3) / 8 */ + DLB_ScF(0.250000000000), /* ld(4) / 8 */ + DLB_ScF(0.290241011861), /* ld(5) / 8 */ + DLB_ScF(0.323120312590), /* ld(6) / 8 */ + DLB_ScF(0.350919365257), /* ld(7) / 8 */ + DLB_ScF(0.375000000000), /* ld(8) / 8 */ + DLB_ScF(0.396240625180), /* ld(9) / 8 */ + DLB_ScF(0.415241011861), /* ld(10) / 8 */ + DLB_ScF(0.432428952330), /* ld(11) / 8 */ + DLB_ScF(0.448120312590), /* ld(12) / 8 */ + DLB_ScF(0.462554964768), /* ld(13) / 8 */ + DLB_ScF(0.475919365257), /* ld(14) / 8 */ + DLB_ScF(0.488361324451), /* ld(15) / 8 */ + DLB_ScF(0.500000000000), /* ld(16) / 8 */ + DLB_ScF(0.510932855156), /* ld(17) / 8 */ + DLB_ScF(0.521240625180), /* ld(18) / 8 */ + DLB_ScF(0.530990939180), /* ld(19) / 8 */ + DLB_ScF(0.540241011861), /* ld(20) / 8 */ + DLB_ScF(0.549039677847), /* ld(21) / 8 */ + DLB_ScF(0.557428952330), /* ld(22) / 8 */ + DLB_ScF(0.565445244507), /* ld(23) / 8 */ + DLB_ScF(0.573120312590), /* ld(24) / 8 */ + DLB_ScF(0.580482023722), /* ld(25) / 8 */ + DLB_ScF(0.587554964768), /* ld(26) / 8 */ + DLB_ScF(0.594360937770), /* ld(27) / 8 */ + DLB_ScF(0.600919365257), /* ld(28) / 8 */ + DLB_ScF(0.607247624391), /* ld(29) / 8 */ + DLB_ScF(0.613361324451), /* ld(30) / 8 */ + DLB_ScF(0.619274538798), /* ld(31) / 8 */ + DLB_ScF(0.625000000000), /* ld(32) / 8 */ + DLB_ScF(0.630549264920), /* ld(33) / 8 */ + DLB_ScF(0.635932855156), /* ld(34) / 8 */ + DLB_ScF(0.641160377118), /* ld(35) / 8 */ + DLB_ScF(0.646240625180), /* ld(36) / 8 */ + DLB_ScF(0.651181670704), /* ld(37) / 8 */ + DLB_ScF(0.655990939180), /* ld(38) / 8 */ + DLB_ScF(0.660675277358), /* ld(39) / 8 */ + DLB_ScF(0.665241011861), /* ld(40) / 8 */ + DLB_ScF(0.669694000577), /* ld(41) / 8 */ + DLB_ScF(0.674039677847), /* ld(42) / 8 */ + DLB_ScF(0.678283094338), /* ld(43) / 8 */ + DLB_ScF(0.682428952330), /* ld(44) / 8 */ + DLB_ScF(0.686481637041), /* ld(45) / 8 */ + DLB_ScF(0.690445244507), /* ld(46) / 8 */ + DLB_ScF(0.694323606460), /* ld(47) / 8 */ + DLB_ScF(0.698120312590), /* ld(48) / 8 */ + DLB_ScF(0.701838730514), /* ld(49) / 8 */ + DLB_ScF(0.705482023722), /* ld(50) / 8 */ + DLB_ScF(0.709053167746), /* ld(51) / 8 */ + DLB_ScF(0.712554964768), /* ld(52) / 8 */ + DLB_ScF(0.715990056820), /* ld(53) / 8 */ + DLB_ScF(0.719360937770), /* ld(54) / 8 */ + DLB_ScF(0.722669964191), /* ld(55) / 8 */ + DLB_ScF(0.725919365257), /* ld(56) / 8 */ + DLB_ScF(0.729111251771), /* ld(57) / 8 */ + DLB_ScF(0.732247624391), /* ld(58) / 8 */ + DLB_ScF(0.735330381170), /* ld(59) / 8 */ + DLB_ScF(0.738361324451), /* ld(60) / 8 */ + DLB_ScF(0.741342167195), /* ld(61) / 8 */ + DLB_ScF(0.744274538798), /* ld(62) / 8 */ + DLB_ScF(0.747159990437), /* ld(63) / 8 */ + DLB_ScF(0.750000000000) /* ld(64) / 8 */ +}; + + +/** + @brief Scaled Logarithm dualis by table lookup + + The valid range for a is 1 to LOG_DUALIS_TABLE_SIZE. + For a=0, the result will be -1 (should be -inf). + + @return ld(a) / 8 +*/ +static inline float +log_dualis_div8 + (unsigned int a /**< Index for logarithm table */ + ) +{ + //DLB_assert(a 1) + { + /* For frame rate fraction values greater than one, the decoder shall process an output frame. + Therefore, we count the dropped frames as well. The decoder is supposed to conceal for an incomplete frame, + which results in silence at the output. */ + *p_num_slices_available = 1; + *pb_dropped_first_slice = 1; + } + } + else + { + ++(*p_num_slices_available); + } + } + + return ++(*p_num_slices_available) == frame_rate_fraction; +} + +/* + * Determines and assigns data to the frame data structure which exists for every single frame and is stored in the internal FIFO + * buffer. Moreover, the config_change message is complemented with a frame event (FRAME_DROP or FRAME_REPETITION). + * Note that short frame equivalents - as used for frame length information - means, that e.g. a long frame has the length of 4. + */ +int +function_c + (int b_collection_frame_previous /* [in] Flag indicating if the previous frame was a collection + frame. */ + ,unsigned int sequence_counter_current /* [in] Sequence counter of current frame. */ + ,unsigned int frame_rate_fraction_previous /* [in] Frame rate fraction of previous frame. */ + ,unsigned int frame_rate_fraction_current /* [in] Frame rate fraction of current frame. */ + ,unsigned int length_frame_delayed /* [in] Length of the delayed frame in units of short frame + equivalents. */ + ,unsigned int length_frame_current /* [in] Length of the current frame in units of short frame + equivalents. */ + ,cch_config_change_t *p_config_change /* [in,out] Configuration change. */ + ,unsigned int *p_length_frames_collected /* [in,out] Stores the overall length of collected frames in units of + short frame equivalents. + This variable is updated within this function. */ + ,unsigned int *p_num_frames_collected /* [in,out] Stores the number of collected frames during a + collection phase. + This variable is updated within this function. */ + ,unsigned int *p_num_slices_available /* [in,out] Slice counter holding the number of available slices. + This variable is updated within this function. */ + ,cch_config_change_t *p_config_change_previous /* [out] Config change of previous frame. */ + ,cch_frame_data_t *p_frame_data_current /* [out] Frame data structure to be filled. */ + ) +{ + const unsigned int max_slice_index_previous = frame_rate_fraction_previous - 1; + const unsigned int max_slice_index_current = frame_rate_fraction_current - 1; + const unsigned int sequence_counter_previous = sequence_counter_current - 1; + const unsigned int slice_index_previous = cch_get_slice_index(sequence_counter_previous, frame_rate_fraction_previous); + const unsigned int slice_index_current = cch_get_slice_index(sequence_counter_current, frame_rate_fraction_current); + int b_dropped_last_slice = 0; + int b_dropped_first_slice; + + /* reset frame length collector variable in case of splice */ + if ( (SPLICE == GET_CONFIG_EVENT(*p_config_change)) + || ( (FRAME_DROP == GET_FRAME_EVENT(*p_config_change)) + && (!b_collection_frame_previous) + && (0 == (sequence_counter_current & max_slice_index_current)) + ) /* frame drop at last slice of previous frame */ + ) + { + *p_length_frames_collected = 0; + } + + /* reset collection frame counter variable */ + if (0 == *p_length_frames_collected) + { + *p_num_frames_collected = 0; + } + + if (FRAME_REPETITION == GET_FRAME_EVENT(*p_config_change)) + { + p_frame_data_current->b_frame_complete = frame_rate_fraction_current == 1; + p_frame_data_current->b_collection_frame = (length_frame_delayed > length_frame_current) ? 1 : b_collection_frame_previous; + + p_frame_data_current->config_change = *p_config_change; /* assign config change message */ + + return 0; + } + + /* determine and assign frame completion flag */ + p_frame_data_current->b_frame_complete = function_c_aux + (sequence_counter_current + ,frame_rate_fraction_current + ,*p_config_change + ,p_num_slices_available + ,&b_dropped_first_slice + ); + + /* determine collection frame flag */ + if (1 == (*p_num_slices_available - b_dropped_first_slice)) + { + /* increase the frame length counter only if there is a decodable frame available */ + *p_length_frames_collected += length_frame_current; + (*p_num_frames_collected)++; + } + + /* determine completion flag */ + p_frame_data_current->b_collection_frame = *p_length_frames_collected < length_frame_delayed; + + if ( (!p_frame_data_current->b_collection_frame) + && (p_frame_data_current->b_frame_complete) + ) + { + /* On exit of the collection phase, the overall collection frame length is reset. + Note, that the number of collected frames (num_frames_collected) is needed later on. Hence this variable is reset when + entering this function. */ + *p_length_frames_collected = 0; + } + + if (FRAME_DROP == GET_FRAME_EVENT(*p_config_change)) + { + /* mark an EHFR frame as dropped */ + if ( (frame_rate_fraction_current > 1) + && (frame_rate_fraction_previous > 1) + ) /* previous and current frame are EHFR frames */ + { + SET_FRAME_EVENT(*p_config_change, FRAME_DROP); + + if (slice_index_previous == max_slice_index_previous) + { + b_dropped_last_slice = 1; + } + } + else if ( (1 == frame_rate_fraction_current) + && (frame_rate_fraction_previous > 1) + && (slice_index_previous < max_slice_index_previous) + ) /* current frame is self-contained */ + { + SET_FRAME_EVENT(*p_config_change_previous, FRAME_DROP); + } + else if ( (frame_rate_fraction_current > 1) + && (1 == frame_rate_fraction_previous) + && (slice_index_current > 0) + ) /* previous frame was self-contained */ + { + SET_FRAME_EVENT(*p_config_change, FRAME_DROP); + } + } + + p_frame_data_current->config_change = *p_config_change; /* assign config change message */ + return b_dropped_last_slice; +} From a069b985c39d31a12c410a480431dc641c5f9536 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Tue, 10 Dec 2024 19:56:27 +0200 Subject: [PATCH 44/68] don't require RECORD_AUDIO permission for REMOTE_SUBMIX audio source RECORD_AUDIO wasn't required before Android 15 QPR1, MODIFY_AUDIO_ROUTING permission was enough. REMOTE_SUBMIX audio source is used by Android Auto to reroute audio output to the car. Change-Id: I32013d38efdbc0d0ee8bb6873e8d9d8806f5b9e9 Signed-off-by: Pranav Vashi --- media/utils/ServiceUtilities.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp index 8966544108a..51eb726c73e 100644 --- a/media/utils/ServiceUtilities.cpp +++ b/media/utils/ServiceUtilities.cpp @@ -169,6 +169,9 @@ static int checkRecordingInternal(const AttributionSourceState &attributionSourc return PERMISSION_HARD_DENIED; } + auto permission = source == AUDIO_SOURCE_REMOTE_SUBMIX ? + sModifyAudioRouting : sAndroidPermissionRecordAudio; + permission::PermissionChecker permissionChecker; int permitted; if (start) { @@ -182,7 +185,7 @@ static int checkRecordingInternal(const AttributionSourceState &attributionSourc // // TODO(b/294609684) To be removed when the pause state for an OP is removed. permitted = permissionChecker.checkPermissionForPreflightFromDatasource( - sAndroidPermissionRecordAudio, resolvedAttributionSource.value(), msg, + permission, resolvedAttributionSource.value(), msg, attributedOpCode); if (permitted == PERMISSION_GRANTED) { permitted = permissionChecker.checkPermissionForStartDataDeliveryFromDatasource( @@ -196,7 +199,7 @@ static int checkRecordingInternal(const AttributionSourceState &attributionSourc } } else { permitted = permissionChecker.checkPermissionForPreflightFromDatasource( - sAndroidPermissionRecordAudio, resolvedAttributionSource.value(), msg, + permission, resolvedAttributionSource.value(), msg, attributedOpCode); } From 543735726fc7895a10e291d37b19f201136eac8f Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Tue, 3 Feb 2026 23:02:14 +0530 Subject: [PATCH 45/68] codec2,aom/Android.bp: Disable CFI * This happens with cortex-a76 arch setup. Log: FAILED: out/soong/.intermediates/frameworks/av/media/codec2/components/aom/libcodec2_soft_av1enc/android_arm64_armv8-2a-dotprod_shared_cfi_apex31/unstripped/libcodec2_soft_av1enc.so prebuilts/clang/host/linux-x86/clang-r563880c/bin/clang++ out/soong/.intermediates/bionic/libc/crtbegin_so/android_arm64_armv8-2a-dotprod_apex31/crtbegin_so.o @out/soong/.intermediates /frameworks/av/media/codec2/components/aom/libcodec2_soft_av1enc/android_arm64_armv8-2a-dotprod_shared_cfi_apex31/unstripped/libcodec2_soft_av1enc.so.rsp out/soong/.intermediates/bioni c/libc/crtend_so/android_arm64_armv8-2a-dotprod_apex31/crtend_so.o out/soong/.intermediates/bionic/libc/crt_pad_segment/android_arm64_armv8-2a-dotprod_apex31/crt_pad_segment.o -o out/s oong/.intermediates/frameworks/av/media/codec2/components/aom/libcodec2_soft_av1enc/android_arm64_armv8-2a-dotprod_shared_cfi_apex31/unstripped/libcodec2_soft_av1enc.so -target aarch64 -linux-android29 -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--build-id=md5 -Wl,--fatal-warnings -Wl,--no-undefined-version -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_str ipped.a -Wl,--exclude-libs,libunwind_llvm.a -Wl,--exclude-libs,libunwind.a -Wl,--compress-debug-sections=zstd -fuse-ld=lld -Wl,--icf=safe -Wl,--no-demangle -Wl,--no-undefined -Wl,-z,se parate-code -Wl,-z,separate-loadable-segments -Wl,-z,max-page-size=4096 -Wl,--pack-dyn-relocs=android+relr -Wl,--use-android-relr-tags -nostdlib -Wl,--gc-sections -shared -Wl,-soname ,libcodec2_soft_av1enc.so -Wl,-Bsymbolic -Wl,--version-script,frameworks/av/media/codec2/components/base/exports.lds -Wl,--version-script,build/soong/cc/config/cfi_exports.map -flto -f sanitize-cfi-cross-dso -fsanitize=cfi -Wl,-plugin-opt,O1 -fsanitize=unsigned-integer-overflow,signed-integer-overflow,cfi -fno-sanitize-link-runtime -Wl,--exclude-libs=libclang_rt.buil tins-aarch64-android.a -Wl,--exclude-libs=libclang_rt.ubsan_minimal-aarch64-android.a ld.lld: error: linking module flags 'CFI Canonical Jump Tables': IDs have conflicting override values in 'out/soong/.intermediates/external/libaom/libaom/android_arm64_armv8-2a-dotprod _static_cfi_apex31/libaom.a(av1_config.o at 7434244)' and 'ld-temp.o' clang++-real: error: linker command failed with exit code 1 (use -v to see invocation) 22:50:16 ninja failed with: exit status 1 Signed-off-by: Pranav Vashi --- media/codec2/components/aom/Android.bp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/media/codec2/components/aom/Android.bp b/media/codec2/components/aom/Android.bp index 257cf4ea95d..067e7596940 100644 --- a/media/codec2/components/aom/Android.bp +++ b/media/codec2/components/aom/Android.bp @@ -22,6 +22,10 @@ cc_library { srcs: ["C2SoftAomDec.cpp"], static_libs: ["libaom"], + + sanitize: { + cfi: false, + }, } cc_library { @@ -42,4 +46,7 @@ cc_library { "com.android.media.swcodec", ], + sanitize: { + cfi: false, + }, } From 8eca8322a262f9f53b96d8d0b3646dbb05bacbb1 Mon Sep 17 00:00:00 2001 From: cjybyjk Date: Sat, 24 Jan 2026 14:39:17 +0100 Subject: [PATCH 46/68] av: support per-app volume [1/3] Dhina17: Ported to 14 QPR2 nurkeinneid: Ported to 16 QPR2 Change-Id: Ib22a04d7b99706042b903a223d0b3900c0838fbd Signed-off-by: cjybyjk Signed-off-by: Pranav Vashi --- include/media/AppVolume.h | 85 +++++++++++++++++++ media/aidl/Android.bp | 1 + media/aidl/android/media/AppVolumeData.aidl | 27 ++++++ media/libaudioclient/AudioSystem.cpp | 21 +++++ media/libaudioclient/IAudioFlinger.cpp | 42 +++++++++ .../android/media/IAudioFlingerService.aidl | 5 ++ .../include/media/AudioSystem.h | 5 ++ .../include/media/IAudioFlinger.h | 16 ++++ services/audioflinger/AudioFlinger.cpp | 63 ++++++++++++++ services/audioflinger/AudioFlinger.h | 10 +++ services/audioflinger/IAfThread.h | 4 + services/audioflinger/IAfTrack.h | 8 +- services/audioflinger/PlaybackTracks.h | 13 ++- services/audioflinger/Threads.cpp | 50 +++++++++-- services/audioflinger/Threads.h | 4 + services/audioflinger/Tracks.cpp | 27 ++++++ 16 files changed, 373 insertions(+), 8 deletions(-) create mode 100644 include/media/AppVolume.h create mode 100644 media/aidl/android/media/AppVolumeData.aidl diff --git a/include/media/AppVolume.h b/include/media/AppVolume.h new file mode 100644 index 00000000000..5c12c11ae79 --- /dev/null +++ b/include/media/AppVolume.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Project Kaleidoscope + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APP_VOLUME_H +#define APP_VOLUME_H + +#include +#include +#include +#include +#include + +namespace android { +namespace media { + class AppVolume : public Parcelable { + public: + String8 packageName; + bool muted; + float volume; + bool active; + + bool operator <(const AppVolume &obj) const { + if (active != obj.active) return active < obj.active; + return packageName < obj.packageName; + } + + virtual status_t writeToParcel(Parcel* parcel) const { + AppVolumeData parcelable; + return writeToParcelable(&parcelable) + ?: parcelable.writeToParcel(parcel); + } + + virtual status_t writeToParcelable(AppVolumeData* parcelable) const { + parcelable->packageName = packageName.c_str(); + parcelable->muted = muted; + parcelable->volume = volume; + parcelable->active = active; + return OK; + } + + virtual status_t readFromParcel(const Parcel* parcel) { + AppVolumeData data; + return data.readFromParcel(parcel) + ?: readFromParcelable(data); + } + + virtual status_t readFromParcelable(const AppVolumeData& parcelable) { + packageName = parcelable.packageName.c_str(); + muted = parcelable.muted; + volume = parcelable.volume; + active = parcelable.active; + return OK; + } + }; + + inline ConversionResult + aidl2legacy_AppVolume(const AppVolumeData& aidl) { + AppVolume legacy; + RETURN_IF_ERROR(legacy.readFromParcelable(aidl)); + return legacy; + } + + inline ConversionResult + legacy2aidl_AppVolume(const AppVolume& legacy) { + AppVolumeData aidl; + RETURN_IF_ERROR(legacy.writeToParcelable(&aidl)); + return aidl; + } +} // namespace media +}; // namespace android + +#endif // APP_VOLUME_H diff --git a/media/aidl/Android.bp b/media/aidl/Android.bp index cf0f8399f19..7eef94229e3 100644 --- a/media/aidl/Android.bp +++ b/media/aidl/Android.bp @@ -43,6 +43,7 @@ aidl_interface { double_loadable: true, local_include_dir: ".", srcs: [ + "android/media/AppVolumeData.aidl", "android/media/IAudioManagerNative.aidl", "android/media/InterpolatorConfig.aidl", "android/media/InterpolatorType.aidl", diff --git a/media/aidl/android/media/AppVolumeData.aidl b/media/aidl/android/media/AppVolumeData.aidl new file mode 100644 index 00000000000..e0e38e84267 --- /dev/null +++ b/media/aidl/android/media/AppVolumeData.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2022 Project Kaleidoscope + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +/** + * {@hide} + */ +parcelable AppVolumeData { + @utf8InCpp String packageName; + int muted; + float volume; + int active; +} diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp index 7e59d9e6070..13509d93beb 100644 --- a/media/libaudioclient/AudioSystem.cpp +++ b/media/libaudioclient/AudioSystem.cpp @@ -2916,6 +2916,27 @@ status_t AudioSystem::registerSoundTriggerCaptureStateListener( return NO_ERROR; } +status_t AudioSystem::setAppVolume(const String8& packageName, const float volume) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + return af->setAppVolume(packageName, volume); +} + +status_t AudioSystem::setAppMute(const String8& packageName, const bool mute) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + return af->setAppMute(packageName, mute); +} + +status_t AudioSystem::listAppVolumes(std::vector *vols) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + return af->listAppVolumes(vols); +} + status_t AudioSystem::setVibratorInfos( const std::vector& vibratorInfos) { const sp af = get_audio_flinger(); diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp index 5d4e8b46d64..0fada5231a2 100644 --- a/media/libaudioclient/IAudioFlinger.cpp +++ b/media/libaudioclient/IAudioFlinger.cpp @@ -336,6 +336,28 @@ status_t AudioFlingerClientAdapter::getMasterBalance(float* balance) const{ return statusTFromBinderStatus(mDelegate->getMasterBalance(balance)); } +status_t AudioFlingerClientAdapter::setAppVolume(const String8& packageName, const float value) { + std::string packageNameAidl = VALUE_OR_RETURN_STATUS( + legacy2aidl_String8_string(packageName)); + return mDelegate->setAppVolume(packageNameAidl, value).transactionError(); +} + +status_t AudioFlingerClientAdapter::setAppMute(const String8& packageName, const bool value) { + std::string packageNameAidl = VALUE_OR_RETURN_STATUS( + legacy2aidl_String8_string(packageName)); + return mDelegate->setAppMute(packageNameAidl, value).transactionError(); +} + +status_t AudioFlingerClientAdapter::listAppVolumes(std::vector* vols) { + std::vector aidlRet; + RETURN_STATUS_IF_ERROR(mDelegate->listAppVolumes(&aidlRet).transactionError()); + if (vols != nullptr) { + *vols = VALUE_OR_RETURN_STATUS( + convertContainer>(aidlRet, media::aidl2legacy_AppVolume)); + } + return OK; +} + status_t AudioFlingerClientAdapter::setPortsVolume( const std::vector &portIds, float volume, bool muted, audio_io_handle_t output) { @@ -1000,6 +1022,26 @@ Status AudioFlingerServerAdapter::getMasterBalance(float* _aidl_return) { return Status::fromStatusT(mDelegate->getMasterBalance(_aidl_return)); } +Status AudioFlingerServerAdapter::setAppVolume(const std::string& packageName, const float value) { + String8 packageNameLegacy = VALUE_OR_RETURN_BINDER( + aidl2legacy_string_view_String8(packageName)); + return Status::fromStatusT(mDelegate->setAppVolume(packageNameLegacy, value)); +} + +Status AudioFlingerServerAdapter::setAppMute(const std::string& packageName, const bool value) { + String8 packageNameLegacy = VALUE_OR_RETURN_BINDER( + aidl2legacy_string_view_String8(packageName)); + return Status::fromStatusT(mDelegate->setAppMute(packageNameLegacy, value)); +} + +Status AudioFlingerServerAdapter::listAppVolumes(std::vector* _aidl_return) { + std::vector resultLegacy; + RETURN_BINDER_IF_ERROR(mDelegate->listAppVolumes(&resultLegacy)); + *_aidl_return = VALUE_OR_RETURN_BINDER(convertContainer>( + resultLegacy, media::legacy2aidl_AppVolume)); + return Status::ok(); +} + Status AudioFlingerServerAdapter::setPortsVolume( const std::vector& portIds, float volume, bool muted, int32_t output) { std::vector portIdsLegacy = VALUE_OR_RETURN_BINDER( diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl index 7ea947fd6e4..4999a79525a 100644 --- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl +++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl @@ -16,6 +16,7 @@ package android.media; +import android.media.AppVolumeData; import android.media.AudioPatchFw; import android.media.AudioPolicyConfig; import android.media.AudioPortFw; @@ -98,6 +99,10 @@ interface IAudioFlingerService { void setMasterBalance(float balance); float getMasterBalance(); + void setAppVolume(@utf8InCpp String packageName, float value); + void setAppMute(@utf8InCpp String packageName, boolean muted); + AppVolumeData[] listAppVolumes(); + /* * Set AudioTrack port ids volume attribute. This is the new way of controlling volume from * AudioPolicyManager to AudioFlinger. diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h index a7c7a39265b..389e671455f 100644 --- a/media/libaudioclient/include/media/AudioSystem.h +++ b/media/libaudioclient/include/media/AudioSystem.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -866,6 +867,10 @@ class AudioSystem media::audio::common::AudioMMapPolicyType policyType, audio_devices_t device, media::audio::common::AudioMMapPolicyInfo *policyInfo); + static status_t setAppVolume(const String8& packageName, const float value); + static status_t setAppMute(const String8& packageName, const bool value); + static status_t listAppVolumes(std::vector *vols); + class AudioFlingerClient: public media::BnAudioFlingerClient { public: diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h index f12e8f47258..67c115cce43 100644 --- a/media/libaudioclient/include/media/IAudioFlinger.h +++ b/media/libaudioclient/include/media/IAudioFlinger.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -399,6 +400,10 @@ class IAudioFlinger : public virtual RefBase { const std::vector& tracksInternalMute) = 0; virtual status_t resetReferencesForTest() = 0; + + virtual status_t setAppVolume(const String8& packageName, const float value) = 0; + virtual status_t setAppMute(const String8& packageName, const bool value) = 0; + virtual status_t listAppVolumes(std::vector *vols) = 0; }; /** @@ -520,6 +525,10 @@ class AudioFlingerClientAdapter : public IAudioFlinger { const std::vector& tracksInternalMute) override; status_t resetReferencesForTest() override; + status_t setAppVolume(const String8& packageName, const float value) override; + status_t setAppMute(const String8& packageName, const bool value) override; + status_t listAppVolumes(std::vector *vols) override; + private: const sp mDelegate; }; @@ -621,6 +630,9 @@ class AudioFlingerServerAdapter : public media::BnAudioFlingerService { SET_TRACKS_INTERNAL_MUTE = media::BnAudioFlingerService::TRANSACTION_setTracksInternalMute, RESET_REFERENCES_FOR_TEST = media::BnAudioFlingerService::TRANSACTION_resetReferencesForTest, + SET_APP_VOLUME = media::BnAudioFlingerService::TRANSACTION_setAppVolume, + SET_APP_MUTE = media::BnAudioFlingerService::TRANSACTION_setAppMute, + LIST_APP_VOLUMES = media::BnAudioFlingerService::TRANSACTION_listAppVolumes, }; protected: @@ -759,6 +771,10 @@ class AudioFlingerServerAdapter : public media::BnAudioFlingerService { Status setTracksInternalMute( const std::vector& tracksInternalMute) override; Status resetReferencesForTest() override; + + Status setAppVolume(const std::string& packageName, const float value) override; + Status setAppMute(const std::string& packageName, const bool value) override; + Status listAppVolumes(std::vector *vols) override; private: const sp mDelegate; }; diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 1c19c2bc23c..f82b660e91d 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1167,6 +1167,15 @@ status_t AudioFlinger::createTrack(const media::CreateTrackRequest& _input, output.portId = portId; if (lStatus == NO_ERROR) { + // set volume + String8 trackCreatorPackage = track->getPackageName(); + if (!trackCreatorPackage.empty() && + mAppVolumeConfigs.find(trackCreatorPackage) != mAppVolumeConfigs.end()) { + media::AppVolume config = mAppVolumeConfigs[trackCreatorPackage]; + track->setAppMute(config.muted); + track->setAppVolume(config.volume); + } + // no risk of deadlock because AudioFlinger::mutex() is held audio_utils::lock_guard _dl(thread->mutex()); // Connect secondary outputs. Failure on a secondary output must not imped the primary @@ -2016,6 +2025,60 @@ uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const return 0; } +status_t AudioFlinger::listAppVolumes(std::vector *vols) +{ + std::set volSet; + audio_utils::lock_guard _l(mutex()); + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { + sp thread = mPlaybackThreads.valueAt(i); + thread->listAppVolumes(volSet); + } + + vols->insert(vols->begin(), volSet.begin(), volSet.end()); + + return NO_ERROR; +} + +status_t AudioFlinger::setAppVolume(const String8& packageName, const float value) +{ + audio_utils::lock_guard _l(mutex()); + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { + sp t = mPlaybackThreads.valueAt(i); + t->setAppVolume(packageName, value); + } + + if (mAppVolumeConfigs.find(packageName) == mAppVolumeConfigs.end()) { + media::AppVolume vol; + vol.packageName = packageName; + vol.volume = value; + vol.muted = false; + mAppVolumeConfigs[packageName] = vol; + } else { + mAppVolumeConfigs[packageName].volume = value; + } + return NO_ERROR; +} + +status_t AudioFlinger::setAppMute(const String8& packageName, const bool value) +{ + audio_utils::lock_guard _l(mutex()); + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { + sp t = mPlaybackThreads.valueAt(i); + t->setAppMute(packageName, value); + } + + if (mAppVolumeConfigs.find(packageName) == mAppVolumeConfigs.end()) { + media::AppVolume vol; + vol.packageName = packageName; + vol.volume = 1.0f; + vol.muted = value; + mAppVolumeConfigs[packageName] = vol; + } else { + mAppVolumeConfigs[packageName].muted = value; + } + return NO_ERROR; +} + status_t AudioFlinger::setVoiceVolume(float value) { status_t ret = initCheck(); diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index ca9e19d87ab..35c4c8c1dbc 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -441,6 +442,15 @@ class AudioFlinger return mStartupFinishedTime.load(std::memory_order_acquire); } +public: + status_t setAppVolume(const String8& packageName, const float value); + status_t setAppMute(const String8& packageName, const bool value); + status_t listAppVolumes(std::vector *vols); + +private: + std::map mAppVolumeConfigs; + +public: status_t openMmapStreamImpl(bool isOutput, const audio_attributes_t& attr, audio_config_base_t* config, diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h index 893d7416b4d..0fb97ef149a 100644 --- a/services/audioflinger/IAfThread.h +++ b/services/audioflinger/IAfThread.h @@ -544,6 +544,10 @@ class IAfPlaybackThread : public virtual IAfThreadBase { // Return the asynchronous signal wait time. virtual int64_t computeWaitTimeNs_l() const REQUIRES(mutex()) = 0; + virtual status_t setAppVolume(const String8& packageName, const float value) = 0; + virtual status_t setAppMute(const String8& packageName, const bool muted) = 0; + virtual void listAppVolumes(std::set &container) = 0; + // returns true if the track is allowed to be added to the thread. virtual bool isTrackAllowed_l( audio_channel_mask_t channelMask, audio_format_t format, audio_session_t sessionId, diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h index f52fc52ef7c..15e2137f213 100644 --- a/services/audioflinger/IAfTrack.h +++ b/services/audioflinger/IAfTrack.h @@ -520,11 +520,17 @@ class IAfTrack : public virtual IAfTrackBase, public virtual AfPlaybackCommon { virtual sp getVolumeShaperState(int id) const = 0; virtual sp getVolumeHandler() const = 0; /** Set the computed normalized final volume of the track. - * !masterMute * masterVolume * portVolume * averageLRVolume */ + * !masterMute * !appMuted * masterVolume * streamVolume * averageLRVolume * appVolume */ virtual void setFinalVolume(float volumeLeft, float volumeRight) = 0; virtual float getFinalVolume() const = 0; virtual void getFinalVolume(float* left, float* right) const = 0; + virtual void setAppVolume(float volume) = 0; + virtual float getAppVolume() const = 0; + virtual void setAppMute(bool val) = 0; + virtual bool isAppMuted() = 0; + virtual String8 getPackageName() const = 0; + using SourceMetadatas = std::vector; using MetadataInserter = std::back_insert_iterator; /** Copy the track metadata in the provided iterator. Thread safe. */ diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index 8451417ebc6..433a9526bfd 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -154,7 +154,7 @@ class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider { sp getVolumeShaperState(int id) const final; sp getVolumeHandler() const final{ return mVolumeHandler; } /** Set the computed normalized final volume of the track. - * !masterMute * masterVolume * streamVolume * averageLRVolume */ + * !masterMute * !appMuted * masterVolume * streamVolume * averageLRVolume * appVolume */ void setFinalVolume(float volumeLeft, float volumeRight) final; float getFinalVolume() const final { return mFinalVolume; } void getFinalVolume(float* left, float* right) const final { @@ -162,6 +162,13 @@ class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider { *right = mFinalVolumeRight; } + void setAppVolume(float volume) final; + float getAppVolume() const { return mAppVolume; }; + void setAppMute(bool val) final; + bool isAppMuted() { return mAppMuted; }; + + String8 getPackageName() const { return mPackageName; } + using SourceMetadatas = std::vector; using MetadataInserter = std::back_insert_iterator; /** Copy the track metadata in the provided iterator. Thread safe. */ @@ -383,6 +390,8 @@ class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider { void populateUsageAndContentTypeFromStreamType(); + String8 mPackageName; + size_t mPresentationCompleteFrames = 0; // (Used for Mixed tracks) // The number of frames written to the // audio HAL when this track is considered fully rendered. @@ -408,6 +417,8 @@ class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider { // volume float mFinalVolumeRight; // combine master volume, stream type volume and track // volume + float mAppVolume; // volume control for separate processes + bool mAppMuted; sp mAudioTrackServerProxy; bool mResumeToStopping; // track was paused in stopping state. bool mFlushHwPending; // track requests for thread flush diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index a8234475618..e9f2093bd2d 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2252,6 +2252,43 @@ void ThreadBase::checkUpdateTrackMetadataForUid(uid_t uid) { } } +void PlaybackThread::listAppVolumes(std::set &container) +{ + audio_utils::lock_guard _l(mutex()); + for (sp track : mTracks) { + if (!track->getPackageName().empty()) { + media::AppVolume av; + av.packageName = track->getPackageName(); + av.muted = track->isAppMuted(); + av.volume = track->getAppVolume(); + av.active = mActiveTracks.indexOf(track) >= 0; + container.insert(av); + } + } +} + +status_t PlaybackThread::setAppVolume(const String8& packageName, const float value) +{ + audio_utils::lock_guard _l(mutex()); + for (sp track : mTracks) { + if (packageName == track->getPackageName()) { + track->setAppVolume(value); + } + } + return NO_ERROR; +} + +status_t PlaybackThread::setAppMute(const String8& packageName, const bool value) +{ + audio_utils::lock_guard _l(mutex()); + for (sp track : mTracks) { + if (packageName == track->getPackageName()) { + track->setAppMute(value); + } + } + return NO_ERROR; +} + // ---------------------------------------------------------------------------- // Playback // ---------------------------------------------------------------------------- @@ -5760,16 +5797,16 @@ PlaybackThread::mixer_state MixerThread::prepareTracks_l( if (com_android_media_audio_ring_my_car()) { if (!track->canBypassMute() - && (track->isPlaybackRestricted() || track->getPortMute())) { + && (track->isPlaybackRestricted() || track->getPortMute() || track->isAppMuted())) { volume = 0.f; } else { - volume = masterVolume * track->getPortVolume(); + volume = masterVolume * track->getPortVolume() * track->getAppVolume(); } } else { - if (track->isPlaybackRestricted() || track->getPortMute()) { + if (track->isPlaybackRestricted() || track->getPortMute() || track->isAppMuted()) { volume = 0.f; } else { - volume = masterVolume * track->getPortVolume(); + volume = masterVolume * track->getPortVolume() * track->getAppVolume(); } } @@ -6758,11 +6795,12 @@ void DirectOutputThread::processVolume_l(const sp& track, bool lastTra const auto amn = mAfThreadCallback->getAudioManagerNative(); - if (mMasterMute || track->isPlaybackRestricted()) { + if (mMasterMute || track->isPlaybackRestricted() || track->isAppMuted()) { left = right = 0; } else { float typeVolume = track->getPortVolume(); - const float v = mMasterVolume * typeVolume * shaperVolume; + float appVolume = track->getAppVolume(); + const float v = mMasterVolume * typeVolume * shaperVolume * appVolume; if (left > GAIN_FLOAT_UNITY) { left = GAIN_FLOAT_UNITY; diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 203672508da..cfba6fbde4e 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -1173,6 +1173,10 @@ class PlaybackThread : public ThreadBase, public virtual IAfPlaybackThread, void setVolumeForOutput_l(float left, float right) const final; + status_t setAppVolume(const String8& packageName, const float value) final; + status_t setAppMute(const String8& packageName, const bool muted) final; + void listAppVolumes(std::set &container) final; + sp createTrack_l( const sp& client, audio_stream_type_t streamType, diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 3e395b11ad3..e54615f0628 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -951,6 +951,23 @@ Track::Track( ALOGV_IF(sharedBuffer != 0, "%s(%d): sharedBuffer: %p, size: %zu", __func__, mId, sharedBuffer->unsecurePointer(), sharedBuffer->size()); + /* get package name */ + if (attributionSource.packageName.has_value() && !attributionSource.packageName.value().empty()) { + mPackageName = String8(String16(attributionSource.packageName.value().c_str())); + } else { + const auto& provider = thread->afThreadCallback()->getPermissionProvider(); + const auto res = provider.getPackagesForUid(attributionSource.uid); + if (res.ok() && !res->empty()) { + mPackageName = String8(String16(res->at(0).c_str())); + } else { + mPackageName = ""; + } + } + + /* init app volume */ + mAppMuted = false; + mAppVolume = 1.0f; + if (mCblk == NULL) { return; } @@ -1804,6 +1821,16 @@ void Track::setFinalVolume(float volumeLeft, float volumeRight) } } +void Track::setAppVolume(float volume) +{ + mAppVolume = volume; +} + +void Track::setAppMute(bool val) +{ + mAppMuted = val; +} + void Track::copyMetadataTo(MetadataInserter& backInserter) const { // Do not forward metadata for PatchTrack with unspecified stream type From 6cd6ecc93048ce3410ad5c763de2a07d0465b536 Mon Sep 17 00:00:00 2001 From: someone5678 Date: Sat, 24 Jan 2026 14:42:32 +0100 Subject: [PATCH 47/68] fixup! av: support per-app volume [1/3] * Apply per-app volume to portid_volume_management Change-Id: Id02507e7a426cc0b5c6b1095005d170200f8842a Signed-off-by: Pranav Vashi --- services/audioflinger/Threads.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index e9f2093bd2d..72b15427a1f 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -6006,16 +6006,16 @@ PlaybackThread::mixer_state MixerThread::prepareTracks_l( if (com_android_media_audio_ring_my_car()) { if (!track->canBypassMute() - && (track->isPlaybackRestricted() || track->getPortMute())) { + && (track->isPlaybackRestricted() || track->getPortMute() || track->isAppMuted())) { v = 0; } else { - v = masterVolume * track->getPortVolume(); + v = masterVolume * track->getPortVolume() * track->getAppVolume(); } } else { - if (track->isPlaybackRestricted() || track->getPortMute()) { + if (track->isPlaybackRestricted() || track->getPortMute() || track->isAppMuted()) { v = 0; } else { - v = masterVolume * track->getPortVolume(); + v = masterVolume * track->getPortVolume() * track->getAppVolume(); } } From d4981887413aed782496918e8586752a4247161c Mon Sep 17 00:00:00 2001 From: rmp22 <195054967+rmp22@users.noreply.github.com> Date: Sat, 24 Jan 2026 14:45:42 +0100 Subject: [PATCH 48/68] av: updating syntax for keyed vector -> map transition Change-Id: Ibb5ec56bfc923db417048ab88c90c2a3ed790b20 Signed-off-by: rmp22 <195054967+rmp22@users.noreply.github.com> Signed-off-by: Pranav Vashi --- services/audioflinger/AudioFlinger.cpp | 37 ++++++++++++++++---------- services/audioflinger/Threads.cpp | 2 +- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index f82b660e91d..db95e017869 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -2029,53 +2029,62 @@ status_t AudioFlinger::listAppVolumes(std::vector *vols) { std::set volSet; audio_utils::lock_guard _l(mutex()); - for (size_t i = 0; i < mPlaybackThreads.size(); i++) { - sp thread = mPlaybackThreads.valueAt(i); - thread->listAppVolumes(volSet); + + for (auto& [ioHandle, thread] : mPlaybackThreads) { + if (thread != nullptr) { + thread->listAppVolumes(volSet); + } } vols->insert(vols->begin(), volSet.begin(), volSet.end()); - return NO_ERROR; } status_t AudioFlinger::setAppVolume(const String8& packageName, const float value) { audio_utils::lock_guard _l(mutex()); - for (size_t i = 0; i < mPlaybackThreads.size(); i++) { - sp t = mPlaybackThreads.valueAt(i); - t->setAppVolume(packageName, value); + + for (auto& [ioHandle, thread] : mPlaybackThreads) { + if (thread != nullptr) { + thread->setAppVolume(packageName, value); + } } - if (mAppVolumeConfigs.find(packageName) == mAppVolumeConfigs.end()) { + auto it = mAppVolumeConfigs.find(packageName); + if (it == mAppVolumeConfigs.end()) { media::AppVolume vol; vol.packageName = packageName; vol.volume = value; vol.muted = false; mAppVolumeConfigs[packageName] = vol; } else { - mAppVolumeConfigs[packageName].volume = value; + it->second.volume = value; } + return NO_ERROR; } status_t AudioFlinger::setAppMute(const String8& packageName, const bool value) { audio_utils::lock_guard _l(mutex()); - for (size_t i = 0; i < mPlaybackThreads.size(); i++) { - sp t = mPlaybackThreads.valueAt(i); - t->setAppMute(packageName, value); + + for (auto& [ioHandle, thread] : mPlaybackThreads) { + if (thread != nullptr) { + thread->setAppMute(packageName, value); + } } - if (mAppVolumeConfigs.find(packageName) == mAppVolumeConfigs.end()) { + auto it = mAppVolumeConfigs.find(packageName); + if (it == mAppVolumeConfigs.end()) { media::AppVolume vol; vol.packageName = packageName; vol.volume = 1.0f; vol.muted = value; mAppVolumeConfigs[packageName] = vol; } else { - mAppVolumeConfigs[packageName].muted = value; + it->second.muted = value; } + return NO_ERROR; } diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 72b15427a1f..003112164d7 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2261,7 +2261,7 @@ void PlaybackThread::listAppVolumes(std::set &container) av.packageName = track->getPackageName(); av.muted = track->isAppMuted(); av.volume = track->getAppVolume(); - av.active = mActiveTracks.indexOf(track) >= 0; + av.active = mActiveTracks.count(track) > 0; container.insert(av); } } From cd23f0820a40cd24d64a35d40b90ca6f7c949a0c Mon Sep 17 00:00:00 2001 From: rmp22 <195054967+rmp22@users.noreply.github.com> Date: Sat, 24 Jan 2026 14:48:01 +0100 Subject: [PATCH 49/68] av: updating syntax for IAfTrackBase Change-Id: I767ee8165ec77749b2850eacb877768de8f48eff Signed-off-by: rmp22 <195054967+rmp22@users.noreply.github.com> Signed-off-by: Pranav Vashi --- services/audioflinger/IAfTrack.h | 16 +++++++++++----- services/audioflinger/PlaybackTracks.h | 15 +++++++-------- services/audioflinger/Threads.cpp | 14 ++++++++++---- services/audioflinger/Tracks.cpp | 14 -------------- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h index 15e2137f213..6c5c3ee993e 100644 --- a/services/audioflinger/IAfTrack.h +++ b/services/audioflinger/IAfTrack.h @@ -207,6 +207,12 @@ class IAfTrackBase : public VolumePortInterface { virtual bool isPatchTrack() const = 0; virtual bool isExternalTrack() const = 0; + virtual void setAppVolume(float volume) { (void)volume; } + virtual void setAppMute(bool val) { (void)val; } + virtual float getAppVolume() const { return 1.0f; } + virtual bool isAppMuted() const { return false; } + virtual String8 getPackageName() const { return String8(); } + virtual void invalidate() = 0; virtual bool isInvalid() const = 0; @@ -525,11 +531,11 @@ class IAfTrack : public virtual IAfTrackBase, public virtual AfPlaybackCommon { virtual float getFinalVolume() const = 0; virtual void getFinalVolume(float* left, float* right) const = 0; - virtual void setAppVolume(float volume) = 0; - virtual float getAppVolume() const = 0; - virtual void setAppMute(bool val) = 0; - virtual bool isAppMuted() = 0; - virtual String8 getPackageName() const = 0; + void setAppVolume(float volume) override { IAfTrackBase::setAppVolume(volume); } + float getAppVolume() const override { return IAfTrackBase::getAppVolume(); } + void setAppMute(bool val) override { IAfTrackBase::setAppMute(val); } + bool isAppMuted() const override { return IAfTrackBase::isAppMuted(); } + String8 getPackageName() const override { return IAfTrackBase::getPackageName(); } using SourceMetadatas = std::vector; using MetadataInserter = std::back_insert_iterator; diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index 433a9526bfd..661586662e8 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -162,12 +162,11 @@ class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider { *right = mFinalVolumeRight; } - void setAppVolume(float volume) final; - float getAppVolume() const { return mAppVolume; }; - void setAppMute(bool val) final; - bool isAppMuted() { return mAppMuted; }; - - String8 getPackageName() const { return mPackageName; } + void setAppVolume(float volume) override { mAppVolume = volume; } + float getAppVolume() const override { return mAppVolume; } + void setAppMute(bool val) override { mAppMuted = val; } + bool isAppMuted() const override { return mAppMuted; } + String8 getPackageName() const override { return mPackageName; } using SourceMetadatas = std::vector; using MetadataInserter = std::back_insert_iterator; @@ -417,8 +416,8 @@ class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider { // volume float mFinalVolumeRight; // combine master volume, stream type volume and track // volume - float mAppVolume; // volume control for separate processes - bool mAppMuted; + float mAppVolume = 1.0f; // volume control for separate processes + bool mAppMuted = false; sp mAudioTrackServerProxy; bool mResumeToStopping; // track was paused in stopping state. bool mFlushHwPending; // track requests for thread flush diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 003112164d7..7b54613e847 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2254,14 +2254,16 @@ void ThreadBase::checkUpdateTrackMetadataForUid(uid_t uid) { void PlaybackThread::listAppVolumes(std::set &container) { - audio_utils::lock_guard _l(mutex()); - for (sp track : mTracks) { + audio_utils::lock_guard _l(mutex()); + + for (const sp& track : mTracks) { if (!track->getPackageName().empty()) { media::AppVolume av; av.packageName = track->getPackageName(); av.muted = track->isAppMuted(); av.volume = track->getAppVolume(); av.active = mActiveTracks.count(track) > 0; + container.insert(av); } } @@ -2270,22 +2272,26 @@ void PlaybackThread::listAppVolumes(std::set &container) status_t PlaybackThread::setAppVolume(const String8& packageName, const float value) { audio_utils::lock_guard _l(mutex()); - for (sp track : mTracks) { + + for (const sp& track : mTracks) { if (packageName == track->getPackageName()) { track->setAppVolume(value); } } + return NO_ERROR; } status_t PlaybackThread::setAppMute(const String8& packageName, const bool value) { audio_utils::lock_guard _l(mutex()); - for (sp track : mTracks) { + + for (const sp& track : mTracks) { if (packageName == track->getPackageName()) { track->setAppMute(value); } } + return NO_ERROR; } diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index e54615f0628..fef8a7d9ee2 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -964,10 +964,6 @@ Track::Track( } } - /* init app volume */ - mAppMuted = false; - mAppVolume = 1.0f; - if (mCblk == NULL) { return; } @@ -1821,16 +1817,6 @@ void Track::setFinalVolume(float volumeLeft, float volumeRight) } } -void Track::setAppVolume(float volume) -{ - mAppVolume = volume; -} - -void Track::setAppMute(bool val) -{ - mAppMuted = val; -} - void Track::copyMetadataTo(MetadataInserter& backInserter) const { // Do not forward metadata for PatchTrack with unspecified stream type From fa46990d1cfb4cf06e7c5b265edb53d84e9ecfaa Mon Sep 17 00:00:00 2001 From: Adithya R Date: Sat, 24 Jan 2026 14:50:56 +0100 Subject: [PATCH 50/68] audio: Check MODIFY_AUDIO_ROUTING permission for per-app volume We need to use this from SystemUI which runs under app uid. Instead check for MODIFY_AUDIO_ROUTING permission which is granted only to select system apps (including SystemUI) and also matches the API @RequiresPermission annotation in framework. Change-Id: Ib78565c15cbdc8619bf94240a2329e97fd40c6a9 Signed-off-by: Pranav Vashi --- services/audioflinger/AudioFlinger.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index db95e017869..ff472f44bff 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -101,6 +101,7 @@ using com::android::media::permission::IPermissionProvider; using com::android::media::permission::NativePermissionController; using com::android::media::permission::PermissionEnum; using com::android::media::permission::PermissionEnum::MODIFY_AUDIO_SETTINGS; +using com::android::media::permission::PermissionEnum::MODIFY_AUDIO_ROUTING; using com::android::media::permission::ValidatedAttributionSourceState; static const AudioHalVersionInfo kMaxAAudioPropertyDeviceHalVersion = @@ -5175,6 +5176,24 @@ status_t AudioFlinger::onTransactWrapper(TransactionCode code, break; } + // make sure the following transactions require MODIFY_AUDIO_ROUTING permission + switch (code) { + case TransactionCode::SET_APP_VOLUME: + case TransactionCode::SET_APP_MUTE: { + const uid_t callingUid = IPCThreadState::self()->getCallingUid(); + const auto res = getPermissionProvider().checkPermission(MODIFY_AUDIO_ROUTING, callingUid); + if (!res.ok() || !res.value()) { + ALOGW("%s: transaction %d received from PID %d UID %d does not have " + "MODIFY_AUDIO_ROUTING permission", + __func__, static_cast(code), IPCThreadState::self()->getCallingPid(), + callingUid); + return INVALID_OPERATION; + } + } break; + default: + break; + } + const std::string methodName = getIAudioFlingerStatistics().getMethodForCode(code); mediautils::TimeCheck check( std::string("IAudioFlinger::").append(methodName), From 088bf74e9863fbf542f3cb865afd7fdf385bb19c Mon Sep 17 00:00:00 2001 From: rmp22 <195054967+rmp22@users.noreply.github.com> Date: Tue, 16 Dec 2025 09:05:28 +0800 Subject: [PATCH 51/68] fixing visualizer not working on bluetooth audio Change-Id: If4a63ad1d892af3fb1f87d9b3b1128ab59a106c9 Signed-off-by: rmp22 <195054967+rmp22@users.noreply.github.com> Signed-off-by: Pranav Vashi --- .../common/managerdefinitions/src/EffectDescriptor.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp index a49d588b04b..c81cf11a9ca 100644 --- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp @@ -22,6 +22,7 @@ #include "AudioInputDescriptor.h" #include "EffectDescriptor.h" #include +#include #include #include @@ -175,6 +176,14 @@ bool EffectDescriptorCollection::isNonOffloadableEffectEnabled( effectDesc->mSession); return true; } + // Also check for Visualizer effects on global session (AUDIO_SESSION_OUTPUT_MIX = 0) + // Visualizer needs audio to go through the mixer to capture it, so block offload + if (effectDesc->mEnabled && + effectDesc->mSession == AUDIO_SESSION_OUTPUT_MIX && + memcmp(&effectDesc->mDesc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) { + ALOGV("%s: visualizer effect enabled on global session, blocking offload", __func__); + return true; + } } return false; } From 7bfda39e077b678d3ccf2ae4e53b031e432c1e09 Mon Sep 17 00:00:00 2001 From: Abdelrahman Daim Date: Wed, 23 Jul 2025 11:33:40 -0700 Subject: [PATCH 52/68] fix null derefence exception when surface is reset Summary: when media player is stopped flush is called to flush the remaining buffer and the output surface is set to null. However while the buffer is getting flushed the output can still be used causing the null dereference crash. This diff adds a check in renderOneBufferItem_l to check if output is valid and go through the regular abandon flow instead of using the null output. Test: successful build on master Change-Id: Ic3d6707e2f8e0943ca2368a8e50ea683b6dac46a Signed-off-by: Abdelrahman Daim --- media/libstagefright/MediaSync.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp index 1891954d63a..f87df899d9f 100644 --- a/media/libstagefright/MediaSync.cpp +++ b/media/libstagefright/MediaSync.cpp @@ -717,6 +717,13 @@ void MediaSync::onFrameAvailableFromInput() { } void MediaSync::renderOneBufferItem_l(const BufferItem &bufferItem) { + if (!mOutput) { + // If the output has been abandoned, move on. + ALOGD("output is abandoned"); + onAbandoned_l(false /* isInput */); + return; + } + IGraphicBufferProducer::QueueBufferInput queueInput( bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp, From d445983706b45ea0d03fc917546d7e743fa78f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Sebechlebsk=C3=BD?= Date: Mon, 23 Mar 2026 05:40:08 -0700 Subject: [PATCH 53/68] Fix PlanesLockGuard buffer lock leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PlanesLockGuard constructor never stored hwBuffer into mHwBuffer. The destructor checks mHwBuffer == nullptr and bails out, so AHardwareBuffer_unlock was never called — leaking a buffer lock on every JPEG capture. Test: atest virtual_camera_tests Change-Id: I1a0a2f56faf7aa4178178f3dbd98d5f9ceac5bfa --- services/camera/virtualcamera/util/Util.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/services/camera/virtualcamera/util/Util.cc b/services/camera/virtualcamera/util/Util.cc index 26015d1d5c5..c92177e7e90 100644 --- a/services/camera/virtualcamera/util/Util.cc +++ b/services/camera/virtualcamera/util/Util.cc @@ -99,6 +99,7 @@ PlanesLockGuard::PlanesLockGuard(std::shared_ptr hwBuffer, if (rawFence >= 0) { close(rawFence); } + mHwBuffer = hwBuffer; } PlanesLockGuard::~PlanesLockGuard() { From 9d0820ac694112c05a28613eea325f6c1c113bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Sebechlebsk=C3=BD?= Date: Mon, 23 Mar 2026 06:04:35 -0700 Subject: [PATCH 54/68] Fix PlanesLockGuard::getStatus() return type Implementation declared int return type while the header and sister class YCbCrLockGuard both use status_t. Align the implementation to match. Test: atest virtual_camera_tests Change-Id: I069417febdae83d5567243a2507231412bd47687 --- services/camera/virtualcamera/util/Util.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/camera/virtualcamera/util/Util.cc b/services/camera/virtualcamera/util/Util.cc index c92177e7e90..b9ba1bb088b 100644 --- a/services/camera/virtualcamera/util/Util.cc +++ b/services/camera/virtualcamera/util/Util.cc @@ -109,7 +109,7 @@ PlanesLockGuard::~PlanesLockGuard() { AHardwareBuffer_unlock(mHwBuffer.get(), /*fence=*/nullptr); } -int PlanesLockGuard::getStatus() const { +status_t PlanesLockGuard::getStatus() const { return mLockStatus; } From a73eb19aae805e979c9407858fb9210ca4c3be19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Sebechlebsk=C3=BD?= Date: Mon, 23 Mar 2026 06:06:15 -0700 Subject: [PATCH 55/68] Fix PlanesLockGuard copy-assignment delete type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The deleted copy-assignment operator had wrong parameter type YCbCrLockGuard instead of PlanesLockGuard — a copy-paste error from the sister class. Test: atest virtual_camera_tests Change-Id: Ibe7e11f08ba0cd401c13ea58304a3722bc3ab65a --- services/camera/virtualcamera/util/Util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/camera/virtualcamera/util/Util.h b/services/camera/virtualcamera/util/Util.h index 1ebcc6d08c9..ff0622b1601 100644 --- a/services/camera/virtualcamera/util/Util.h +++ b/services/camera/virtualcamera/util/Util.h @@ -92,7 +92,7 @@ class PlanesLockGuard { // Disable copy. PlanesLockGuard(const PlanesLockGuard&) = delete; - PlanesLockGuard& operator=(const YCbCrLockGuard&) = delete; + PlanesLockGuard& operator=(const PlanesLockGuard&) = delete; private: std::shared_ptr mHwBuffer; From 0bfce8691b64544975497a574bd6a5e29d19220d Mon Sep 17 00:00:00 2001 From: "Zhang, Fan" Date: Tue, 31 Mar 2026 16:36:38 +0800 Subject: [PATCH 56/68] Adapt dynamic resolution in nuplayer with enable sample aspect ratio parameter [Why] C2 parameter of changing picture size will be overridden if mediaplayer doesn't enable sample aspect ratio [How] Add sample aspect ratio to input format if compontent output format contains aspect ratio parameter change Change-Id: I8ad6aa68f9f5e2ec2446d4653fd0af6129b9d2ae --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index dcd79a9d1fd..4a1b6064c13 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -1144,6 +1144,13 @@ void NuPlayer::onMessageReceived(const sp &msg) { sp inputFormat = mSource->getFormat(false /* audio */); + int32_t sarWidth = 0, sarHeight = 0; + if (format->findInt32("sar-width", &sarWidth) && format->findInt32("sar-height", &sarHeight) && sarWidth > 0 + && sarHeight > 0) { + inputFormat->setInt32("sar-width", sarWidth); + inputFormat->setInt32("sar-height", sarHeight); + } + setVideoScalingMode(mVideoScalingMode); updateVideoSize(inputFormat, format); } else if (what == DecoderBase::kWhatShutdownCompleted) { From 982e22b3588d7b4cf155120850c2fa5f6ab1ea1b Mon Sep 17 00:00:00 2001 From: Abhay Singh Gill Date: Sat, 2 Aug 2025 12:50:11 +0530 Subject: [PATCH 57/68] Revert "MultiAccessUnit reflector helper allocated once per ComponentStore" Breaks dolby decoders This reverts commit 07b6b1570b4d4b77bfd5ec12aa56dda2e449ee6b. Signed-off-by: Debayan Kar Signed-off-by: Ghosuto Signed-off-by: Pranav Vashi --- media/codec2/hal/aidl/ComponentStore.cpp | 11 +++-------- .../hal/aidl/include/codec2/aidl/ComponentStore.h | 3 --- media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp | 13 ++++--------- .../utils/include/codec2/hidl/1.0/ComponentStore.h | 3 --- media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp | 13 ++++--------- .../utils/include/codec2/hidl/1.1/ComponentStore.h | 3 --- media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp | 12 +++--------- .../utils/include/codec2/hidl/1.2/ComponentStore.h | 3 --- 8 files changed, 14 insertions(+), 47 deletions(-) diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp index 4daa6c8d4ff..adb0b6a3762 100644 --- a/media/codec2/hal/aidl/ComponentStore.cpp +++ b/media/codec2/hal/aidl/ComponentStore.cpp @@ -156,13 +156,6 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) mParamReflectors.push_back(paramReflector); } #endif - // MultiAccessUnit reflector helper is allocated once per store. - // All components in this store can reuse this reflector helper. - if (MultiAccessUnitHelper::isEnabledOnPlatform()) { - std::shared_ptr helper = std::make_shared(); - mParamReflectors.push_back(helper); - mMultiAccessUnitReflector = helper; - } // Retrieve supported parameters from store using namespace std::placeholders; @@ -250,9 +243,11 @@ std::shared_ptr ComponentStore::tryCreateMultiAccessUn // 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]. + std::shared_ptr multiAccessReflector(new C2ReflectorHelper()); multiAccessUnitIntf = std::make_shared( c2interface, - mMultiAccessUnitReflector); + multiAccessReflector); + mParamReflectors.push_back(multiAccessReflector); } } } diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h index bb4c596cba7..0e8ac41dce8 100644 --- a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h +++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h @@ -127,9 +127,6 @@ struct ComponentStore : public BnComponentStore { std::shared_ptr mStore; std::vector> mParamReflectors; - // Reflector helper for MultiAccessUnitHelper - std::shared_ptr mMultiAccessUnitReflector; - std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; std::set mLoadedInterfaces; diff --git a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp index 664088a8965..1584d6269b1 100644 --- a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp +++ b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp @@ -146,14 +146,6 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) } #endif - // MultiAccessUnit reflector helper is allocated once per store. - // All components in this store can reuse this reflector helper. - if (MultiAccessUnitHelper::isEnabledOnPlatform()) { - std::shared_ptr helper = std::make_shared(); - mParamReflectors.push_back(helper); - mMultiAccessUnitReflector = helper; - } - // Retrieve supported parameters from store using namespace std::placeholders; mInit = mConfigurable->init(mParameterCache); @@ -236,9 +228,12 @@ std::shared_ptr ComponentStore::tryCreateMultiAccessUn } } if (!isComponentSupportsLargeAudioFrame) { + std::shared_ptr multiAccessReflector(new C2ReflectorHelper()); multiAccessUnitIntf = std::make_shared( c2interface, - mMultiAccessUnitReflector); + multiAccessReflector); + mParamReflectors.push_back(multiAccessReflector); + } } } 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 028238bd24a..07ffa219ecd 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 @@ -131,9 +131,6 @@ struct ComponentStore : public IComponentStore { std::shared_ptr mStore; std::vector> mParamReflectors; - // Reflector helper for MultiAccessUnitHelper - std::shared_ptr mMultiAccessUnitReflector; - std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; std::set mLoadedInterfaces; diff --git a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp index 15f4d68b896..a715fdc7f6e 100644 --- a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp +++ b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp @@ -146,14 +146,6 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) } #endif - // MultiAccessUnit reflector helper is allocated once per store. - // All components in this store can reuse this reflector helper. - if (MultiAccessUnitHelper::isEnabledOnPlatform()) { - std::shared_ptr helper = std::make_shared(); - mParamReflectors.push_back(helper); - mMultiAccessUnitReflector = helper; - } - // Retrieve supported parameters from store using namespace std::placeholders; mInit = mConfigurable->init(mParameterCache); @@ -235,10 +227,13 @@ std::shared_ptr ComponentStore::tryCreateMultiAccessUn break; } } + if (!isComponentSupportsLargeAudioFrame) { + std::shared_ptr multiAccessReflector(new C2ReflectorHelper()); multiAccessUnitIntf = std::make_shared( c2interface, - mMultiAccessUnitReflector); + multiAccessReflector); + mParamReflectors.push_back(multiAccessReflector); } } } 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 b0231151b38..5dcb359d4df 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 @@ -139,9 +139,6 @@ struct ComponentStore : public IComponentStore { std::shared_ptr mStore; std::vector> mParamReflectors; - // Reflector helper for MultiAccessUnitHelper - std::shared_ptr mMultiAccessUnitReflector; - std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; std::set mLoadedInterfaces; diff --git a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp index aa498191851..ca047b043aa 100644 --- a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp +++ b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp @@ -146,14 +146,6 @@ ComponentStore::ComponentStore(const std::shared_ptr& store) } #endif - // MultiAccessUnit reflector helper is allocated once per store. - // All components in this store can reuse this reflector helper. - if (MultiAccessUnitHelper::isEnabledOnPlatform()) { - std::shared_ptr helper = std::make_shared(); - mParamReflectors.push_back(helper); - mMultiAccessUnitReflector = helper; - } - // Retrieve supported parameters from store using namespace std::placeholders; mInit = mConfigurable->init(mParameterCache); @@ -236,9 +228,11 @@ std::shared_ptr ComponentStore::tryCreateMultiAccessUn } } if (!isComponentSupportsLargeAudioFrame) { + std::shared_ptr multiAccessReflector(new C2ReflectorHelper()); multiAccessUnitIntf = std::make_shared( c2interface, - mMultiAccessUnitReflector); + multiAccessReflector); + mParamReflectors.push_back(multiAccessReflector); } } } 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 a7e043bc5f0..16a524093c8 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 @@ -146,9 +146,6 @@ struct ComponentStore : public IComponentStore { std::shared_ptr mStore; std::vector> mParamReflectors; - // Reflector helper for MultiAccessUnitHelper - std::shared_ptr mMultiAccessUnitReflector; - std::map> mStructDescriptors; std::set mUnsupportedStructDescriptors; std::set mLoadedInterfaces; From f74dbad5a0dba20b0e46d84ee376f5e204bbfa35 Mon Sep 17 00:00:00 2001 From: Rashid Zaman Date: Tue, 14 Apr 2026 13:18:04 -0700 Subject: [PATCH 58/68] MediaSync: fix nullptr dereference when detachNextBuffer fails MediaSync::onBufferReleasedByOutput is called via the IProducerListener::onBufferReleased callback when the output Surface's BufferQueueConsumer::releaseBuffer is called. It calls mOutput->detachNextBuffer() to retrieve the released buffer from the output Surface's producer, but only handles the NO_INIT error code, falling through to dereference the buffer sp<> (which is nullptr on any error) for all other error codes. When the output Surface's BnGraphicBufferProducer is hosted in a different process than MediaSync, detachNextBuffer is a binder call that can return DEAD_OBJECT (-32) or FAILED_TRANSACTION (-2147483646) if that process dies or has its binder interface frozen, causing a nullptr dereference (SIGSEGV). These errors arise from two distinct races: 1. DEAD_OBJECT: If the process hosting the output Surface's BnGraphicBufferProducer sends an onBufferReleased binder transaction to MediaSync's IProducerListener and then dies before MediaSync calls detachNextBuffer, detachNextBuffer targets the dead process and returns DEAD_OBJECT. Because onBufferReleased is a oneway binder transaction, it is not guaranteed to be processed before the death notification is delivered and binderDied runs, though in the common case it will be. If the death notification is delivered while onBufferReleasedByOutput holds mMutex, binderDied blocks on mMutex and cannot run cleanup before the nullptr dereference. If it has not yet been delivered, onBufferReleasedByOutput completes (and crashes) before binderDied runs at all. 2. FAILED_TRANSACTION: If the process hosting the output Surface's BnGraphicBufferProducer sends an onBufferReleased binder transaction to MediaSync's IProducerListener and then has its binder interface frozen before MediaSync calls detachNextBuffer, detachNextBuffer targets the frozen process and returns FAILED_TRANSACTION. This race became possible in Android 11 when commit 3e91d35fa70a ("CachedAppOptimizer: freeze/unfreeze binder") introduced binder interface freezing for cached apps freezing and can also manifest through other paths outside of cached apps freezer such as ActivityManager.forceStopPackage() since commit 79825c6f2f8b ("Freeze package cgroup before killing") in Android 14 extended binder interface freezing to ProcessList.killPackageProcessesLSP(). These races can manifest, for example, when a Surface from a SurfaceView in one app process is passed over Binder to a different app process that creates a MediaSync with it as output. The SurfaceView's BLASTBufferQueue creates the BnGraphicBufferProducer in the first process, so detachNextBuffer from the process hosting the MediaSync to the process hosting the BnGraphicBufferProducer is a cross-process binder call subject to both races above. Fix this by returning early from onBufferReleasedByOutput when detachNextBuffer returns any error other than NO_INIT. The buffer sp<> is nullptr in this case. For DEAD_OBJECT, the existing binderDied cleanup path will handle teardown once it is delivered and acquires mMutex. FAILED_TRANSACTION is returned when the binder driver returns BR_FROZEN_REPLY or BR_FAILED_REPLY, which are indistinguishable in userspace. For FAILED_TRANSACTION from BR_FROZEN_REPLY, when the binder interface of the process hosting the output Surface's BnGraphicBufferProducer is frozen as part of killing package processes the freeze is immediately followed by SIGKILL, so binderDied handles cleanup the same way as the DEAD_OBJECT case. When the binder interface is frozen for cached apps freezing, since detachNextBuffer is a synchronous binder transaction, this results in the process being killed when it is unfrozen due to the behavior introduced in commit 5b5fdb80ec9f ("ActivityManager: kill frozen processes receiving sync transactions"), so binderDied again handles cleanup. For FAILED_TRANSACTION from BR_FAILED_REPLY, returning early strands the buffer in the output Surface BufferQueue and inflates mNumOutstandingBuffers, but this is strictly better than the pre-existing nullptr dereference (SIGSEGV). Also add tests to verify that onBufferReleasedByOutput handles errors from detachNextBuffer without crashing. Flag: EXEMPT bugfix Test: PoC app using MediaSync SDK API with output Surface in a separate process crashes without fix and no longer crashes with fix on aosp_cf_x86_64_phone-bp4a-eng Test: atest MediaSyncTest on aosp_cf_x86_64_phone-bp4a-eng Test: atest CtsMediaMiscTestCases:android.media.misc.cts.MediaSyncTest on aosp_cf_x86_64_phone-bp4a-eng Change-Id: Ie73f75fed37438684c969a95de415eab9013b48c --- media/libstagefright/MediaSync.cpp | 24 +++++ .../libstagefright/tests/mediasync/Android.bp | 53 +++++++++++ .../tests/mediasync/MediaSyncTest.cpp | 88 +++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 media/libstagefright/tests/mediasync/Android.bp create mode 100644 media/libstagefright/tests/mediasync/MediaSyncTest.cpp diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp index f87df899d9f..4390c15c125 100644 --- a/media/libstagefright/MediaSync.cpp +++ b/media/libstagefright/MediaSync.cpp @@ -787,6 +787,30 @@ void MediaSync::onBufferReleasedByOutput(sp &output) { return; } + if (status != NO_ERROR) { + // For any other error such as DEAD_OBJECT or + // FAILED_TRANSACTION, the buffer sp<> is nullptr. For + // DEAD_OBJECT, the binderDied callback will handle cleanup + // once it is delivered and acquires mMutex. + // FAILED_TRANSACTION is returned when the binder driver + // returns BR_FROZEN_REPLY or BR_FAILED_REPLY, which are + // indistinguishable in userspace. For BR_FROZEN_REPLY the + // process hosting the output Surface's + // BnGraphicBufferProducer always ends up dead. In the + // freeze-before-kill case, SIGKILL follows immediately. In + // the cached apps freezing case, detachNextBuffer is a + // synchronous binder transaction to the frozen process and + // when unfreezing ActivityManager kills any frozen process + // that received a synchronous binder transaction instead + // of unfreezing it. In both cases binderDied handles + // cleanup. NOTE: For BR_FAILED_REPLY, returning early strands + // the buffer in the output Surface BufferQueue and + // inflates mNumOutstandingBuffers, but this is strictly + // better than the nullptr dereference that occurs without + // this check. + return; + } + ALOGV("detached buffer %#llx from output", (long long)buffer->getId()); // If we've been abandoned, we can't return the buffer to the input, so just diff --git a/media/libstagefright/tests/mediasync/Android.bp b/media/libstagefright/tests/mediasync/Android.bp new file mode 100644 index 00000000000..3d5d41b85d0 --- /dev/null +++ b/media/libstagefright/tests/mediasync/Android.bp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2026 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: [ + "frameworks_av_media_libstagefright_tests_license", + ], +} + +cc_test { + name: "MediaSyncTest", + + srcs: [ + "MediaSyncTest.cpp", + ], + + header_libs: [ + "libnativewindow_headers", + ], + + shared_libs: [ + "libbinder", + "libgui", + "libstagefright", + "libutils", + ], + + static_libs: [ + "libgmock", + "libgui_mocks", + ], + + cflags: [ + "-Werror", + ], + + test_suites: [ + "device-tests", + ], +} diff --git a/media/libstagefright/tests/mediasync/MediaSyncTest.cpp b/media/libstagefright/tests/mediasync/MediaSyncTest.cpp new file mode 100644 index 00000000000..7de965700cf --- /dev/null +++ b/media/libstagefright/tests/mediasync/MediaSyncTest.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2026 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace android; +using ::testing::_; +using ::testing::Return; + +class MediaSyncTest : public ::testing::Test { + protected: + MediaSyncTest() { + ON_CALL(*mMockProducer, connect(_, _, _, _)) + .WillByDefault([this](const sp& listener, int, bool, + IGraphicBufferProducer::QueueBufferOutput* output) { + mCapturedListener = listener; + *output = IGraphicBufferProducer::QueueBufferOutput(); + return NO_ERROR; + }); + + ON_CALL(*mMockProducer, query(_, _)).WillByDefault([](int what, int* value) { + switch (what) { + case NATIVE_WINDOW_CONSUMER_USAGE_BITS: + *value = 0; + return NO_ERROR; + case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: + *value = 1; + return NO_ERROR; + default: + return BAD_VALUE; + } + }); + } + + void setSurfaceAndCaptureListener() { ASSERT_EQ(OK, mMediaSync->setSurface(mMockProducer)); } + + sp mMockProducer = + sp<::testing::NiceMock>::make(); + sp mMediaSync = MediaSync::create(); + sp mCapturedListener; +}; + +// Verify that onBufferReleasedByOutput handles DEAD_OBJECT from +// detachNextBuffer without crashing. +TEST_F(MediaSyncTest, DetachNextBufferReturnsDeadObject) { + setSurfaceAndCaptureListener(); + EXPECT_CALL(*mMockProducer, detachNextBuffer(_, _)).WillOnce(Return(DEAD_OBJECT)); + mCapturedListener->onBufferReleased(); +} + +// Verify that onBufferReleasedByOutput handles FAILED_TRANSACTION from +// detachNextBuffer without crashing. +TEST_F(MediaSyncTest, DetachNextBufferReturnsFailedTransaction) { + setSurfaceAndCaptureListener(); + EXPECT_CALL(*mMockProducer, detachNextBuffer(_, _)).WillOnce(Return(FAILED_TRANSACTION)); + mCapturedListener->onBufferReleased(); +} + +// Verify that onBufferReleasedByOutput handles NO_INIT from +// detachNextBuffer without crashing. +TEST_F(MediaSyncTest, DetachNextBufferReturnsNoInit) { + setSurfaceAndCaptureListener(); + sp inputProducer; + ASSERT_EQ(OK, mMediaSync->createInputSurface(&inputProducer)); + EXPECT_CALL(*mMockProducer, detachNextBuffer(_, _)).WillOnce(Return(NO_INIT)); + mCapturedListener->onBufferReleased(); +} From 90f37d218ea54fea7c0153243ff76f665efe6416 Mon Sep 17 00:00:00 2001 From: Rashid Zaman Date: Wed, 22 Apr 2026 01:09:13 -0700 Subject: [PATCH 59/68] MediaSync: remove InputListener death recipient dead code Commit b62ae14731 ("bufferqueues: Replace usage of BnConsumerListener with IConsumerListener") removed the linkToDeath registration on the input IGraphicBufferConsumer as part of a topic that removed binder support for IGraphicBufferConsumer entirely. However, it left InputListener derived from IBinder::DeathRecipient with a binderDied implementation that can no longer be called. Remove the IBinder::DeathRecipient base class and binderDied method from InputListener as this is dead code. Flag: EXEMPT remove dead code Test: atest CtsMediaMiscTestCases:android.media.misc.cts.MediaSyncTest on aosp_cf_x86_64_phone-bp4a-eng Change-Id: I7618c52cbb36db67ad0db54987001ae2fac7083b --- media/libstagefright/MediaSync.cpp | 6 ------ media/libstagefright/include/media/stagefright/MediaSync.h | 5 +---- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp index 4390c15c125..d7721f651bf 100644 --- a/media/libstagefright/MediaSync.cpp +++ b/media/libstagefright/MediaSync.cpp @@ -928,12 +928,6 @@ void MediaSync::InputListener::onFrameAvailable(const BufferItem &/* item */) { void MediaSync::InputListener::onSidebandStreamChanged() { ALOGE("onSidebandStreamChanged: got sideband stream unexpectedly."); } - - -void MediaSync::InputListener::binderDied(const wp &/* who */) { - Mutex::Autolock lock(mSync->mMutex); - mSync->onAbandoned_l(true /* isInput */); -} #endif MediaSync::OutputListener::OutputListener(const sp &sync, diff --git a/media/libstagefright/include/media/stagefright/MediaSync.h b/media/libstagefright/include/media/stagefright/MediaSync.h index f6f36bbab33..beece1666bb 100644 --- a/media/libstagefright/include/media/stagefright/MediaSync.h +++ b/media/libstagefright/include/media/stagefright/MediaSync.h @@ -151,7 +151,7 @@ class MediaSync : public AHandler { #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_MEDIA_MIGRATION) class InputListener : public BufferItemConsumer::FrameAvailableListener { #else - class InputListener : public IConsumerListener, public IBinder::DeathRecipient { + class InputListener : public IConsumerListener { #endif public: InputListener(const sp &sync); @@ -171,9 +171,6 @@ class MediaSync : public AHandler { // From IConsumerListener // We don't care about sideband streams, since we won't relay them. virtual void onSidebandStreamChanged(); - - // From IBinder::DeathRecipient - virtual void binderDied(const wp &who); #endif private: From 44c63d687f36bb0bca9a717bec368bf7443c9463 Mon Sep 17 00:00:00 2001 From: Rashid Zaman Date: Tue, 5 May 2026 16:13:20 -0700 Subject: [PATCH 60/68] MediaSync: fix nullptr dereference in onAbandoned_l on output death When MediaSync::OutputListener::binderDied fires because the process hosting the output Surface's BnGraphicBufferProducer has died, it calls MediaSync::onAbandoned_l on the output-abandoned path, which dereferences mInput. However, mInput is only assigned in createInputSurface(). When that process dies before createInputSurface() has been called, this can lead to a nullptr dereference of mInput depending on the outcome of a race between two libbinder code paths that the binder driver triggers in the MediaSync process in response to that death. Both paths operate on the OutputListener BBinder's strong refcount, and they run on binder threads in the MediaSync process, possibly in parallel: 1. wp::promote() inside BpBinder::reportOneDeath, called when the binder driver delivers BR_DEAD_BINDER. If promote succeeds, it returns a strong reference and binderDied is invoked, which calls onAbandoned_l and dereferences mInput. 2. decStrong on the OutputListener BBinder, called by libbinder in response to BR_RELEASE. The binder driver delivers BR_RELEASE because the strong reference held by the output BufferQueue's mConnectedProducerListener in the (now-dead) process is dropped when the binder driver releases the dying process's binder references. If decStrong drops the OutputListener's strong refcount to zero before (1) runs, the OutputListener is destroyed and (1)'s promote returns nullptr, so binderDied is never invoked. If (1) wins the race, onAbandoned_l runs with a null mInput, causing the SIGSEGV. Since mInput is only assigned in createInputSurface() and never cleared, it is null exactly when createInputSurface() has not been called. Fix the SIGSEGV by skipping the mInput dereference on the output-abandoned path in that case. Flag: EXEMPT bugfix Test: PoC app that uses MediaSync SDK API with output Surface in a separate process, without calling createInputSurface(), and kills the separate process: crashes within a few iterations without fix and no longer crashes with fix on aosp_cf_x86_64_phone-bp4a-eng Test: atest MediaSyncTest on aosp_cf_x86_64_phone-bp4a-eng Test: atest CtsMediaMiscTestCases:android.media.misc.cts.MediaSyncTest on aosp_cf_x86_64_phone-bp4a-eng Change-Id: I86b042a71bf7d8a5e5705d2965f714396e44a17d --- media/libstagefright/MediaSync.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp index d7721f651bf..18152a3d45d 100644 --- a/media/libstagefright/MediaSync.cpp +++ b/media/libstagefright/MediaSync.cpp @@ -873,7 +873,10 @@ void MediaSync::onAbandoned_l(bool isInput) { if (!mIsAbandoned) { if (isInput) { mOutput->disconnect(NATIVE_WINDOW_API_MEDIA); - } else { + } else if (mInput != nullptr) { + // mInput is only assigned in createInputSurface(); guard against + // the case where the process hosting the output Surface's + // BnGraphicBufferProducer dies before that's called. #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_MEDIA_MIGRATION) mInput->abandon(); #else From 2be627e84ee417cf904b2a98a2d1bcfc91dc280a Mon Sep 17 00:00:00 2001 From: Adrian Kuehn Date: Thu, 21 May 2026 02:22:40 -0700 Subject: [PATCH 61/68] Fix Active Array Size calculation logic This diff fixes the calculation logic in getMaxResolution(). Test: atest virtual_camera_tests Change-Id: I5bd28804856885ffec001bcc3b6be964c826eabe --- services/camera/virtualcamera/VirtualCameraDevice.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/camera/virtualcamera/VirtualCameraDevice.cc b/services/camera/virtualcamera/VirtualCameraDevice.cc index dd0d73ea014..3db0409d57a 100644 --- a/services/camera/virtualcamera/VirtualCameraDevice.cc +++ b/services/camera/virtualcamera/VirtualCameraDevice.cc @@ -163,7 +163,7 @@ std::optional getMaxResolution( auto itMax = std::max_element(configs.begin(), configs.end(), [](const SupportedStreamConfiguration& a, const SupportedStreamConfiguration& b) { - return a.width * b.height < a.width * b.height; + return a.width * a.height < b.width * b.height; }); if (itMax == configs.end()) { ALOGE( From b31f3d6f843414a80cc5db278ba6e53b8f242fda Mon Sep 17 00:00:00 2001 From: Sui Jiang Date: Thu, 21 May 2026 02:14:20 -0700 Subject: [PATCH 62/68] Explicitly initialize chrono types in VirtualCameraRenderThread mLastAcquisitionTimestampNanoseconds wasn't initialized explicilty. If it was initialized to a random large number, it would cause ``` const std::chrono::nanoseconds frameDuration = timestamp - lastAcquisitionTimestamp; ``` to be a large negative number, which would cause ``` const std::chrono::nanoseconds sleepTime = minFrameDuration - frameDuration; ``` to be a large number, causing the thread to sleep for a long time. Change-Id: I1e3ec7423398aab88110d5c78c35f0c903295234 --- services/camera/virtualcamera/VirtualCameraRenderThread.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc index d1b1ff46c4c..ad4502a03dd 100644 --- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc +++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc @@ -292,6 +292,11 @@ VirtualCameraRenderThread::VirtualCameraRenderThread( mInputSurfaceSize(inputSurfaceSize), mReportedSensorSize(reportedSensorSize), mSessionContext(sessionContext), + mLastAcquisitionTimestampNanoseconds( + std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()) + .count()), + mLastSurfaceTimestampNanoseconds(0), mInputSurfaceFuture(mInputSurfacePromise.get_future()) { } From 6bc717cc5adb61e2304773c50b3d6fbac1b9e597 Mon Sep 17 00:00:00 2001 From: Hecheng Yu Date: Sun, 31 May 2026 19:02:32 +0800 Subject: [PATCH 63/68] CameraService: Add OnePlus camera extension support for zoom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add necessary stubs and hooks to load and delegate Binder transactions to the proprietary OnePlus camera extension library (libcsextimpl.so). - Add empty ICameraServiceExt constructor/destructor to satisfy linker symbols required by the extension. - Implement CameraServiceExtFactory to dlopen libcsextimpl.so, resolve getExtFactoryImpl and onTransact symbols, and provide a function table as expected by OxygenOS. - Hook CameraService::onTransact: delegate all non‑shell commands to CameraServiceExtFactory::onTransact, which calls the extension's onTransact method. This handles transaction 10015 (CMD_UI_EVENT) used for zoom. - Add missing CameraSessionStats constants (CAMERA_STATE_EXCEPTION, CAMERA_STATE_SESSION_CONFIGURED, CAMERA_STATE_FIRST_FRAME_ARRIVED) used by the extension. - Add OxygenOS‑compatible overload of collectReturnableOutputBuffers to support the extension's buffer handling. - Add four‑parameter overload of CameraProviderManager::getCameraCharacteristics to match the signature expected by the extension. Test: Camera zoom works on custom ROM with prebuilt libcsextimpl.so. Signed-off-by: Pranav Vashi --- camera/CameraSessionStats.cpp | 4 + camera/include/camera/CameraSessionStats.h | 3 + services/camera/libcameraservice/Android.bp | 3 + .../camera/libcameraservice/CameraService.cpp | 8 ++ .../common/CameraProviderManager.cpp | 9 +- .../common/CameraProviderManager.h | 2 + .../device3/Camera3OutputUtils.cpp | 32 ++++++ .../device3/Camera3OutputUtils.h | 19 ++++ .../ext/CameraServiceExtFactory.cpp | 103 ++++++++++++++++++ .../ext/ICameraServiceExt.cpp | 16 +++ .../ext/include/CameraServiceExtFactory.h | 24 ++++ .../ext/include/ICameraServiceExt.h | 14 +++ 12 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 services/camera/libcameraservice/ext/CameraServiceExtFactory.cpp create mode 100644 services/camera/libcameraservice/ext/ICameraServiceExt.cpp create mode 100644 services/camera/libcameraservice/ext/include/CameraServiceExtFactory.h create mode 100644 services/camera/libcameraservice/ext/include/ICameraServiceExt.h diff --git a/camera/CameraSessionStats.cpp b/camera/CameraSessionStats.cpp index 450bdd870c3..4ec76244f98 100644 --- a/camera/CameraSessionStats.cpp +++ b/camera/CameraSessionStats.cpp @@ -260,6 +260,10 @@ const int CameraSessionStats::CAMERA_STATE_ACTIVE = 1; const int CameraSessionStats::CAMERA_STATE_IDLE = 2; const int CameraSessionStats::CAMERA_STATE_CLOSED = 3; +const int CameraSessionStats::CAMERA_STATE_EXCEPTION = 4; +const int CameraSessionStats::CAMERA_STATE_SESSION_CONFIGURED = 5; +const int CameraSessionStats::CAMERA_STATE_FIRST_FRAME_ARRIVED = 6; + const int CameraSessionStats::CAMERA_FACING_BACK = 0; const int CameraSessionStats::CAMERA_FACING_FRONT = 1; const int CameraSessionStats::CAMERA_FACING_EXTERNAL = 2; diff --git a/camera/include/camera/CameraSessionStats.h b/camera/include/camera/CameraSessionStats.h index 34ee882d609..f9e960b9dea 100644 --- a/camera/include/camera/CameraSessionStats.h +++ b/camera/include/camera/CameraSessionStats.h @@ -109,6 +109,9 @@ class CameraSessionStats : public android::Parcelable { static const int CAMERA_STATE_ACTIVE; static const int CAMERA_STATE_IDLE; static const int CAMERA_STATE_CLOSED; + static const int CAMERA_STATE_EXCEPTION; + static const int CAMERA_STATE_SESSION_CONFIGURED; + static const int CAMERA_STATE_FIRST_FRAME_ARRIVED; /** * Values for notifyCameraState facing diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index 5062e4c6731..4175e8ad7a0 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -211,6 +211,8 @@ cc_library { "utils/LatencyHistogram.cpp", "utils/Utils.cpp", "utils/VirtualDeviceCameraIdMapper.cpp", + "ext/ICameraServiceExt.cpp", + "ext/CameraServiceExtFactory.cpp", ], header_libs: [ @@ -244,6 +246,7 @@ cc_library { include_dirs: [ "system/media/private/camera/include", "frameworks/native/include/media/openmax", + "frameworks/av/services/camera/libcameraservice/ext/include", ], export_include_dirs: ["."], diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index ae4e98453e9..562081cded8 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -91,6 +91,8 @@ #include "utils/TagMonitor.h" #include "utils/Utils.h" +#include "ext/include/CameraServiceExtFactory.h" + #ifdef CAMERA_NEEDS_CLIENT_INFO_LIB #include #endif @@ -4143,6 +4145,7 @@ void CameraService::logServiceError(const std::string &msg, int errorCode) { status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { + ALOGI("CameraService::onTransact: code=0x%x (%d)", code, code); // Permission checks switch (code) { case SHELL_COMMAND_TRANSACTION: { @@ -4171,6 +4174,11 @@ status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* re } } + // Let the extension handle it first + if (CameraServiceExtFactory::onTransact(code, data, reply, flags) == 0) { + return NO_ERROR; + } + return BnCameraService::onTransact(code, data, reply, flags); } diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index 8d8f0e21217..fa468f87e45 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -59,6 +59,9 @@ #include "common/CameraProviderExtension.h" +#include "CameraServiceExtFactory.h" +#include "ICameraServiceExt.h" + namespace android { using namespace ::android::hardware::camera; @@ -546,7 +549,11 @@ status_t CameraProviderManager::getCameraCharacteristics(const std::string &id, std::lock_guard lock(mInterfaceMutex); return getCameraCharacteristicsLocked(id, overrideForPerfClass, characteristics, compatInfo); } - +status_t CameraProviderManager::getCameraCharacteristics( const std::string &id, bool overrideForPerfClass, + CameraMetadata* characteristics, int /*unused*/) const { + return getCameraCharacteristics(id, overrideForPerfClass, characteristics, + CameraCompatibilityInfo()); +} status_t CameraProviderManager::getHighestSupportedVersion(const std::string &id, hardware::hidl_version *v, IPCTransport *transport) { if (v == nullptr || transport == nullptr) { diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h index 40a4254725d..a2231d6f263 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.h +++ b/services/camera/libcameraservice/common/CameraProviderManager.h @@ -315,6 +315,8 @@ class CameraProviderManager : virtual public hidl::manager::V1_0::IServiceNotifi status_t getCameraCharacteristics(const std::string &id, bool overrideForPerfClass, CameraMetadata* characteristics, const CameraCompatibilityInfo& compatInfo) const; + status_t getCameraCharacteristics(const std::string &id, bool overrideForPerfClass, + CameraMetadata* characteristics, int) const; status_t isConcurrentSessionConfigurationSupported( const std::vector diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp index cd965e37f48..094395c797e 100644 --- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp +++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp @@ -1057,6 +1057,38 @@ void collectAndRemovePendingOutputBuffers(bool useHalBufManager, } } +void collectReturnableOutputBuffers( + bool useHalBufManager, + const std::set& halBufferManagedStreams, + sp listener, + const camera_stream_buffer_t* outputBuffers, + size_t numBuffers, + int64_t timestamp, + int64_t readoutTimestamp, + bool requested, + int64_t requestTimeNs, + SessionStatsBuilder& sessionStatsBuilder, + std::vector* returnableBuffers, + bool timestampIncreasing, + const std::unordered_map>& outputSurfaces, + const CaptureResultExtras& resultExtras, + ERROR_BUF_STRATEGY errorBufStrategy, + int /*extraParam*/) { + + // Convert the OxygenOS map (uint64_t) to AOSP map (size_t) + std::unordered_map> surfacesSizeT; + for (const auto& pair : outputSurfaces) { + surfacesSizeT[pair.first].assign(pair.second.begin(), pair.second.end()); + } + + // Call the AOSP overload (which takes sp by value) + collectReturnableOutputBuffers(useHalBufManager, halBufferManagedStreams, listener, + outputBuffers, numBuffers, timestamp, readoutTimestamp, requested, requestTimeNs, + sessionStatsBuilder, returnableBuffers, timestampIncreasing, surfacesSizeT, + resultExtras, errorBufStrategy, TransformationMap{}); +} + + void notifyShutter(CaptureOutputStates& states, const camera_shutter_msg_t &msg) { ATRACE_CALL(); ssize_t idx; diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h index 82ca6c80c3e..986a9766a58 100644 --- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h +++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h @@ -96,6 +96,25 @@ namespace camera3 { ERROR_BUF_STRATEGY errorBufStrategy = ERROR_BUF_RETURN, const TransformationMap &transform = TransformationMap{}); + // OxygenOS-compatible overload for libcsextimpl.so + void collectReturnableOutputBuffers( + bool useHalBufManager, + const std::set &halBufferManagedStreams, + sp listener, + const camera_stream_buffer_t *outputBuffers, + size_t numBuffers, + nsecs_t timestamp, + nsecs_t readoutTimestamp, + bool requested, + nsecs_t requestTimeNs, + SessionStatsBuilder& sessionStatsBuilder, + std::vector *returnableBuffers, + bool timestampIncreasing, + const std::unordered_map> &outputSurfaces, + const CaptureResultExtras &resultExtras, + ERROR_BUF_STRATEGY errorBufStrategy, + int extraParam); + // helper function to collect the output buffers ready to be // returned to output streams, and to remove these buffers from // the inflight request's pending buffers vector. Does not make diff --git a/services/camera/libcameraservice/ext/CameraServiceExtFactory.cpp b/services/camera/libcameraservice/ext/CameraServiceExtFactory.cpp new file mode 100644 index 00000000000..df12292b7bf --- /dev/null +++ b/services/camera/libcameraservice/ext/CameraServiceExtFactory.cpp @@ -0,0 +1,103 @@ +#include "CameraServiceExtFactory.h" +#include +#include + +namespace android { + +void* CameraServiceExtFactory::sFunctionTable = nullptr; +void* CameraServiceExtFactory::sExtObject = nullptr; +int (*CameraServiceExtFactory::sOnTransactFunc)(void*, uint32_t, const Parcel&, Parcel*, uint32_t) = nullptr; + +void CameraServiceExtFactory::ensureLoaded() { + if (sFunctionTable != nullptr) return; + + const char* libPath = "system_ext/lib64/libcsextimpl.so"; + void* handle = dlopen(libPath, RTLD_NOW); + if (handle == nullptr) { + ALOGE("CameraServiceExtFactory: dlopen failed: %s", dlerror()); + return; + } + ALOGI("CameraServiceExtFactory: dlopen succeeded, handle=%p", handle); + + typedef void* (*GetFactoryFunc)(); + GetFactoryFunc getExtFactoryImpl = (GetFactoryFunc)dlsym(handle, "getExtFactoryImpl"); + if (getExtFactoryImpl == nullptr) { + ALOGE("CameraServiceExtFactory: dlsym getExtFactoryImpl failed: %s", dlerror()); + dlclose(handle); + return; + } + ALOGI("CameraServiceExtFactory: getExtFactoryImpl at %p", getExtFactoryImpl); + + // Triple indirection as determined from logs: getExtFactoryImpl returns ptr to ptr to ptr to function + void* ptrToPtr = getExtFactoryImpl(); + if (ptrToPtr == nullptr) { + ALOGE("CameraServiceExtFactory: getExtFactoryImpl returned null"); + dlclose(handle); + return; + } + + void* ptrToFunc = *(void**)ptrToPtr; + if (ptrToFunc == nullptr) { + ALOGE("CameraServiceExtFactory: first deref gave null"); + dlclose(handle); + return; + } + + void* actualFunc = *(void**)ptrToFunc; + if (actualFunc == nullptr) { + ALOGE("CameraServiceExtFactory: second deref gave null"); + dlclose(handle); + return; + } + ALOGI("CameraServiceExtFactory: actual factory function at %p", actualFunc); + + sFunctionTable = operator new(8); + *(void**)sFunctionTable = actualFunc; + ALOGI("CameraServiceExtFactory: function table at %p", sFunctionTable); + + // Resolve onTransact (for direct call via vtable) + sOnTransactFunc = (int (*)(void*, uint32_t, const Parcel&, Parcel*, uint32_t)) + dlsym(handle, "_ZN7android20CameraServiceExtImpl10onTransactEjRKNS_6ParcelEPS1_j"); + if (sOnTransactFunc == nullptr) { + ALOGE("CameraServiceExtFactory: dlsym onTransact failed: %s", dlerror()); + } else { + ALOGI("CameraServiceExtFactory: onTransact found at %p", sOnTransactFunc); + } +} + +void* CameraServiceExtFactory::getInstance() { + ensureLoaded(); + return sFunctionTable; // may be null +} + +int CameraServiceExtFactory::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { + ensureLoaded(); + if (sExtObject == nullptr) { + if (sFunctionTable == nullptr) { + ALOGE("CameraServiceExtFactory::onTransact: extension not loaded"); + return -1; + } + void* actualFunc = *(void**)sFunctionTable; + if (actualFunc == nullptr) return -1; + typedef void* (*GetObjectFunc)(); + sExtObject = ((GetObjectFunc)actualFunc)(); + if (sExtObject == nullptr) { + ALOGE("CameraServiceExtFactory: factory returned null"); + return -1; + } + ALOGI("CameraServiceExtFactory: real extension object at %p", sExtObject); + } + + if (sOnTransactFunc == nullptr) { + ALOGE("CameraServiceExtFactory::onTransact: no function pointer"); + return -1; + } + return sOnTransactFunc(sExtObject, code, data, reply, flags); +} + +CameraServiceExtFactory::~CameraServiceExtFactory() { + // No cleanup needed – the extension library manages its own singleton. + ALOGV("CameraServiceExtFactory destructor (stub)"); +} + +} // namespace android diff --git a/services/camera/libcameraservice/ext/ICameraServiceExt.cpp b/services/camera/libcameraservice/ext/ICameraServiceExt.cpp new file mode 100644 index 00000000000..d691995a42d --- /dev/null +++ b/services/camera/libcameraservice/ext/ICameraServiceExt.cpp @@ -0,0 +1,16 @@ +#include "ICameraServiceExt.h" +#include + +namespace android { + + ICameraServiceExt::ICameraServiceExt() { + // Do nothing – the real object will call this as part of its construction. + // No member initialisation to avoid corrupting the real object's memory. + ALOGV("ICameraServiceExt constructor (stub, no-op)"); + } + + ICameraServiceExt::~ICameraServiceExt() { + ALOGV("ICameraServiceExt destructor (stub, no-op)"); + } + +} // namespace android diff --git a/services/camera/libcameraservice/ext/include/CameraServiceExtFactory.h b/services/camera/libcameraservice/ext/include/CameraServiceExtFactory.h new file mode 100644 index 00000000000..f7ab9c68596 --- /dev/null +++ b/services/camera/libcameraservice/ext/include/CameraServiceExtFactory.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace android { + +// Forward declaration – we will not define this class +class ICameraServiceExt; + +class CameraServiceExtFactory { +public: + // Returns a pointer to a function table (as required by OxygenOS) + static void* getInstance(); + static int onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); + virtual ~CameraServiceExtFactory(); + +private: + static void ensureLoaded(); + static void* sFunctionTable; // pointer to function pointer + static void* sExtObject; // the real extension object (as void*) + static int (*sOnTransactFunc)(void*, uint32_t, const Parcel&, Parcel*, uint32_t); +}; + +} // namespace android diff --git a/services/camera/libcameraservice/ext/include/ICameraServiceExt.h b/services/camera/libcameraservice/ext/include/ICameraServiceExt.h new file mode 100644 index 00000000000..daf72d5b5d1 --- /dev/null +++ b/services/camera/libcameraservice/ext/include/ICameraServiceExt.h @@ -0,0 +1,14 @@ +#pragma once + +namespace android { + + // Empty placeholder class – no members, no base classes. + // The real implementation from the extension library will provide its own. + class ICameraServiceExt { + public: + ICameraServiceExt(); + ~ICameraServiceExt(); + // No other methods – the real object's vtable will be used. + }; + +} // namespace android From 90817c2cfa90747178cbf68511c47f48f695e486 Mon Sep 17 00:00:00 2001 From: AdarshGrewal Date: Fri, 12 Jun 2026 23:11:03 +0530 Subject: [PATCH 64/68] camera: bypass roundBufferDimensionNearest for Y16 Used by portrait mode in xiaomi 8650 (peridot) stock camera 540422489 = Y16 202981: 06-07 18:50:30.025 2243 6084 E cameraserver: roundBufferDimensionNearest: No configurations for format 540422489 width 4096, height 3072, maxResolution ? false Change-Id: I75bac917cc06840ce48ad41d58e3b729f6645221 Signed-off-by: Pranav Vashi --- .../camera/libcameraservice/utils/SessionConfigurationUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp index 81c1089e22f..dfab38a36ba 100644 --- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp +++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp @@ -237,7 +237,7 @@ bool roundBufferDimensionNearest(int32_t width, int32_t height, // those are not populated in static capabilities. if (isPriviledgedClient == true && (format == HAL_PIXEL_FORMAT_YCbCr_420_888 || format == HAL_PIXEL_FORMAT_BLOB || - format == HAL_PIXEL_FORMAT_Y8)) { + format == HAL_PIXEL_FORMAT_Y8 || format == HAL_PIXEL_FORMAT_Y16)) { ALOGI("Bypass roundBufferDimensionNearest for privilegedClient YUV streams " "width %d height %d for format %d", width, height, format); From 0cbb72f32de35b528e076e030bace67dba09aeac Mon Sep 17 00:00:00 2001 From: "jiangli.liu" Date: Wed, 24 Jun 2026 11:39:40 +0800 Subject: [PATCH 65/68] Nuplayer: Fix use-after-free in AWakeLock PMDeathRecipient held a raw pointer to AWakeLock. If binderDied() fired on a binder thread after AWakeLock was destroyed, the raw pointer dereference caused a use-after-free. Replace the raw pointer with a weak pointer (wp) so that promote() returns NULL when the parent is already gone. Additionally, clear the weak reference in ~AWakeLock() to make the window explicit and avoid any stale callback. Test: manual stress test triggering binder death during NuPlayer Change-Id: I39b46b308999f7491c6c88027b6a3e00cc58e352 --- media/libmediaplayerservice/nuplayer/AWakeLock.cpp | 14 +++++++++++--- .../nuplayer/include/nuplayer/AWakeLock.h | 5 ++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/media/libmediaplayerservice/nuplayer/AWakeLock.cpp b/media/libmediaplayerservice/nuplayer/AWakeLock.cpp index e8556ddec5f..ef6e71a3748 100644 --- a/media/libmediaplayerservice/nuplayer/AWakeLock.cpp +++ b/media/libmediaplayerservice/nuplayer/AWakeLock.cpp @@ -37,6 +37,11 @@ AWakeLock::AWakeLock() : mDeathRecipient(new PMDeathRecipient(this)){} AWakeLock::~AWakeLock() { + // Clear the back-pointer in PMDeathRecipient first to prevent a + // use-after-free race: if binderDied() fires on a binder thread after + // this object is destroyed, promote() will return NULL and the callback + // will be safely ignored. + mDeathRecipient->clearWakeLock(); if (mPowerManager != NULL) { sp binder = IInterface::asBinder(mPowerManager); binder->unlinkToDeath(mDeathRecipient); @@ -107,12 +112,15 @@ void AWakeLock::release(bool force) { void AWakeLock::clearPowerManager() { release(true); - mPowerManager.clear(); + if (mPowerManager != NULL) { + mPowerManager.clear(); + } } void AWakeLock::PMDeathRecipient::binderDied(const wp& who __unused) { - if (mWakeLock != NULL) { - mWakeLock->clearPowerManager(); + sp wakeLock = mWakeLock.promote(); + if (wakeLock != NULL) { + wakeLock->clearPowerManager(); } } diff --git a/media/libmediaplayerservice/nuplayer/include/nuplayer/AWakeLock.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/AWakeLock.h index 8aa3b41a703..8cf9d05a554 100644 --- a/media/libmediaplayerservice/nuplayer/include/nuplayer/AWakeLock.h +++ b/media/libmediaplayerservice/nuplayer/include/nuplayer/AWakeLock.h @@ -49,11 +49,14 @@ class AWakeLock : public RefBase { // IBinder::DeathRecipient virtual void binderDied(const wp &who); + // Called by AWakeLock destructor to prevent use-after-free in binderDied + void clearWakeLock() { mWakeLock.clear(); } + private: PMDeathRecipient(const PMDeathRecipient&); PMDeathRecipient& operator= (const PMDeathRecipient&); - AWakeLock *mWakeLock; + wp mWakeLock; }; const sp mDeathRecipient; From 7debd2e2df4b83cfd3389a1c8b2351f4c82394c3 Mon Sep 17 00:00:00 2001 From: Pranav Vashi Date: Thu, 2 Jul 2026 11:03:31 +0530 Subject: [PATCH 66/68] Revert "issue: After connecting the Bluetooth earphones and projecting the screen, music will play from the earphones. At this point, disconnect the earphones, click play, and the projection will be silent" This reverts commit f332fc5350498913128ef4344defede9ff192987. --- .../common/managerdefinitions/include/DeviceDescriptor.h | 5 ----- .../common/managerdefinitions/src/DeviceDescriptor.cpp | 4 ---- services/audiopolicy/managerdefault/AudioPolicyManager.cpp | 2 -- 3 files changed, 11 deletions(-) diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h index c1c57f3a2df..9e4a735894e 100644 --- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h @@ -58,10 +58,6 @@ class DeviceDescriptor : public DeviceDescriptorBase, mCurrentEncodedFormat = format; } - void setDeviceConnectState(bool connected){ - mIsConnected = connected; - } - bool equals(const sp& other) const; bool hasCurrentEncodedFormat() const; @@ -111,7 +107,6 @@ class DeviceDescriptor : public DeviceDescriptorBase, } std::string mTagName; // Unique human readable identifier for a device port found in conf file. - bool mIsConnected = false; audio_format_t mCurrentEncodedFormat; bool mIsDynamic = false; std::string mDeclaredAddress; // Original device address diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp index cac0bd43f06..9523c73abf8 100644 --- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp @@ -106,10 +106,6 @@ bool DeviceDescriptor::hasCurrentEncodedFormat() const if (mEncodedFormats.empty()) { return true; } - if(device_has_encoding_capability(type()) && !mIsConnected) { - ALOGD("%s: mIsConnected is false", __func__); - return true; - } return (mCurrentEncodedFormat != AUDIO_FORMAT_DEFAULT); } diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index bf303e0ce69..abf76554703 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -271,7 +271,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const spsetEncapsulationInfoFromHal(mpClientInterface); - device->setDeviceConnectState(true); // outputs should never be empty here ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():" @@ -304,7 +303,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const spsetEncodedFormat(AUDIO_FORMAT_DEFAULT); - device->setDeviceConnectState(false); // remove device from mReportedFormatsMap cache mReportedFormatsMap.erase(device); From 2598b568888069f73551f4502181eccb21066215 Mon Sep 17 00:00:00 2001 From: Ionut Date: Thu, 18 Jun 2026 00:31:36 +0300 Subject: [PATCH 67/68] audiopolicy: Do not wipe device's known codec during bluetooth disconnection The actual problem is an order-of-operations bug: during Bluetooth disconnection, the framework wipes out the device's known codec format (AUDIO_FORMAT_DEFAULT) before running the routing logic that decides if a track needs restoration. By deferring that codec reset to the end of the disconnection sequence is fixing the screen projection silence bug without breaking global template descriptors or destroying codec routing pipeline Signed-off-by: Pranav Vashi --- .../audiopolicy/managerdefault/AudioPolicyManager.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index abf76554703..8d91d994de3 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -301,12 +301,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const spsetEncodedFormat(AUDIO_FORMAT_DEFAULT); - - // remove device from mReportedFormatsMap cache - mReportedFormatsMap.erase(device); - // remove preferred mixer configurations mPreferredMixerAttrInfos.erase(device->getId()); @@ -415,6 +409,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const spsetEncodedFormat(AUDIO_FORMAT_DEFAULT); + mReportedFormatsMap.erase(device); + cleanUpForDevice(device); } From b8d2f0bae0a7ec0d43d6c2af914c16a15f4e8366 Mon Sep 17 00:00:00 2001 From: Pbzin Date: Mon, 3 Aug 2026 23:58:20 -0300 Subject: [PATCH 68/68] codec2: restore legacy sync fence ABI --- media/codec2/vndk/C2Fence.cpp | 5 ++++- media/codec2/vndk/include/C2FenceFactory.h | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/media/codec2/vndk/C2Fence.cpp b/media/codec2/vndk/C2Fence.cpp index fe8a9eb3748..c095035c1dc 100644 --- a/media/codec2/vndk/C2Fence.cpp +++ b/media/codec2/vndk/C2Fence.cpp @@ -472,6 +472,10 @@ std::vector ExtractFdsFromCodec2SyncFence(const C2Fence& fence) { return retFds; } +C2Fence _C2FenceFactory::CreateSyncFence(int fenceFd) { + return CreateSyncFence(fenceFd, true); +} + C2Fence _C2FenceFactory::CreateSyncFence(int fenceFd, bool validate) { std::shared_ptr p; if (fenceFd >= 0) { @@ -812,4 +816,3 @@ C2Fence _C2FenceFactory::CreateFromNativeHandle( } return C2Fence(p); } - diff --git a/media/codec2/vndk/include/C2FenceFactory.h b/media/codec2/vndk/include/C2FenceFactory.h index cabd5d91cd6..d8e1bb3f261 100644 --- a/media/codec2/vndk/include/C2FenceFactory.h +++ b/media/codec2/vndk/include/C2FenceFactory.h @@ -67,7 +67,10 @@ struct _C2FenceFactory { * \param validate If true, the fence fd will be validated to ensure * it is a valid pending sync fence fd. */ - static C2Fence CreateSyncFence(int fenceFd, bool validate = true); + // Keep the legacy one-argument ABI for vendor Codec2 implementations that + // were built before fence validation became an explicit parameter. + static C2Fence CreateSyncFence(int fenceFd); + static C2Fence CreateSyncFence(int fenceFd, bool validate); /* * Create C2Fence from list of sync fence fds, while also merging them to