Merge "TimeCheck: Track waiting through thread join in AudioFlinger" into main
diff --git a/media/audio/aconfig/Android.bp b/media/audio/aconfig/Android.bp
index 71c2cd1..ec45e2f 100644
--- a/media/audio/aconfig/Android.bp
+++ b/media/audio/aconfig/Android.bp
@@ -6,6 +6,13 @@
}
aconfig_declarations {
+ name: "com.android.media.audioclient-aconfig",
+ package: "com.android.media.audioclient",
+ container: "system",
+ srcs: ["audioclient.aconfig"],
+}
+
+aconfig_declarations {
name: "com.android.media.audioserver-aconfig",
package: "com.android.media.audioserver",
container: "system",
@@ -66,6 +73,12 @@
defaults: ["audio-aconfig-cc-defaults"],
}
+cc_aconfig_library {
+ name: "com.android.media.audioclient-aconfig-cc",
+ aconfig_declarations: "com.android.media.audioclient-aconfig",
+ defaults: ["audio-aconfig-cc-defaults"],
+}
+
java_aconfig_library {
name: "com.android.media.audio-aconfig-java",
aconfig_declarations: "com.android.media.audio-aconfig",
diff --git a/media/audio/aconfig/audio.aconfig b/media/audio/aconfig/audio.aconfig
index 1df5727..02367dc 100644
--- a/media/audio/aconfig/audio.aconfig
+++ b/media/audio/aconfig/audio.aconfig
@@ -53,6 +53,15 @@
}
flag {
+ name: "set_stream_volume_order"
+ namespace: "media_audio"
+ description:
+ "Fix race condition by adjusting the order when"
+ "setStreamVolume is calling into the BT stack"
+ bug: "329202581"
+}
+
+flag {
name: "spatializer_offload"
namespace: "media_audio"
description: "Enable spatializer offload"
diff --git a/media/audio/aconfig/audio_framework.aconfig b/media/audio/aconfig/audio_framework.aconfig
index a2e9849..0209e28 100644
--- a/media/audio/aconfig/audio_framework.aconfig
+++ b/media/audio/aconfig/audio_framework.aconfig
@@ -40,6 +40,7 @@
bug: "316414750"
}
+# TODO remove
flag {
name: "foreground_audio_control"
is_exported: true
@@ -103,6 +104,27 @@
}
flag {
+ name: "ro_foreground_audio_control"
+ is_exported: true
+ namespace: "media_audio"
+ description:
+ "Audio focus gain requires FGS or delegation to "
+ "take effect"
+ bug: "296232417"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "ro_volume_ringer_api_hardening"
+ namespace: "media_audio"
+ description: "Limit access to volume and ringer SDK APIs in AudioManager"
+ bug: "296232417"
+ is_fixed_read_only: true
+}
+
+
+# TODO remove
+flag {
name: "volume_ringer_api_hardening"
namespace: "media_audio"
description: "Limit access to volume and ringer SDK APIs in AudioManager"
diff --git a/media/audio/aconfig/audioclient.aconfig b/media/audio/aconfig/audioclient.aconfig
new file mode 100644
index 0000000..a804834
--- /dev/null
+++ b/media/audio/aconfig/audioclient.aconfig
@@ -0,0 +1,16 @@
+# Flags for libaudioclient, and other native client libraries.
+#
+# Please add flags in alphabetical order.
+
+package: "com.android.media.audioclient"
+container: "system"
+
+flag {
+ name: "audiosystem_service_acquisition"
+ namespace: "media_audio"
+ description: "Clean up audiosystem service acquisition."
+ bug: "330358287"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
index 76680a3..4ec26d6 100644
--- a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
@@ -243,10 +243,17 @@
.build());
addParameter(
+ DefineParam(mLowLatencyMode, C2_PARAMKEY_LOW_LATENCY_MODE)
+ .withDefault(new C2GlobalLowLatencyModeTuning(0))
+ .withFields({C2F(mLowLatencyMode, value).oneOf({0,1})})
+ .withSetter(Setter<decltype(*mLowLatencyMode)>::StrictValueWithNoDeps)
+ .build());
+
+ addParameter(
DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
.withDefault(new C2PortActualDelayTuning::output(kOutputDelay))
.withFields({C2F(mActualOutputDelay, value).inRange(0, kOutputDelay)})
- .withSetter(Setter<decltype(*mActualOutputDelay)>::StrictValueWithNoDeps)
+ .withSetter(ActualOutputDelaySetter, mLowLatencyMode)
.build());
}
@@ -365,6 +372,10 @@
return mPixelFormat;
}
+ std::shared_ptr<C2PortActualDelayTuning::output> getActualOutputDelay_l() const {
+ return mActualOutputDelay;
+ }
+
static C2R HdrStaticInfoSetter(bool mayBlock, C2P<C2StreamHdrStaticInfo::output>& me) {
(void)mayBlock;
if (me.v.mastering.red.x > 1) {
@@ -406,6 +417,13 @@
return C2R::Ok();
}
+ static C2R ActualOutputDelaySetter(bool mayBlock, C2P<C2PortActualDelayTuning::output>& me,
+ const C2P<C2GlobalLowLatencyModeTuning>& lowLatencyMode) {
+ (void)mayBlock;
+ me.set().value = lowLatencyMode.v.value ? 1 : kOutputDelay;
+ return C2R::Ok();
+ }
+
private:
std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
@@ -419,6 +437,7 @@
std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo;
+ std::shared_ptr<C2GlobalLowLatencyModeTuning> mLowLatencyMode;
};
C2SoftDav1dDec::C2SoftDav1dDec(const char* name, c2_node_id_t id,
@@ -516,6 +535,7 @@
{
IntfImpl::Lock lock = mIntf->lock();
mPixelFormatInfo = mIntf->getPixelFormat_l();
+ mActualOutputDelayInfo = mIntf->getActualOutputDelay_l();
}
const char* version = dav1d_version();
@@ -529,7 +549,7 @@
android::base::GetIntProperty(NUM_THREADS_DAV1D_PROPERTY, NUM_THREADS_DAV1D_DEFAULT);
if (numThreads > 0) lib_settings.n_threads = numThreads;
- lib_settings.max_frame_delay = kOutputDelay;
+ lib_settings.max_frame_delay = mActualOutputDelayInfo->value;
int res = 0;
if ((res = dav1d_open(&mDav1dCtx, &lib_settings))) {
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.h b/media/codec2/components/dav1d/C2SoftDav1dDec.h
index 5d2a725..6008325 100644
--- a/media/codec2/components/dav1d/C2SoftDav1dDec.h
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.h
@@ -62,6 +62,7 @@
// configurations used by component in process
// (TODO: keep this in intf but make them internal only)
std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormatInfo;
+ std::shared_ptr<C2PortActualDelayTuning::output> mActualOutputDelayInfo;
uint32_t mHalPixelFormat;
uint32_t mWidth;
diff --git a/media/codec2/hal/aidl/ComponentInterface.cpp b/media/codec2/hal/aidl/ComponentInterface.cpp
index 8ae9fa8..8c7a986 100644
--- a/media/codec2/hal/aidl/ComponentInterface.cpp
+++ b/media/codec2/hal/aidl/ComponentInterface.cpp
@@ -79,6 +79,26 @@
}
c2_status_t err2 = C2_OK;
if (paramsToLargeFrameIntf.size() > 0) {
+ C2ComponentKindSetting kind;
+ C2StreamMaxBufferSizeInfo::input maxInputSize(0);
+ c2_status_t err = mIntf->query_vb(
+ {&kind, &maxInputSize}, {}, C2_MAY_BLOCK, nullptr);
+ if ((err == C2_OK) && (kind.value == C2Component::KIND_ENCODER)) {
+ for (int i = 0 ; i < paramsToLargeFrameIntf.size(); i++) {
+ if (paramsToLargeFrameIntf[i]->index() ==
+ C2LargeFrame::output::PARAM_TYPE) {
+ C2LargeFrame::output *lfp = C2LargeFrame::output::From(
+ paramsToLargeFrameIntf[i]);
+ // This is assuming a worst case compression ratio of 1:1
+ // In no case the encoder should give an output more than
+ // what is being provided to the encoder in a single call.
+ if (lfp && (lfp->maxSize < maxInputSize.value)) {
+ lfp->maxSize = maxInputSize.value;
+ }
+ break;
+ }
+ }
+ }
err2 = mMultiAccessUnitIntf->config(
paramsToLargeFrameIntf, mayBlock, failures);
}
diff --git a/media/codec2/hal/hidl/1.0/utils/ComponentInterface.cpp b/media/codec2/hal/hidl/1.0/utils/ComponentInterface.cpp
index 41a8904..08f1ae2 100644
--- a/media/codec2/hal/hidl/1.0/utils/ComponentInterface.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/ComponentInterface.cpp
@@ -78,6 +78,26 @@
}
c2_status_t err2 = C2_OK;
if (paramsToLargeFrameIntf.size() > 0) {
+ C2ComponentKindSetting kind;
+ C2StreamMaxBufferSizeInfo::input maxInputSize(0);
+ c2_status_t err = mIntf->query_vb(
+ {&kind, &maxInputSize}, {}, C2_MAY_BLOCK, nullptr);
+ if ((err == C2_OK) && (kind.value == C2Component::KIND_ENCODER)) {
+ for (int i = 0 ; i < paramsToLargeFrameIntf.size(); i++) {
+ if (paramsToLargeFrameIntf[i]->index() ==
+ C2LargeFrame::output::PARAM_TYPE) {
+ C2LargeFrame::output *lfp = C2LargeFrame::output::From(
+ paramsToLargeFrameIntf[i]);
+ // This is assuming a worst case compression ratio of 1:1
+ // In no case the encoder should give an output more than
+ // what is being provided to the encoder in a single call.
+ if (lfp && (lfp->maxSize < maxInputSize.value)) {
+ lfp->maxSize = maxInputSize.value;
+ }
+ break;
+ }
+ }
+ }
err2 = mMultiAccessUnitIntf->config(
paramsToLargeFrameIntf, mayBlock, failures);
}
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 9c264af..7bf4dcc 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -40,6 +40,7 @@
#include <media/openmax/OMX_Core.h>
#include <media/openmax/OMX_IndexExt.h>
#include <media/stagefright/foundation/avc_utils.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
#include <media/stagefright/omx/OmxGraphicBufferSource.h>
#include <media/stagefright/CCodec.h>
@@ -1458,7 +1459,8 @@
int64_t blockUsage =
usage.value | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE;
std::shared_ptr<C2GraphicBlock> block = FetchGraphicBlock(
- width, height, componentColorFormat, blockUsage, {comp->getName()});
+ align(width, 2), align(height, 2), componentColorFormat, blockUsage,
+ {comp->getName()});
sp<GraphicBlockBuffer> buffer;
if (block) {
buffer = GraphicBlockBuffer::Allocate(
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index d313f33..2fa89e7 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -24,6 +24,7 @@
#include <C2PlatformSupport.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include <media/stagefright/CodecBase.h>
#include <media/stagefright/MediaCodecConstants.h>
@@ -57,7 +58,7 @@
std::shared_ptr<C2GraphicBlock> block;
c2_status_t err = pool->fetchGraphicBlock(
- width, height, pixelFormat, fullUsage, &block);
+ align(width, 2), align(height, 2), pixelFormat, fullUsage, &block);
if (err != C2_OK) {
ALOGD("fetch graphic block failed: %d", err);
return nullptr;
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index 261fd05..75e9bbc 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -593,8 +593,6 @@
uint8_t *dstY, size_t dstStride, size_t dstVStride, size_t bufferSize,
const C2GraphicView &src, C2Color::matrix_t colorMatrix, C2Color::range_t colorRange) {
CHECK(dstY != nullptr);
- CHECK((src.width() & 1) == 0);
- CHECK((src.height() & 1) == 0);
if (dstStride * dstVStride * 3 / 2 > bufferSize) {
ALOGD("conversion buffer is too small for converting from RGB to YUV");
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 2505c7c..04a8a45 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -130,6 +130,7 @@
"audiopolicy-types-aidl-cpp",
"av-types-aidl-cpp",
"capture_state_listener-aidl-cpp",
+ "com.android.media.audioclient-aconfig-cc",
"framework-permission-aidl-cpp",
"libaudio_aidl_conversion_common_cpp",
"libaudioclient_aidl_conversion",
diff --git a/media/libaudiohal/impl/AidlUtils.h b/media/libaudiohal/impl/AidlUtils.h
new file mode 100644
index 0000000..3d42b53
--- /dev/null
+++ b/media/libaudiohal/impl/AidlUtils.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+
+namespace android {
+
+template<class Intf>
+std::shared_ptr<Intf> getServiceInstance(const std::string& instanceName) {
+ const std::string serviceName =
+ std::string(Intf::descriptor).append("/").append(instanceName);
+ std::shared_ptr<Intf> service;
+ while (!service) {
+ AIBinder* serviceBinder = nullptr;
+ while (!serviceBinder) {
+ // 'waitForService' may return a nullptr, hopefully a transient error.
+ serviceBinder = AServiceManager_waitForService(serviceName.c_str());
+ }
+ // `fromBinder` may fail and return a nullptr if the service has died in the meantime.
+ service = Intf::fromBinder(ndk::SpAIBinder(serviceBinder));
+ }
+ return service;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index 347afa6..68b650f 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -31,6 +31,7 @@
#include <media/AidlConversionUtil.h>
#include <utils/Log.h>
+#include "AidlUtils.h"
#include "DeviceHalAidl.h"
#include "DevicesFactoryHalAidl.h"
@@ -179,16 +180,8 @@
if (name == nullptr || device == nullptr) {
return BAD_VALUE;
}
- std::shared_ptr<IModule> service;
if (strcmp(name, "primary") == 0) name = "default";
- auto serviceName = std::string(IModule::descriptor) + "/" + name;
- service = IModule::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
- if (service == nullptr) {
- ALOGE("%s fromBinder %s failed", __func__, serviceName.c_str());
- return NO_INIT;
- }
- *device = sp<DeviceHalAidl>::make(name, service, mVendorExt);
+ *device = sp<DeviceHalAidl>::make(name, getServiceInstance<IModule>(name), mVendorExt);
return OK;
}
@@ -229,14 +222,7 @@
// Main entry-point to the shared library.
extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
- auto serviceName = std::string(IConfig::descriptor) + "/default";
- auto service = IConfig::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
- if (!service) {
- ALOGE("%s binder service %s not exist", __func__, serviceName.c_str());
- return nullptr;
- }
- return new DevicesFactoryHalAidl(service);
+ return new DevicesFactoryHalAidl(getServiceInstance<IConfig>("default"));
}
} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index 424fdb7..3b2f344 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -31,6 +31,7 @@
#include <system/audio_aidl_utils.h>
#include <utils/Log.h>
+#include "AidlUtils.h"
#include "EffectBufferHalAidl.h"
#include "EffectHalAidl.h"
#include "EffectProxy.h"
@@ -356,14 +357,7 @@
// exports from a static library are optimized out unless actually used by
// the shared library. See EffectsFactoryHalEntry.cpp.
extern "C" void* createIEffectsFactoryImpl() {
- auto serviceName = std::string(IFactory::descriptor) + "/default";
- auto service = IFactory::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
- if (!service) {
- ALOGE("%s binder service %s not exist", __func__, serviceName.c_str());
- return nullptr;
- }
- return new effect::EffectsFactoryHalAidl(service);
+ return new effect::EffectsFactoryHalAidl(getServiceInstance<IFactory>("default"));
}
} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 2a8ebc6..ce56d87 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -569,7 +569,19 @@
status_t StreamOutHalAidl::setVolume(float left, float right) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
+ size_t channelCount = audio_channel_out_mask_from_count(mConfig.channel_mask);
+ if (channelCount == 0) channelCount = 2;
+ std::vector<float> volumes(channelCount);
+ if (channelCount == 1) {
+ volumes[0] = (left + right) / 2;
+ } else {
+ volumes[0] = left;
+ volumes[1] = right;
+ for (size_t i = 2; i < channelCount; ++i) {
+ volumes[i] = (left + right) / 2;
+ }
+ }
+ return statusTFromBinderStatus(mStream->setHwVolume(volumes));
}
status_t StreamOutHalAidl::selectPresentation(int presentationId, int programId) {
@@ -866,7 +878,9 @@
status_t StreamInHalAidl::setGain(float gain) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- return statusTFromBinderStatus(mStream->setHwGain({gain}));
+ const size_t channelCount = audio_channel_count_from_in_mask(mConfig.channel_mask);
+ std::vector<float> gains(channelCount != 0 ? channelCount : 1, gain);
+ return statusTFromBinderStatus(mStream->setHwGain(gains));
}
status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index dd6da15..b7efbce 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -20,7 +20,6 @@
{
"exclude-annotation": "android.platform.test.annotations.RequiresDevice"
},
- // TODO: b/149314419
{
"exclude-filter": "android.media.audio.cts.AudioPlaybackCaptureTest"
},
diff --git a/media/module/extractors/fuzzers/Android.bp b/media/module/extractors/fuzzers/Android.bp
index d096d63..7a49d8e 100644
--- a/media/module/extractors/fuzzers/Android.bp
+++ b/media/module/extractors/fuzzers/Android.bp
@@ -134,6 +134,8 @@
],
dictionary: "mp4_extractor_fuzzer.dict",
+
+ corpus: ["corpus_mp4/*"],
}
cc_fuzz {
@@ -202,7 +204,6 @@
"ogg_extractor_fuzzer.cpp",
],
-
static_libs: [
"libstagefright_metadatautils",
"libvorbisidec",
diff --git a/media/module/extractors/fuzzers/corpus_mp4/164a5bad5340b262316f93932c4160813657e1e0 b/media/module/extractors/fuzzers/corpus_mp4/164a5bad5340b262316f93932c4160813657e1e0
new file mode 100644
index 0000000..c17251b
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/164a5bad5340b262316f93932c4160813657e1e0
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/24f242f3b30fd5c2ff0f9aebed4375a3ab5cdceb b/media/module/extractors/fuzzers/corpus_mp4/24f242f3b30fd5c2ff0f9aebed4375a3ab5cdceb
new file mode 100644
index 0000000..16907fd
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/24f242f3b30fd5c2ff0f9aebed4375a3ab5cdceb
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/2a017927fdab79a8cc3b0bb75224cb44f4c1b35b b/media/module/extractors/fuzzers/corpus_mp4/2a017927fdab79a8cc3b0bb75224cb44f4c1b35b
new file mode 100644
index 0000000..2ec7881
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/2a017927fdab79a8cc3b0bb75224cb44f4c1b35b
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/58b3155e64ac16e4e6c68b68257871bcd769b92f b/media/module/extractors/fuzzers/corpus_mp4/58b3155e64ac16e4e6c68b68257871bcd769b92f
new file mode 100644
index 0000000..cd1fdcc
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/58b3155e64ac16e4e6c68b68257871bcd769b92f
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/64093d4da00ba406310c7679cd8b37562e6344b5 b/media/module/extractors/fuzzers/corpus_mp4/64093d4da00ba406310c7679cd8b37562e6344b5
new file mode 100644
index 0000000..f1ea812
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/64093d4da00ba406310c7679cd8b37562e6344b5
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/7355066d4975de07e9b6d0e9907c896eeb90577a b/media/module/extractors/fuzzers/corpus_mp4/7355066d4975de07e9b6d0e9907c896eeb90577a
new file mode 100644
index 0000000..c5d3eb2
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/7355066d4975de07e9b6d0e9907c896eeb90577a
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/7a48b0237581c794097a15add08517b3c6dc0aa2 b/media/module/extractors/fuzzers/corpus_mp4/7a48b0237581c794097a15add08517b3c6dc0aa2
new file mode 100644
index 0000000..1f6c29d
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/7a48b0237581c794097a15add08517b3c6dc0aa2
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/8706f07041a0cf828a7b40d727533d6c732b5ebc b/media/module/extractors/fuzzers/corpus_mp4/8706f07041a0cf828a7b40d727533d6c732b5ebc
new file mode 100644
index 0000000..40d639d
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/8706f07041a0cf828a7b40d727533d6c732b5ebc
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/911a46d40d60b9a806dbdc70799048df2f546615 b/media/module/extractors/fuzzers/corpus_mp4/911a46d40d60b9a806dbdc70799048df2f546615
new file mode 100644
index 0000000..2056348
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/911a46d40d60b9a806dbdc70799048df2f546615
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/97b1d0e78525c793574cce3e66f86564c2a10271 b/media/module/extractors/fuzzers/corpus_mp4/97b1d0e78525c793574cce3e66f86564c2a10271
new file mode 100644
index 0000000..f50d4f4
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/97b1d0e78525c793574cce3e66f86564c2a10271
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/d52e7095534fdf1f040b10a80df4cbc069a97a4e b/media/module/extractors/fuzzers/corpus_mp4/d52e7095534fdf1f040b10a80df4cbc069a97a4e
new file mode 100644
index 0000000..25ea55b
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/d52e7095534fdf1f040b10a80df4cbc069a97a4e
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/ec6bd6069f74a2f6e92442f88efb29288ad6f456 b/media/module/extractors/fuzzers/corpus_mp4/ec6bd6069f74a2f6e92442f88efb29288ad6f456
new file mode 100644
index 0000000..62d259b
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/ec6bd6069f74a2f6e92442f88efb29288ad6f456
Binary files differ
diff --git a/media/module/extractors/fuzzers/corpus_mp4/faa22bcb745206340d5d411b498a3868d2b1feec b/media/module/extractors/fuzzers/corpus_mp4/faa22bcb745206340d5d411b498a3868d2b1feec
new file mode 100644
index 0000000..d649632
--- /dev/null
+++ b/media/module/extractors/fuzzers/corpus_mp4/faa22bcb745206340d5d411b498a3868d2b1feec
Binary files differ
diff --git a/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
index 3683649..b48c854 100644
--- a/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
+++ b/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
@@ -246,3 +246,4 @@
kw245="iso5"
kw246="resv"
kw247="iso6"
+kw248="clap"
diff --git a/media/module/extractors/mkv/MatroskaExtractor.cpp b/media/module/extractors/mkv/MatroskaExtractor.cpp
index 6900341..a328ab9 100644
--- a/media/module/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/module/extractors/mkv/MatroskaExtractor.cpp
@@ -1769,6 +1769,30 @@
}
+status_t MatroskaExtractor::synthesizeVP9(TrackInfo* trackInfo, size_t index) {
+ BlockIterator iter(this, trackInfo->mTrackNum, index);
+ if (iter.eos()) {
+ return ERROR_MALFORMED;
+ }
+
+ const mkvparser::Block* block = iter.block();
+ if (block->GetFrameCount() <= 0) {
+ return ERROR_MALFORMED;
+ }
+
+ const mkvparser::Block::Frame& frame = block->GetFrame(0);
+ auto tmpData = heapbuffer<unsigned char>(frame.len);
+ long n = frame.Read(mReader, tmpData.get());
+ if (n != 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (!MakeVP9CodecSpecificData(trackInfo->mMeta, tmpData.get(), frame.len)) {
+ return ERROR_MALFORMED;
+ }
+
+ return OK;
+}
static inline bool isValidInt32ColourValue(long long value) {
return value != mkvparser::Colour::kValueNotPresent
@@ -2002,6 +2026,8 @@
// specified in http://www.webmproject.org/vp9/profiles/.
AMediaFormat_setBuffer(meta,
AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
+ } else {
+ isSetCsdFrom1stFrame = true;
}
} else if (!strcmp("V_AV1", codecID)) {
AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
@@ -2254,6 +2280,14 @@
mTracks.pop();
continue;
}
+ } else if ((!strcmp("V_VP9", codecID) && codecPrivateSize == 0) ||
+ (!strcmp(mimetype, MEDIA_MIMETYPE_VIDEO_VP9) && isSetCsdFrom1stFrame)) {
+ // Attempt to recover from VP9 track without codec private data
+ err = synthesizeVP9(trackInfo, n);
+ if (err != OK) {
+ mTracks.pop();
+ continue;
+ }
}
// the TrackInfo owns the metadata now
meta = nullptr;
diff --git a/media/module/extractors/mkv/include/MatroskaExtractor.h b/media/module/extractors/mkv/include/MatroskaExtractor.h
index 99fad17..2e4d955 100644
--- a/media/module/extractors/mkv/include/MatroskaExtractor.h
+++ b/media/module/extractors/mkv/include/MatroskaExtractor.h
@@ -95,6 +95,7 @@
status_t synthesizeAVCC(TrackInfo *trackInfo, size_t index);
status_t synthesizeMPEG2(TrackInfo *trackInfo, size_t index);
status_t synthesizeMPEG4(TrackInfo *trackInfo, size_t index);
+ status_t synthesizeVP9(TrackInfo* trackInfo, size_t index);
status_t initTrackInfo(
const mkvparser::Track *track,
AMediaFormat *meta,
diff --git a/media/module/metadatautils/MetaDataUtils.cpp b/media/module/metadatautils/MetaDataUtils.cpp
index db60f04..e5854b6 100644
--- a/media/module/metadatautils/MetaDataUtils.cpp
+++ b/media/module/metadatautils/MetaDataUtils.cpp
@@ -81,6 +81,124 @@
return true;
}
+// The param data contains the first frame data, starting with the uncompressed frame
+// header. This uncompressed header (refer section 6.2 of the VP9 bitstream spec) is
+// used to parse profile, bitdepth and subsampling.
+bool MakeVP9CodecSpecificData(AMediaFormat* meta, const uint8_t* data, size_t size) {
+ if (meta == nullptr || data == nullptr || size == 0) {
+ return false;
+ }
+
+ ABitReader bits(data, size);
+
+ // First 2 bits of the uncompressed header should be the frame_marker.
+ if (bits.getBits(2) != 0b10) {
+ return false;
+ }
+
+ int32_t profileLowBit = bits.getBits(1);
+ int32_t profileHighBit = bits.getBits(1);
+ int32_t profile = profileHighBit * 2 + profileLowBit;
+
+ // One reserved '0' bit if profile is 3.
+ if (profile == 3 && bits.getBits(1) != 0) {
+ return false;
+ }
+
+ // If show_existing_frame is set, we get no more data. Since this is
+ // expected to be the first frame, we can return false which will cascade
+ // into ERROR_MALFORMED.
+ if (bits.getBits(1)) {
+ return false;
+ }
+
+ // This should be the first frame, so expect a KEY_FRAME.
+ // if (frame_type != KEY_FRAME)
+ if (bits.getBits(1) != 0) {
+ return false;
+ }
+
+ // Upto 7 bits could be read till now, which were guaranteed to be available
+ // since size > 0. Check for bits available before reading them from now on.
+ if (bits.numBitsLeft() < 26) {
+ return false;
+ }
+ // Discard show_frame and error_resilient_mode.
+ bits.skipBits(2);
+
+ // Check for sync code.
+ if (bits.getBits(24) != 0x498342) {
+ return false;
+ }
+
+ int32_t bitDepth;
+ if (profile >= 2) {
+ if (bits.numBitsLeft() < 1) {
+ return false;
+ }
+ bitDepth = bits.getBits(1) ? 12 : 10;
+ } else {
+ bitDepth = 8;
+ }
+
+ uint32_t colorspace;
+ if (!bits.getBitsGraceful(3, &colorspace)) {
+ return false;
+ }
+
+ int32_t chromaSubsampling = -1;
+ if (colorspace != 7 /*SRGB*/) {
+ // Skip yuv_range_flag
+ if (!bits.skipBits(1)) {
+ return false;
+ }
+ // Check for subsampling only for profiles 1 and 3.
+ if (profile == 1 || profile == 3) {
+ uint32_t ss_x;
+ uint32_t ss_y;
+ if (bits.getBitsGraceful(1, &ss_x) && bits.getBitsGraceful(1, &ss_y)) {
+ chromaSubsampling = ss_x << 1 & ss_y;
+ } else {
+ return false;
+ }
+ } else {
+ chromaSubsampling = 3;
+ }
+ } else {
+ if (profile == 1 || profile == 3) {
+ chromaSubsampling = 0;
+ }
+ }
+
+ int32_t csdSize = 6;
+ if (chromaSubsampling != -1) {
+ csdSize += 3;
+ }
+
+ // Create VP9 Codec Feature Metadata (CodecPrivate) that can be parsed
+ // https://www.webmproject.org/docs/container/#vp9-codec-feature-metadata-codecprivate
+ sp<ABuffer> csd = sp<ABuffer>::make(csdSize);
+ uint8_t* csdData = csd->data();
+
+ *csdData++ = 0x01 /* FEATURE PROFILE */;
+ *csdData++ = 0x01 /* length */;
+ *csdData++ = profile;
+
+ *csdData++ = 0x03 /* FEATURE BITDEPTH */;
+ *csdData++ = 0x01 /* length */;
+ *csdData++ = bitDepth;
+
+ // csdSize more than 6 means chroma subsampling data was found.
+ if (csdSize > 6) {
+ *csdData++ = 0x04 /* FEATURE SUBSAMPLING */;
+ *csdData++ = 0x01 /* length */;
+ *csdData++ = chromaSubsampling;
+ }
+
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, csd->data(), csd->size());
+ return true;
+}
+
bool MakeAACCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size) {
if (data == nullptr || size < 7) {
return false;
diff --git a/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h b/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
index dcaf27f..69cf21a 100644
--- a/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
+++ b/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
@@ -38,6 +38,8 @@
void parseVorbisComment(
AMediaFormat *fileMeta, const char *comment, size_t commentLength);
+bool MakeVP9CodecSpecificData(AMediaFormat* meta, const uint8_t* data, size_t size);
+
} // namespace android
#endif // META_DATA_UTILS_H_
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 01f55dd..d5d778f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1079,6 +1079,7 @@
client = registerPid(clientPid);
IAfPlaybackThread* effectThread = nullptr;
+ sp<IAfEffectChain> effectChain = nullptr;
// check if an effect chain with the same session ID is present on another
// output thread and move it here.
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -1091,6 +1092,10 @@
}
}
}
+ // Check if an orphan effect chain exists for this session
+ if (effectThread == nullptr) {
+ effectChain = getOrphanEffectChain_l(sessionId);
+ }
ALOGV("createTrack() sessionId: %d", sessionId);
output.sampleRate = input.config.sample_rate;
@@ -1135,6 +1140,13 @@
effectIds = thread->getEffectIds_l(sessionId);
}
}
+ if (effectChain != nullptr) {
+ if (moveEffectChain_ll(sessionId, nullptr, thread, effectChain.get())
+ == NO_ERROR) {
+ effectThreadId = thread->id();
+ effectIds = thread->getEffectIds_l(sessionId);
+ }
+ }
}
// Look for sync events awaiting for a session to be used.
@@ -4222,8 +4234,9 @@
// before creating the AudioEffect or the io handle must be specified.
//
// Detect if the effect is created after an AudioRecord is destroyed.
- if ((sessionId != AUDIO_SESSION_OUTPUT_MIX) &&
- getOrphanEffectChain_l(sessionId).get() != nullptr) {
+ if (sessionId != AUDIO_SESSION_OUTPUT_MIX
+ && ((descOut.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)
+ && getOrphanEffectChain_l(sessionId).get() != nullptr) {
ALOGE("%s: effect %s with no specified io handle is denied because the AudioRecord"
" for session %d no longer exists",
__func__, descOut.name, sessionId);
@@ -4234,11 +4247,27 @@
// Legacy handling of creating an effect on an expired or made-up
// session id. We think that it is a Playback effect.
//
- // If no output thread contains the requested session ID, default to
- // first output. The effect chain will be moved to the correct output
- // thread when a track with the same session ID is created
- if (io == AUDIO_IO_HANDLE_NONE && mPlaybackThreads.size() > 0) {
- io = mPlaybackThreads.keyAt(0);
+ // If no output thread contains the requested session ID, park the effect to
+ // the orphan chains. The effect chain will be moved to the correct output
+ // thread when a track with the same session ID is created.
+ if (io == AUDIO_IO_HANDLE_NONE) {
+ if (probe) {
+ // In probe mode, as no compatible thread found, exit with error.
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ ALOGV("%s() got io %d for effect %s", __func__, io, descOut.name);
+ sp<Client> client = registerPid(currentPid);
+ bool pinned = !audio_is_global_session(sessionId) && isSessionAcquired_l(sessionId);
+ handle = createOrphanEffect_l(client, effectClient, priority, sessionId,
+ &descOut, &enabledOut, &lStatus, pinned,
+ request.notifyFramesProcessed);
+ if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
+ // remove local strong reference to Client with clientMutex() held
+ audio_utils::lock_guard _cl(clientMutex());
+ client.clear();
+ }
+ goto Register;
}
ALOGV("createEffect() got io %d for effect %s", io, descOut.name);
} else if (checkPlaybackThread_l(io) != nullptr
@@ -4356,6 +4385,85 @@
return lStatus;
}
+sp<IAfEffectHandle> AudioFlinger::createOrphanEffect_l(
+ const sp<Client>& client,
+ const sp<IEffectClient>& effectClient,
+ int32_t priority,
+ audio_session_t sessionId,
+ effect_descriptor_t *desc,
+ int *enabled,
+ status_t *status,
+ bool pinned,
+ bool notifyFramesProcessed)
+{
+ ALOGV("%s effectClient %p, priority %d, sessionId %d, factory %p",
+ __func__, effectClient.get(), priority, sessionId, mEffectsFactoryHal.get());
+
+ // Check if an orphan effect chain exists for this session or create new chain for this session
+ sp<IAfEffectModule> effect;
+ sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
+ bool chainCreated = false;
+ if (chain == nullptr) {
+ chain = IAfEffectChain::create(/* ThreadBase= */ nullptr, sessionId, this);
+ chainCreated = true;
+ } else {
+ effect = chain->getEffectFromDesc(desc);
+ }
+ bool effectCreated = false;
+ if (effect == nullptr) {
+ audio_unique_id_t effectId = nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
+ // create a new effect module if none present in the chain
+ status_t llStatus =
+ chain->createEffect(effect, desc, effectId, sessionId, pinned);
+ if (llStatus != NO_ERROR) {
+ *status = llStatus;
+ // if the effect chain was not created here, put it back
+ if (!chainCreated) {
+ putOrphanEffectChain_l(chain);
+ }
+ return nullptr;
+ }
+ effect->setMode(getMode());
+
+ if (effect->isHapticGenerator()) {
+ // TODO(b/184194057): Use the vibrator information from the vibrator that will be used
+ // for the HapticGenerator.
+ const std::optional<media::AudioVibratorInfo> defaultVibratorInfo =
+ std::move(getDefaultVibratorInfo_l());
+ if (defaultVibratorInfo) {
+ // Only set the vibrator info when it is a valid one.
+ audio_utils::lock_guard _cl(chain->mutex());
+ effect->setVibratorInfo_l(*defaultVibratorInfo);
+ }
+ }
+ effectCreated = true;
+ }
+ // create effect handle and connect it to effect module
+ sp<IAfEffectHandle> handle =
+ IAfEffectHandle::create(effect, client, effectClient, priority, notifyFramesProcessed);
+ status_t lStatus = handle->initCheck();
+ if (lStatus == OK) {
+ lStatus = effect->addHandle(handle.get());
+ }
+ // in case of lStatus error, EffectHandle will still return and caller should do the clear
+ if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
+ if (effectCreated) {
+ chain->removeEffect(effect);
+ }
+ // if the effect chain was not created here, put it back
+ if (!chainCreated) {
+ putOrphanEffectChain_l(chain);
+ }
+ } else {
+ if (enabled != NULL) {
+ *enabled = (int)effect->isEnabled();
+ }
+ putOrphanEffectChain_l(chain);
+ }
+ *status = lStatus;
+ return handle;
+}
+
status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcIo,
audio_io_handle_t dstIo)
NO_THREAD_SAFETY_ANALYSIS
@@ -4487,7 +4595,7 @@
if (srcThread != nullptr) {
srcThread->removeEffect_l(effect);
} else {
- chain->removeEffect_l(effect);
+ chain->removeEffect(effect);
}
removed.add(effect);
status = dstThread->addEffect_ll(effect);
@@ -4730,7 +4838,7 @@
ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
if (index >= 0) {
sp<IAfEffectChain> chain = mOrphanEffectChains.valueAt(index);
- if (chain->removeEffect_l(effect, true) == 0) {
+ if (chain->removeEffect(effect, true) == 0) {
ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index);
mOrphanEffectChains.removeItemsAt(index);
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 7c26f72..4e46bea 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -703,6 +703,16 @@
sp<Client> registerPid(pid_t pid) EXCLUDES_AudioFlinger_ClientMutex; // always returns non-0
+ sp<IAfEffectHandle> createOrphanEffect_l(const sp<Client>& client,
+ const sp<media::IEffectClient>& effectClient,
+ int32_t priority,
+ audio_session_t sessionId,
+ effect_descriptor_t *desc,
+ int *enabled,
+ status_t *status /*non-NULL*/,
+ bool pinned,
+ bool notifyFramesProcessed) REQUIRES(mutex());
+
// for use from destructor
status_t closeOutput_nonvirtual(audio_io_handle_t output) EXCLUDES_AudioFlinger_Mutex;
status_t closeInput_nonvirtual(audio_io_handle_t input) EXCLUDES_AudioFlinger_Mutex;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 10a8883..ab098de 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1357,7 +1357,7 @@
}
}
-status_t EffectModule::setVolume(uint32_t* left, uint32_t* right, bool controller) {
+status_t EffectModule::setVolume(uint32_t* left, uint32_t* right, bool controller, bool force) {
AutoLockReentrant _l(mutex(), mSetVolumeReentrantTid);
if (mStatus != NO_ERROR) {
return mStatus;
@@ -1365,7 +1365,7 @@
status_t status = NO_ERROR;
// Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
// if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
- if (isProcessEnabled() &&
+ if ((isProcessEnabled() || force) &&
((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
(mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND ||
(mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_MONITOR)) {
@@ -1376,6 +1376,9 @@
status_t EffectModule::setVolumeInternal(
uint32_t *left, uint32_t *right, bool controller) {
+ if (mVolume.has_value() && *left == mVolume.value()[0] && *right == mVolume.value()[1]) {
+ return NO_ERROR;
+ }
uint32_t volume[2] = {*left, *right};
uint32_t *pVolume = controller ? volume : nullptr;
uint32_t size = sizeof(volume);
@@ -1387,6 +1390,7 @@
if (controller && status == NO_ERROR && size == sizeof(volume)) {
*left = volume[0];
*right = volume[1];
+ mVolume = {*left, *right};
}
return status;
}
@@ -2157,27 +2161,31 @@
/* static */
sp<IAfEffectChain> IAfEffectChain::create(
const sp<IAfThreadBase>& thread,
- audio_session_t sessionId)
+ audio_session_t sessionId,
+ const sp<IAfThreadCallback>& afThreadCallback)
{
- return sp<EffectChain>::make(thread, sessionId);
+ return sp<EffectChain>::make(thread, sessionId, afThreadCallback);
}
-EffectChain::EffectChain(const sp<IAfThreadBase>& thread,
- audio_session_t sessionId)
+EffectChain::EffectChain(const sp<IAfThreadBase>& thread, audio_session_t sessionId,
+ const sp<IAfThreadCallback>& afThreadCallback)
: mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
- mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
+ mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread, afThreadCallback))
{
- mStrategy = thread->getStrategyForStream(AUDIO_STREAM_MUSIC);
- mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
- thread->frameCount();
+ if (thread != nullptr) {
+ mStrategy = thread->getStrategyForStream(AUDIO_STREAM_MUSIC);
+ mMaxTailBuffers =
+ ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
+ thread->frameCount();
+ }
}
-// getEffectFromDesc_l() must be called with IAfThreadBase::mutex() held
-sp<IAfEffectModule> EffectChain::getEffectFromDesc_l(
+sp<IAfEffectModule> EffectChain::getEffectFromDesc(
effect_descriptor_t *descriptor) const
{
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -2191,6 +2199,7 @@
// getEffectFromId_l() must be called with IAfThreadBase::mutex() held
sp<IAfEffectModule> EffectChain::getEffectFromId_l(int id) const
{
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -2206,6 +2215,7 @@
sp<IAfEffectModule> EffectChain::getEffectFromType_l(
const effect_uuid_t *type) const
{
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
@@ -2296,8 +2306,7 @@
}
}
-// createEffect_l() must be called with IAfThreadBase::mutex() held
-status_t EffectChain::createEffect_l(sp<IAfEffectModule>& effect,
+status_t EffectChain::createEffect(sp<IAfEffectModule>& effect,
effect_descriptor_t *desc,
int id,
audio_session_t sessionId,
@@ -2307,7 +2316,7 @@
effect = new EffectModule(mEffectCallback, desc, id, sessionId, pinned, AUDIO_PORT_HANDLE_NONE);
status_t lStatus = effect->status();
if (lStatus == NO_ERROR) {
- lStatus = addEffect_ll(effect);
+ lStatus = addEffect_l(effect);
}
if (lStatus != NO_ERROR) {
effect.clear();
@@ -2315,22 +2324,22 @@
return lStatus;
}
-// addEffect_l() must be called with IAfThreadBase::mutex() held
-status_t EffectChain::addEffect_l(const sp<IAfEffectModule>& effect)
+status_t EffectChain::addEffect(const sp<IAfEffectModule>& effect)
{
audio_utils::lock_guard _l(mutex());
- return addEffect_ll(effect);
+ return addEffect_l(effect);
}
-// addEffect_l() must be called with IAfThreadBase::mutex() and EffectChain::mutex() held
-status_t EffectChain::addEffect_ll(const sp<IAfEffectModule>& effect)
+// addEffect_l() must be called with EffectChain::mutex() held
+status_t EffectChain::addEffect_l(const sp<IAfEffectModule>& effect)
{
effect->setCallback(mEffectCallback);
effect_descriptor_t desc = effect->desc();
+ ssize_t idx_insert = 0;
if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
// Auxiliary effects are inserted at the beginning of mEffects vector as
// they are processed first and accumulated in chain input buffer
- mEffects.insertAt(effect, 0);
+ mEffects.insertAt(effect, idx_insert);
// the input buffer for auxiliary effect contains mono samples in
// 32 bit format. This is to avoid saturation in AudoMixer
@@ -2350,7 +2359,7 @@
// by insert effects
effect->setOutBuffer(mInBuffer);
} else {
- ssize_t idx_insert = getInsertIndex_ll(desc);
+ idx_insert = getInsertIndex_l(desc);
if (idx_insert < 0) {
return INVALID_OPERATION;
}
@@ -2399,6 +2408,18 @@
}
effect->configure_l();
+ if (effect->isVolumeControl()) {
+ const auto volumeControlIndex = findVolumeControl_l(0, mEffects.size());
+ if (!volumeControlIndex.has_value() || (ssize_t)volumeControlIndex.value() < idx_insert) {
+ // If this effect will be the new volume control effect when it is enabled, force
+ // initializing the volume as 0 for volume control effect for safer ramping. The actual
+ // volume will be set from setVolume_l.
+ uint32_t left = 0;
+ uint32_t right = 0;
+ effect->setVolume(&left, &right, true /*controller*/, true /*force*/);
+ }
+ }
+
return NO_ERROR;
}
@@ -2411,7 +2432,7 @@
return std::nullopt;
}
-ssize_t EffectChain::getInsertIndex_ll(const effect_descriptor_t& desc) {
+ssize_t EffectChain::getInsertIndex_l(const effect_descriptor_t& desc) {
// Insert effects are inserted at the end of mEffects vector as they are processed
// after track and auxiliary effects.
// Insert effect order as a function of indicated preference:
@@ -2484,8 +2505,7 @@
return idx_insert;
}
-// removeEffect_l() must be called with IAfThreadBase::mutex() held
-size_t EffectChain::removeEffect_l(const sp<IAfEffectModule>& effect,
+size_t EffectChain::removeEffect(const sp<IAfEffectModule>& effect,
bool release)
{
audio_utils::lock_guard _l(mutex());
@@ -2536,6 +2556,7 @@
// setDevices_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
{
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
mEffects[i]->setDevices(devices);
@@ -2545,6 +2566,7 @@
// setInputDevice_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
{
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
mEffects[i]->setInputDevice(device);
@@ -2554,6 +2576,7 @@
// setMode_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setMode_l(audio_mode_t mode)
{
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
mEffects[i]->setMode(mode);
@@ -2563,6 +2586,7 @@
// setAudioSource_l() must be called with IAfThreadBase::mutex() held
void EffectChain::setAudioSource_l(audio_source_t source)
{
+ audio_utils::lock_guard _l(mutex());
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
mEffects[i]->setAudioSource(source);
@@ -2604,21 +2628,16 @@
return volumeControlIndex.has_value();
}
- if (volumeControlEffect != cachedVolumeControlEffect) {
- // The volume control effect is a new one. Set the old one as full volume. Set the new onw
- // as zero for safe ramping.
- if (cachedVolumeControlEffect != nullptr) {
+ for (int i = 0; i < ctrlIdx; ++i) {
+ // For all volume control effects before the effect that controls volume, set the volume
+ // to maximum to avoid double attenuation.
+ if (mEffects[i]->isVolumeControl()) {
uint32_t leftMax = 1 << 24;
uint32_t rightMax = 1 << 24;
- cachedVolumeControlEffect->setVolume(&leftMax, &rightMax, true /*controller*/);
+ mEffects[i]->setVolume(&leftMax, &rightMax, true /*controller*/, true /*force*/);
}
- if (volumeControlEffect != nullptr) {
- uint32_t leftZero = 0;
- uint32_t rightZero = 0;
- volumeControlEffect->setVolume(&leftZero, &rightZero, true /*controller*/);
- }
- mVolumeControlEffect = volumeControlEffect;
}
+
mLeftVolume = newLeft;
mRightVolume = newRight;
@@ -2668,8 +2687,12 @@
}
}
-// containsHapticGeneratingEffect_l must be called with
-// IAfThreadBase::mutex() or EffectChain::mutex() held
+bool EffectChain::containsHapticGeneratingEffect()
+{
+ audio_utils::lock_guard _l(mutex());
+ return containsHapticGeneratingEffect_l();
+}
+// containsHapticGeneratingEffect_l must be called with EffectChain::mutex() held
bool EffectChain::containsHapticGeneratingEffect_l()
{
for (size_t i = 0; i < mEffects.size(); ++i) {
@@ -2810,7 +2833,7 @@
}
if (desc->mRefCount++ == 0) {
Vector< sp<IAfEffectModule> > effects;
- getSuspendEligibleEffects_l(effects);
+ getSuspendEligibleEffects(effects);
for (size_t i = 0; i < effects.size(); i++) {
setEffectSuspended_l(&effects[i]->desc().type, true);
}
@@ -2860,7 +2883,7 @@
return false;
}
-bool EffectChain::isEffectEligibleForSuspend_l(const effect_descriptor_t& desc)
+bool EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
{
// auxiliary effects and visualizer are never suspended on output mix
if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
@@ -2873,12 +2896,13 @@
return true;
}
-void EffectChain::getSuspendEligibleEffects_l(
+void EffectChain::getSuspendEligibleEffects(
Vector< sp<IAfEffectModule> > &effects)
{
effects.clear();
+ audio_utils::lock_guard _l(mutex());
for (size_t i = 0; i < mEffects.size(); i++) {
- if (isEffectEligibleForSuspend_l(mEffects[i]->desc())) {
+ if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
effects.add(mEffects[i]);
}
}
@@ -2899,7 +2923,7 @@
if (index < 0) {
return;
}
- if (!isEffectEligibleForSuspend_l(effect->desc())) {
+ if (!isEffectEligibleForSuspend(effect->desc())) {
return;
}
setEffectSuspended_l(&effect->desc().type, enabled);
@@ -2947,6 +2971,12 @@
void EffectChain::setThread(const sp<IAfThreadBase>& thread)
{
+ if (thread != nullptr) {
+ mStrategy = thread->getStrategyForStream(AUDIO_STREAM_MUSIC);
+ mMaxTailBuffers =
+ ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
+ thread->frameCount();
+ }
audio_utils::lock_guard _l(mutex());
mEffectCallback->setThread(thread);
}
@@ -3136,7 +3166,7 @@
uint32_t EffectChain::EffectCallback::sampleRate() const {
const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
- return 0;
+ return DEFAULT_OUTPUT_SAMPLE_RATE;
}
return t->sampleRate();
}
@@ -3144,6 +3174,7 @@
audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const
NO_THREAD_SAFETY_ANALYSIS
// calling function 'hasAudioSession_l' requires holding mutex 'ThreadBase_Mutex' exclusively
+// calling function 'isFirstEffect_l' requires holding mutex 'EffectChain_Mutex' exclusively
{
const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
@@ -3156,7 +3187,7 @@
if (mThreadType == IAfThreadBase::SPATIALIZER) {
if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
- if (c->isFirstEffect(id)) {
+ if (c->isFirstEffect_l(id)) {
return t->mixerChannelMask();
} else {
return t->channelMask();
@@ -3224,7 +3255,8 @@
size_t EffectChain::EffectCallback::frameCount() const {
const sp<IAfThreadBase> t = thread().promote();
if (t == nullptr) {
- return 0;
+ // frameCount cannot be zero.
+ return 1;
}
return t->frameCount();
}
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 5e527d3..0fa1b83 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -25,6 +25,8 @@
#include <private/media/AudioEffectShared.h>
#include <map> // avoid transitive dependency
+#include <optional>
+#include <vector>
namespace android {
@@ -215,7 +217,7 @@
}
status_t setDevices(const AudioDeviceTypeAddrVector& devices) final EXCLUDES_EffectBase_Mutex;
status_t setInputDevice(const AudioDeviceTypeAddr& device) final EXCLUDES_EffectBase_Mutex;
- status_t setVolume(uint32_t *left, uint32_t *right, bool controller) final;
+ status_t setVolume(uint32_t *left, uint32_t *right, bool controller, bool force) final;
status_t setMode(audio_mode_t mode) final EXCLUDES_EffectBase_Mutex;
status_t setAudioSource(audio_source_t source) final EXCLUDES_EffectBase_Mutex;
status_t start_l() final REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex;
@@ -234,9 +236,9 @@
bool isSpatializer() const final;
status_t setHapticScale_l(int id, os::HapticScale hapticScale) final
- REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectBase_Mutex;
+ REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex;
status_t setVibratorInfo_l(const media::AudioVibratorInfo& vibratorInfo) final
- REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectBase_Mutex;
+ REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex;
status_t sendMetadata_ll(const std::vector<playback_track_metadata_v7_t>& metadata) final
REQUIRES(audio_utils::ThreadBase_Mutex,
audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex;
@@ -304,6 +306,8 @@
static constexpr pid_t INVALID_PID = (pid_t)-1;
// this tid is allowed to call setVolume() without acquiring the mutex.
pid_t mSetVolumeReentrantTid = INVALID_PID;
+
+ std::optional<std::vector<uint32_t>> mVolume;
};
// The EffectHandle class implements the IEffect interface. It provides resources
@@ -412,7 +416,9 @@
// it also provide it's own input buffer used by the track as accumulation buffer.
class EffectChain : public IAfEffectChain {
public:
- EffectChain(const sp<IAfThreadBase>& thread, audio_session_t sessionId);
+ EffectChain(const sp<IAfThreadBase>& thread,
+ audio_session_t sessionId,
+ const sp<IAfThreadCallback>& afThreadCallback);
void process_l() final REQUIRES(audio_utils::EffectChain_Mutex);
@@ -420,25 +426,25 @@
return mMutex;
}
- status_t createEffect_l(sp<IAfEffectModule>& effect, effect_descriptor_t* desc, int id,
+ status_t createEffect(sp<IAfEffectModule>& effect, effect_descriptor_t* desc, int id,
audio_session_t sessionId, bool pinned) final
- REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
+ EXCLUDES_EffectChain_Mutex;
+ status_t addEffect(const sp<IAfEffectModule>& handle) final
+ EXCLUDES_EffectChain_Mutex;
status_t addEffect_l(const sp<IAfEffectModule>& handle) final
- REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
- status_t addEffect_ll(const sp<IAfEffectModule>& handle) final
- REQUIRES(audio_utils::ThreadBase_Mutex, audio_utils::EffectChain_Mutex);
- size_t removeEffect_l(const sp<IAfEffectModule>& handle, bool release = false) final
- REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
+ REQUIRES(audio_utils::EffectChain_Mutex);
+ size_t removeEffect(const sp<IAfEffectModule>& handle, bool release = false) final
+ EXCLUDES_EffectChain_Mutex;
audio_session_t sessionId() const final { return mSessionId; }
void setSessionId(audio_session_t sessionId) final { mSessionId = sessionId; }
- sp<IAfEffectModule> getEffectFromDesc_l(effect_descriptor_t* descriptor) const final
- REQUIRES(audio_utils::ThreadBase_Mutex);
+ sp<IAfEffectModule> getEffectFromDesc(effect_descriptor_t* descriptor) const final
+ EXCLUDES_EffectChain_Mutex;
sp<IAfEffectModule> getEffectFromId_l(int id) const final
- REQUIRES(audio_utils::ThreadBase_Mutex);
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t* type) const final
- REQUIRES(audio_utils::ThreadBase_Mutex);
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
std::vector<int> getEffectIds_l() const final REQUIRES(audio_utils::ThreadBase_Mutex);
// FIXME use float to improve the dynamic range
@@ -446,11 +452,13 @@
bool force = false) final EXCLUDES_EffectChain_Mutex;
void resetVolume_l() final REQUIRES(audio_utils::EffectChain_Mutex);
void setDevices_l(const AudioDeviceTypeAddrVector& devices) final
- REQUIRES(audio_utils::ThreadBase_Mutex);
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
void setInputDevice_l(const AudioDeviceTypeAddr& device) final
- REQUIRES(audio_utils::ThreadBase_Mutex);
- void setMode_l(audio_mode_t mode) final REQUIRES(audio_utils::ThreadBase_Mutex);
- void setAudioSource_l(audio_source_t source) final REQUIRES(audio_utils::ThreadBase_Mutex);
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
+ void setMode_l(audio_mode_t mode) final
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
+ void setAudioSource_l(audio_source_t source) final
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final {
mInBuffer = buffer;
@@ -517,8 +525,11 @@
bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final
REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
- // Requires either IAfThreadBase::mutex() or EffectChain::mutex() held
- bool containsHapticGeneratingEffect_l() final;
+ bool containsHapticGeneratingEffect() final
+ EXCLUDES_EffectChain_Mutex;
+
+ bool containsHapticGeneratingEffect_l() final
+ REQUIRES(audio_utils::EffectChain_Mutex);
void setHapticScale_l(int id, os::HapticScale hapticScale) final
REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex;
@@ -527,15 +538,19 @@
wp<IAfThreadBase> thread() const final { return mEffectCallback->thread(); }
- bool isFirstEffect(int id) const final {
+ bool isFirstEffect_l(int id) const final REQUIRES(audio_utils::EffectChain_Mutex) {
return !mEffects.isEmpty() && id == mEffects[0]->id();
}
void dump(int fd, const Vector<String16>& args) const final;
- size_t numberOfEffects() const final { return mEffects.size(); }
+ size_t numberOfEffects() const final {
+ audio_utils::lock_guard _l(mutex());
+ return mEffects.size();
+ }
sp<IAfEffectModule> getEffectModule(size_t index) const final {
+ audio_utils::lock_guard _l(mutex());
return mEffects[index];
}
@@ -560,11 +575,13 @@
// Note: ctors taking a weak pointer to their owner must not promote it
// during construction (but may keep a reference for later promotion).
EffectCallback(const wp<EffectChain>& owner,
- const sp<IAfThreadBase>& thread) // we take a sp<> but store a wp<>.
+ const sp<IAfThreadBase>& thread,
+ const sp<IAfThreadCallback>& afThreadCallback) // we take a sp<> but store a wp<>.
: mChain(owner)
- , mThread(thread) {
- mThreadType = thread->type();
- mAfThreadCallback = thread->afThreadCallback();
+ , mThread(thread), mAfThreadCallback(afThreadCallback) {
+ if (thread != nullptr) {
+ mThreadType = thread->type();
+ }
}
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -606,6 +623,9 @@
wp<IAfEffectChain> chain() const final { return mChain; }
bool isAudioPolicyReady() const final {
+ if (mAfThreadCallback == nullptr) {
+ return false;
+ }
return mAfThreadCallback->isAudioPolicyReady();
}
@@ -613,8 +633,10 @@
void setThread(const sp<IAfThreadBase>& thread) {
mThread = thread;
- mThreadType = thread->type();
- mAfThreadCallback = thread->afThreadCallback();
+ if (thread != nullptr) {
+ mThreadType = thread->type();
+ mAfThreadCallback = thread->afThreadCallback();
+ }
}
bool hasThreadAttached() const {
return thread().promote() != nullptr;
@@ -623,7 +645,7 @@
const wp<IAfEffectChain> mChain;
mediautils::atomic_wp<IAfThreadBase> mThread;
sp<IAfThreadCallback> mAfThreadCallback;
- IAfThreadBase::type_t mThreadType;
+ IAfThreadBase::type_t mThreadType = IAfThreadBase::MIXER;
};
DISALLOW_COPY_AND_ASSIGN(EffectChain);
@@ -639,8 +661,8 @@
// get a list of effect modules to suspend when an effect of the type
// passed is enabled.
- void getSuspendEligibleEffects_l(Vector<sp<IAfEffectModule>>& effects)
- REQUIRES(audio_utils::ThreadBase_Mutex);
+ void getSuspendEligibleEffects(Vector<sp<IAfEffectModule>>& effects)
+ EXCLUDES_EffectChain_Mutex;
// get an effect module if it is currently enable
sp<IAfEffectModule> getEffectIfEnabled_l(const effect_uuid_t* type)
@@ -648,8 +670,7 @@
// true if the effect whose descriptor is passed can be suspended
// OEMs can modify the rules implemented in this method to exclude specific effect
// types or implementations from the suspend/restore mechanism.
- bool isEffectEligibleForSuspend_l(const effect_descriptor_t& desc)
- REQUIRES(audio_utils::ThreadBase_Mutex);
+ bool isEffectEligibleForSuspend(const effect_descriptor_t& desc);
static bool isEffectEligibleForBtNrecSuspend_l(const effect_uuid_t* type)
REQUIRES(audio_utils::ThreadBase_Mutex);
@@ -662,15 +683,15 @@
void setVolumeForOutput_l(uint32_t left, uint32_t right)
REQUIRES(audio_utils::EffectChain_Mutex);
- ssize_t getInsertIndex_ll(const effect_descriptor_t& desc)
- REQUIRES(audio_utils::ThreadBase_Mutex, audio_utils::EffectChain_Mutex);
+ ssize_t getInsertIndex_l(const effect_descriptor_t& desc)
+ REQUIRES(audio_utils::EffectChain_Mutex);
std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const
REQUIRES(audio_utils::EffectChain_Mutex);
// mutex protecting effect list
mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kEffectChain_Mutex};
- Vector<sp<IAfEffectModule>> mEffects; // list of effect modules
+ Vector<sp<IAfEffectModule>> mEffects GUARDED_BY(mutex()); // list of effect modules
audio_session_t mSessionId; // audio session ID
sp<EffectBufferHalInterface> mInBuffer; // chain input buffer
sp<EffectBufferHalInterface> mOutBuffer; // chain output buffer
diff --git a/services/audioflinger/IAfEffect.h b/services/audioflinger/IAfEffect.h
index fd4dd62..d5adeb4 100644
--- a/services/audioflinger/IAfEffect.h
+++ b/services/audioflinger/IAfEffect.h
@@ -163,7 +163,8 @@
virtual int16_t *inBuffer() const = 0;
virtual status_t setDevices(const AudioDeviceTypeAddrVector &devices) = 0;
virtual status_t setInputDevice(const AudioDeviceTypeAddr &device) = 0;
- virtual status_t setVolume(uint32_t *left, uint32_t *right, bool controller) = 0;
+ virtual status_t setVolume(uint32_t *left, uint32_t *right, bool controller,
+ bool force = false) = 0;
virtual status_t setOffloaded_l(bool offloaded, audio_io_handle_t io) = 0;
virtual bool isOffloaded_l() const = 0;
@@ -181,9 +182,9 @@
virtual bool isSpatializer() const = 0;
virtual status_t setHapticScale_l(int id, os::HapticScale hapticScale)
- REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectBase_Mutex = 0;
+ REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex = 0;
virtual status_t setVibratorInfo_l(const media::AudioVibratorInfo& vibratorInfo)
- REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectBase_Mutex = 0;
+ REQUIRES(audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex = 0;
virtual status_t sendMetadata_ll(const std::vector<playback_track_metadata_v7_t>& metadata)
REQUIRES(audio_utils::ThreadBase_Mutex,
audio_utils::EffectChain_Mutex) EXCLUDES_EffectBase_Mutex = 0;
@@ -218,7 +219,8 @@
public:
static sp<IAfEffectChain> create(
const sp<IAfThreadBase>& thread,
- audio_session_t sessionId);
+ audio_session_t sessionId,
+ const sp<IAfThreadCallback>& afThreadCallback);
// special key used for an entry in mSuspendedEffects keyed vector
// corresponding to a suspend all request.
@@ -232,35 +234,36 @@
virtual audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::EffectChain_Mutex) = 0;
- virtual status_t createEffect_l(sp<IAfEffectModule>& effect, effect_descriptor_t* desc, int id,
+ virtual status_t createEffect(sp<IAfEffectModule>& effect, effect_descriptor_t* desc, int id,
audio_session_t sessionId, bool pinned)
- REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex = 0;
+ EXCLUDES_EffectChain_Mutex = 0;
+ virtual status_t addEffect(const sp<IAfEffectModule>& handle)
+ EXCLUDES_EffectChain_Mutex = 0;
virtual status_t addEffect_l(const sp<IAfEffectModule>& handle)
- REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex = 0;
- virtual status_t addEffect_ll(const sp<IAfEffectModule>& handle)
- REQUIRES(audio_utils::ThreadBase_Mutex, audio_utils::EffectChain_Mutex) = 0;
- virtual size_t removeEffect_l(const sp<IAfEffectModule>& handle,
+ REQUIRES(audio_utils::EffectChain_Mutex) = 0;
+ virtual size_t removeEffect(const sp<IAfEffectModule>& handle,
bool release = false) EXCLUDES_EffectChain_Mutex = 0;
virtual audio_session_t sessionId() const = 0;
virtual void setSessionId(audio_session_t sessionId) = 0;
- virtual sp<IAfEffectModule> getEffectFromDesc_l(effect_descriptor_t* descriptor) const
- REQUIRES(audio_utils::ThreadBase_Mutex) = 0;
+ virtual sp<IAfEffectModule> getEffectFromDesc(effect_descriptor_t* descriptor) const
+ EXCLUDES_EffectChain_Mutex = 0;
virtual sp<IAfEffectModule> getEffectFromId_l(int id) const
- REQUIRES(audio_utils::ThreadBase_Mutex) = 0;
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex = 0;
virtual sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t* type) const
- REQUIRES(audio_utils::ThreadBase_Mutex) = 0;
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex = 0;
virtual std::vector<int> getEffectIds_l() const = 0;
virtual bool setVolume(uint32_t* left, uint32_t* right,
bool force = false) EXCLUDES_EffectChain_Mutex = 0;
virtual void resetVolume_l() REQUIRES(audio_utils::EffectChain_Mutex) = 0;
virtual void setDevices_l(const AudioDeviceTypeAddrVector& devices)
- REQUIRES(audio_utils::ThreadBase_Mutex) = 0;
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex = 0;
virtual void setInputDevice_l(const AudioDeviceTypeAddr& device)
- REQUIRES(audio_utils::ThreadBase_Mutex) = 0;
- virtual void setMode_l(audio_mode_t mode) REQUIRES(audio_utils::ThreadBase_Mutex) = 0;
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex = 0;
+ virtual void setMode_l(audio_mode_t mode)
+ REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex = 0;
virtual void setAudioSource_l(audio_source_t source)
REQUIRES(audio_utils::ThreadBase_Mutex) = 0;
@@ -317,7 +320,11 @@
virtual bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const
REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex = 0;
- virtual bool containsHapticGeneratingEffect_l() = 0;
+ virtual bool containsHapticGeneratingEffect()
+ EXCLUDES_EffectChain_Mutex = 0;
+
+ virtual bool containsHapticGeneratingEffect_l()
+ REQUIRES(audio_utils::EffectChain_Mutex) = 0;
virtual void setHapticScale_l(int id, os::HapticScale hapticScale)
REQUIRES(audio_utils::ThreadBase_Mutex) EXCLUDES_EffectChain_Mutex = 0;
@@ -327,7 +334,7 @@
virtual wp<IAfThreadBase> thread() const = 0;
virtual void setThread(const sp<IAfThreadBase>& thread) EXCLUDES_EffectChain_Mutex = 0;
- virtual bool isFirstEffect(int id) const = 0;
+ virtual bool isFirstEffect_l(int id) const REQUIRES(audio_utils::EffectChain_Mutex) = 0;
virtual size_t numberOfEffects() const = 0;
virtual sp<IAfEffectModule> getEffectModule(size_t index) const = 0;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b6021c2..bcd8b99 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1666,12 +1666,12 @@
if (chain == 0) {
// create a new chain for this session
ALOGV("createEffect_l() new effect chain for session %d", sessionId);
- chain = IAfEffectChain::create(this, sessionId);
+ chain = IAfEffectChain::create(this, sessionId, mAfThreadCallback);
addEffectChain_l(chain);
chain->setStrategy(getStrategyForSession_l(sessionId));
chainCreated = true;
} else {
- effect = chain->getEffectFromDesc_l(desc);
+ effect = chain->getEffectFromDesc(desc);
}
ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
@@ -1679,7 +1679,7 @@
if (effect == 0) {
effectId = mAfThreadCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
// create a new effect module if none present in the chain
- lStatus = chain->createEffect_l(effect, desc, effectId, sessionId, pinned);
+ lStatus = chain->createEffect(effect, desc, effectId, sessionId, pinned);
if (lStatus != NO_ERROR) {
goto Exit;
}
@@ -1697,6 +1697,7 @@
const std::optional<media::AudioVibratorInfo> defaultVibratorInfo =
std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
if (defaultVibratorInfo) {
+ audio_utils::lock_guard _cl(chain->mutex());
// Only set the vibrator info when it is a valid one.
effect->setVibratorInfo_l(*defaultVibratorInfo);
}
@@ -1718,7 +1719,7 @@
if (!probe && lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
audio_utils::lock_guard _l(mutex());
if (effectCreated) {
- chain->removeEffect_l(effect);
+ chain->removeEffect(effect);
}
if (chainCreated) {
removeEffectChain_l(chain);
@@ -1819,7 +1820,7 @@
if (chain == 0) {
// create a new chain for this session
ALOGV("%s: new effect chain for session %d", __func__, sessionId);
- chain = IAfEffectChain::create(this, sessionId);
+ chain = IAfEffectChain::create(this, sessionId, mAfThreadCallback);
addEffectChain_l(chain);
chain->setStrategy(getStrategyForSession_l(sessionId));
chainCreated = true;
@@ -1834,7 +1835,7 @@
effect->setOffloaded_l(mType == OFFLOAD, mId);
- status_t status = chain->addEffect_l(effect);
+ status_t status = chain->addEffect(effect);
if (status != NO_ERROR) {
if (chainCreated) {
removeEffectChain_l(chain);
@@ -1861,7 +1862,7 @@
sp<IAfEffectChain> chain = effect->getCallback()->chain().promote();
if (chain != 0) {
// remove effect chain if removing last effect
- if (chain->removeEffect_l(effect, release) == 0) {
+ if (chain->removeEffect(effect, release) == 0) {
removeEffectChain_l(chain);
}
} else {
@@ -2901,7 +2902,7 @@
sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
if (mHapticChannelMask != AUDIO_CHANNEL_NONE
&& ((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
- || (chain != nullptr && chain->containsHapticGeneratingEffect_l()))) {
+ || (chain != nullptr && chain->containsHapticGeneratingEffect()))) {
// Unlock due to VibratorService will lock for this call and will
// call Tracks.mute/unmute which also require thread's lock.
mutex().unlock();
@@ -4804,7 +4805,7 @@
}
if (mHapticChannelCount > 0 &&
((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
- || (chain != nullptr && chain->containsHapticGeneratingEffect_l()))) {
+ || (chain != nullptr && chain->containsHapticGeneratingEffect()))) {
mutex().unlock();
// Unlock due to VibratorService will lock for this call and will
// call Tracks.mute/unmute which also require thread's lock.
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index efcd420..2dea379 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3190,7 +3190,12 @@
ALOGV("%s %d", __FUNCTION__, input);
inputDesc->removeClient(portId);
- mEffects.putOrphanEffects(client->session(), input, &mInputs, mpClientInterface);
+
+ // If no more clients are present in this session, park effects to an orphan chain
+ RecordClientVector clientsOnSession = inputDesc->getClientsForSession(client->session());
+ if (clientsOnSession.size() == 0) {
+ mEffects.putOrphanEffects(client->session(), input, &mInputs, mpClientInterface);
+ }
if (inputDesc->getClientCount() > 0) {
ALOGV("%s(%d) %zu clients remaining", __func__, portId, inputDesc->getClientCount());
return;
@@ -3590,7 +3595,7 @@
int session,
int id)
{
- if (session != AUDIO_SESSION_DEVICE) {
+ if (session != AUDIO_SESSION_DEVICE && io != AUDIO_IO_HANDLE_NONE) {
ssize_t index = mOutputs.indexOfKey(io);
if (index < 0) {
index = mInputs.indexOfKey(io);
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index c9e9090..b9b30f6 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -188,7 +188,6 @@
"aidl/DeathPipe.cpp",
"utils/AttributionAndPermissionUtils.cpp",
"utils/CameraServiceProxyWrapper.cpp",
- "utils/CameraThreadState.cpp",
"utils/CameraTraces.cpp",
"utils/AutoConditionLock.cpp",
"utils/SchedulingPolicyUtils.cpp",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 26208c5..e30775d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -81,7 +81,6 @@
#include "api2/CameraDeviceClient.h"
#include "utils/CameraTraces.h"
#include "utils/TagMonitor.h"
-#include "utils/CameraThreadState.h"
#include "utils/CameraServiceProxyWrapper.h"
#include "utils/SessionConfigurationUtils.h"
@@ -174,12 +173,6 @@
}
}
-// The word 'System' here does not refer to clients only on the system
-// partition. They just need to have a android system uid.
-static bool doesClientHaveSystemUid() {
- return (CameraThreadState::getCallingUid() < AID_APP_START);
-}
-
// Enable processes with isolated AID to request the binder
void CameraService::instantiate() {
CameraService::publish(true);
@@ -757,8 +750,8 @@
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
bool hasSystemCameraPermissions =
- hasPermissionsForSystemCamera(std::string(), CameraThreadState::getCallingPid(),
- CameraThreadState::getCallingUid());
+ hasPermissionsForSystemCamera(std::string(), getCallingPid(),
+ getCallingUid());
switch (type) {
case CAMERA_TYPE_BACKWARD_COMPATIBLE:
if (hasSystemCameraPermissions) {
@@ -785,8 +778,8 @@
Status CameraService::remapCameraIds(const hardware::CameraIdRemapping& cameraIdRemapping) {
if (!checkCallingPermission(toString16(sCameraInjectExternalCameraPermission))) {
- const int pid = CameraThreadState::getCallingPid();
- const int uid = CameraThreadState::getCallingUid();
+ const int pid = getCallingPid();
+ const int uid = getCallingUid();
ALOGE("%s: Permission Denial: can't configure camera ID mapping pid=%d, uid=%d",
__FUNCTION__, pid, uid);
return STATUS_ERROR(ERROR_PERMISSION_DENIED,
@@ -817,7 +810,7 @@
}
const std::string cameraId = resolveCameraId(unresolvedCameraId,
- CameraThreadState::getCallingUid());
+ getCallingUid());
binder::Status res;
if (request == nullptr) {
@@ -873,7 +866,7 @@
}
const std::string cameraId = resolveCameraId(unresolvedCameraId,
- CameraThreadState::getCallingUid());
+ getCallingUid());
if (supported == nullptr) {
std::string msg = fmt::sprintf("Camera %s: Invalid 'support' input!",
unresolvedCameraId.c_str());
@@ -930,7 +923,7 @@
}
const std::string cameraId =
- resolveCameraId(unresolvedCameraId, CameraThreadState::getCallingUid());
+ resolveCameraId(unresolvedCameraId, getCallingUid());
if (outMetadata == nullptr) {
std::string msg =
@@ -1047,7 +1040,7 @@
mServiceLock.unlock();
// Clear calling identity for disconnect() PID checks.
- int64_t token = CameraThreadState::clearCallingIdentity();
+ int64_t token = clearCallingIdentity();
// Disconnect clients.
for (auto& clientSp : clientsToDisconnect) {
@@ -1059,7 +1052,7 @@
// Invoke destructors (which call disconnect()) now while we don't hold the mServiceLock.
clientsToDisconnect.clear();
- CameraThreadState::restoreCallingIdentity(token);
+ restoreCallingIdentity(token);
mServiceLock.lock();
{
@@ -1074,8 +1067,8 @@
const std::string& cameraId,
const CameraMetadata& sessionParams) {
if (!checkCallingPermission(toString16(sCameraInjectExternalCameraPermission))) {
- const int pid = CameraThreadState::getCallingPid();
- const int uid = CameraThreadState::getCallingUid();
+ const int pid = getCallingPid();
+ const int uid = getCallingUid();
ALOGE("%s: Permission Denial: can't inject session params pid=%d, uid=%d",
__FUNCTION__, pid, uid);
return STATUS_ERROR(ERROR_PERMISSION_DENIED,
@@ -1153,7 +1146,7 @@
Mutex::Autolock l(mServiceLock);
std::string unresolvedCameraId = cameraIdIntToStrLocked(cameraId);
std::string cameraIdStr = resolveCameraId(
- unresolvedCameraId, CameraThreadState::getCallingUid());
+ unresolvedCameraId, getCallingUid());
if (shouldRejectSystemCameraConnection(cameraIdStr)) {
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
@@ -1166,7 +1159,7 @@
"Camera subsystem is not available");
}
bool hasSystemCameraPermissions = hasPermissionsForSystemCamera(std::to_string(cameraId),
- CameraThreadState::getCallingPid(), CameraThreadState::getCallingUid());
+ getCallingPid(), getCallingUid());
int cameraIdBound = mNumberOfCamerasWithoutSystemCamera;
if (hasSystemCameraPermissions) {
cameraIdBound = mNumberOfCameras;
@@ -1193,8 +1186,8 @@
std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt) {
const std::vector<std::string> *deviceIds = &mNormalDeviceIdsWithoutSystemCamera;
- auto callingPid = CameraThreadState::getCallingPid();
- auto callingUid = CameraThreadState::getCallingUid();
+ auto callingPid = getCallingPid();
+ auto callingUid = getCallingUid();
bool systemCameraPermissions = hasPermissionsForSystemCamera(std::to_string(cameraIdInt),
callingPid, callingUid, /* checkCameraPermissions= */ false);
if (systemCameraPermissions || getpid() == callingPid) {
@@ -1219,7 +1212,7 @@
ATRACE_CALL();
const std::string cameraId = resolveCameraId(unresolvedCameraId,
- CameraThreadState::getCallingUid());
+ getCallingUid());
if (!cameraInfo) {
ALOGE("%s: cameraInfo is NULL", __FUNCTION__);
@@ -1264,8 +1257,8 @@
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera kind "
"for device %s", cameraId.c_str());
}
- int callingPid = CameraThreadState::getCallingPid();
- int callingUid = CameraThreadState::getCallingUid();
+ int callingPid = getCallingPid();
+ int callingUid = getCallingUid();
std::vector<int32_t> tagsRemoved;
// If it's not calling from cameraserver, check the permission only if
// android.permission.CAMERA is required. If android.permission.SYSTEM_CAMERA was needed,
@@ -1305,7 +1298,7 @@
Mutex::Autolock l(mServiceLock);
const std::string cameraId = resolveCameraId(
- unresolvedCameraId, CameraThreadState::getCallingUid());
+ unresolvedCameraId, getCallingUid());
if (!mInitialized) {
ALOGE("%s: Camera HAL couldn't be initialized.", __FUNCTION__);
return STATUS_ERROR(ERROR_DISCONNECTED, "Camera HAL couldn't be initialized.");
@@ -1551,7 +1544,7 @@
}
Status CameraService::initializeShimMetadata(int cameraId) {
- int uid = CameraThreadState::getCallingUid();
+ int uid = getCallingUid();
std::string cameraIdStr = std::to_string(cameraId);
Status ret = Status::ok();
@@ -1583,7 +1576,7 @@
std::string unresolvedCameraId = std::to_string(cameraId);
std::string cameraIdStr = resolveCameraId(unresolvedCameraId,
- CameraThreadState::getCallingUid());
+ getCallingUid());
// Check if we already have parameters
{
@@ -1602,9 +1595,9 @@
}
}
- int64_t token = CameraThreadState::clearCallingIdentity();
+ int64_t token = clearCallingIdentity();
ret = initializeShimMetadata(cameraId);
- CameraThreadState::restoreCallingIdentity(token);
+ restoreCallingIdentity(token);
if (!ret.isOk()) {
// Error already logged by callee
return ret;
@@ -1649,7 +1642,7 @@
}
#endif // __BRILLO__
- int callingPid = CameraThreadState::getCallingPid();
+ int callingPid = getCallingPid();
if (!mInitialized) {
ALOGE("CameraService::connect X (PID %d) rejected (camera HAL module not loaded)",
@@ -1683,8 +1676,8 @@
Status CameraService::validateClientPermissionsLocked(const std::string& cameraId,
const std::string& clientName, int& clientUid, int& clientPid,
/*out*/int& originalClientPid) const {
- int callingPid = CameraThreadState::getCallingPid();
- int callingUid = CameraThreadState::getCallingUid();
+ int callingPid = getCallingPid();
+ int callingUid = getCallingUid();
// Check if we can trust clientUid
if (clientUid == USE_CALLING_UID) {
@@ -1772,7 +1765,7 @@
// For non-system clients : Only allow clients who are being used by the current foreground
// device user, unless calling from our own process.
- if (!doesClientHaveSystemUid() && callingPid != getpid() &&
+ if (!callerHasSystemUid() && callingPid != getpid() &&
(mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) {
ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from "
"device user %d, currently allowed device users: %s)", callingPid, clientUserId,
@@ -1802,7 +1795,7 @@
status_t CameraService::checkIfDeviceIsUsable(const std::string& cameraId) const {
auto cameraState = getCameraState(cameraId);
- int callingPid = CameraThreadState::getCallingPid();
+ int callingPid = getCallingPid();
if (cameraState == nullptr) {
ALOGE("CameraService::connect X (PID %d) rejected (invalid camera ID %s)", callingPid,
cameraId.c_str());
@@ -1900,7 +1893,7 @@
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->checkService(String16(kProcessInfoServiceName));
- if (!binder && isAutomotivePrivilegedClient(CameraThreadState::getCallingUid())) {
+ if (!binder && isAutomotivePrivilegedClient(getCallingUid())) {
// If processinfo service is not available and the client is automotive privileged
// client used for safety critical uses cases such as rear-view and surround-view which
// needs to be available before android boot completes, then use the hardcoded values
@@ -2033,7 +2026,7 @@
mServiceLock.unlock();
// Clear caller identity temporarily so client disconnect PID checks work correctly
- int64_t token = CameraThreadState::clearCallingIdentity();
+ int64_t token = clearCallingIdentity();
// Destroy evicted clients
for (auto& i : evictedClients) {
@@ -2041,7 +2034,7 @@
i->getValue()->disconnect(); // Clients will remove themselves from the active client list
}
- CameraThreadState::restoreCallingIdentity(token);
+ restoreCallingIdentity(token);
for (const auto& i : evictedClients) {
ALOGV("%s: Waiting for disconnect to complete for client for device %s (PID %" PRId32 ")",
@@ -2092,7 +2085,7 @@
std::string unresolvedCameraId = cameraIdIntToStr(api1CameraId);
std::string cameraIdStr = resolveCameraId(unresolvedCameraId,
- CameraThreadState::getCallingUid());
+ getCallingUid());
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId,
@@ -2101,7 +2094,7 @@
overrideToPortrait, forceSlowJpegMode, cameraIdStr, /*out*/client);
if(!ret.isOk()) {
- logRejected(cameraIdStr, CameraThreadState::getCallingPid(), clientPackageName,
+ logRejected(cameraIdStr, getCallingPid(), clientPackageName,
toStdString(ret.toString8()));
return ret;
}
@@ -2112,8 +2105,8 @@
const auto& mActivityManager = getActivityManager();
if (mActivityManager) {
mActivityManager->logFgsApiBegin(LOG_FGS_CAMERA_API,
- CameraThreadState::getCallingUid(),
- CameraThreadState::getCallingPid());
+ getCallingUid(),
+ getCallingPid());
}
return ret;
@@ -2143,9 +2136,9 @@
// and the serving thread is a non hwbinder thread, the client must have
// android.permission.SYSTEM_CAMERA permissions to connect.
- int cPid = CameraThreadState::getCallingPid();
- int cUid = CameraThreadState::getCallingUid();
- bool systemClient = doesClientHaveSystemUid();
+ int cPid = getCallingPid();
+ int cUid = getCallingUid();
+ bool systemClient = callerHasSystemUid();
SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
if (getSystemCameraKind(cameraId, &systemCameraKind) != OK) {
// This isn't a known camera ID, so it's not a system camera
@@ -2190,10 +2183,10 @@
Status ret = Status::ok();
sp<CameraDeviceClient> client = nullptr;
std::string clientPackageNameAdj = clientPackageName;
- int callingPid = CameraThreadState::getCallingPid();
- int callingUid = CameraThreadState::getCallingUid();
+ int callingPid = getCallingPid();
+ int callingUid = getCallingUid();
bool systemNativeClient = false;
- if (doesClientHaveSystemUid() && (clientPackageNameAdj.size() == 0)) {
+ if (callerHasSystemUid() && (clientPackageNameAdj.size() == 0)) {
std::string systemClient = fmt::sprintf("client.pid<%d>", callingPid);
clientPackageNameAdj = systemClient;
systemNativeClient = true;
@@ -2363,7 +2356,7 @@
bool isNonSystemNdk = false;
std::string clientPackageName;
int packageUid = (clientUid == USE_CALLING_UID) ?
- CameraThreadState::getCallingUid() : clientUid;
+ getCallingUid() : clientUid;
if (clientPackageNameMaybe.size() <= 0) {
// NDK calls don't come with package names, but we need one for various cases.
// Generally, there's a 1:1 mapping between UID and package name, but shared UIDs
@@ -2379,7 +2372,7 @@
int originalClientPid = 0;
int packagePid = (clientPid == USE_CALLING_PID) ?
- CameraThreadState::getCallingPid() : clientPid;
+ getCallingPid() : clientPid;
ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) and "
"Camera API version %d", packagePid, clientPackageName.c_str(), cameraId.c_str(),
static_cast<int>(effectiveApiLevel));
@@ -2616,11 +2609,11 @@
mServiceLock.unlock();
// Clear caller identity temporarily so client disconnect PID
// checks work correctly
- int64_t token = CameraThreadState::clearCallingIdentity();
+ int64_t token = clearCallingIdentity();
// Note AppOp to trigger the "Unblock" dialog
client->noteAppOp();
client->disconnect();
- CameraThreadState::restoreCallingIdentity(token);
+ restoreCallingIdentity(token);
// Reacquire mServiceLock
mServiceLock.lock();
@@ -2772,7 +2765,7 @@
"Torch client binder in null.");
}
- int uid = CameraThreadState::getCallingUid();
+ int uid = getCallingUid();
const std::string cameraId = resolveCameraId(unresolvedCameraId, uid);
if (shouldRejectSystemCameraConnection(cameraId)) {
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to change the strength level"
@@ -2880,7 +2873,7 @@
clientBinder->linkToDeath(this);
}
- int clientPid = CameraThreadState::getCallingPid();
+ int clientPid = getCallingPid();
ALOGI("%s: Torch strength for camera id %s changed to %d for client PID %d",
__FUNCTION__, cameraId.c_str(), torchStrength, clientPid);
if (!shouldSkipTorchStrengthUpdates) {
@@ -2900,7 +2893,7 @@
"Torch client Binder is null");
}
- int uid = CameraThreadState::getCallingUid();
+ int uid = getCallingUid();
const std::string cameraId = resolveCameraId(unresolvedCameraId, uid);
if (shouldRejectSystemCameraConnection(cameraId)) {
@@ -3008,7 +3001,7 @@
}
}
- int clientPid = CameraThreadState::getCallingPid();
+ int clientPid = getCallingPid();
std::string torchState = enabled ? "on" : "off";
ALOGI("Torch for camera id %s turned %s for client PID %d", cameraId.c_str(),
torchState.c_str(), clientPid);
@@ -3028,7 +3021,7 @@
Status CameraService::notifySystemEvent(int32_t eventId,
const std::vector<int32_t>& args) {
- const int pid = CameraThreadState::getCallingPid();
+ const int pid = getCallingPid();
const int selfPid = getpid();
// Permission checks
@@ -3036,7 +3029,7 @@
// Ensure we're being called by system_server, or similar process with
// permissions to notify the camera service about system events
if (!checkCallingPermission(toString16(sCameraSendSystemEventsPermission))) {
- const int uid = CameraThreadState::getCallingUid();
+ const int uid = getCallingUid();
ALOGE("Permission Denial: cannot send updates to camera service about system"
" events from pid=%d, uid=%d", pid, uid);
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
@@ -3102,7 +3095,7 @@
}
Status CameraService::notifyDeviceStateChange(int64_t newState) {
- const int pid = CameraThreadState::getCallingPid();
+ const int pid = getCallingPid();
const int selfPid = getpid();
// Permission checks
@@ -3110,7 +3103,7 @@
// Ensure we're being called by system_server, or similar process with
// permissions to notify the camera service about system events
if (!checkCallingPermission(toString16(sCameraSendSystemEventsPermission))) {
- const int uid = CameraThreadState::getCallingUid();
+ const int uid = getCallingUid();
ALOGE("Permission Denial: cannot send updates to camera service about device"
" state changes from pid=%d, uid=%d", pid, uid);
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
@@ -3133,7 +3126,7 @@
Status CameraService::notifyDisplayConfigurationChange() {
ATRACE_CALL();
- const int callingPid = CameraThreadState::getCallingPid();
+ const int callingPid = getCallingPid();
const int selfPid = getpid();
// Permission checks
@@ -3141,7 +3134,7 @@
// Ensure we're being called by system_server, or similar process with
// permissions to notify the camera service about system events
if (!checkCallingPermission(toString16(sCameraSendSystemEventsPermission))) {
- const int uid = CameraThreadState::getCallingUid();
+ const int uid = getCallingUid();
ALOGE("Permission Denial: cannot send updates to camera service about orientation"
" changes from pid=%d, uid=%d", callingPid, uid);
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
@@ -3230,8 +3223,8 @@
}
// Check for camera permissions
- int callingPid = CameraThreadState::getCallingPid();
- int callingUid = CameraThreadState::getCallingUid();
+ int callingPid = getCallingPid();
+ int callingUid = getCallingUid();
bool hasCameraPermission = ((callingPid == getpid()) ||
hasPermissionsForCamera(callingPid, callingUid));
if (!hasCameraPermission) {
@@ -3278,8 +3271,8 @@
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Null listener given to addListener");
}
- auto clientPid = CameraThreadState::getCallingPid();
- auto clientUid = CameraThreadState::getCallingUid();
+ auto clientPid = getCallingPid();
+ auto clientUid = getCallingUid();
bool openCloseCallbackAllowed = hasPermissionsForOpenCloseListener(clientPid, clientUid);
Mutex::Autolock lock(mServiceLock);
@@ -3421,7 +3414,7 @@
ATRACE_CALL();
const std::string cameraId = resolveCameraId(
- unresolvedCameraId, CameraThreadState::getCallingUid());
+ unresolvedCameraId, getCallingUid());
ALOGV("%s: for camera ID = %s", __FUNCTION__, cameraId.c_str());
@@ -3486,7 +3479,7 @@
ATRACE_CALL();
const std::string cameraId = resolveCameraId(unresolvedCameraId,
- CameraThreadState::getCallingUid());
+ getCallingUid());
ALOGV("%s: for camera ID = %s", __FUNCTION__, cameraId.c_str());
*isSupported = mCameraProviderManager->isHiddenPhysicalCamera(cameraId);
@@ -3503,8 +3496,8 @@
ATRACE_CALL();
if (!checkCallingPermission(toString16(sCameraInjectExternalCameraPermission))) {
- const int pid = CameraThreadState::getCallingPid();
- const int uid = CameraThreadState::getCallingUid();
+ const int pid = getCallingPid();
+ const int uid = getCallingUid();
ALOGE("Permission Denial: can't inject camera pid=%d, uid=%d", pid, uid);
return STATUS_ERROR(ERROR_PERMISSION_DENIED,
"Permission Denial: no permission to inject camera");
@@ -3706,13 +3699,13 @@
mServiceLock.unlock();
// Clear caller identity temporarily so client disconnect PID checks work correctly
- int64_t token = CameraThreadState::clearCallingIdentity();
+ int64_t token = clearCallingIdentity();
for (auto& i : evicted) {
i->disconnect();
}
- CameraThreadState::restoreCallingIdentity(token);
+ restoreCallingIdentity(token);
// Reacquire mServiceLock
mServiceLock.lock();
@@ -3939,7 +3932,7 @@
servicePid, overrideToPortrait),
mCameraId(api1CameraId)
{
- int callingPid = CameraThreadState::getCallingPid();
+ int callingPid = getCallingPid();
LOG1("Client::Client E (pid %d, id %d)", callingPid, mCameraId);
mRemoteCallback = cameraClient;
@@ -4038,8 +4031,8 @@
const auto& mActivityManager = getActivityManager();
if (mActivityManager) {
mActivityManager->logFgsApiEnd(LOG_FGS_CAMERA_API,
- CameraThreadState::getCallingUid(),
- CameraThreadState::getCallingPid());
+ getCallingUid(),
+ getCallingPid());
}
return res;
@@ -4049,7 +4042,7 @@
// No dumping of clients directly over Binder,
// must go through CameraService::dump
android_errorWriteWithInfoLog(SN_EVENT_LOG_ID, "26265403",
- CameraThreadState::getCallingUid(), NULL, 0);
+ getCallingUid(), NULL, 0);
return OK;
}
@@ -4382,7 +4375,7 @@
// Reset the client PID to allow server-initiated disconnect,
// and to prevent further calls by client.
- mClientPid = CameraThreadState::getCallingPid();
+ mClientPid = getCallingPid();
CaptureResultExtras resultExtras; // a dummy result (invalid)
notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISABLED, resultExtras);
disconnect();
@@ -5214,8 +5207,8 @@
if (checkCallingPermission(toString16(sDumpPermission)) == false) {
dprintf(fd, "Permission Denial: can't dump CameraService from pid=%d, uid=%d\n",
- CameraThreadState::getCallingPid(),
- CameraThreadState::getCallingUid());
+ getCallingPid(),
+ getCallingUid());
return NO_ERROR;
}
bool locked = tryLock(mServiceLock);
@@ -5464,7 +5457,7 @@
* binder driver
*/
// PID here is approximate and can be wrong.
- logClientDied(CameraThreadState::getCallingPid(), "Binder died unexpectedly");
+ logClientDied(getCallingPid(), "Binder died unexpectedly");
// check torch client
handleTorchClientBinderDied(who);
@@ -6480,9 +6473,9 @@
mServiceLock.unlock();
// Clear caller identity temporarily so client disconnect PID checks work correctly
- int64_t token = CameraThreadState::clearCallingIdentity();
+ int64_t token = clearCallingIdentity();
clientSp->disconnect();
- CameraThreadState::restoreCallingIdentity(token);
+ restoreCallingIdentity(token);
// Reacquire mServiceLock
mServiceLock.lock();
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 19e2999..c0d9fdf 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -38,7 +38,6 @@
#include "api1/client2/CallbackProcessor.h"
#include "api1/client2/ZslProcessor.h"
#include "device3/RotateAndCropMapper.h"
-#include "utils/CameraThreadState.h"
#include "utils/CameraServiceProxyWrapper.h"
#define ALOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
@@ -446,7 +445,7 @@
binder::Status res = binder::Status::ok();
// Allow both client and the cameraserver to disconnect at all times
- int callingPid = CameraThreadState::getCallingPid();
+ int callingPid = getCallingPid();
if (callingPid != mClientPid && callingPid != mServicePid) return res;
if (mDevice == 0) return res;
@@ -515,14 +514,14 @@
ALOGV("%s: E", __FUNCTION__);
Mutex::Autolock icl(mBinderSerializationLock);
- if (mClientPid != 0 && CameraThreadState::getCallingPid() != mClientPid) {
+ if (mClientPid != 0 && getCallingPid() != mClientPid) {
ALOGE("%s: Camera %d: Connection attempt from pid %d; "
"current locked to pid %d", __FUNCTION__,
- mCameraId, CameraThreadState::getCallingPid(), mClientPid);
+ mCameraId, getCallingPid(), mClientPid);
return BAD_VALUE;
}
- mClientPid = CameraThreadState::getCallingPid();
+ mClientPid = getCallingPid();
mRemoteCallback = client;
mSharedCameraCallbacks = client;
@@ -535,16 +534,16 @@
ALOGV("%s: E", __FUNCTION__);
Mutex::Autolock icl(mBinderSerializationLock);
ALOGV("%s: Camera %d: Lock call from pid %d; current client pid %d",
- __FUNCTION__, mCameraId, CameraThreadState::getCallingPid(), mClientPid);
+ __FUNCTION__, mCameraId, getCallingPid(), mClientPid);
if (mClientPid == 0) {
- mClientPid = CameraThreadState::getCallingPid();
+ mClientPid = getCallingPid();
return OK;
}
- if (mClientPid != CameraThreadState::getCallingPid()) {
+ if (mClientPid != getCallingPid()) {
ALOGE("%s: Camera %d: Lock call from pid %d; currently locked to pid %d",
- __FUNCTION__, mCameraId, CameraThreadState::getCallingPid(), mClientPid);
+ __FUNCTION__, mCameraId, getCallingPid(), mClientPid);
return EBUSY;
}
@@ -556,9 +555,9 @@
ALOGV("%s: E", __FUNCTION__);
Mutex::Autolock icl(mBinderSerializationLock);
ALOGV("%s: Camera %d: Unlock call from pid %d; current client pid %d",
- __FUNCTION__, mCameraId, CameraThreadState::getCallingPid(), mClientPid);
+ __FUNCTION__, mCameraId, getCallingPid(), mClientPid);
- if (mClientPid == CameraThreadState::getCallingPid()) {
+ if (mClientPid == getCallingPid()) {
SharedParameters::Lock l(mParameters);
if (l.mParameters.state == Parameters::RECORD ||
l.mParameters.state == Parameters::VIDEO_SNAPSHOT) {
@@ -572,7 +571,7 @@
}
ALOGE("%s: Camera %d: Unlock call from pid %d; currently locked to pid %d",
- __FUNCTION__, mCameraId, CameraThreadState::getCallingPid(), mClientPid);
+ __FUNCTION__, mCameraId, getCallingPid(), mClientPid);
return EBUSY;
}
@@ -1646,7 +1645,7 @@
ALOGV("%s: Camera %d", __FUNCTION__, mCameraId);
Mutex::Autolock icl(mBinderSerializationLock);
// The camera service can unconditionally get the parameters at all times
- if (CameraThreadState::getCallingPid() != mServicePid && checkPid(__FUNCTION__) != OK) return String8();
+ if (getCallingPid() != mServicePid && checkPid(__FUNCTION__) != OK) return String8();
SharedParameters::ReadLock l(mParameters);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 59828fb..9513eeb 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -20,7 +20,6 @@
#include <com_android_internal_camera_flags.h>
#include <cutils/properties.h>
-#include <utils/CameraThreadState.h>
#include <utils/Log.h>
#include <utils/SessionConfigurationUtils.h>
#include <utils/Trace.h>
@@ -2204,7 +2203,7 @@
// TODO: move to Camera2ClientBase
bool CameraDeviceClient::enforceRequestPermissions(CameraMetadata& metadata) {
- const int pid = CameraThreadState::getCallingPid();
+ const int pid = getCallingPid();
const int selfPid = getpid();
camera_metadata_entry_t entry;
@@ -2243,7 +2242,7 @@
String16 permissionString =
toString16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
if (!checkCallingPermission(permissionString)) {
- const int uid = CameraThreadState::getCallingUid();
+ const int uid = getCallingUid();
ALOGE("Permission Denial: "
"can't disable transmit LED pid=%d, uid=%d", pid, uid);
return false;
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index dc9e0c1..93564ac 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -19,7 +19,6 @@
//#define LOG_NDEBUG 0
#include "CameraOfflineSessionClient.h"
-#include "utils/CameraThreadState.h"
#include <utils/Trace.h>
#include <camera/StringUtils.h>
@@ -163,7 +162,7 @@
return res;
}
// Allow both client and the media server to disconnect at all times
- int callingPid = CameraThreadState::getCallingPid();
+ int callingPid = getCallingPid();
if (callingPid != mClientPid &&
callingPid != mServicePid) {
return res;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 3a78937..34964d4 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -37,7 +37,6 @@
#include "device3/Camera3Device.h"
#include "device3/aidl/AidlCamera3Device.h"
#include "device3/hidl/HidlCamera3Device.h"
-#include "utils/CameraThreadState.h"
namespace android {
@@ -83,7 +82,7 @@
status_t Camera2ClientBase<TClientBase>::checkPid(const char* checkLocation)
const {
- int callingPid = CameraThreadState::getCallingPid();
+ int callingPid = TClientBase::getCallingPid();
if (callingPid == TClientBase::mClientPid) return NO_ERROR;
ALOGE("%s: attempt to use a locked camera from a different process"
@@ -116,12 +115,14 @@
case IPCTransport::HIDL:
mDevice =
new HidlCamera3Device(mCameraServiceProxyWrapper,
+ TClientBase::mAttributionAndPermissionUtils,
TClientBase::mCameraIdStr, mOverrideForPerfClass,
TClientBase::mOverrideToPortrait, mLegacyClient);
break;
case IPCTransport::AIDL:
mDevice =
new AidlCamera3Device(mCameraServiceProxyWrapper,
+ TClientBase::mAttributionAndPermissionUtils,
TClientBase::mCameraIdStr, mOverrideForPerfClass,
TClientBase::mOverrideToPortrait, mLegacyClient);
break;
@@ -267,7 +268,7 @@
ALOGD("Camera %s: serializationLock acquired", TClientBase::mCameraIdStr.c_str());
binder::Status res = binder::Status::ok();
// Allow both client and the media server to disconnect at all times
- int callingPid = CameraThreadState::getCallingPid();
+ int callingPid = TClientBase::getCallingPid();
if (callingPid != TClientBase::mClientPid &&
callingPid != TClientBase::mServicePid) return res;
@@ -306,18 +307,18 @@
Mutex::Autolock icl(mBinderSerializationLock);
if (TClientBase::mClientPid != 0 &&
- CameraThreadState::getCallingPid() != TClientBase::mClientPid) {
+ TClientBase::getCallingPid() != TClientBase::mClientPid) {
ALOGE("%s: Camera %s: Connection attempt from pid %d; "
"current locked to pid %d",
__FUNCTION__,
TClientBase::mCameraIdStr.c_str(),
- CameraThreadState::getCallingPid(),
+ TClientBase::getCallingPid(),
TClientBase::mClientPid);
return BAD_VALUE;
}
- TClientBase::mClientPid = CameraThreadState::getCallingPid();
+ TClientBase::mClientPid = TClientBase::getCallingPid();
TClientBase::mRemoteCallback = client;
mSharedCameraCallbacks = client;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 392959e..ecebad4 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -65,7 +65,6 @@
#include "device3/Camera3InputStream.h"
#include "device3/Camera3OutputStream.h"
#include "device3/Camera3SharedOutputStream.h"
-#include "utils/CameraThreadState.h"
#include "utils/CameraTraces.h"
#include "utils/SchedulingPolicyUtils.h"
#include "utils/SessionConfigurationUtils.h"
@@ -85,8 +84,10 @@
namespace android {
Camera3Device::Camera3Device(std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+ std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const std::string &id, bool overrideForPerfClass, bool overrideToPortrait,
bool legacyClient):
+ AttributionAndPermissionUtilsEncapsulator(attributionAndPermissionUtils),
mCameraServiceProxyWrapper(cameraServiceProxyWrapper),
mId(id),
mLegacyClient(legacyClient),
@@ -1433,7 +1434,7 @@
if (templateId <= 0 || templateId >= CAMERA_TEMPLATE_COUNT) {
android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
- CameraThreadState::getCallingUid(), nullptr, 0);
+ getCallingUid(), nullptr, 0);
return BAD_VALUE;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 775eefd..5b37f6c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -47,6 +47,7 @@
#include "device3/Camera3OutputInterface.h"
#include "device3/Camera3OfflineSession.h"
#include "device3/Camera3StreamInterface.h"
+#include "utils/AttributionAndPermissionUtils.h"
#include "utils/TagMonitor.h"
#include "utils/IPCTransport.h"
#include "utils/LatencyHistogram.h"
@@ -79,12 +80,14 @@
public camera3::SetErrorInterface,
public camera3::InflightRequestUpdateInterface,
public camera3::RequestBufferInterface,
- public camera3::FlushBufferInterface {
+ public camera3::FlushBufferInterface,
+ public AttributionAndPermissionUtilsEncapsulator {
friend class HidlCamera3Device;
friend class AidlCamera3Device;
public:
explicit Camera3Device(std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+ std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const std::string& id, bool overrideForPerfClass, bool overrideToPortrait,
bool legacyClient = false);
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index e8ef692..7f30f5e 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -68,7 +68,6 @@
#include "device3/aidl/AidlCamera3OutputUtils.h"
#include "device3/aidl/AidlCamera3OfflineSession.h"
#include "CameraService.h"
-#include "utils/CameraThreadState.h"
#include "utils/SessionConfigurationUtils.h"
#include "utils/TraceHFR.h"
#include "utils/CameraServiceProxyWrapper.h"
@@ -173,10 +172,11 @@
AidlCamera3Device::AidlCamera3Device(
std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+ std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const std::string& id, bool overrideForPerfClass, bool overrideToPortrait,
bool legacyClient) :
- Camera3Device(cameraServiceProxyWrapper, id, overrideForPerfClass, overrideToPortrait,
- legacyClient) {
+ Camera3Device(cameraServiceProxyWrapper, attributionAndPermissionUtils, id,
+ overrideForPerfClass, overrideToPortrait, legacyClient) {
mCallbacks = ndk::SharedRefBase::make<AidlCameraDeviceCallbacks>(this);
}
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index f0a5f7e..ac29bbc 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -41,6 +41,7 @@
friend class AidlCameraDeviceCallbacks;
explicit AidlCamera3Device(
std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+ std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const std::string& id, bool overrideForPerfClass, bool overrideToPortrait,
bool legacyClient = false);
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index 350b072..f11db5d 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -33,10 +33,11 @@
explicit HidlCamera3Device(
std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+ std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const std::string& id, bool overrideForPerfClass, bool overrideToPortrait,
bool legacyClient = false) :
- Camera3Device(cameraServiceProxyWrapper, id, overrideForPerfClass, overrideToPortrait,
- legacyClient) { }
+ Camera3Device(cameraServiceProxyWrapper, attributionAndPermissionUtils, id,
+ overrideForPerfClass, overrideToPortrait, legacyClient) { }
virtual ~HidlCamera3Device() {}
diff --git a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
index e8301c1..93b440b 100644
--- a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
+++ b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
@@ -23,7 +23,10 @@
#include <private/android_filesystem_config.h>
#include "CameraService.h"
-#include "CameraThreadState.h"
+
+#include <binder/IPCThreadState.h>
+#include <hwbinder/IPCThreadState.h>
+#include <binderthreadstate/CallerUtils.h>
namespace android {
@@ -47,6 +50,36 @@
const std::string AttributionAndPermissionUtils::sCameraInjectExternalCameraPermission(
"android.permission.CAMERA_INJECT_EXTERNAL_CAMERA");
+int AttributionAndPermissionUtils::getCallingUid() {
+ if (getCurrentServingCall() == BinderCallType::HWBINDER) {
+ return hardware::IPCThreadState::self()->getCallingUid();
+ }
+ return IPCThreadState::self()->getCallingUid();
+}
+
+int AttributionAndPermissionUtils::getCallingPid() {
+ if (getCurrentServingCall() == BinderCallType::HWBINDER) {
+ return hardware::IPCThreadState::self()->getCallingPid();
+ }
+ return IPCThreadState::self()->getCallingPid();
+}
+
+int64_t AttributionAndPermissionUtils::clearCallingIdentity() {
+ if (getCurrentServingCall() == BinderCallType::HWBINDER) {
+ return hardware::IPCThreadState::self()->clearCallingIdentity();
+ }
+ return IPCThreadState::self()->clearCallingIdentity();
+}
+
+void AttributionAndPermissionUtils::restoreCallingIdentity(int64_t token) {
+ if (getCurrentServingCall() == BinderCallType::HWBINDER) {
+ hardware::IPCThreadState::self()->restoreCallingIdentity(token);
+ } else {
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ }
+ return;
+}
+
bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient(const std::string &cameraId,
const AttributionSourceState &attributionSource) {
if (isAutomotivePrivilegedClient(attributionSource.uid)) {
@@ -150,7 +183,7 @@
}
bool AttributionAndPermissionUtils::isCallerCameraServerNotDelegating() {
- return CameraThreadState::getCallingPid() == getpid();
+ return (getCallingPid() == getpid());
}
bool AttributionAndPermissionUtils::hasPermissionsForCamera(const std::string& cameraId,
diff --git a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
index 830a8e8..db6457f 100644
--- a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
+++ b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
@@ -19,6 +19,7 @@
#include <android/content/AttributionSourceState.h>
#include <android/permission/PermissionChecker.h>
#include <binder/BinderService.h>
+#include <private/android_filesystem_config.h>
namespace android {
@@ -40,6 +41,12 @@
mCameraService = cameraService;
}
+ // Utilities handling Binder calling identities (previously in CameraThreadState)
+ virtual int getCallingUid();
+ virtual int getCallingPid();
+ virtual int64_t clearCallingIdentity();
+ virtual void restoreCallingIdentity(int64_t token);
+
/**
* Pre-grants the permission if the attribution source uid is for an automotive
* privileged client. Otherwise uses system service permission checker to check
@@ -129,6 +136,28 @@
return attributionSource;
}
+ int getCallingUid() const {
+ return mAttributionAndPermissionUtils->getCallingUid();
+ }
+
+ int getCallingPid() const {
+ return mAttributionAndPermissionUtils->getCallingPid();
+ }
+
+ int64_t clearCallingIdentity() const {
+ return mAttributionAndPermissionUtils->clearCallingIdentity();
+ }
+
+ void restoreCallingIdentity(int64_t token) const {
+ mAttributionAndPermissionUtils->restoreCallingIdentity(token);
+ }
+
+ // The word 'System' here does not refer to callers only on the system
+ // partition. They just need to have an android system uid.
+ bool callerHasSystemUid() const {
+ return (getCallingUid() < AID_APP_START);
+ }
+
bool hasPermissionsForCamera(int callingPid, int callingUid) const {
return hasPermissionsForCamera(std::string(), callingPid, callingUid);
}
diff --git a/services/camera/libcameraservice/utils/CameraThreadState.cpp b/services/camera/libcameraservice/utils/CameraThreadState.cpp
deleted file mode 100644
index 2352b80..0000000
--- a/services/camera/libcameraservice/utils/CameraThreadState.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2018 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 "CameraThreadState.h"
-#include <binder/IPCThreadState.h>
-#include <hwbinder/IPCThreadState.h>
-#include <binderthreadstate/CallerUtils.h>
-#include <unistd.h>
-
-namespace android {
-
-int CameraThreadState::getCallingUid() {
- if (getCurrentServingCall() == BinderCallType::HWBINDER) {
- return hardware::IPCThreadState::self()->getCallingUid();
- }
- return IPCThreadState::self()->getCallingUid();
-}
-
-int CameraThreadState::getCallingPid() {
- if (getCurrentServingCall() == BinderCallType::HWBINDER) {
- return hardware::IPCThreadState::self()->getCallingPid();
- }
- return IPCThreadState::self()->getCallingPid();
-}
-
-int64_t CameraThreadState::clearCallingIdentity() {
- if (getCurrentServingCall() == BinderCallType::HWBINDER) {
- return hardware::IPCThreadState::self()->clearCallingIdentity();
- }
- return IPCThreadState::self()->clearCallingIdentity();
-}
-
-void CameraThreadState::restoreCallingIdentity(int64_t token) {
- if (getCurrentServingCall() == BinderCallType::HWBINDER) {
- hardware::IPCThreadState::self()->restoreCallingIdentity(token);
- } else {
- IPCThreadState::self()->restoreCallingIdentity(token);
- }
- return;
-}
-
-} // android
diff --git a/services/camera/libcameraservice/utils/CameraThreadState.h b/services/camera/libcameraservice/utils/CameraThreadState.h
deleted file mode 100644
index e1a70de..0000000
--- a/services/camera/libcameraservice/utils/CameraThreadState.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2018 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 <stdint.h>
-
-namespace android {
-class CameraThreadState {
-public:
- static int64_t clearCallingIdentity();
-
- static void restoreCallingIdentity(int64_t token);
-
- static int getCallingUid();
-
- static int getCallingPid();
-};
-
-} // android
diff --git a/services/camera/libcameraservice/utils/SchedulingPolicyUtils.cpp b/services/camera/libcameraservice/utils/SchedulingPolicyUtils.cpp
index 92a1030..f3afc69 100644
--- a/services/camera/libcameraservice/utils/SchedulingPolicyUtils.cpp
+++ b/services/camera/libcameraservice/utils/SchedulingPolicyUtils.cpp
@@ -20,7 +20,6 @@
#include <pthread.h>
#include <sched.h>
-#include "CameraThreadState.h"
#include <private/android_filesystem_config.h>
#include <processgroup/processgroup.h>
#include <processgroup/sched_policy.h>
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
index f68efe2..25cc270 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
@@ -489,7 +489,7 @@
return;
}
- ALOGD("%s: Successfully called processCaptureResult", __func__);
+ ALOGV("%s: Successfully called processCaptureResult", __func__);
}
void VirtualCameraRenderThread::flushCaptureRequest(
diff --git a/services/camera/virtualcamera/VirtualCameraSession.cc b/services/camera/virtualcamera/VirtualCameraSession.cc
index 05fa5ae..7c17d7c 100644
--- a/services/camera/virtualcamera/VirtualCameraSession.cc
+++ b/services/camera/virtualcamera/VirtualCameraSession.cc
@@ -518,7 +518,7 @@
ndk::ScopedAStatus VirtualCameraSession::processCaptureRequest(
const CaptureRequest& request) {
- ALOGD("%s: request: %s", __func__, request.toString().c_str());
+ ALOGV("%s: request: %s", __func__, request.toString().c_str());
std::shared_ptr<ICameraDeviceCallback> cameraCallback = nullptr;
RequestSettings requestSettings;
diff --git a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc
index f729f73..d530d91 100644
--- a/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc
+++ b/services/camera/virtualcamera/tests/VirtualCameraServiceTest.cc
@@ -14,8 +14,11 @@
* limitations under the License.
*/
+#include <algorithm>
#include <cstdio>
+#include <iterator>
#include <memory>
+#include <regex>
#include "VirtualCameraService.h"
#include "aidl/android/companion/virtualcamera/BnVirtualCameraCallback.h"
@@ -48,6 +51,7 @@
using ::aidl::android::hardware::graphics::common::PixelFormat;
using ::aidl::android::view::Surface;
using ::testing::_;
+using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::Ge;
using ::testing::IsEmpty;
@@ -134,19 +138,22 @@
close(mDevNullFd);
}
- void execute_shell_command(const std::string cmd) {
- std::array<const char*, 1> args{cmd.data()};
- ASSERT_THAT(
- mCameraService->handleShellCommand(mDevNullFd, mDevNullFd, mDevNullFd,
- args.data(), args.size()),
- Eq(NO_ERROR));
- }
+ void execute_shell_command(const std::string& cmd) {
+ const static std::regex whitespaceRegex("\\s+");
+ std::vector<std::string> tokens;
+ std::copy_if(
+ std::sregex_token_iterator(cmd.begin(), cmd.end(), whitespaceRegex, -1),
+ std::sregex_token_iterator(), std::back_inserter(tokens),
+ [](const std::string& token) { return !token.empty(); });
- void execute_shell_command(const std::string cmd, const std::string cameraId) {
- std::array<const char*, 2> args{cmd.data(), cameraId.data()};
+ std::vector<const char*> argv;
+ argv.reserve(tokens.size());
+ std::transform(tokens.begin(), tokens.end(), std::back_inserter(argv),
+ [](const std::string& str) { return str.c_str(); });
+
ASSERT_THAT(
mCameraService->handleShellCommand(mDevNullFd, mDevNullFd, mDevNullFd,
- args.data(), args.size()),
+ argv.data(), argv.size()),
Eq(NO_ERROR));
}
@@ -379,10 +386,10 @@
}
TEST_F(VirtualCameraServiceTest, TestCameraShellCmdWithId) {
- execute_shell_command("enable_test_camera", "12345");
+ execute_shell_command("enable_test_camera 12345");
std::vector<std::string> cameraIdsAfterEnable = getCameraIds();
- EXPECT_THAT(cameraIdsAfterEnable, SizeIs(1));
+ EXPECT_THAT(cameraIdsAfterEnable, ElementsAre("device@1.1/virtual/12345"));
execute_shell_command("disable_test_camera");