Merge "Revert "Add Java library to query state of VirtualCamera build flag."" into main
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index 1f50570..c00e16e 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -133,3 +133,13 @@
description: "Enables 10-bit support in the camera extensions."
bug: "316375635"
}
+
+flag {
+ namespace: "camera_platform"
+ name: "surface_leak_fix"
+ description: "Address Surface release leaks in CaptureRequest"
+ bug: "324071855"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/media/Android.mk b/media/Android.mk
deleted file mode 100644
index 220a358..0000000
--- a/media/Android.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-$(eval $(call declare-1p-copy-files,frameworks/av/media/libeffects,audio_effects.conf))
-$(eval $(call declare-1p-copy-files,frameworks/av/media/libeffects,audio_effects.xml))
-$(eval $(call declare-1p-copy-files,frameworks/av/media/libstagefright,))
diff --git a/media/aconfig/Android.bp b/media/aconfig/Android.bp
index e0d1fa9..16beb28 100644
--- a/media/aconfig/Android.bp
+++ b/media/aconfig/Android.bp
@@ -43,6 +43,7 @@
name: "android.media.codec-aconfig-cc",
min_sdk_version: "30",
vendor_available: true,
+ double_loadable: true,
apex_available: [
"//apex_available:platform",
"com.android.media.swcodec",
diff --git a/media/aconfig/codec_fwk.aconfig b/media/aconfig/codec_fwk.aconfig
index 3092091..a2b6a82 100644
--- a/media/aconfig/codec_fwk.aconfig
+++ b/media/aconfig/codec_fwk.aconfig
@@ -14,6 +14,7 @@
flag {
name: "dynamic_color_aspects"
+ is_exported: true
namespace: "codec_fwk"
description: "Feature flag for dynamic color aspect support"
bug: "297914560"
@@ -21,6 +22,7 @@
flag {
name: "hlg_editing"
+ is_exported: true
namespace: "codec_fwk"
description: "Feature flag for HLG editing support"
bug: "316397061"
@@ -28,6 +30,7 @@
flag {
name: "in_process_sw_audio_codec"
+ is_exported: true
namespace: "codec_fwk"
description: "Feature flag for in-process software audio codec API"
bug: "297922713"
@@ -48,7 +51,15 @@
}
flag {
+ name: "native_capabilites"
+ namespace: "codec_fwk"
+ description: "Feature flag for native codec capabilities"
+ bug: "306023029"
+}
+
+flag {
name: "null_output_surface"
+ is_exported: true
namespace: "codec_fwk"
description: "Feature flag for null output Surface API"
bug: "297920102"
@@ -63,6 +74,7 @@
flag {
name: "region_of_interest"
+ is_exported: true
namespace: "codec_fwk"
description: "Feature flag for region of interest API"
bug: "299191092"
@@ -74,3 +86,10 @@
description: "Feature flag for region of interest support"
bug: "325549730"
}
+
+flag {
+ name: "teamfood"
+ namespace: "codec_fwk"
+ description: "Feature flag to track teamfood population"
+ bug: "328770262"
+}
diff --git a/media/aconfig/mediacodec_flags.aconfig b/media/aconfig/mediacodec_flags.aconfig
index 4d1e5ca..3cc9a1a 100644
--- a/media/aconfig/mediacodec_flags.aconfig
+++ b/media/aconfig/mediacodec_flags.aconfig
@@ -7,22 +7,23 @@
# ******************************************************************
flag {
- name: "large_audio_frame"
+ name: "aidl_hal"
namespace: "codec_fwk"
- description: "Feature flags for large audio frame support"
- bug: "297219557"
+ description: "Feature flags for enabling AIDL HAL handling"
+ bug: "251850069"
}
flag {
name: "codec_importance"
+ is_exported: true
namespace: "codec_fwk"
description: "Feature flags for media codec importance"
bug: "297929011"
}
flag {
- name: "aidl_hal"
+ name: "large_audio_frame"
namespace: "codec_fwk"
- description: "Feature flags for enabling AIDL HAL handling"
- bug: "251850069"
+ description: "Feature flags for large audio frame support"
+ bug: "297219557"
}
diff --git a/media/audio/aconfig/audio.aconfig b/media/audio/aconfig/audio.aconfig
index 4d0df77..1df5727 100644
--- a/media/audio/aconfig/audio.aconfig
+++ b/media/audio/aconfig/audio.aconfig
@@ -13,6 +13,13 @@
}
flag {
+ name: "as_device_connection_failure"
+ namespace: "media_audio"
+ description: "AudioService handles device connection failures."
+ bug: "326597760"
+}
+
+flag {
name: "bluetooth_mac_address_anonymization"
namespace: "media_audio"
description:
@@ -53,6 +60,13 @@
}
flag {
+ name: "spatializer_upmix"
+ namespace: "media_audio"
+ description: "Enable spatializer upmix"
+ bug: "323985367"
+}
+
+flag {
name: "stereo_spatialization"
namespace: "media_audio"
description: "Enable stereo channel mask for spatialization."
diff --git a/media/audio/aconfig/audio_framework.aconfig b/media/audio/aconfig/audio_framework.aconfig
index 525dceb..cfdf1ab 100644
--- a/media/audio/aconfig/audio_framework.aconfig
+++ b/media/audio/aconfig/audio_framework.aconfig
@@ -71,6 +71,13 @@
}
flag {
+ name: "mute_background_audio"
+ namespace: "media_audio"
+ description: "mute audio playing in background"
+ bug: "296232417"
+}
+
+flag {
name: "sco_managed_by_audio"
namespace: "media_audio"
description: "\
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index c7a1bfd..55847f4 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -169,6 +169,11 @@
"%s: AudioSystem already has an AudioFlinger instance!", __func__);
const auto aps = sp<AudioPolicyService>::make();
ALOGD("%s: AudioPolicy created", __func__);
+ ALOGW_IF(AudioSystem::setLocalAudioPolicyService(aps) != OK,
+ "%s: AudioSystem already has an AudioPolicyService instance!", __func__);
+
+ // Start initialization of internally managed audio objects such as Device Effects.
+ aps->onAudioSystemReady();
// Add AudioFlinger and AudioPolicy to ServiceManager.
sp<IServiceManager> sm = defaultServiceManager();
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
index ba5f8d4..87c9d87 100644
--- a/media/codec2/hal/aidl/Component.cpp
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -205,30 +205,7 @@
mDeathContext(nullptr) {
// Retrieve supported parameters from store
// TODO: We could cache this per component/interface type
- if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
- c2_status_t err = C2_OK;
- C2ComponentDomainSetting domain;
- std::vector<std::unique_ptr<C2Param>> heapParams;
- err = component->intf()->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
- if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
- std::vector<std::shared_ptr<C2ParamDescriptor>> params;
- bool isComponentSupportsLargeAudioFrame = false;
- component->intf()->querySupportedParams_nb(¶ms);
- for (const auto ¶mDesc : params) {
- if (paramDesc->name().compare(C2_PARAMKEY_OUTPUT_LARGE_FRAME) == 0) {
- isComponentSupportsLargeAudioFrame = true;
- LOG(VERBOSE) << "Underlying component supports large frame audio";
- break;
- }
- }
- if (!isComponentSupportsLargeAudioFrame) {
- mMultiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
- component->intf(),
- std::static_pointer_cast<C2ReflectorHelper>(
- ::android::GetCodec2PlatformComponentStore()->getParamReflector()));
- }
- }
- }
+ mMultiAccessUnitIntf = store->tryCreateMultiAccessUnitInterface(component->intf());
mInterface = SharedRefBase::make<ComponentInterface>(
component->intf(), mMultiAccessUnitIntf, store->getParameterCache());
mInit = mInterface->status();
@@ -510,7 +487,19 @@
if (__builtin_available(android __ANDROID_API_T__, *)) {
std::shared_ptr<C2Component::Listener> c2listener;
if (mMultiAccessUnitIntf) {
- mMultiAccessUnitHelper = std::make_shared<MultiAccessUnitHelper>(mMultiAccessUnitIntf);
+ std::shared_ptr<C2Allocator> allocator;
+ std::shared_ptr<C2BlockPool> linearPool;
+ std::shared_ptr<C2AllocatorStore> store = ::android::GetCodec2PlatformAllocatorStore();
+ if(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator) == C2_OK) {
+ ::android::C2PlatformAllocatorDesc desc;
+ desc.allocatorId = allocator->getId();
+ if (C2_OK == CreateCodec2BlockPool(desc, mComponent, &linearPool)) {
+ if (linearPool) {
+ mMultiAccessUnitHelper = std::make_shared<MultiAccessUnitHelper>(
+ mMultiAccessUnitIntf, linearPool);
+ }
+ }
+ }
}
c2listener = mMultiAccessUnitHelper ?
std::make_shared<MultiAccessUnitListener>(self, mMultiAccessUnitHelper) :
diff --git a/media/codec2/hal/aidl/ComponentInterface.cpp b/media/codec2/hal/aidl/ComponentInterface.cpp
index 1f0534d..8ae9fa8 100644
--- a/media/codec2/hal/aidl/ComponentInterface.cpp
+++ b/media/codec2/hal/aidl/ComponentInterface.cpp
@@ -131,9 +131,35 @@
virtual c2_status_t querySupportedValues(
std::vector<C2FieldSupportedValuesQuery>& fields,
c2_blocking_t mayBlock) const override {
- c2_status_t err = mIntf->querySupportedValues_vb(fields, mayBlock);
- if (mMultiAccessUnitIntf != nullptr) {
- err = mMultiAccessUnitIntf->querySupportedValues(fields, mayBlock);
+ if (mMultiAccessUnitIntf == nullptr) {
+ return mIntf->querySupportedValues_vb(fields, mayBlock);
+ }
+ std::vector<C2FieldSupportedValuesQuery> dup = fields;
+ std::vector<C2FieldSupportedValuesQuery> queryArray[2];
+ std::map<C2ParamField, std::pair<uint32_t, size_t>> queryMap;
+ c2_status_t err = C2_OK;
+ for (int i = 0 ; i < fields.size(); i++) {
+ const C2ParamField &field = fields[i].field();
+ uint32_t queryArrayIdx = 1;
+ if (mMultiAccessUnitIntf->isValidField(fields[i].field())) {
+ queryArrayIdx = 0;
+ }
+ queryMap[field] = std::make_pair(
+ queryArrayIdx, queryArray[queryArrayIdx].size());
+ queryArray[queryArrayIdx].push_back(fields[i]);
+ }
+ if (queryArray[0].size() > 0) {
+ err = mMultiAccessUnitIntf->querySupportedValues(queryArray[0], mayBlock);
+ }
+ if (queryArray[1].size() > 0) {
+ err = mIntf->querySupportedValues_vb(queryArray[1], mayBlock);
+ }
+ for (int i = 0 ; i < dup.size(); i++) {
+ auto it = queryMap.find(dup[i].field());
+ if (it != queryMap.end()) {
+ std::pair<uint32_t, size_t> queryid = it->second;
+ fields[i] = queryArray[queryid.first][queryid.second];
+ }
}
return err;
}
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
index ef49308..b95c09e 100644
--- a/media/codec2/hal/aidl/ComponentStore.cpp
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -199,6 +199,36 @@
}
#endif
+std::shared_ptr<MultiAccessUnitInterface> ComponentStore::tryCreateMultiAccessUnitInterface(
+ const std::shared_ptr<C2ComponentInterface> &c2interface) {
+ std::shared_ptr<MultiAccessUnitInterface> multiAccessUnitIntf = nullptr;
+ if (c2interface == nullptr) {
+ return nullptr;
+ }
+ if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
+ c2_status_t err = C2_OK;
+ C2ComponentDomainSetting domain;
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ err = c2interface->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
+ if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
+ std::vector<std::shared_ptr<C2ParamDescriptor>> params;
+ bool isComponentSupportsLargeAudioFrame = false;
+ c2interface->querySupportedParams_nb(¶ms);
+ for (const auto ¶mDesc : params) {
+ if (paramDesc->name().compare(C2_PARAMKEY_OUTPUT_LARGE_FRAME) == 0) {
+ isComponentSupportsLargeAudioFrame = true;
+ break;
+ }
+ }
+ if (!isComponentSupportsLargeAudioFrame) {
+ multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
+ c2interface, std::static_pointer_cast<C2ReflectorHelper>(mParamReflector));
+ }
+ }
+ }
+ return multiAccessUnitIntf;
+}
+
// Methods from ::aidl::android::hardware::media::c2::IComponentStore
ScopedAStatus ComponentStore::createComponent(
const std::string& name,
@@ -258,7 +288,10 @@
c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
#endif
onInterfaceLoaded(c2interface);
- *intf = SharedRefBase::make<ComponentInterface>(c2interface, mParameterCache);
+ std::shared_ptr<MultiAccessUnitInterface> multiAccessUnitIntf =
+ tryCreateMultiAccessUnitInterface(c2interface);
+ *intf = SharedRefBase::make<ComponentInterface>(
+ c2interface, multiAccessUnitIntf, mParameterCache);
return ScopedAStatus::ok();
}
return ScopedAStatus::fromServiceSpecificError(res);
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
index 0698b0f..746e1bf 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
@@ -75,6 +75,9 @@
static std::shared_ptr<::android::FilterWrapper> GetFilterWrapper();
+ std::shared_ptr<MultiAccessUnitInterface> tryCreateMultiAccessUnitInterface(
+ const std::shared_ptr<C2ComponentInterface> &c2interface);
+
// Methods from ::aidl::android::hardware::media::c2::IComponentStore.
virtual ::ndk::ScopedAStatus createComponent(
const std::string& name,
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index 9ed9458..b3ae514 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -649,7 +649,7 @@
return C2_CORRUPTED;
}
size_t i = 0;
- size_t numUpdatedStackParams = 0;
+ size_t numQueried = 0;
for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
C2Param* paramPointer = *it;
if (numStackIndices > 0) {
@@ -678,7 +678,7 @@
continue;
}
if (stackParams[i++]->updateFrom(*paramPointer)) {
- ++numUpdatedStackParams;
+ ++numQueried;
} else {
LOG(WARNING) << "query -- param update failed: "
"index = "
@@ -695,14 +695,11 @@
"unexpected extra stack param.";
} else {
heapParams->emplace_back(C2Param::Copy(*paramPointer));
+ ++numQueried;
}
}
++it;
}
- size_t numQueried = numUpdatedStackParams;
- if (heapParams) {
- numQueried += heapParams->size();
- }
if (status == C2_OK && indices.size() != numQueried) {
status = C2_BAD_INDEX;
}
diff --git a/media/codec2/hal/common/MultiAccessUnitHelper.cpp b/media/codec2/hal/common/MultiAccessUnitHelper.cpp
index 9221a24..8086ef2 100644
--- a/media/codec2/hal/common/MultiAccessUnitHelper.cpp
+++ b/media/codec2/hal/common/MultiAccessUnitHelper.cpp
@@ -73,12 +73,17 @@
for (std::shared_ptr<C2ParamDescriptor> &desc : supportedParams) {
mSupportedParamIndexSet.insert(desc->index());
}
+ mParamFields.emplace_back(mLargeFrameParams.get(), &(mLargeFrameParams.get()->maxSize));
+ mParamFields.emplace_back(mLargeFrameParams.get(), &(mLargeFrameParams.get()->thresholdSize));
if (mC2ComponentIntf) {
c2_status_t err = mC2ComponentIntf->query_vb({&mKind}, {}, C2_MAY_BLOCK, nullptr);
}
}
+bool MultiAccessUnitInterface::isValidField(const C2ParamField &field) const {
+ return (std::find(mParamFields.begin(), mParamFields.end(), field) != mParamFields.end());
+}
bool MultiAccessUnitInterface::isParamSupported(C2Param::Index index) {
return (mSupportedParamIndexSet.count(index) != 0);
}
@@ -91,18 +96,23 @@
return (C2Component::kind_t)(mKind.value);
}
-void MultiAccessUnitInterface::getDecoderSampleRateAndChannelCount(
- uint32_t &sampleRate_, uint32_t &channelCount_) const {
+bool MultiAccessUnitInterface::getDecoderSampleRateAndChannelCount(
+ uint32_t * const sampleRate_, uint32_t * const channelCount_) const {
+ if (sampleRate_ == nullptr || channelCount_ == nullptr) {
+ return false;
+ }
if (mC2ComponentIntf) {
C2StreamSampleRateInfo::output sampleRate;
C2StreamChannelCountInfo::output channelCount;
c2_status_t res = mC2ComponentIntf->query_vb(
{&sampleRate, &channelCount}, {}, C2_MAY_BLOCK, nullptr);
- if (res == C2_OK) {
- sampleRate_ = sampleRate.value;
- channelCount_ = channelCount.value;
+ if (res == C2_OK && sampleRate.value > 0 && channelCount.value > 0) {
+ *sampleRate_ = sampleRate.value;
+ *channelCount_ = channelCount.value;
+ return true;
}
}
+ return false;
}
//C2MultiAccessUnitBuffer
@@ -116,12 +126,12 @@
//MultiAccessUnitHelper
MultiAccessUnitHelper::MultiAccessUnitHelper(
- const std::shared_ptr<MultiAccessUnitInterface>& intf):
+ const std::shared_ptr<MultiAccessUnitInterface>& intf,
+ std::shared_ptr<C2BlockPool>& linearPool):
mInit(false),
- mInterface(intf) {
- std::shared_ptr<C2AllocatorStore> store = GetCodec2PlatformAllocatorStore();
- if(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator) == C2_OK) {
- mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, ++mBlockPoolId);
+ mInterface(intf),
+ mLinearPool(linearPool) {
+ if (mLinearPool) {
mInit = true;
}
}
@@ -159,6 +169,7 @@
std::list<std::unique_ptr<C2Work>> * const worklist) {
if (worklist == nullptr) {
LOG(ERROR) << "Provided null worklist for error()";
+ mFrameHolder.clear();
return C2_OK;
}
std::unique_lock<std::mutex> l(mLock);
@@ -267,6 +278,7 @@
LOG(ERROR) << "ERROR: Work has Large frame info but has no linear blocks.";
return C2_CORRUPTED;
}
+ frameInfo.mInputC2Ref = inBuffers;
const std::vector<C2ConstLinearBlock>& multiAU =
inBuffers.front()->data().linearBlocks();
std::shared_ptr<const C2AccessUnitInfos::input> auInfo =
@@ -315,26 +327,10 @@
}
}
if (!processedWork->empty()) {
- {
- C2LargeFrame::output multiAccessParams = mInterface->getLargeFrameParam();
- if (mInterface->kind() == C2Component::KIND_DECODER) {
- uint32_t sampleRate = 0;
- uint32_t channelCount = 0;
- uint32_t frameSize = 0;
- mInterface->getDecoderSampleRateAndChannelCount(
- sampleRate, channelCount);
- if (sampleRate > 0 && channelCount > 0) {
- frameSize = channelCount * 2;
- multiAccessParams.maxSize =
- (multiAccessParams.maxSize / frameSize) * frameSize;
- multiAccessParams.thresholdSize =
- (multiAccessParams.thresholdSize / frameSize) * frameSize;
- }
- }
- frameInfo.mLargeFrameTuning = multiAccessParams;
- std::lock_guard<std::mutex> l(mLock);
- mFrameHolder.push_back(std::move(frameInfo));
- }
+ C2LargeFrame::output multiAccessParams = mInterface->getLargeFrameParam();
+ frameInfo.mLargeFrameTuning = multiAccessParams;
+ std::lock_guard<std::mutex> l(mLock);
+ mFrameHolder.push_back(std::move(frameInfo));
}
}
return C2_OK;
@@ -501,6 +497,20 @@
frame.reset();
return C2_OK;
}
+ int64_t sampleTimeUs = 0;
+ uint32_t frameSize = 0;
+ uint32_t sampleRate = 0;
+ uint32_t channelCount = 0;
+ if (mInterface->getDecoderSampleRateAndChannelCount(&sampleRate, &channelCount)) {
+ sampleTimeUs = (1000000u) / (sampleRate * channelCount * 2);
+ frameSize = channelCount * 2;
+ if (mInterface->kind() == C2Component::KIND_DECODER) {
+ frame.mLargeFrameTuning.maxSize =
+ (frame.mLargeFrameTuning.maxSize / frameSize) * frameSize;
+ frame.mLargeFrameTuning.thresholdSize =
+ (frame.mLargeFrameTuning.thresholdSize / frameSize) * frameSize;
+ }
+ }
c2_status_t c2ret = allocateWork(frame, true);
if (c2ret != C2_OK) {
return c2ret;
@@ -515,15 +525,7 @@
outputFramedata.infoBuffers.insert(outputFramedata.infoBuffers.begin(),
(*worklet)->output.infoBuffers.begin(),
(*worklet)->output.infoBuffers.end());
- int64_t sampleTimeUs = 0;
- uint32_t frameSize = 0;
- uint32_t sampleRate = 0;
- uint32_t channelCount = 0;
- mInterface->getDecoderSampleRateAndChannelCount(sampleRate, channelCount);
- if (sampleRate > 0 && channelCount > 0) {
- sampleTimeUs = (1000000u) / (sampleRate * channelCount * 2);
- frameSize = channelCount * 2;
- }
+
LOG(DEBUG) << "maxOutSize " << frame.mLargeFrameTuning.maxSize
<< " threshold " << frame.mLargeFrameTuning.thresholdSize;
if ((*worklet)->output.buffers.size() > 0) {
diff --git a/media/codec2/hal/common/include/codec2/common/MultiAccessUnitHelper.h b/media/codec2/hal/common/include/codec2/common/MultiAccessUnitHelper.h
index ef5cff9..bb4464c 100644
--- a/media/codec2/hal/common/include/codec2/common/MultiAccessUnitHelper.h
+++ b/media/codec2/hal/common/include/codec2/common/MultiAccessUnitHelper.h
@@ -41,14 +41,16 @@
bool isParamSupported(C2Param::Index index);
C2LargeFrame::output getLargeFrameParam() const;
C2Component::kind_t kind() const;
+ bool isValidField(const C2ParamField &field) const;
protected:
- void getDecoderSampleRateAndChannelCount(
- uint32_t &sampleRate_, uint32_t &channelCount_) const;
+ bool getDecoderSampleRateAndChannelCount(
+ uint32_t * const sampleRate_, uint32_t * const channelCount_) const;
const std::shared_ptr<C2ComponentInterface> mC2ComponentIntf;
std::shared_ptr<C2LargeFrame::output> mLargeFrameParams;
C2ComponentKindSetting mKind;
std::set<C2Param::Index> mSupportedParamIndexSet;
+ std::vector<C2ParamField> mParamFields;
friend struct MultiAccessUnitHelper;
};
@@ -56,7 +58,8 @@
struct MultiAccessUnitHelper {
public:
MultiAccessUnitHelper(
- const std::shared_ptr<MultiAccessUnitInterface>& intf);
+ const std::shared_ptr<MultiAccessUnitInterface>& intf,
+ std::shared_ptr<C2BlockPool> &linearPool);
virtual ~MultiAccessUnitHelper();
@@ -151,6 +154,11 @@
*/
std::unique_ptr<C2Work> mLargeWork;
+ /*
+ * For holding a reference to the incoming buffer
+ */
+ std::vector<std::shared_ptr<C2Buffer>> mInputC2Ref;
+
MultiAccessUnitInfo(C2WorkOrdinalStruct ordinal):inOrdinal(ordinal) {
}
@@ -195,8 +203,6 @@
C2BlockPool::local_id_t mBlockPoolId;
// C2Blockpool for output buffer allocation
std::shared_ptr<C2BlockPool> mLinearPool;
- // Allocator for output buffer allocation
- std::shared_ptr<C2Allocator> mLinearAllocator;
// FrameIndex for the current outgoing work
std::atomic_uint64_t mFrameIndex;
// Mutex to protect mFrameHolder
diff --git a/media/codec2/hal/hidl/1.0/utils/Component.cpp b/media/codec2/hal/hidl/1.0/utils/Component.cpp
index ebbaafc..0259d90 100644
--- a/media/codec2/hal/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/Component.cpp
@@ -259,30 +259,7 @@
mBufferPoolSender{clientPoolManager} {
// Retrieve supported parameters from store
// TODO: We could cache this per component/interface type
- if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
- c2_status_t err = C2_OK;
- C2ComponentDomainSetting domain;
- std::vector<std::unique_ptr<C2Param>> heapParams;
- err = component->intf()->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
- if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
- std::vector<std::shared_ptr<C2ParamDescriptor>> params;
- bool isComponentSupportsLargeAudioFrame = false;
- component->intf()->querySupportedParams_nb(¶ms);
- for (const auto ¶mDesc : params) {
- if (paramDesc->name().compare(C2_PARAMKEY_OUTPUT_LARGE_FRAME) == 0) {
- isComponentSupportsLargeAudioFrame = true;
- LOG(VERBOSE) << "Underlying component supports large frame audio";
- break;
- }
- }
- if (!isComponentSupportsLargeAudioFrame) {
- mMultiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
- component->intf(),
- std::static_pointer_cast<C2ReflectorHelper>(
- GetCodec2PlatformComponentStore()->getParamReflector()));
- }
- }
- }
+ mMultiAccessUnitIntf = store->tryCreateMultiAccessUnitInterface(component->intf());
mInterface = new ComponentInterface(
component->intf(), mMultiAccessUnitIntf, store->getParameterCache());
mInit = mInterface->status();
@@ -593,7 +570,19 @@
void Component::initListener(const sp<Component>& self) {
std::shared_ptr<C2Component::Listener> c2listener;
if (mMultiAccessUnitIntf) {
- mMultiAccessUnitHelper = std::make_shared<MultiAccessUnitHelper>(mMultiAccessUnitIntf);
+ std::shared_ptr<C2Allocator> allocator;
+ std::shared_ptr<C2BlockPool> linearPool;
+ std::shared_ptr<C2AllocatorStore> store = ::android::GetCodec2PlatformAllocatorStore();
+ if(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator) == C2_OK) {
+ ::android::C2PlatformAllocatorDesc desc;
+ desc.allocatorId = allocator->getId();
+ if (C2_OK == CreateCodec2BlockPool(desc, mComponent, &linearPool)) {
+ if (linearPool) {
+ mMultiAccessUnitHelper = std::make_shared<MultiAccessUnitHelper>(
+ mMultiAccessUnitIntf, linearPool);
+ }
+ }
+ }
}
c2listener = mMultiAccessUnitHelper ?
std::make_shared<MultiAccessUnitListener>(self, mMultiAccessUnitHelper) :
diff --git a/media/codec2/hal/hidl/1.0/utils/ComponentInterface.cpp b/media/codec2/hal/hidl/1.0/utils/ComponentInterface.cpp
index 5a5e780..41a8904 100644
--- a/media/codec2/hal/hidl/1.0/utils/ComponentInterface.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/ComponentInterface.cpp
@@ -130,9 +130,35 @@
virtual c2_status_t querySupportedValues(
std::vector<C2FieldSupportedValuesQuery>& fields,
c2_blocking_t mayBlock) const override {
- c2_status_t err = mIntf->querySupportedValues_vb(fields, mayBlock);
- if (mMultiAccessUnitIntf != nullptr) {
- err = mMultiAccessUnitIntf->querySupportedValues(fields, mayBlock);
+ if (mMultiAccessUnitIntf == nullptr) {
+ return mIntf->querySupportedValues_vb(fields, mayBlock);
+ }
+ std::vector<C2FieldSupportedValuesQuery> dup = fields;
+ std::vector<C2FieldSupportedValuesQuery> queryArray[2];
+ std::map<C2ParamField, std::pair<uint32_t, size_t>> queryMap;
+ c2_status_t err = C2_OK;
+ for (int i = 0 ; i < fields.size(); i++) {
+ const C2ParamField &field = fields[i].field();
+ uint32_t queryArrayIdx = 1;
+ if (mMultiAccessUnitIntf->isValidField(field)) {
+ queryArrayIdx = 0;
+ }
+ queryMap[field] = std::make_pair(
+ queryArrayIdx, queryArray[queryArrayIdx].size());
+ queryArray[queryArrayIdx].push_back(fields[i]);
+ }
+ if (queryArray[0].size() > 0) {
+ err = mMultiAccessUnitIntf->querySupportedValues(queryArray[0], mayBlock);
+ }
+ if (queryArray[1].size() > 0) {
+ err = mIntf->querySupportedValues_vb(queryArray[1], mayBlock);
+ }
+ for (int i = 0 ; i < dup.size(); i++) {
+ auto it = queryMap.find(dup[i].field());
+ if (it != queryMap.end()) {
+ std::pair<uint32_t, size_t> queryid = it->second;
+ fields[i] = queryArray[queryid.first][queryid.second];
+ }
}
return err;
}
diff --git a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp
index 1c0d5b0..988ab6f 100644
--- a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp
@@ -194,6 +194,36 @@
}
#endif
+std::shared_ptr<MultiAccessUnitInterface> ComponentStore::tryCreateMultiAccessUnitInterface(
+ const std::shared_ptr<C2ComponentInterface> &c2interface) {
+ std::shared_ptr<MultiAccessUnitInterface> multiAccessUnitIntf = nullptr;
+ if (c2interface == nullptr) {
+ return nullptr;
+ }
+ if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
+ c2_status_t err = C2_OK;
+ C2ComponentDomainSetting domain;
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ err = c2interface->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
+ if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
+ std::vector<std::shared_ptr<C2ParamDescriptor>> params;
+ bool isComponentSupportsLargeAudioFrame = false;
+ c2interface->querySupportedParams_nb(¶ms);
+ for (const auto ¶mDesc : params) {
+ if (paramDesc->name().compare(C2_PARAMKEY_OUTPUT_LARGE_FRAME) == 0) {
+ isComponentSupportsLargeAudioFrame = true;
+ break;
+ }
+ }
+ if (!isComponentSupportsLargeAudioFrame) {
+ multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
+ c2interface, std::static_pointer_cast<C2ReflectorHelper>(mParamReflector));
+ }
+ }
+ }
+ return multiAccessUnitIntf;
+}
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
Return<void> ComponentStore::createComponent(
const hidl_string& name,
@@ -242,7 +272,9 @@
c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
#endif
onInterfaceLoaded(c2interface);
- interface = new ComponentInterface(c2interface, mParameterCache);
+ std::shared_ptr<MultiAccessUnitInterface> multiAccessUnitIntf =
+ tryCreateMultiAccessUnitInterface(c2interface);
+ interface = new ComponentInterface(c2interface, multiAccessUnitIntf, mParameterCache);
}
_hidl_cb(static_cast<Status>(res), interface);
return Void();
diff --git a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
index 27e2a05..b5d85da 100644
--- a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
+++ b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
@@ -78,6 +78,9 @@
static std::shared_ptr<FilterWrapper> GetFilterWrapper();
+ std::shared_ptr<MultiAccessUnitInterface> tryCreateMultiAccessUnitInterface(
+ const std::shared_ptr<C2ComponentInterface> &c2interface);
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
virtual Return<void> createComponent(
const hidl_string& name,
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
index 275a721..ab47b7c 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/component/VtsHalMediaC2V1_0TargetComponentTest.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "codec2_hidl_hal_component_test"
#include <android-base/logging.h>
+#include <android/binder_process.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
@@ -382,5 +383,6 @@
}
::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
}
diff --git a/media/codec2/hal/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
index a34cef1..d1f0fb5 100644
--- a/media/codec2/hal/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
+++ b/media/codec2/hal/hidl/1.0/vts/functional/master/VtsHalMediaC2V1_0TargetMasterTest.cpp
@@ -84,14 +84,11 @@
}
TEST_P(Codec2MasterHalTest, MustUseAidlBeyond202404) {
- static int sBoardFirstApiLevel = android::base::GetIntProperty("ro.board.first_api_level", 0);
- static int sBoardApiLevel = android::base::GetIntProperty("ro.board.api_level", 0);
- if (sBoardFirstApiLevel < 202404 && sBoardApiLevel < 202404) {
- GTEST_SKIP() << "board first level less than 202404:"
- << " ro.board.first_api_level = " << sBoardFirstApiLevel
- << " ro.board.api_level = " << sBoardApiLevel;
+ static int sVendorApiLevel = android::base::GetIntProperty("ro.vendor.api_level", 0);
+ if (sVendorApiLevel < 202404) {
+ GTEST_SKIP() << "vendor api level less than 202404: " << sVendorApiLevel;
}
- ALOGV("HidlCodecAllowed Test");
+ ALOGV("MustUseAidlBeyond202404 Test");
EXPECT_NE(mClient->getAidlBase(), nullptr) << "android.hardware.media.c2 MUST use AIDL "
<< "for chipsets launching at 202404 or above";
diff --git a/media/codec2/hal/hidl/1.1/utils/Component.cpp b/media/codec2/hal/hidl/1.1/utils/Component.cpp
index 5073983..d34d84e 100644
--- a/media/codec2/hal/hidl/1.1/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.1/utils/Component.cpp
@@ -263,30 +263,7 @@
mBufferPoolSender{clientPoolManager} {
// Retrieve supported parameters from store
// TODO: We could cache this per component/interface type
- if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
- c2_status_t err = C2_OK;
- C2ComponentDomainSetting domain;
- std::vector<std::unique_ptr<C2Param>> heapParams;
- err = component->intf()->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
- if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
- std::vector<std::shared_ptr<C2ParamDescriptor>> params;
- bool isComponentSupportsLargeAudioFrame = false;
- component->intf()->querySupportedParams_nb(¶ms);
- for (const auto ¶mDesc : params) {
- if (paramDesc->name().compare(C2_PARAMKEY_OUTPUT_LARGE_FRAME) == 0) {
- isComponentSupportsLargeAudioFrame = true;
- LOG(VERBOSE) << "Underlying component supports large frame audio";
- break;
- }
- }
- if (!isComponentSupportsLargeAudioFrame) {
- mMultiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
- component->intf(),
- std::static_pointer_cast<C2ReflectorHelper>(
- GetCodec2PlatformComponentStore()->getParamReflector()));
- }
- }
- }
+ mMultiAccessUnitIntf = store->tryCreateMultiAccessUnitInterface(component->intf());
mInterface = new ComponentInterface(
component->intf(), mMultiAccessUnitIntf, store->getParameterCache());
mInit = mInterface->status();
@@ -606,7 +583,19 @@
void Component::initListener(const sp<Component>& self) {
std::shared_ptr<C2Component::Listener> c2listener;
if (mMultiAccessUnitIntf) {
- mMultiAccessUnitHelper = std::make_shared<MultiAccessUnitHelper>(mMultiAccessUnitIntf);
+ std::shared_ptr<C2Allocator> allocator;
+ std::shared_ptr<C2BlockPool> linearPool;
+ std::shared_ptr<C2AllocatorStore> store = ::android::GetCodec2PlatformAllocatorStore();
+ if(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator) == C2_OK) {
+ ::android::C2PlatformAllocatorDesc desc;
+ desc.allocatorId = allocator->getId();
+ if (C2_OK == CreateCodec2BlockPool(desc, mComponent, &linearPool)) {
+ if (linearPool) {
+ mMultiAccessUnitHelper = std::make_shared<MultiAccessUnitHelper>(
+ mMultiAccessUnitIntf, linearPool);
+ }
+ }
+ }
}
c2listener = mMultiAccessUnitHelper ?
std::make_shared<MultiAccessUnitListener>(self, mMultiAccessUnitHelper) :
diff --git a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp
index d47abdd..46af809 100644
--- a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp
+++ b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp
@@ -194,6 +194,37 @@
}
#endif
+std::shared_ptr<MultiAccessUnitInterface> ComponentStore::tryCreateMultiAccessUnitInterface(
+ const std::shared_ptr<C2ComponentInterface> &c2interface) {
+ std::shared_ptr<MultiAccessUnitInterface> multiAccessUnitIntf = nullptr;
+ if (c2interface == nullptr) {
+ return nullptr;
+ }
+ if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
+ c2_status_t err = C2_OK;
+ C2ComponentDomainSetting domain;
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ err = c2interface->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
+ if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
+ std::vector<std::shared_ptr<C2ParamDescriptor>> params;
+ bool isComponentSupportsLargeAudioFrame = false;
+ c2interface->querySupportedParams_nb(¶ms);
+ for (const auto ¶mDesc : params) {
+ if (paramDesc->name().compare(C2_PARAMKEY_OUTPUT_LARGE_FRAME) == 0) {
+ isComponentSupportsLargeAudioFrame = true;
+ break;
+ }
+ }
+
+ if (!isComponentSupportsLargeAudioFrame) {
+ multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
+ c2interface, std::static_pointer_cast<C2ReflectorHelper>(mParamReflector));
+ }
+ }
+ }
+ return multiAccessUnitIntf;
+}
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
Return<void> ComponentStore::createComponent(
const hidl_string& name,
@@ -241,7 +272,10 @@
c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
#endif
onInterfaceLoaded(c2interface);
- interface = new ComponentInterface(c2interface, mParameterCache);
+ std::shared_ptr<MultiAccessUnitInterface> multiAccessUnitIntf =
+ tryCreateMultiAccessUnitInterface(c2interface);
+ interface = new ComponentInterface(
+ c2interface, multiAccessUnitIntf, mParameterCache);
}
_hidl_cb(static_cast<Status>(res), interface);
return Void();
diff --git a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
index f6daee7..85862a9 100644
--- a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
+++ b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
@@ -79,6 +79,9 @@
static std::shared_ptr<FilterWrapper> GetFilterWrapper();
+ std::shared_ptr<MultiAccessUnitInterface> tryCreateMultiAccessUnitInterface(
+ const std::shared_ptr<C2ComponentInterface> &c2interface);
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
virtual Return<void> createComponent(
const hidl_string& name,
diff --git a/media/codec2/hal/hidl/1.2/utils/Component.cpp b/media/codec2/hal/hidl/1.2/utils/Component.cpp
index bbdbef5..f78e827 100644
--- a/media/codec2/hal/hidl/1.2/utils/Component.cpp
+++ b/media/codec2/hal/hidl/1.2/utils/Component.cpp
@@ -261,30 +261,7 @@
mBufferPoolSender{clientPoolManager} {
// Retrieve supported parameters from store
// TODO: We could cache this per component/interface type
- if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
- c2_status_t err = C2_OK;
- C2ComponentDomainSetting domain;
- std::vector<std::unique_ptr<C2Param>> heapParams;
- err = component->intf()->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
- if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
- std::vector<std::shared_ptr<C2ParamDescriptor>> params;
- bool isComponentSupportsLargeAudioFrame = false;
- component->intf()->querySupportedParams_nb(¶ms);
- for (const auto ¶mDesc : params) {
- if (paramDesc->name().compare(C2_PARAMKEY_OUTPUT_LARGE_FRAME) == 0) {
- isComponentSupportsLargeAudioFrame = true;
- LOG(VERBOSE) << "Underlying component supports large frame audio";
- break;
- }
- }
- if (!isComponentSupportsLargeAudioFrame) {
- mMultiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
- component->intf(),
- std::static_pointer_cast<C2ReflectorHelper>(
- GetCodec2PlatformComponentStore()->getParamReflector()));
- }
- }
- }
+ mMultiAccessUnitIntf = store->tryCreateMultiAccessUnitInterface(component->intf());
mInterface = new ComponentInterface(
component->intf(), mMultiAccessUnitIntf, store->getParameterCache());
mInit = mInterface->status();
@@ -633,7 +610,19 @@
void Component::initListener(const sp<Component>& self) {
std::shared_ptr<C2Component::Listener> c2listener;
if (mMultiAccessUnitIntf) {
- mMultiAccessUnitHelper = std::make_shared<MultiAccessUnitHelper>(mMultiAccessUnitIntf);
+ std::shared_ptr<C2Allocator> allocator;
+ std::shared_ptr<C2BlockPool> linearPool;
+ std::shared_ptr<C2AllocatorStore> store = ::android::GetCodec2PlatformAllocatorStore();
+ if(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator) == C2_OK) {
+ ::android::C2PlatformAllocatorDesc desc;
+ desc.allocatorId = allocator->getId();
+ if (C2_OK == CreateCodec2BlockPool(desc, mComponent, &linearPool)) {
+ if (linearPool) {
+ mMultiAccessUnitHelper = std::make_shared<MultiAccessUnitHelper>(
+ mMultiAccessUnitIntf, linearPool);
+ }
+ }
+ }
}
c2listener = mMultiAccessUnitHelper ?
std::make_shared<MultiAccessUnitListener>(self, mMultiAccessUnitHelper) :
diff --git a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp
index 9fac5d5..f89c835 100644
--- a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp
+++ b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp
@@ -194,6 +194,36 @@
}
#endif
+std::shared_ptr<MultiAccessUnitInterface> ComponentStore::tryCreateMultiAccessUnitInterface(
+ const std::shared_ptr<C2ComponentInterface> &c2interface) {
+ std::shared_ptr<MultiAccessUnitInterface> multiAccessUnitIntf = nullptr;
+ if (c2interface == nullptr) {
+ return nullptr;
+ }
+ if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
+ c2_status_t err = C2_OK;
+ C2ComponentDomainSetting domain;
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ err = c2interface->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
+ if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
+ std::vector<std::shared_ptr<C2ParamDescriptor>> params;
+ bool isComponentSupportsLargeAudioFrame = false;
+ c2interface->querySupportedParams_nb(¶ms);
+ for (const auto ¶mDesc : params) {
+ if (paramDesc->name().compare(C2_PARAMKEY_OUTPUT_LARGE_FRAME) == 0) {
+ isComponentSupportsLargeAudioFrame = true;
+ break;
+ }
+ }
+ if (!isComponentSupportsLargeAudioFrame) {
+ multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
+ c2interface, std::static_pointer_cast<C2ReflectorHelper>(mParamReflector));
+ }
+ }
+ }
+ return multiAccessUnitIntf;
+}
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
Return<void> ComponentStore::createComponent(
const hidl_string& name,
@@ -241,7 +271,9 @@
c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
#endif
onInterfaceLoaded(c2interface);
- interface = new ComponentInterface(c2interface, mParameterCache);
+ std::shared_ptr<MultiAccessUnitInterface> multiAccessUnitIntf =
+ tryCreateMultiAccessUnitInterface(c2interface);
+ interface = new ComponentInterface(c2interface, multiAccessUnitIntf, mParameterCache);
}
_hidl_cb(static_cast<Status>(res), interface);
return Void();
diff --git a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h
index e95a651..c08fce4 100644
--- a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h
+++ b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h
@@ -79,6 +79,9 @@
static std::shared_ptr<FilterWrapper> GetFilterWrapper();
+ std::shared_ptr<MultiAccessUnitInterface> tryCreateMultiAccessUnitInterface(
+ const std::shared_ptr<C2ComponentInterface> &c2interface);
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
virtual Return<void> createComponent(
const hidl_string& name,
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index d867eb1..4de2347 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -45,6 +45,8 @@
static_libs: [
"libSurfaceFlingerProperties",
+ "aconfig_mediacodec_flags_c_lib",
+ "android.media.codec-aconfig-cc",
],
shared_libs: [
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 40656ff..f58dc65 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -552,8 +552,7 @@
}
ssize_t result = -1;
- ssize_t codecDataOffset = 0;
- size_t inBufferOffset = 0;
+ size_t srcOffset = offset;
size_t outBufferSize = 0;
uint32_t cryptoInfoIdx = 0;
int32_t heapSeqNum = getHeapSeqNum(memory);
@@ -565,18 +564,20 @@
for (int i = 0; i < bufferInfos->value.size(); i++) {
if (bufferInfos->value[i].mSize > 0) {
std::unique_ptr<CodecCryptoInfo> info = std::move(cryptoInfos->value[cryptoInfoIdx++]);
+ src.offset = srcOffset;
+ src.size = bufferInfos->value[i].mSize;
result = mCrypto->decrypt(
(uint8_t*)info->mKey,
(uint8_t*)info->mIv,
info->mMode,
info->mPattern,
src,
- inBufferOffset,
+ 0,
info->mSubSamples,
info->mNumSubSamples,
dst,
errorDetailMsg);
- inBufferOffset += bufferInfos->value[i].mSize;
+ srcOffset += bufferInfos->value[i].mSize;
if (result < 0) {
ALOGI("[%s] attachEncryptedBuffers: decrypt failed: result = %zd",
mName, result);
@@ -599,7 +600,7 @@
wView.setOffset(0);
}
std::shared_ptr<C2Buffer> c2Buffer{C2Buffer::CreateLinearBuffer(
- block->share(codecDataOffset, outBufferSize - codecDataOffset, C2Fence{}))};
+ block->share(0, outBufferSize, C2Fence{}))};
if (!buffer->copy(c2Buffer)) {
ALOGI("[%s] attachEncryptedBuffers: buffer copy failed", mName);
return -ENOSYS;
@@ -980,8 +981,7 @@
}
// size of cryptoInfo and accessUnitInfo should be the same?
ssize_t result = -1;
- ssize_t codecDataOffset = 0;
- size_t inBufferOffset = 0;
+ size_t srcOffset = 0;
size_t outBufferSize = 0;
uint32_t cryptoInfoIdx = 0;
{
@@ -994,6 +994,7 @@
encryptedBuffer->getMappedBlock(&mappedBlock);
hardware::drm::V1_0::SharedBuffer source;
encryptedBuffer->fillSourceBuffer(&source);
+ srcOffset = source.offset;
for (int i = 0 ; i < bufferInfos->value.size(); i++) {
if (bufferInfos->value[i].mSize > 0) {
std::unique_ptr<CodecCryptoInfo> info =
@@ -1004,18 +1005,20 @@
// no data so we only populate the bufferInfo
result = 0;
} else {
+ source.offset = srcOffset;
+ source.size = bufferInfos->value[i].mSize;
result = mCrypto->decrypt(
(uint8_t*)info->mKey,
(uint8_t*)info->mIv,
info->mMode,
info->mPattern,
source,
- inBufferOffset,
+ buffer->offset(),
info->mSubSamples,
info->mNumSubSamples,
destination,
errorDetailMsg);
- inBufferOffset += bufferInfos->value[i].mSize;
+ srcOffset += bufferInfos->value[i].mSize;
if (result < 0) {
ALOGI("[%s] decrypt failed: result=%zd", mName, result);
return result;
@@ -1028,7 +1031,7 @@
}
}
}
- buffer->setRange(codecDataOffset, outBufferSize - codecDataOffset);
+ buffer->setRange(0, outBufferSize);
}
return queueInputBufferInternal(buffer, block, bufferSize);
}
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index 453a0d2..37a7a4f 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -20,6 +20,9 @@
#include <strings.h>
+#include <com_android_media_codec_flags.h>
+#include <android_media_codec.h>
+
#include <C2Component.h>
#include <C2Config.h>
#include <C2Debug.h>
@@ -752,6 +755,25 @@
}
addSupportedColorFormats(
intf, caps.get(), trait, mediaType, it->second);
+
+ if (com::android::media::codec::flags::provider_->large_audio_frame()
+ && android::media::codec::provider_->large_audio_frame_finish()) {
+ // Adding feature-multiple-frames when C2LargeFrame param is present
+ if (trait.domain == C2Component::DOMAIN_AUDIO) {
+ std::vector<std::shared_ptr<C2ParamDescriptor>> params;
+ c2_status_t err = intf->querySupportedParams(¶ms);
+ if (err == C2_OK) {
+ for (const auto ¶mDesc : params) {
+ if (C2LargeFrame::output::PARAM_TYPE == paramDesc->index()) {
+ std::string featureMultipleFrames =
+ std::string(KEY_FEATURE_) + FEATURE_MultipleFrames;
+ caps->addDetail(featureMultipleFrames.c_str(), 0);
+ break;
+ }
+ }
+ }
+ }
+ }
}
}
}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index d723493..90910a1 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -68,7 +68,6 @@
"libaudioclient_aidl_conversion",
"libaudioutils",
"libbinder",
- "libbinder_ndk",
"libcutils",
"liblog",
"libutils",
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 4bc5c8a..d1b1849 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -66,113 +66,183 @@
using media::audio::common::Int;
std::mutex AudioSystem::gMutex;
-sp<IAudioFlinger> AudioSystem::gAudioFlinger;
-sp<IBinder> AudioSystem::gAudioFlingerBinder;
-sp<IAudioFlinger> AudioSystem::gLocalAudioFlinger;
-sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL;
record_config_callback AudioSystem::gRecordConfigCallback = NULL;
routing_callback AudioSystem::gRoutingCallback = NULL;
vol_range_init_req_callback AudioSystem::gVolRangeInitReqCallback = NULL;
+std::mutex AudioSystem::gApsCallbackMutex;
std::mutex AudioSystem::gErrorCallbacksMutex;
std::set<audio_error_callback> AudioSystem::gAudioErrorCallbacks;
std::mutex AudioSystem::gSoundTriggerMutex;
sp<CaptureStateListenerImpl> AudioSystem::gSoundTriggerCaptureStateListener;
-std::mutex AudioSystem::gAPSMutex;
-sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
-sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient;
-
// Sets the Binder for the AudioFlinger service, passed to this client process
// from the system server.
// This allows specific isolated processes to access the audio system. Currently used only for the
// HotwordDetectionService.
-void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
- if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
- ALOGE("setAudioFlingerBinder: received a binder of type %s",
- String8(audioFlinger->getInterfaceDescriptor()).c_str());
- return;
- }
- std::lock_guard _l(gMutex);
- if (gAudioFlinger != nullptr) {
- ALOGW("setAudioFlingerBinder: ignoring; AudioFlinger connection already established.");
- return;
- }
- gAudioFlingerBinder = audioFlinger;
-}
+template <typename ServiceInterface, typename Client, typename AidlInterface,
+ typename ServiceTraits>
+class ServiceHandler {
+public:
+ sp<ServiceInterface> getService(bool canStartThreadPool = true)
+ EXCLUDES(mMutex) NO_THREAD_SAFETY_ANALYSIS { // std::unique_ptr
+ sp<ServiceInterface> service;
+ sp<Client> client;
-status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) {
- std::lock_guard _l(gMutex);
- if (gAudioFlinger != nullptr) return INVALID_OPERATION;
- gLocalAudioFlinger = af;
- return OK;
-}
-
-// establish binder interface to AudioFlinger service
-const sp<IAudioFlinger> AudioSystem::getAudioFlingerImpl(bool canStartThreadPool = true) {
- sp<IAudioFlinger> af;
- sp<AudioFlingerClient> afc;
- bool reportNoError = false;
- {
- std::lock_guard _l(gMutex);
- if (gAudioFlinger != nullptr) {
- return gAudioFlinger;
+ bool reportNoError = false;
+ {
+ std::lock_guard _l(mMutex);
+ if (mService != nullptr) {
+ return mService;
+ }
}
- if (gAudioFlingerClient == nullptr) {
- gAudioFlingerClient = sp<AudioFlingerClient>::make();
+ std::unique_lock ul_only1thread(mSingleGetter);
+ std::unique_lock ul(mMutex);
+ if (mService != nullptr) {
+ return mService;
+ }
+ if (mClient == nullptr) {
+ mClient = sp<Client>::make();
} else {
reportNoError = true;
}
+ while (true) {
+ mService = mLocalService;
+ if (mService != nullptr) break;
- if (gLocalAudioFlinger != nullptr) {
- gAudioFlinger = gLocalAudioFlinger;
- } else {
- sp<IBinder> binder;
- if (gAudioFlingerBinder != nullptr) {
- binder = gAudioFlingerBinder;
- } else {
- sp<IServiceManager> sm = defaultServiceManager();
- binder = sm->waitForService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
+ sp<IBinder> binder = mBinder;
+ if (binder == nullptr) {
+ sp <IServiceManager> sm = defaultServiceManager();
+ binder = sm->checkService(String16(ServiceTraits::SERVICE_NAME));
if (binder == nullptr) {
- return nullptr;
+ ALOGD("%s: waiting for %s", __func__, ServiceTraits::SERVICE_NAME);
+
+ // if the condition variable is present, setLocalService() and
+ // setBinder() is allowed to use it to notify us.
+ if (mCvGetter == nullptr) {
+ mCvGetter = std::make_shared<std::condition_variable>();
+ }
+ mCvGetter->wait_for(ul, std::chrono::seconds(1));
+ continue;
}
}
- binder->linkToDeath(gAudioFlingerClient);
- const auto afs = interface_cast<media::IAudioFlingerService>(binder);
- LOG_ALWAYS_FATAL_IF(afs == nullptr);
- gAudioFlinger = sp<AudioFlingerClientAdapter>::make(afs);
+ binder->linkToDeath(mClient);
+ auto aidlInterface = interface_cast<AidlInterface>(binder);
+ LOG_ALWAYS_FATAL_IF(aidlInterface == nullptr);
+ if constexpr (std::is_same_v<ServiceInterface, AidlInterface>) {
+ mService = std::move(aidlInterface);
+ } else /* constexpr */ {
+ mService = ServiceTraits::createServiceAdapter(aidlInterface);
+ }
+ break;
}
- afc = gAudioFlingerClient;
- af = gAudioFlinger;
- // Make sure callbacks can be received by gAudioFlingerClient
- if(canStartThreadPool) {
+ if (mCvGetter) mCvGetter.reset(); // remove condition variable.
+ client = mClient;
+ service = mService;
+ // Make sure callbacks can be received by the client
+ if (canStartThreadPool) {
ProcessState::self()->startThreadPool();
}
+ ul.unlock();
+ ul_only1thread.unlock();
+ ServiceTraits::onServiceCreate(service, client);
+ if (reportNoError) AudioSystem::reportError(NO_ERROR);
+ return service;
}
- const int64_t token = IPCThreadState::self()->clearCallingIdentity();
- af->registerClient(afc);
- IPCThreadState::self()->restoreCallingIdentity(token);
- if (reportNoError) reportError(NO_ERROR);
- return af;
-}
+
+ status_t setLocalService(const sp<ServiceInterface>& service) EXCLUDES(mMutex) {
+ std::lock_guard _l(mMutex);
+ // we allow clearing once set, but not a double non-null set.
+ if (mService != nullptr && service != nullptr) return INVALID_OPERATION;
+ mLocalService = service;
+ if (mCvGetter) mCvGetter->notify_one();
+ return OK;
+ }
+
+ sp<Client> getClient() EXCLUDES(mMutex) {
+ const auto service = getService();
+ if (service == nullptr) return nullptr;
+ std::lock_guard _l(mMutex);
+ return mClient;
+ }
+
+ void setBinder(const sp<IBinder>& binder) EXCLUDES(mMutex) {
+ std::lock_guard _l(mMutex);
+ if (mService != nullptr) {
+ ALOGW("%s: ignoring; %s connection already established.",
+ __func__, ServiceTraits::SERVICE_NAME);
+ return;
+ }
+ mBinder = binder;
+ if (mCvGetter) mCvGetter->notify_one();
+ }
+
+ void clearService() EXCLUDES(mMutex) {
+ std::lock_guard _l(mMutex);
+ mService.clear();
+ if (mClient) ServiceTraits::onClearService(mClient);
+ }
+
+private:
+ std::mutex mSingleGetter;
+ std::mutex mMutex;
+ std::shared_ptr<std::condition_variable> mCvGetter GUARDED_BY(mMutex);
+ sp<IBinder> mBinder GUARDED_BY(mMutex);
+ sp<ServiceInterface> mLocalService GUARDED_BY(mMutex);
+ sp<ServiceInterface> mService GUARDED_BY(mMutex);
+ sp<Client> mClient GUARDED_BY(mMutex);
+};
+
+struct AudioFlingerTraits {
+ static void onServiceCreate(
+ const sp<IAudioFlinger>& af, const sp<AudioSystem::AudioFlingerClient>& afc) {
+ const int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ af->registerClient(afc);
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ }
+
+ static sp<IAudioFlinger> createServiceAdapter(
+ const sp<media::IAudioFlingerService>& aidlInterface) {
+ return sp<AudioFlingerClientAdapter>::make(aidlInterface);
+ }
+
+ static void onClearService(const sp<AudioSystem::AudioFlingerClient>& afc) {
+ afc->clearIoCache();
+ }
+
+ static constexpr const char* SERVICE_NAME = IAudioFlinger::DEFAULT_SERVICE_NAME;
+};
+
+[[clang::no_destroy]] static constinit ServiceHandler<IAudioFlinger,
+ AudioSystem::AudioFlingerClient, media::IAudioFlingerService,
+ AudioFlingerTraits> gAudioFlingerServiceHandler;
sp<IAudioFlinger> AudioSystem::get_audio_flinger() {
- return getAudioFlingerImpl();
+ return gAudioFlingerServiceHandler.getService();
}
sp<IAudioFlinger> AudioSystem::get_audio_flinger_for_fuzzer() {
- return getAudioFlingerImpl(false);
+ return gAudioFlingerServiceHandler.getService(false /* canStartThreadPool */);
}
-const sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient() {
- // calling get_audio_flinger() will initialize gAudioFlingerClient if needed
- const sp<IAudioFlinger> af = get_audio_flinger();
- if (af == 0) return 0;
- std::lock_guard _l(gMutex);
- return gAudioFlingerClient;
+sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient() {
+ return gAudioFlingerServiceHandler.getClient();
+}
+
+void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
+ if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
+ ALOGE("%s: received a binder of type %s",
+ __func__, String8(audioFlinger->getInterfaceDescriptor()).c_str());
+ return;
+ }
+ gAudioFlingerServiceHandler.setBinder(audioFlinger);
+}
+
+status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) {
+ return gAudioFlingerServiceHandler.setLocalService(af);
}
sp<AudioIoDescriptor> AudioSystem::getIoDescriptor(audio_io_handle_t ioHandle) {
@@ -557,14 +627,7 @@
}
void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who __unused) {
- {
- std::lock_guard _l(AudioSystem::gMutex);
- AudioSystem::gAudioFlinger.clear();
- }
-
- // clear output handles and stream to output map caches
- clearIoCache();
-
+ gAudioFlingerServiceHandler.clearService();
reportError(DEAD_OBJECT);
ALOGW("AudioFlinger server died!");
@@ -863,44 +926,35 @@
gVolRangeInitReqCallback = cb;
}
-// establish binder interface to AudioPolicy service
-sp<IAudioPolicyService> AudioSystem::get_audio_policy_service() {
- sp<IAudioPolicyService> ap;
- sp<AudioPolicyServiceClient> apc;
- {
- std::lock_guard _l(gAPSMutex);
- if (gAudioPolicyService == 0) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->waitForService(String16("media.audio_policy"));
- if (binder == nullptr) {
- return nullptr;
- }
- if (gAudioPolicyServiceClient == NULL) {
- gAudioPolicyServiceClient = new AudioPolicyServiceClient();
- }
- binder->linkToDeath(gAudioPolicyServiceClient);
- gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
- LOG_ALWAYS_FATAL_IF(gAudioPolicyService == 0);
- apc = gAudioPolicyServiceClient;
- // Make sure callbacks can be received by gAudioPolicyServiceClient
- ProcessState::self()->startThreadPool();
- }
- ap = gAudioPolicyService;
- }
- if (apc != 0) {
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
+struct AudioPolicyTraits {
+ static void onServiceCreate(const sp<IAudioPolicyService>& ap,
+ const sp<AudioSystem::AudioPolicyServiceClient>& apc) {
+ const int64_t token = IPCThreadState::self()->clearCallingIdentity();
ap->registerClient(apc);
ap->setAudioPortCallbacksEnabled(apc->isAudioPortCbEnabled());
ap->setAudioVolumeGroupCallbacksEnabled(apc->isAudioVolumeGroupCbEnabled());
IPCThreadState::self()->restoreCallingIdentity(token);
}
- return ap;
+ static void onClearService(const sp<AudioSystem::AudioPolicyServiceClient>&) {}
+
+ static constexpr const char *SERVICE_NAME = "media.audio_policy";
+};
+
+[[clang::no_destroy]] static constinit ServiceHandler<IAudioPolicyService,
+ AudioSystem::AudioPolicyServiceClient, IAudioPolicyService,
+ AudioPolicyTraits> gAudioPolicyServiceHandler;
+
+status_t AudioSystem::setLocalAudioPolicyService(const sp<IAudioPolicyService>& aps) {
+ return gAudioPolicyServiceHandler.setLocalService(aps);
+}
+
+sp<IAudioPolicyService> AudioSystem::get_audio_policy_service() {
+ return gAudioPolicyServiceHandler.getService();
}
void AudioSystem::clearAudioPolicyService() {
- std::lock_guard _l(gAPSMutex);
- gAudioPolicyService.clear();
+ gAudioPolicyServiceHandler.clearService();
}
// ---------------------------------------------------------------------------
@@ -1501,13 +1555,7 @@
void AudioSystem::clearAudioConfigCache() {
// called by restoreTrack_l(), which needs new IAudioFlinger and IAudioPolicyService instances
ALOGV("clearAudioConfigCache()");
- {
- std::lock_guard _l(gMutex);
- if (gAudioFlingerClient != 0) {
- gAudioFlingerClient->clearIoCache();
- }
- gAudioFlinger.clear();
- }
+ gAudioFlingerServiceHandler.clearService();
clearAudioPolicyService();
}
@@ -1670,12 +1718,11 @@
status_t AudioSystem::addAudioPortCallback(const sp<AudioPortCallback>& callback) {
const sp<IAudioPolicyService> aps = get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
+ const auto apc = gAudioPolicyServiceHandler.getClient();
+ if (apc == nullptr) return NO_INIT;
- std::lock_guard _l(gAPSMutex);
- if (gAudioPolicyServiceClient == 0) {
- return NO_INIT;
- }
- int ret = gAudioPolicyServiceClient->addAudioPortCallback(callback);
+ std::lock_guard _l(gApsCallbackMutex);
+ const int ret = apc->addAudioPortCallback(callback);
if (ret == 1) {
aps->setAudioPortCallbacksEnabled(true);
}
@@ -1686,12 +1733,11 @@
status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callback) {
const sp<IAudioPolicyService> aps = get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
+ const auto apc = gAudioPolicyServiceHandler.getClient();
+ if (apc == nullptr) return NO_INIT;
- std::lock_guard _l(gAPSMutex);
- if (gAudioPolicyServiceClient == 0) {
- return NO_INIT;
- }
- int ret = gAudioPolicyServiceClient->removeAudioPortCallback(callback);
+ std::lock_guard _l(gApsCallbackMutex);
+ const int ret = apc->removeAudioPortCallback(callback);
if (ret == 0) {
aps->setAudioPortCallbacksEnabled(false);
}
@@ -1701,12 +1747,11 @@
status_t AudioSystem::addAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback) {
const sp<IAudioPolicyService> aps = get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
+ const auto apc = gAudioPolicyServiceHandler.getClient();
+ if (apc == nullptr) return NO_INIT;
- std::lock_guard _l(gAPSMutex);
- if (gAudioPolicyServiceClient == 0) {
- return NO_INIT;
- }
- int ret = gAudioPolicyServiceClient->addAudioVolumeGroupCallback(callback);
+ std::lock_guard _l(gApsCallbackMutex);
+ const int ret = apc->addAudioVolumeGroupCallback(callback);
if (ret == 1) {
aps->setAudioVolumeGroupCallbacksEnabled(true);
}
@@ -1716,12 +1761,11 @@
status_t AudioSystem::removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCallback>& callback) {
const sp<IAudioPolicyService> aps = get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
+ const auto apc = gAudioPolicyServiceHandler.getClient();
+ if (apc == nullptr) return NO_INIT;
- std::lock_guard _l(gAPSMutex);
- if (gAudioPolicyServiceClient == 0) {
- return NO_INIT;
- }
- int ret = gAudioPolicyServiceClient->removeAudioVolumeGroupCallback(callback);
+ std::lock_guard _l(gApsCallbackMutex);
+ const int ret = apc->removeAudioVolumeGroupCallback(callback);
if (ret == 0) {
aps->setAudioVolumeGroupCallbacksEnabled(false);
}
diff --git a/media/libaudioclient/PolicyAidlConversion.cpp b/media/libaudioclient/PolicyAidlConversion.cpp
index 60b08fa..a71bb18 100644
--- a/media/libaudioclient/PolicyAidlConversion.cpp
+++ b/media/libaudioclient/PolicyAidlConversion.cpp
@@ -242,6 +242,7 @@
legacy.mCbFlags = VALUE_OR_RETURN(aidl2legacy_AudioMixCallbackFlag_uint32_t_mask(aidl.cbFlags));
legacy.mAllowPrivilegedMediaPlaybackCapture = aidl.allowPrivilegedMediaPlaybackCapture;
legacy.mVoiceCommunicationCaptureAllowed = aidl.voiceCommunicationCaptureAllowed;
+ legacy.mToken = aidl.mToken;
return legacy;
}
@@ -265,6 +266,7 @@
aidl.cbFlags = VALUE_OR_RETURN(legacy2aidl_uint32_t_AudioMixCallbackFlag_mask(legacy.mCbFlags));
aidl.allowPrivilegedMediaPlaybackCapture = legacy.mAllowPrivilegedMediaPlaybackCapture;
aidl.voiceCommunicationCaptureAllowed = legacy.mVoiceCommunicationCaptureAllowed;
+ aidl.mToken = legacy.mToken;
return aidl;
}
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index 9c4ccb8..e213f08 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -872,6 +872,18 @@
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
.repeatCnt = 3,
.repeatSegment = 0 }, // TONE_NZ_CALL_WAITING
+ { .segments = { { .duration = 500, .waveFreq = { 425, 0 }, 0, 0 },
+ { .duration = 250, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_MY_CONGESTION
+ { .segments = { { .duration = 400, .waveFreq = { 425, 0 }, 0, 0 },
+ { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 400, .waveFreq = { 425, 0 }, 0, 0 },
+ { .duration = 2000, .waveFreq = { 0 }, 0, 0},
+ { .duration = 0, .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 } // TONE_MY_RINGTONE
};
// Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
@@ -976,6 +988,16 @@
TONE_SUP_ERROR, // TONE_SUP_ERROR
TONE_NZ_CALL_WAITING, // TONE_SUP_CALL_WAITING
TONE_GB_RINGTONE // TONE_SUP_RINGTONE
+ },
+ { // MALAYSIA
+ TONE_SUP_DIAL, // TONE_SUP_DIAL
+ TONE_SUP_BUSY, // TONE_SUP_BUSY
+ TONE_MY_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_MY_RINGTONE // TONE_SUP_RINGTONE
}
};
@@ -1055,6 +1077,8 @@
mRegion = TAIWAN;
} else if (strstr(value, "nz") != NULL) {
mRegion = NZ;
+ } else if (strstr(value, "my") != NULL) {
+ mRegion = MY;
} else {
mRegion = CEPT;
}
diff --git a/media/libaudioclient/aidl/android/media/AudioMix.aidl b/media/libaudioclient/aidl/android/media/AudioMix.aidl
index 88b0450..f0c561c 100644
--- a/media/libaudioclient/aidl/android/media/AudioMix.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioMix.aidl
@@ -39,4 +39,6 @@
boolean allowPrivilegedMediaPlaybackCapture;
/** Indicates if the caller can capture voice communication output */
boolean voiceCommunicationCaptureAllowed;
+ /** Identifies the owner of the AudioPolicy that this AudioMix belongs to */
+ IBinder mToken;
}
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index ec35e93..9e4ae54 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -18,6 +18,7 @@
#ifndef ANDROID_AUDIO_POLICY_H
#define ANDROID_AUDIO_POLICY_H
+#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <media/AudioDeviceTypeAddr.h>
#include <system/audio.h>
@@ -127,6 +128,7 @@
audio_devices_t mDeviceType;
String8 mDeviceAddress;
uint32_t mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
+ sp<IBinder> mToken;
/** Ignore the AUDIO_FLAG_NO_MEDIA_PROJECTION */
bool mAllowPrivilegedMediaPlaybackCapture = false;
/** Indicates if the caller can capture voice communication output */
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 3061633..338534d 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -100,6 +100,10 @@
friend class AudioFlingerClient;
friend class AudioPolicyServiceClient;
friend class CaptureStateListenerImpl;
+ template <typename ServiceInterface, typename Client, typename AidlInterface,
+ typename ServiceTraits>
+ friend class ServiceHandler;
+
public:
// FIXME Declare in binder opcode order, similarly to IAudioFlinger.h and IAudioFlinger.cpp
@@ -407,6 +411,11 @@
// and output configuration cache (gOutputs)
static void clearAudioConfigCache();
+ // Sets a local AudioPolicyService interface to be used by AudioSystem.
+ // This is used by audioserver main() to allow client object initialization
+ // before exposing any interfaces to ServiceManager.
+ static status_t setLocalAudioPolicyService(const sp<media::IAudioPolicyService>& aps);
+
static sp<media::IAudioPolicyService> get_audio_policy_service();
static void clearAudioPolicyService();
@@ -781,8 +790,6 @@
static int32_t getAAudioHardwareBurstMinUsec();
-private:
-
class AudioFlingerClient: public IBinder::DeathRecipient, public media::BnAudioFlingerClient
{
public:
@@ -892,24 +899,22 @@
std::set<sp<AudioVolumeGroupCallback>> mAudioVolumeGroupCallbacks GUARDED_BY(mMutex);
};
+ private:
+
static audio_io_handle_t getOutput(audio_stream_type_t stream);
- static const sp<AudioFlingerClient> getAudioFlingerClient();
+ static sp<AudioFlingerClient> getAudioFlingerClient();
static sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle);
- static const sp<IAudioFlinger> getAudioFlingerImpl(bool canStartThreadPool);
// Invokes all registered error callbacks with the given error code.
static void reportError(status_t err);
[[clang::no_destroy]] static std::mutex gMutex;
- [[clang::no_destroy]] static sp<IAudioFlinger> gAudioFlinger GUARDED_BY(gMutex);
- [[clang::no_destroy]] static sp<IBinder> gAudioFlingerBinder GUARDED_BY(gMutex);
- [[clang::no_destroy]] static sp<IAudioFlinger> gLocalAudioFlinger GUARDED_BY(gMutex);
- [[clang::no_destroy]] static sp<AudioFlingerClient> gAudioFlingerClient GUARDED_BY(gMutex);
static dynamic_policy_callback gDynPolicyCallback GUARDED_BY(gMutex);
static record_config_callback gRecordConfigCallback GUARDED_BY(gMutex);
static routing_callback gRoutingCallback GUARDED_BY(gMutex);
static vol_range_init_req_callback gVolRangeInitReqCallback GUARDED_BY(gMutex);
+ [[clang::no_destroy]] static std::mutex gApsCallbackMutex;
[[clang::no_destroy]] static std::mutex gErrorCallbacksMutex;
[[clang::no_destroy]] static std::set<audio_error_callback> gAudioErrorCallbacks
GUARDED_BY(gErrorCallbacksMutex);
@@ -917,12 +922,6 @@
[[clang::no_destroy]] static std::mutex gSoundTriggerMutex;
[[clang::no_destroy]] static sp<CaptureStateListenerImpl> gSoundTriggerCaptureStateListener
GUARDED_BY(gSoundTriggerMutex);
-
- [[clang::no_destroy]] static std::mutex gAPSMutex;
- [[clang::no_destroy]] static sp<media::IAudioPolicyService> gAudioPolicyService
- GUARDED_BY(gAPSMutex);
- [[clang::no_destroy]] static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient
- GUARDED_BY(gAPSMutex);
};
} // namespace android
diff --git a/media/libaudioclient/include/media/EffectClientAsyncProxy.h b/media/libaudioclient/include/media/EffectClientAsyncProxy.h
new file mode 100644
index 0000000..e7d6d80
--- /dev/null
+++ b/media/libaudioclient/include/media/EffectClientAsyncProxy.h
@@ -0,0 +1,111 @@
+/*
+ * 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 <android/media/BnEffectClient.h>
+#include <audio_utils/CommandThread.h>
+
+namespace android::media {
+
+class EffectClientAsyncProxy : public IEffectClient {
+public:
+
+ /**
+ * Call this factory method to interpose a worker thread when a binder
+ * callback interface is invoked in-proc.
+ */
+ static sp<IEffectClient> makeIfNeeded(const sp<IEffectClient>& effectClient) {
+ if (isLocalBinder(effectClient)) {
+ return sp<EffectClientAsyncProxy>::make(effectClient);
+ }
+ return effectClient;
+ }
+
+ explicit EffectClientAsyncProxy(const sp<IEffectClient>& effectClient)
+ : mEffectClient(effectClient) {}
+
+ ::android::IBinder* onAsBinder() override {
+ return nullptr;
+ }
+
+ ::android::binder::Status controlStatusChanged(bool controlGranted) override {
+ getThread().add(__func__, [=, effectClient = mEffectClient]() {
+ effectClient->controlStatusChanged(controlGranted);
+ });
+ return ::android::binder::Status::fromStatusT(::android::NO_ERROR);
+ }
+
+ ::android::binder::Status enableStatusChanged(bool enabled) override {
+ getThread().add(__func__, [=, effectClient = mEffectClient]() {
+ effectClient->enableStatusChanged(enabled);
+ });
+ return ::android::binder::Status::fromStatusT(::android::NO_ERROR);
+ }
+
+ ::android::binder::Status commandExecuted(
+ int32_t cmdCode, const ::std::vector<uint8_t>& cmdData,
+ const ::std::vector<uint8_t>& replyData) override {
+ getThread().add(__func__, [=, effectClient = mEffectClient]() {
+ effectClient->commandExecuted(cmdCode, cmdData, replyData);
+ });
+ return ::android::binder::Status::fromStatusT(::android::NO_ERROR);
+ }
+
+ ::android::binder::Status framesProcessed(int32_t frames) override {
+ getThread().add(__func__, [=, effectClient = mEffectClient]() {
+ effectClient->framesProcessed(frames);
+ });
+ return ::android::binder::Status::fromStatusT(::android::NO_ERROR);
+ }
+
+ /**
+ * Returns true if the binder interface is local (in-proc).
+ *
+ * Move to a binder helper class?
+ */
+ static bool isLocalBinder(const sp<IInterface>& interface) {
+ const auto b = IInterface::asBinder(interface);
+ return b && b->localBinder();
+ }
+
+private:
+ const sp<IEffectClient> mEffectClient;
+
+ /**
+ * Returns the per-interface-descriptor CommandThread for in-proc binder transactions.
+ *
+ * Note: Remote RPC transactions to a given binder (kernel) node enter that node's
+ * async_todo list, which serializes all async operations to that binder node.
+ * Each transaction on the async_todo list must complete before the next one
+ * starts, even though there may be available threads in the process threadpool.
+ *
+ * For local transactions, we order all async requests entering
+ * the CommandThread. We do not maintain a threadpool, though a future implementation
+ * could use a shared ThreadPool.
+ *
+ * By using a static here, all in-proc binder interfaces made async with
+ * EffectClientAsyncProxy will get the same CommandThread.
+ *
+ * @return CommandThread to use.
+ */
+ static audio_utils::CommandThread& getThread() {
+ [[clang::no_destroy]] static audio_utils::CommandThread commandThread;
+ return commandThread;
+ }
+}; // class EffectClientAsyncProxy
+
+} // namespace android::media
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 46e9501..3e515fc 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -225,11 +225,14 @@
TONE_INDIA_CONGESTION, // Congestion tone: 400 Hz, 250ms ON, 250ms OFF...
TONE_INDIA_CALL_WAITING, // Call waiting tone: 400 Hz, tone repeated in a 0.2s on, 0.1s off, 0.2s on, 7.5s off pattern.
TONE_INDIA_RINGTONE, // Ring tone: 400 Hz tone modulated with 25Hz, 0.4 on 0.2 off 0.4 on 2..0 off
- // TAIWAN supervisory tones
+ // TAIWAN supervisory tones
TONE_TW_RINGTONE, // Ring Tone: 440 Hz + 480 Hz repeated with pattern 1s on, 3s off.
- // NEW ZEALAND supervisory tones
+ // NEW ZEALAND supervisory tones
TONE_NZ_CALL_WAITING, // Call waiting tone: 400 Hz, 0.2s ON, 3s OFF,
// 0.2s ON, 3s OFF, 0.2s ON, 3s OFF, 0.2s ON
+ // MALAYSIA supervisory tones
+ TONE_MY_CONGESTION, // Congestion tone: 425 Hz, 500ms ON, 250ms OFF...
+ TONE_MY_RINGTONE, // Ring tone: 425 Hz, 400ms ON 200ms OFF 400ms ON 2s OFF..
NUM_ALTERNATE_TONES
};
@@ -244,6 +247,7 @@
INDIA,
TAIWAN,
NZ,
+ MY,
CEPT,
NUM_REGIONS
};
diff --git a/media/libaudioclient/tests/audiorouting_tests.cpp b/media/libaudioclient/tests/audiorouting_tests.cpp
index 8f76f9b..3b2285e 100644
--- a/media/libaudioclient/tests/audiorouting_tests.cpp
+++ b/media/libaudioclient/tests/audiorouting_tests.cpp
@@ -17,6 +17,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "AudioRoutingTest"
+#include <string.h>
+
+#include <binder/Binder.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
#include <gtest/gtest.h>
@@ -149,6 +152,7 @@
config.sample_rate = 48000;
AudioMix mix(criteria, mixType, config, mixFlag, String8{mAddress.c_str()}, 0);
mix.mDeviceType = deviceType;
+ mix.mToken = sp<BBinder>::make();
mMixes.push(mix);
if (OK == AudioSystem::registerPolicyMixes(mMixes, true)) {
mPolicyMixRegistered = true;
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.cpp b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
index a701852..33fe3ed 100644
--- a/media/libaudiohal/impl/EffectBufferHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
@@ -58,25 +58,14 @@
}
EffectBufferHalAidl::~EffectBufferHalAidl() {
+ if (mAudioBuffer.raw) free(mAudioBuffer.raw);
}
status_t EffectBufferHalAidl::init() {
- int fd = ashmem_create_region("audioEffectAidl", mBufferSize);
- if (fd < 0) {
- ALOGE("%s create ashmem failed %d", __func__, fd);
- return fd;
+ if (0 != posix_memalign(&mAudioBuffer.raw, 32, mBufferSize)) {
+ return NO_MEMORY;
}
- ScopedFileDescriptor tempFd(fd);
- mAudioBuffer.raw = mmap(nullptr /* address */, mBufferSize /* length */, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, 0 /* offset */);
- if (mAudioBuffer.raw == MAP_FAILED) {
- ALOGE("mmap failed for fd %d", fd);
- mAudioBuffer.raw = nullptr;
- return INVALID_OPERATION;
- }
-
- mMemory = {std::move(tempFd), static_cast<int64_t>(mBufferSize)};
return OK;
}
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.h b/media/libaudiohal/impl/EffectBufferHalAidl.h
index 035314b..cf6031f 100644
--- a/media/libaudiohal/impl/EffectBufferHalAidl.h
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.h
@@ -50,7 +50,6 @@
const size_t mBufferSize;
bool mFrameCountChanged;
void* mExternalData;
- aidl::android::hardware::common::Ashmem mMemory;
audio_buffer_t mAudioBuffer;
// Can not be constructed directly by clients.
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index d440ef8..9a8d96b 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -208,6 +208,10 @@
if (desc.common.flags.volume == Flags::Volume::NONE) {
common.flags.volume = Flags::Volume::NONE;
}
+ // set to AUXILIARY if any sub-effect is of AUXILIARY type
+ if (desc.common.flags.type == Flags::Type::AUXILIARY) {
+ common.flags.type = Flags::Type::AUXILIARY;
+ }
}
// copy type UUID from any of sub-effects, all sub-effects should have same type
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index 042b063..311d60a 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -485,7 +485,7 @@
if (!stageInUse) {
LOG(WARNING) << __func__ << " not in use " << ::android::internal::ToString(channels);
- return RetCode::SUCCESS;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
}
RETURN_VALUE_IF(!stageInUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
diff --git a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
index 5d9886c..f60d616 100644
--- a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
+++ b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
@@ -114,10 +114,11 @@
std::stringstream ss;
ss << "\t\tHaptic setting:\n";
ss << "\t\t- tracks intensity map:\n";
- for (const auto&[id, intensity] : param.id2Intensity) {
- ss << "\t\t\t- id=" << id << ", intensity=" << (int) intensity;
+ for (const auto&[id, hapticScale] : param.id2HapticScale) {
+ ss << "\t\t\t- id=" << id << ", hapticLevel=" << (int) hapticScale.getLevel()
+ << ", adaptiveScaleFactor=" << hapticScale.getAdaptiveScaleFactor();
}
- ss << "\t\t- max intensity: " << (int) param.maxHapticIntensity << '\n';
+ ss << "\t\t- max scale level: " << (int) param.maxHapticScale.getLevel() << '\n';
ss << "\t\t- max haptic amplitude: " << param.maxHapticAmplitude << '\n';
return ss.str();
}
@@ -145,7 +146,7 @@
memset(context->param.hapticChannelSource, 0, sizeof(context->param.hapticChannelSource));
context->param.hapticChannelCount = 0;
context->param.audioChannelCount = 0;
- context->param.maxHapticIntensity = os::HapticLevel::MUTE;
+ context->param.maxHapticScale = os::HapticScale::mute();
context->param.resonantFrequency = DEFAULT_RESONANT_FREQUENCY;
context->param.bpfQ = 1.0f;
@@ -312,22 +313,25 @@
void *value) {
switch (param) {
case HG_PARAM_HAPTIC_INTENSITY: {
- if (value == nullptr || size != (uint32_t) (2 * sizeof(int))) {
+ if (value == nullptr || size != (uint32_t) (2 * sizeof(int) + sizeof(float))) {
return -EINVAL;
}
- int id = *(int *) value;
- os::HapticLevel hapticIntensity =
- static_cast<os::HapticLevel>(*((int *) value + 1));
- ALOGD("Setting haptic intensity as %d", static_cast<int>(hapticIntensity));
- if (hapticIntensity == os::HapticLevel::MUTE) {
- context->param.id2Intensity.erase(id);
+ const int id = *(int *) value;
+ const os::HapticLevel hapticLevel = static_cast<os::HapticLevel>(*((int *) value + 1));
+ const float adaptiveScaleFactor = (*((float *) value + 2));
+ const os::HapticScale hapticScale = {hapticLevel, adaptiveScaleFactor};
+ ALOGD("Updating haptic scale, hapticLevel=%d, adaptiveScaleFactor=%f",
+ static_cast<int>(hapticLevel), adaptiveScaleFactor);
+ if (hapticScale.isScaleMute()) {
+ context->param.id2HapticScale.erase(id);
} else {
- context->param.id2Intensity.emplace(id, hapticIntensity);
+ context->param.id2HapticScale.emplace(id, hapticScale);
}
- context->param.maxHapticIntensity = hapticIntensity;
- for (const auto&[id, intensity] : context->param.id2Intensity) {
- context->param.maxHapticIntensity = std::max(
- context->param.maxHapticIntensity, intensity);
+ context->param.maxHapticScale = hapticScale;
+ for (const auto&[id, scale] : context->param.id2HapticScale) {
+ if (scale.getLevel() > context->param.maxHapticScale.getLevel()) {
+ context->param.maxHapticScale = scale;
+ }
}
break;
}
@@ -479,7 +483,7 @@
return -ENODATA;
}
- if (context->param.maxHapticIntensity == os::HapticLevel::MUTE) {
+ if (context->param.maxHapticScale.isScaleMute()) {
// Haptic channels are muted, not need to generate haptic data.
return 0;
}
@@ -506,7 +510,7 @@
context->processingChain, context->inputBuffer.data(),
context->outputBuffer.data(), inBuffer->frameCount);
os::scaleHapticData(hapticOutBuffer, hapticSampleCount,
- { /*level=*/context->param.maxHapticIntensity},
+ context->param.maxHapticScale,
context->param.maxHapticAmplitude);
// For haptic data, the haptic playback thread will copy the data from effect input buffer,
diff --git a/media/libeffects/hapticgenerator/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/EffectHapticGenerator.h
index f122c0a..dbfc5ea 100644
--- a/media/libeffects/hapticgenerator/EffectHapticGenerator.h
+++ b/media/libeffects/hapticgenerator/EffectHapticGenerator.h
@@ -48,9 +48,9 @@
uint32_t audioChannelCount;
uint32_t hapticChannelCount;
- // A map from track id to haptic intensity.
- std::map<int, os::HapticLevel> id2Intensity;
- os::HapticLevel maxHapticIntensity; // max intensity will be used to scale haptic data.
+ // A map from track id to haptic scale.
+ std::map<int, os::HapticScale> id2HapticScale;
+ os::HapticScale maxHapticScale; // max haptic scale will be used to scale haptic data.
float maxHapticAmplitude; // max amplitude will be used to limit haptic data absolute values.
float resonantFrequency;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index e79e55b..e4f3b83 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -3395,9 +3395,6 @@
if (bufferInfos == nullptr || bufferInfos->value.empty()) {
return BAD_VALUE;
}
- if (cryptoInfos == nullptr || cryptoInfos->value.empty()) {
- return BAD_VALUE;
- }
status_t err = OK;
sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
msg->setSize("index", index);
@@ -3405,8 +3402,12 @@
new WrapperObject<sp<hardware::HidlMemory>>{buffer}};
msg->setObject("memory", memory);
msg->setSize("offset", offset);
- msg->setSize("ssize", size);
- msg->setObject("cryptoInfos", cryptoInfos);
+ if (cryptoInfos != nullptr) {
+ msg->setSize("ssize", size);
+ msg->setObject("cryptoInfos", cryptoInfos);
+ } else {
+ msg->setSize("size", size);
+ }
msg->setObject("accessUnitInfo", bufferInfos);
if (OK != (err = generateFlagsFromAccessUnitInfo(msg, bufferInfos))) {
return err;
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index 5dd8423..dd6da15 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -1,13 +1,4 @@
{
- "postsubmit": [
- // writerTest fails about 5 out of 66
- // { "name": "writerTest" },
-
- { "name": "HEVCUtilsUnitTest" },
- { "name": "ExtractorFactoryTest" }
-
- ],
-
"presubmit-large": [
{
"name": "CtsMediaMiscTestCases",
@@ -92,8 +83,16 @@
}
],
"postsubmit": [
+ // writerTest fails about 5 out of 66
+ // { "name": "writerTest" },
{
"name": "BatteryChecker_test"
+ },
+ {
+ "name": "ExtractorFactoryTest"
+ },
+ {
+ "name": "HEVCUtilsUnitTest"
}
]
}
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index f4c40e1..24ac2e8 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -697,6 +697,7 @@
inline constexpr char FEATURE_AdaptivePlayback[] = "adaptive-playback";
inline constexpr char FEATURE_EncodingStatistics[] = "encoding-statistics";
inline constexpr char FEATURE_IntraRefresh[] = "intra-refresh";
+inline constexpr char FEATURE_MultipleFrames[] = "multiple-frames";
inline constexpr char FEATURE_PartialFrame[] = "partial-frame";
inline constexpr char FEATURE_QpBounds[] = "qp-bounds";
inline constexpr char FEATURE_SecurePlayback[] = "secure-playback";
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 959f43e..458ac9c 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -626,6 +626,10 @@
// ACodec is waiting for all buffers to be returned, do NOT
// submit any more buffers to the codec.
bufferSource->onOmxIdle();
+ } else if (param == OMX_StateExecuting) {
+ // Initiating transition from Idle -> Executing
+ // Start submitting buffers to codec.
+ bufferSource->onOmxExecuting();
} else if (param == OMX_StateLoaded) {
// Initiating transition from Idle/Executing -> Loaded
// Buffers are about to be freed.
@@ -2404,13 +2408,6 @@
asString(event), event, arg1String, arg1, arg2String, arg2);
const sp<IOMXBufferSource> bufferSource(getBufferSource());
- if (bufferSource != NULL
- && event == OMX_EventCmdComplete
- && arg1 == OMX_CommandStateSet
- && arg2 == OMX_StateExecuting) {
- bufferSource->onOmxExecuting();
- }
-
// allow configuration if we return to the loaded state
if (event == OMX_EventCmdComplete
&& arg1 == OMX_CommandStateSet
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 19f9549..2341af1 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -1,4 +1,3 @@
-
package {
default_applicable_licenses: ["frameworks_av_media_mediaserver_license"],
}
@@ -86,7 +85,16 @@
"-Wall",
],
- vintf_fragments: ["manifest_media_c2_software.xml"],
+ // AIDL is only used when release_aidl_use_unfrozen is true
+ // because the swcodec mainline module is a prebuilt from an
+ // Android U branch in that case.
+ // TODO(b/327508501)
+ vintf_fragments: ["manifest_media_c2_software_hidl.xml"],
+ product_variables: {
+ release_aidl_use_unfrozen: {
+ vintf_fragments: ["manifest_media_c2_software_aidl.xml"],
+ },
+ },
soong_config_variables: {
TARGET_DYNAMIC_64_32_MEDIASERVER: {
diff --git a/media/mediaserver/manifest_media_c2_software_aidl.xml b/media/mediaserver/manifest_media_c2_software_aidl.xml
new file mode 100644
index 0000000..e6bcafa
--- /dev/null
+++ b/media/mediaserver/manifest_media_c2_software_aidl.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="framework">
+ <hal format="aidl">
+ <name>android.hardware.media.c2</name>
+ <version>1</version>
+ <fqname>IComponentStore/software</fqname>
+ </hal>
+</manifest>
diff --git a/media/mediaserver/manifest_media_c2_software.xml b/media/mediaserver/manifest_media_c2_software_hidl.xml
similarity index 68%
rename from media/mediaserver/manifest_media_c2_software.xml
rename to media/mediaserver/manifest_media_c2_software_hidl.xml
index 31dfafb..69a27be 100644
--- a/media/mediaserver/manifest_media_c2_software.xml
+++ b/media/mediaserver/manifest_media_c2_software_hidl.xml
@@ -8,9 +8,4 @@
<instance>software</instance>
</interface>
</hal>
- <hal format="aidl">
- <name>android.hardware.media.c2</name>
- <version>1</version>
- <fqname>IComponentStore/software</fqname>
- </hal>
</manifest>
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index c4f2808..deef31d 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
#define LOG_TAG "ServiceUtilities"
#include <audio_utils/clock.h>
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index b270813..819f2d6 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -31,6 +31,7 @@
#include <media/AudioContainers.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioEffect.h>
+#include <media/EffectClientAsyncProxy.h>
#include <media/ShmemCompat.h>
#include <media/TypeConverter.h>
#include <media/audiohal/EffectHalInterface.h>
@@ -1545,13 +1546,16 @@
return INVALID_OPERATION;
}
- std::vector<uint8_t> request(sizeof(effect_param_t) + 3 * sizeof(uint32_t));
+ std::vector<uint8_t> request(sizeof(effect_param_t) + 3 * sizeof(uint32_t) + sizeof(float));
effect_param_t *param = (effect_param_t*) request.data();
param->psize = sizeof(int32_t);
- param->vsize = sizeof(int32_t) * 2;
+ param->vsize = sizeof(int32_t) * 2 + sizeof(float);
*(int32_t*)param->data = HG_PARAM_HAPTIC_INTENSITY;
- *((int32_t*)param->data + 1) = id;
- *((int32_t*)param->data + 2) = static_cast<int32_t>(hapticScale.getLevel());
+ int32_t* hapticScalePtr = reinterpret_cast<int32_t*>(param->data + sizeof(int32_t));
+ hapticScalePtr[0] = id;
+ hapticScalePtr[1] = static_cast<int32_t>(hapticScale.getLevel());
+ float* adaptiveScaleFactorPtr = reinterpret_cast<float*>(param->data + 3 * sizeof(int32_t));
+ *adaptiveScaleFactorPtr = hapticScale.getAdaptiveScaleFactor();
std::vector<uint8_t> response;
status_t status = command(EFFECT_CMD_SET_PARAM, request, sizeof(int32_t), &response);
if (status == NO_ERROR) {
@@ -1726,7 +1730,8 @@
const sp<media::IEffectClient>& effectClient,
int32_t priority, bool notifyFramesProcessed)
: BnEffect(),
- mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
+ mEffect(effect), mEffectClient(media::EffectClientAsyncProxy::makeIfNeeded(effectClient)),
+ mClient(client), mCblk(nullptr),
mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false),
mNotifyFramesProcessed(notifyFramesProcessed)
{
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d1a09a4..f1be3976 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2927,7 +2927,6 @@
// Set haptic intensity for effect
if (chain != nullptr) {
- // TODO(b/324559333): Add adaptive haptics scaling support for the HapticGenerator.
chain->setHapticScale_l(track->id(), hapticScale);
}
}
@@ -3509,7 +3508,7 @@
char *endptr;
unsigned long ul = strtoul(value, &endptr, 0);
if (*endptr == '\0' && ul != 0) {
- ALOGD("Silence is golden");
+ ALOGW("%s: mute from ro.audio.silent. Silence is golden", __func__);
// The setprop command will not allow a property to be changed after
// the first time it is set, so we don't have to worry about un-muting.
setMasterMute_l(true);
@@ -7895,6 +7894,11 @@
if (mSupportedLatencyModes.empty()) {
return;
}
+ // Do not update the HAL latency mode if no track is active
+ if (mActiveTracks.isEmpty()) {
+ return;
+ }
+
audio_latency_mode_t latencyMode = AUDIO_LATENCY_MODE_FREE;
if (mSupportedLatencyModes.size() == 1) {
// If the HAL only support one latency mode currently, confirm the choice
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 77abaf6..4d07821 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1233,7 +1233,7 @@
&& (state == IDLE || state == STOPPED || state == FLUSHED)) {
mFrameMap.reset();
- if (!isFastTrack() && (isDirect() || isOffloaded())) {
+ if (!isFastTrack()) {
// Start point of track -> sink frame map. If the HAL returns a
// frame position smaller than the first written frame in
// updateTrackFrameInfo, the timestamp can be interpolated
diff --git a/services/audiopolicy/TEST_MAPPING b/services/audiopolicy/TEST_MAPPING
index a2ebb8d..cf1a771 100644
--- a/services/audiopolicy/TEST_MAPPING
+++ b/services/audiopolicy/TEST_MAPPING
@@ -46,6 +46,9 @@
"include-filter": "com.google.android.gts.audio.AudioPolicyHostTest"
}
]
+ },
+ {
+ "name": "spatializer_tests"
}
]
}
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 598d52d..e8b04ce 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -36,6 +36,7 @@
"src/TypeConverter.cpp",
],
shared_libs: [
+ "android.media.audiopolicy-aconfig-cc",
"audioclient-types-aidl-cpp",
"audiopolicy-types-aidl-cpp",
"libaudioclient_aidl_conversion",
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 6f71ac5..44f84b9 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -235,7 +235,8 @@
&deviceType,
String8(mDevice->address().c_str()),
source,
- flags);
+ static_cast<audio_input_flags_t>(
+ flags & mProfile->getFlags()));
LOG_ALWAYS_FATAL_IF(mDevice->type() != deviceType,
"%s openInput returned device %08x when given device %08x",
__FUNCTION__, mDevice->type(), deviceType);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index dc0f466..3430f4b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "APM_AudioPolicyMix"
-// #define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include <algorithm>
#include <iterator>
@@ -28,6 +28,9 @@
#include "PolicyAudioPort.h"
#include "IOProfile.h"
#include <AudioOutputDescriptor.h>
+#include <android_media_audiopolicy.h>
+
+namespace audiopolicy_flags = android::media::audiopolicy;
namespace android {
namespace {
@@ -190,6 +193,12 @@
mix.mDeviceType, mix.mDeviceAddress.c_str());
return BAD_VALUE;
}
+ if (audiopolicy_flags::audio_mix_ownership()) {
+ if (mix.mToken == registeredMix->mToken) {
+ ALOGE("registerMix(): same mix already registered - skipping");
+ return BAD_VALUE;
+ }
+ }
}
if (!areMixCriteriaConsistent(mix.mCriteria)) {
ALOGE("registerMix(): Mix contains inconsistent criteria "
@@ -212,12 +221,21 @@
{
for (size_t i = 0; i < size(); i++) {
const sp<AudioPolicyMix>& registeredMix = itemAt(i);
- if (mix.mDeviceType == registeredMix->mDeviceType
+ if (audiopolicy_flags::audio_mix_ownership()) {
+ if (mix.mToken == registeredMix->mToken) {
+ ALOGD("unregisterMix(): removing mix for dev=0x%x addr=%s",
+ mix.mDeviceType, mix.mDeviceAddress.c_str());
+ removeAt(i);
+ return NO_ERROR;
+ }
+ } else {
+ if (mix.mDeviceType == registeredMix->mDeviceType
&& mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0) {
- ALOGD("unregisterMix(): removing mix for dev=0x%x addr=%s",
- mix.mDeviceType, mix.mDeviceAddress.c_str());
- removeAt(i);
- return NO_ERROR;
+ ALOGD("unregisterMix(): removing mix for dev=0x%x addr=%s",
+ mix.mDeviceType, mix.mDeviceAddress.c_str());
+ removeAt(i);
+ return NO_ERROR;
+ }
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 2761480..154172a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3678,6 +3678,7 @@
status_t res = NO_ERROR;
bool checkOutputs = false;
sp<HwModule> rSubmixModule;
+ Vector<AudioMix> registeredMixes;
// examine each mix's route type
for (size_t i = 0; i < mixes.size(); i++) {
AudioMix mix = mixes[i];
@@ -3801,11 +3802,19 @@
break;
} else {
checkOutputs = true;
+ registeredMixes.add(mix);
}
}
}
if (res != NO_ERROR) {
- unregisterPolicyMixes(mixes);
+ if (audio_flags::audio_mix_ownership()) {
+ // Only unregister mixes that were actually registered to not accidentally unregister
+ // mixes that already existed previously.
+ unregisterPolicyMixes(registeredMixes);
+ registeredMixes.clear();
+ } else {
+ unregisterPolicyMixes(mixes);
+ }
} else if (checkOutputs) {
checkForDeviceAndOutputChanges();
updateCallAndOutputRouting();
@@ -3839,15 +3848,22 @@
continue;
}
- for (auto device : {AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX}) {
+ for (auto device: {AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX}) {
if (getDeviceConnectionState(device, address.c_str()) ==
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
- res = setDeviceConnectionStateInt(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.c_str(), "remote-submix",
- AUDIO_FORMAT_DEFAULT);
- if (res != OK) {
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ status_t currentRes =
+ setDeviceConnectionStateInt(device,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address.c_str(),
+ "remote-submix",
+ AUDIO_FORMAT_DEFAULT);
+ if (!audio_flags::audio_mix_ownership()) {
+ res = currentRes;
+ }
+ if (currentRes != OK) {
ALOGE("Error making RemoteSubmix device unavailable for mix "
"with type %d, address %s", device, address.c_str());
+ res = INVALID_OPERATION;
}
}
}
@@ -3863,6 +3879,7 @@
}
}
}
+
if (res == NO_ERROR && checkOutputs) {
checkForDeviceAndOutputChanges();
updateCallAndOutputRouting();
@@ -3882,9 +3899,10 @@
policyMix->mFormat, policyMix->mRouteFlags, policyMix->mDeviceAddress,
policyMix->mCbFlags);
_aidl_return.back().mDeviceType = policyMix->mDeviceType;
+ _aidl_return.back().mToken = policyMix->mToken;
}
- ALOGVV("%s() returning %zu registered mixes", __func__, _aidl_return->size());
+ ALOGVV("%s() returning %zu registered mixes", __func__, _aidl_return.size());
return OK;
}
@@ -7257,7 +7275,6 @@
DeviceVector devices;
for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
StreamTypeVector streams = mEngine->getStreamTypesForProductStrategy(productStrategy);
- auto attr = mEngine->getAllAttributesForProductStrategy(productStrategy).front();
auto hasStreamActive = [&](auto stream) {
return hasStream(streams, stream) && isStreamActive(stream, 0);
};
@@ -7282,6 +7299,7 @@
mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc))) {
// Retrieval of devices for voice DL is done on primary output profile, cannot
// check the route (would force modifying configuration file for this profile)
+ auto attr = mEngine->getAllAttributesForProductStrategy(productStrategy).front();
devices = mEngine->getOutputDevicesForAttributes(attr, nullptr, fromCache);
break;
}
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index cddbf39..05b0ddb 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -107,3 +107,9 @@
"framework-permission-aidl-cpp",
],
}
+
+cc_library_headers {
+ name: "libaudiopolicyservice_headers",
+ host_supported: true,
+ export_include_dirs: ["."],
+}
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 71edd57..d67ddb6 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -61,11 +61,6 @@
}
}
-void AudioPolicyEffects::setDefaultDeviceEffects() {
- mDefaultDeviceEffectFuture = std::async(
- std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
-}
-
status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
audio_source_t inputSource,
audio_session_t audioSession)
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index a9628c2..259b84a 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -116,10 +116,8 @@
// Remove the default stream effect from wherever it's attached.
status_t removeStreamDefaultEffect(audio_unique_id_t id) EXCLUDES_AudioPolicyEffects_Mutex;
- // Called by AudioPolicyService::onFirstRef() to load device effects
- // on a separate worker thread.
- // TODO(b/319515492) move this initialization after AudioPolicyService::onFirstRef().
- void setDefaultDeviceEffects();
+ // Initializes the Effects (AudioSystem must be ready as this creates audio client objects).
+ void initDefaultDeviceEffects() EXCLUDES(mDeviceEffectsMutex) EXCLUDES_EffectHandle_Mutex;
private:
@@ -201,11 +199,6 @@
};
- // Called on an async thread because it creates AudioEffects
- // which register with AudioFlinger and AudioPolicy.
- // We must therefore exclude the EffectHandle_Mutex.
- void initDefaultDeviceEffects() EXCLUDES(mDeviceEffectsMutex) EXCLUDES_EffectHandle_Mutex;
-
status_t loadAudioEffectConfig_ll(const sp<EffectsFactoryHalInterface>& effectsFactoryHal)
REQUIRES(mMutex, mDeviceEffectsMutex);
@@ -281,18 +274,6 @@
std::mutex mDeviceEffectsMutex;
std::map<std::string, std::unique_ptr<DeviceEffects>> mDeviceEffects
GUARDED_BY(mDeviceEffectsMutex);
-
- /**
- * Device Effect initialization must be asynchronous: the audio_policy service parses and init
- * effect on first reference. AudioFlinger will handle effect creation and register these
- * effect on audio_policy service.
- *
- * The future is associated with the std::async launched thread - no need to lock as
- * it is only set once on init. Due to the async nature, it is conceivable that
- * some device effects are not available immediately after AudioPolicyService::onFirstRef()
- * while the effects are being created.
- */
- std::future<void> mDefaultDeviceEffectFuture;
};
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index bc6498a..e95147e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -313,9 +313,16 @@
}
}
AudioSystem::audioPolicyReady();
- // AudioFlinger will handle effect creation and register these effects on audio_policy
- // service. Hence, audio_policy service must be ready.
- audioPolicyEffects->setDefaultDeviceEffects();
+}
+
+void AudioPolicyService::onAudioSystemReady() {
+ sp<AudioPolicyEffects> audioPolicyEffects;
+ {
+ audio_utils::lock_guard _l(mMutex);
+
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+ audioPolicyEffects->initDefaultDeviceEffects();
}
void AudioPolicyService::unloadAudioPolicyManager()
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index bd56366..7aa80cf 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -322,6 +322,9 @@
// RefBase
virtual void onFirstRef();
+ // Commence initialization when AudioSystem is ready.
+ void onAudioSystemReady();
+
//
// Helpers for the struct audio_policy_service_ops implementation.
// This is used by the audio policy manager for certain operations that
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index dbc48ae..233a484 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -50,12 +50,12 @@
using aidl_utils::statusTFromBinderStatus;
using android::content::AttributionSourceState;
using binder::Status;
+using internal::ToString;
using media::HeadTrackingMode;
using media::Pose3f;
using media::SensorPoseProvider;
using media::audio::common::HeadTracking;
using media::audio::common::Spatialization;
-using ::android::internal::ToString;
using namespace std::chrono_literals;
@@ -349,7 +349,8 @@
bool activeLevelFound = false;
for (const auto spatializationLevel : spatializationLevels) {
if (!aidl_utils::isValidEnum(spatializationLevel)) {
- ALOGW("%s: ignoring spatializationLevel:%d", __func__, (int)spatializationLevel);
+ ALOGW("%s: ignoring spatializationLevel:%s", __func__,
+ ToString(spatializationLevel).c_str());
continue;
}
if (spatializationLevel == Spatialization::Level::NONE) {
@@ -376,7 +377,8 @@
for (const auto spatializationMode : spatializationModes) {
if (!aidl_utils::isValidEnum(spatializationMode)) {
- ALOGW("%s: ignoring spatializationMode:%d", __func__, (int)spatializationMode);
+ ALOGW("%s: ignoring spatializationMode:%s", __func__,
+ ToString(spatializationMode).c_str());
continue;
}
// we don't detect duplicates.
@@ -413,27 +415,26 @@
return BAD_VALUE;
}
- //TODO b/273373363: use AIDL enum when available
if (com::android::media::audio::dsa_over_bt_le_audio()
&& mSupportsHeadTracking) {
- mHeadtrackingConnectionMode = HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED;
- std::vector<uint8_t> headtrackingConnectionModes;
+ mHeadtrackingConnectionMode = HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED;
+ std::vector<HeadTracking::ConnectionMode> headtrackingConnectionModes;
status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_HEADTRACKING_CONNECTION,
&headtrackingConnectionModes);
if (status == NO_ERROR) {
for (const auto htConnectionMode : headtrackingConnectionModes) {
- if (htConnectionMode < HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED ||
- htConnectionMode > HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_TUNNEL) {
- ALOGW("%s: ignoring HT connection mode:%d", __func__, (int)htConnectionMode);
+ if (htConnectionMode < HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED ||
+ htConnectionMode > HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_TUNNEL) {
+ ALOGW("%s: ignoring HT connection mode:%s", __func__,
+ ToString(htConnectionMode).c_str());
continue;
}
- mSupportedHeadtrackingConnectionModes.insert(
- static_cast<headtracking_connection_t> (htConnectionMode));
+ mSupportedHeadtrackingConnectionModes.insert(htConnectionMode);
}
ALOGW_IF(mSupportedHeadtrackingConnectionModes.find(
- HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED)
- == mSupportedHeadtrackingConnectionModes.end(),
- "%s: HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED not reported", __func__);
+ HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED) ==
+ mSupportedHeadtrackingConnectionModes.end(),
+ "%s: Headtracking FRAMEWORK_PROCESSED not reported", __func__);
}
}
@@ -560,12 +561,12 @@
}
audio_utils::lock_guard lock(mMutex);
*level = mLevel;
- ALOGV("%s level %d", __func__, (int)*level);
+ ALOGV("%s level %s", __func__, ToString(*level).c_str());
return Status::ok();
}
Status Spatializer::isHeadTrackingSupported(bool *supports) {
- ALOGV("%s mSupportsHeadTracking %d", __func__, mSupportsHeadTracking);
+ ALOGV("%s mSupportsHeadTracking %s", __func__, ToString(mSupportsHeadTracking).c_str());
if (supports == nullptr) {
return binderStatusFromStatusT(BAD_VALUE);
}
@@ -860,7 +861,7 @@
}
void Spatializer::onActualModeChange(HeadTrackingMode mode) {
- std::string modeStr = media::toString(mode);
+ std::string modeStr = ToString(mode);
ALOGV("%s(%s)", __func__, modeStr.c_str());
sp<AMessage> msg = new AMessage(EngineCallbackHandler::kWhatOnActualModeChange, mHandler);
msg->setInt32(EngineCallbackHandler::kModeKey, static_cast<int>(mode));
@@ -868,7 +869,7 @@
}
void Spatializer::onActualModeChangeMsg(HeadTrackingMode mode) {
- ALOGV("%s(%d)", __func__, (int) mode);
+ ALOGV("%s(%s)", __func__, ToString(mode).c_str());
sp<media::ISpatializerHeadTrackingCallback> callback;
HeadTracking::Mode spatializerMode;
{
@@ -887,7 +888,7 @@
spatializerMode = HeadTracking::Mode::RELATIVE_SCREEN;
break;
default:
- LOG_ALWAYS_FATAL("Unknown mode: %d", static_cast<int>(mode));
+ LOG_ALWAYS_FATAL("Unknown mode: %s", ToString(mode).c_str());
}
}
mActualHeadTrackingMode = spatializerMode;
@@ -901,7 +902,7 @@
}
}
callback = mHeadTrackingCallback;
- mLocalLog.log("%s: updating mode to %s", __func__, media::toString(mode).c_str());
+ mLocalLog.log("%s: updating mode to %s", __func__, ToString(mode).c_str());
}
if (callback != nullptr) {
callback->onHeadTrackingModeChanged(spatializerMode);
@@ -1059,24 +1060,23 @@
}
}
-//TODO b/273373363: use AIDL enum when available
audio_latency_mode_t Spatializer::selectHeadtrackingConnectionMode_l() {
if (!com::android::media::audio::dsa_over_bt_le_audio()) {
return AUDIO_LATENCY_MODE_LOW;
}
// mSupportedLatencyModes is ordered according to system preferences loaded in
// mOrderedLowLatencyModes
- mHeadtrackingConnectionMode = HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED;
+ mHeadtrackingConnectionMode = HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED;
audio_latency_mode_t requestedLatencyMode = mSupportedLatencyModes[0];
if (requestedLatencyMode == AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
if (mSupportedHeadtrackingConnectionModes.find(
- HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_TUNNEL)
+ HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_TUNNEL)
!= mSupportedHeadtrackingConnectionModes.end()) {
- mHeadtrackingConnectionMode = HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_TUNNEL;
+ mHeadtrackingConnectionMode = HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_TUNNEL;
} else if (mSupportedHeadtrackingConnectionModes.find(
- HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_SW)
+ HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_SW)
!= mSupportedHeadtrackingConnectionModes.end()) {
- mHeadtrackingConnectionMode = HEADTRACKING_CONNECTION_DIRECT_TO_SENSOR_SW;
+ mHeadtrackingConnectionMode = HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_SW;
} else {
// if the engine does not support direct reading of IMU data, do not allow
// DYNAMIC_SPATIAL_AUDIO_HARDWARE mode and fallback to next mode
@@ -1096,7 +1096,7 @@
}
void Spatializer::checkSensorsState_l() {
- audio_latency_mode_t requestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
+ mRequestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
const bool supportsSetLatencyMode = !mSupportedLatencyModes.empty();
bool supportsLowLatencyMode;
if (com::android::media::audio::dsa_over_bt_le_audio()) {
@@ -1117,7 +1117,7 @@
&& mDesiredHeadTrackingMode != HeadTrackingMode::STATIC
&& mHeadSensor != SpatializerPoseController::INVALID_SENSOR) {
if (supportsLowLatencyMode) {
- requestedLatencyMode = selectHeadtrackingConnectionMode_l();
+ mRequestedLatencyMode = selectHeadtrackingConnectionMode_l();
}
if (mEngine != nullptr) {
setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
@@ -1139,9 +1139,9 @@
}
if (mOutput != AUDIO_IO_HANDLE_NONE && supportsSetLatencyMode) {
const status_t status =
- AudioSystem::setRequestedLatencyMode(mOutput, requestedLatencyMode);
+ AudioSystem::setRequestedLatencyMode(mOutput, mRequestedLatencyMode);
ALOGD("%s: setRequestedLatencyMode for output thread(%d) to %s returned %d", __func__,
- mOutput, toString(requestedLatencyMode).c_str(), status);
+ mOutput, toString(mRequestedLatencyMode).c_str(), status);
}
}
@@ -1220,7 +1220,7 @@
base::StringAppendF(&ss, " %s", ToString(mode).c_str());
}
base::StringAppendF(&ss, "], Desired: %s, Actual %s\n",
- media::toString(mDesiredHeadTrackingMode).c_str(),
+ ToString(mDesiredHeadTrackingMode).c_str(),
ToString(mActualHeadTrackingMode).c_str());
base::StringAppendF(&ss, "%smSpatializationModes: [", prefixSpace.c_str());
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index 24788dc..c5f159c 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -27,6 +27,7 @@
#include <audio_utils/SimpleLog.h>
#include <math.h>
#include <media/AudioEffect.h>
+#include <media/MediaMetricsItem.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <media/VectorRecorder.h>
#include <media/audiohal/EffectHalInterface.h>
@@ -153,6 +154,34 @@
return mLevel;
}
+ /** For test only */
+ std::unordered_set<media::audio::common::HeadTracking::ConnectionMode>
+ getSupportedHeadtrackingConnectionModes() const {
+ return mSupportedHeadtrackingConnectionModes;
+ }
+
+ /** For test only */
+ media::audio::common::HeadTracking::ConnectionMode getHeadtrackingConnectionMode() const {
+ return mHeadtrackingConnectionMode;
+ }
+
+ /** For test only */
+ std::vector<audio_latency_mode_t> getSupportedLatencyModes() const {
+ audio_utils::lock_guard lock(mMutex);
+ return mSupportedLatencyModes;
+ }
+
+ /** For test only */
+ std::vector<audio_latency_mode_t> getOrderedLowLatencyModes() const {
+ return mOrderedLowLatencyModes;
+ }
+
+ /** For test only */
+ audio_latency_mode_t getRequestedLatencyMode() const {
+ audio_utils::lock_guard lock(mMutex);
+ return mRequestedLatencyMode;
+ }
+
/** Called by audio policy service when the special output mixer dedicated to spatialization
* is opened and the spatializer engine must be created.
*/
@@ -164,6 +193,12 @@
/** Returns the output stream the spatializer is attached to. */
audio_io_handle_t getOutput() const { audio_utils::lock_guard lock(mMutex); return mOutput; }
+ /** For test only */
+ void setOutput(audio_io_handle_t output) {
+ audio_utils::lock_guard lock(mMutex);
+ mOutput = output;
+ }
+
void updateActiveTracks(size_t numActiveTracks);
/** Gets the channel mask, sampling rate and format set for the spatializer input. */
@@ -188,6 +223,10 @@
// NO_INIT: Spatializer creation failed.
static void sendEmptyCreateSpatializerMetricWithStatus(status_t status);
+ /** Made public for test only */
+ void onSupportedLatencyModesChangedMsg(
+ audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes);
+
private:
Spatializer(effect_descriptor_t engineDescriptor,
SpatializerPolicyCallback *callback);
@@ -200,8 +239,6 @@
void onHeadToStagePoseMsg(const std::vector<float>& headToStage);
void onActualModeChangeMsg(media::HeadTrackingMode mode);
- void onSupportedLatencyModesChangedMsg(
- audio_io_handle_t output, std::vector<audio_latency_mode_t>&& modes);
static constexpr int kMaxEffectParamValues = 10;
/**
@@ -484,13 +521,17 @@
std::vector<media::audio::common::Spatialization::Mode> mSpatializationModes;
std::vector<audio_channel_mask_t> mChannelMasks;
bool mSupportsHeadTracking;
- /** List of supported headtracking connection modes reported by the spatializer.
+
+ /** List of supported head tracking connection modes reported by the spatializer.
* If the list is empty, the spatializer does not support any optional connection
- * mode and mode HEADTRACKING_CONNECTION_FRAMEWORK_PROCESSED is assumed.
+ * mode and mode HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED is assumed.
+ * This is set in the factory constructor and can be accessed without mutex.
*/
- std::unordered_set<headtracking_connection_t> mSupportedHeadtrackingConnectionModes;
+ std::unordered_set<media::audio::common::HeadTracking::ConnectionMode>
+ mSupportedHeadtrackingConnectionModes;
/** Selected HT connection mode when several modes are supported by the spatializer */
- headtracking_connection_t mHeadtrackingConnectionMode;
+ media::audio::common::HeadTracking::ConnectionMode mHeadtrackingConnectionMode =
+ media::audio::common::HeadTracking::ConnectionMode::FRAMEWORK_PROCESSED;
// Looper thread for mEngine callbacks
class EngineCallbackHandler;
@@ -502,6 +543,9 @@
std::vector<audio_latency_mode_t> mSupportedLatencyModes GUARDED_BY(mMutex);
/** preference order for low latency modes according to persist.bluetooth.hid.transport */
std::vector<audio_latency_mode_t> mOrderedLowLatencyModes;
+
+ audio_latency_mode_t mRequestedLatencyMode GUARDED_BY(mMutex) = AUDIO_LATENCY_MODE_FREE;
+
/** string to latency mode map used to parse bluetooth.core.le.dsa_transport_preference */
static const std::map<std::string, audio_latency_mode_t> sStringToLatencyModeMap;
static const std::vector<const char*> sHeadPoseKeys;
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 34bd3b4..21ded60 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -108,3 +108,40 @@
test_suites: ["device-tests"],
}
+
+cc_test {
+ name: "spatializer_tests",
+
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ "libaudiopolicyservice_dependencies",
+ ],
+
+ require_root: true,
+
+ shared_libs: [
+ "libaudioclient",
+ "libaudiofoundation",
+ "libcutils",
+ "liblog",
+ ],
+
+ static_libs: [
+ "libaudiopolicyservice",
+ ],
+
+ header_libs: [
+ "libaudiohal_headers",
+ "libaudiopolicyservice_headers",
+ "libmediametrics_headers",
+ ],
+
+ srcs: ["spatializer_tests.cpp"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index e883e10..afd8765 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1330,6 +1330,10 @@
std::string mixAddress, const audio_config_t& audioConfig,
const std::vector<AudioMixMatchCriterion>& matchCriteria);
+ status_t addPolicyMix(const AudioMix& mix);
+
+ status_t removePolicyMixes(const Vector<AudioMix>& mixes);
+
std::vector<AudioMix> getRegisteredPolicyMixes();
void clearPolicyMix();
void addPolicyMixAndStartInputForLoopback(
@@ -1365,9 +1369,14 @@
AudioMix myAudioMix(matchCriteria, mixType, audioConfig, mixFlag,
String8(mixAddress.c_str()), 0);
myAudioMix.mDeviceType = deviceType;
+ myAudioMix.mToken = sp<BBinder>::make();
// Clear mAudioMix before add new one to make sure we don't add already exist mixes.
mAudioMixes.clear();
- mAudioMixes.add(myAudioMix);
+ return addPolicyMix(myAudioMix);
+}
+
+status_t AudioPolicyManagerTestDynamicPolicy::addPolicyMix(const AudioMix& mix) {
+ mAudioMixes.add(mix);
// As the policy mixes registration may fail at some case,
// caller need to check the returned status.
@@ -1375,6 +1384,11 @@
return ret;
}
+status_t AudioPolicyManagerTestDynamicPolicy::removePolicyMixes(const Vector<AudioMix>& mixes) {
+ status_t ret = mManager->unregisterPolicyMixes(mixes);
+ return ret;
+}
+
std::vector<AudioMix> AudioPolicyManagerTestDynamicPolicy::getRegisteredPolicyMixes() {
std::vector<AudioMix> audioMixes;
if (mManager != nullptr) {
@@ -1539,6 +1553,95 @@
TEST_F_WITH_FLAGS(
AudioPolicyManagerTestDynamicPolicy,
+ RegisterInvalidMixesDoesNotImpactPriorMixes,
+ REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(android::media::audiopolicy, audio_mix_test_api),
+ ACONFIG_FLAG(android::media::audiopolicy, audio_mix_ownership))
+) {
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+
+ std::vector<AudioMixMatchCriterion> validMixMatchCriteria = {
+ createUidCriterion(/*uid=*/42),
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/true)};
+ AudioMix validAudioMix(validMixMatchCriteria, MIX_TYPE_PLAYERS, audioConfig,
+ MIX_ROUTE_FLAG_LOOP_BACK, String8(mMixAddress.c_str()), 0);
+ validAudioMix.mDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+
+ mAudioMixes.clear();
+ status_t ret = addPolicyMix(validAudioMix);
+
+ ASSERT_EQ(NO_ERROR, ret);
+
+ std::vector<AudioMix> registeredMixes = getRegisteredPolicyMixes();
+ ASSERT_EQ(1, registeredMixes.size());
+
+ std::vector<AudioMixMatchCriterion> invalidMixMatchCriteria = {
+ createUidCriterion(/*uid=*/42),
+ createUidCriterion(/*uid=*/1235, /*exclude=*/true),
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/true)};
+
+ AudioMix invalidAudioMix(invalidMixMatchCriteria, MIX_TYPE_PLAYERS, audioConfig,
+ MIX_ROUTE_FLAG_LOOP_BACK, String8(mMixAddress.c_str()), 0);
+ validAudioMix.mDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+
+ ret = addPolicyMix(invalidAudioMix);
+
+ ASSERT_EQ(INVALID_OPERATION, ret);
+
+ std::vector<AudioMix> remainingMixes = getRegisteredPolicyMixes();
+ ASSERT_EQ(registeredMixes.size(), remainingMixes.size());
+}
+
+TEST_F_WITH_FLAGS(
+ AudioPolicyManagerTestDynamicPolicy,
+ UnregisterInvalidMixesReturnsError,
+ REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(android::media::audiopolicy, audio_mix_test_api),
+ ACONFIG_FLAG(android::media::audiopolicy, audio_mix_ownership))
+) {
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+
+ std::vector<AudioMixMatchCriterion> validMixMatchCriteria = {
+ createUidCriterion(/*uid=*/42),
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/true)};
+ AudioMix validAudioMix(validMixMatchCriteria, MIX_TYPE_PLAYERS, audioConfig,
+ MIX_ROUTE_FLAG_LOOP_BACK, String8(mMixAddress.c_str()), 0);
+ validAudioMix.mDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+
+ mAudioMixes.clear();
+ status_t ret = addPolicyMix(validAudioMix);
+
+ ASSERT_EQ(NO_ERROR, ret);
+
+ std::vector<AudioMix> registeredMixes = getRegisteredPolicyMixes();
+ ASSERT_EQ(1, registeredMixes.size());
+
+ std::vector<AudioMixMatchCriterion> invalidMixMatchCriteria = {
+ createUidCriterion(/*uid=*/42),
+ createUidCriterion(/*uid=*/1235, /*exclude=*/true),
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/true)};
+
+ AudioMix invalidAudioMix(invalidMixMatchCriteria, MIX_TYPE_PLAYERS, audioConfig,
+ MIX_ROUTE_FLAG_LOOP_BACK, String8(mMixAddress.c_str()), 0);
+ invalidAudioMix.mDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+
+ Vector<AudioMix> mixes;
+ mixes.add(invalidAudioMix);
+ mixes.add(validAudioMix);
+ ret = removePolicyMixes(mixes);
+
+ ASSERT_EQ(INVALID_OPERATION, ret);
+
+ std::vector<AudioMix> remainingMixes = getRegisteredPolicyMixes();
+ EXPECT_THAT(remainingMixes, IsEmpty());
+}
+
+TEST_F_WITH_FLAGS(
+ AudioPolicyManagerTestDynamicPolicy,
GetRegisteredPolicyMixes,
REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(android::media::audiopolicy, audio_mix_test_api))
) {
diff --git a/services/audiopolicy/tests/spatializer_tests.cpp b/services/audiopolicy/tests/spatializer_tests.cpp
new file mode 100644
index 0000000..73bef43
--- /dev/null
+++ b/services/audiopolicy/tests/spatializer_tests.cpp
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Spatializer_Test"
+
+#include "Spatializer.h"
+
+#include <string>
+#include <unordered_set>
+
+#include <gtest/gtest.h>
+
+#include <android/media/audio/common/AudioLatencyMode.h>
+#include <android/media/audio/common/HeadTracking.h>
+#include <android/media/audio/common/Spatialization.h>
+#include <com_android_media_audio.h>
+#include <utils/Log.h>
+
+using namespace android;
+using media::audio::common::HeadTracking;
+using media::audio::common::Spatialization;
+
+class TestSpatializerPolicyCallback :
+ public SpatializerPolicyCallback {
+public:
+ void onCheckSpatializer() override {};
+};
+
+class SpatializerTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ const sp<EffectsFactoryHalInterface> effectsFactoryHal
+ = EffectsFactoryHalInterface::create();
+ mSpatializer = Spatializer::create(&mTestCallback, effectsFactoryHal);
+ if (mSpatializer == nullptr) {
+ GTEST_SKIP() << "Skipping Spatializer tests: no spatializer";
+ }
+ std::vector<Spatialization::Level> levels;
+ binder::Status status = mSpatializer->getSupportedLevels(&levels);
+ ASSERT_TRUE(status.isOk());
+ for (auto level : levels) {
+ if (level != Spatialization::Level::NONE) {
+ mSpatializer->setLevel(level);
+ break;
+ }
+ }
+ mSpatializer->setOutput(sTestOutput);
+ }
+
+ void TearDown() override {
+ if (mSpatializer == nullptr) {
+ return;
+ }
+ mSpatializer->setLevel(Spatialization::Level::NONE);
+ mSpatializer->setOutput(AUDIO_IO_HANDLE_NONE);
+ mSpatializer->setDesiredHeadTrackingMode(HeadTracking::Mode::DISABLED);
+ mSpatializer->setHeadSensor(SpatializerPoseController::INVALID_SENSOR);
+ mSpatializer->updateActiveTracks(0);
+ }
+
+ static constexpr audio_io_handle_t sTestOutput= 1977;
+ static constexpr int sTestSensorHandle = 1980;
+
+ const static inline std::vector<audio_latency_mode_t> sA2DPLatencyModes = {
+ AUDIO_LATENCY_MODE_LOW,
+ AUDIO_LATENCY_MODE_FREE
+ };
+ const static inline std::vector<audio_latency_mode_t> sBLELatencyModes = {
+ AUDIO_LATENCY_MODE_LOW,
+ AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE,
+ AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE,
+ AUDIO_LATENCY_MODE_FREE
+ };
+
+ bool setpUpForHeadtracking() {
+ bool htSupported;
+ mSpatializer->isHeadTrackingSupported(&htSupported);
+ if (!htSupported) {
+ return false;
+ }
+
+ std::vector<HeadTracking::Mode> htModes;
+ mSpatializer->getSupportedHeadTrackingModes(&htModes);
+ for (auto htMode : htModes) {
+ if (htMode != HeadTracking::Mode::DISABLED) {
+ mSpatializer->setDesiredHeadTrackingMode(htMode);
+ break;
+ }
+ }
+
+ mSpatializer->setHeadSensor(sTestSensorHandle);
+ return true;
+ }
+
+ TestSpatializerPolicyCallback mTestCallback;
+ sp<Spatializer> mSpatializer;
+};
+
+TEST_F(SpatializerTest, SupportedA2dpLatencyTest) {
+ if (!setpUpForHeadtracking()) {
+ GTEST_SKIP() << "Skipping SupportedA2dpLatencyTest: head tracking not supported";
+ }
+ std::vector<audio_latency_mode_t> latencies = sA2DPLatencyModes;
+ mSpatializer->onSupportedLatencyModesChangedMsg(sTestOutput, std::move(latencies));
+
+ std::vector<audio_latency_mode_t> supportedLatencies =
+ mSpatializer->getSupportedLatencyModes();
+
+ ASSERT_TRUE(supportedLatencies == sA2DPLatencyModes);
+ // Free mode must always be the last of the ordered list
+ ASSERT_TRUE(supportedLatencies.back() == AUDIO_LATENCY_MODE_FREE);
+}
+
+TEST_F(SpatializerTest, SupportedBleLatencyTest) {
+ if (!setpUpForHeadtracking()) {
+ GTEST_SKIP() << "Skipping SupportedBleLatencyTest: head tracking not supported";
+ }
+ if (!com::android::media::audio::dsa_over_bt_le_audio()) {
+ GTEST_SKIP() << "Skipping SupportedBleLatencyTest: DSA over LE not enabled";
+ }
+ std::vector<audio_latency_mode_t> latencies = sBLELatencyModes;
+ mSpatializer->onSupportedLatencyModesChangedMsg(sTestOutput, std::move(latencies));
+
+ std::vector<audio_latency_mode_t> supportedLatencies =
+ mSpatializer->getSupportedLatencyModes();
+
+ ASSERT_TRUE(supportedLatencies.back() == AUDIO_LATENCY_MODE_FREE);
+ ASSERT_TRUE(std::find(supportedLatencies.begin(), supportedLatencies.end(),
+ AUDIO_LATENCY_MODE_LOW) != supportedLatencies.end());
+
+ std::vector<audio_latency_mode_t> orderedLowLatencyModes =
+ mSpatializer->getOrderedLowLatencyModes();
+
+ std::vector<audio_latency_mode_t> supportedLowLatencyModes;
+ // remove free mode at the end of the supported list to only retain low latency modes
+ std::copy(supportedLatencies.begin(),
+ supportedLatencies.begin() + supportedLatencies.size() - 1,
+ std::back_inserter(supportedLowLatencyModes));
+
+ // Verify that supported low latency modes are always in ordered latency modes list and
+ // in the same order
+ std::vector<audio_latency_mode_t>::iterator lastIt = orderedLowLatencyModes.begin();
+ for (auto latency : supportedLowLatencyModes) {
+ auto it = std::find(orderedLowLatencyModes.begin(), orderedLowLatencyModes.end(), latency);
+ ASSERT_NE(it, orderedLowLatencyModes.end());
+ ASSERT_LE(lastIt, it);
+ lastIt = it;
+ }
+}
+
+TEST_F(SpatializerTest, RequestedA2dpLatencyTest) {
+ if (!setpUpForHeadtracking()) {
+ GTEST_SKIP() << "Skipping RequestedA2dpLatencyTest: head tracking not supported";
+ }
+
+ std::vector<audio_latency_mode_t> latencies = sA2DPLatencyModes;
+ mSpatializer->onSupportedLatencyModesChangedMsg(sTestOutput, std::move(latencies));
+
+ // requested latency mode must be free if no spatialized tracks are active
+ audio_latency_mode_t requestedLatencyMode = mSpatializer->getRequestedLatencyMode();
+ ASSERT_EQ(requestedLatencyMode, AUDIO_LATENCY_MODE_FREE);
+
+ // requested latency mode must be low if at least one spatialized tracks is active
+ mSpatializer->updateActiveTracks(1);
+ requestedLatencyMode = mSpatializer->getRequestedLatencyMode();
+ ASSERT_EQ(requestedLatencyMode, AUDIO_LATENCY_MODE_LOW);
+
+ // requested latency mode must be free after stopping the last spatialized tracks
+ mSpatializer->updateActiveTracks(0);
+ requestedLatencyMode = mSpatializer->getRequestedLatencyMode();
+ ASSERT_EQ(requestedLatencyMode, AUDIO_LATENCY_MODE_FREE);
+}
+
+TEST_F(SpatializerTest, RequestedBleLatencyTest) {
+ if (!setpUpForHeadtracking()) {
+ GTEST_SKIP() << "Skipping RequestedBleLatencyTest: head tracking not supported";
+ }
+ if (!com::android::media::audio::dsa_over_bt_le_audio()) {
+ GTEST_SKIP() << "Skipping RequestedBleLatencyTest: DSA over LE not enabled";
+ }
+
+ mSpatializer->onSupportedLatencyModesChangedMsg(sTestOutput,
+ { AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE,
+ AUDIO_LATENCY_MODE_FREE });
+
+ // requested latency mode must be free if no spatialized tracks are active
+ audio_latency_mode_t requestedLatencyMode = mSpatializer->getRequestedLatencyMode();
+ ASSERT_EQ(requestedLatencyMode, AUDIO_LATENCY_MODE_FREE);
+
+ // requested latency mode must be low software if at least one spatialized tracks is active
+ // and the only supported low latency mode is low software
+ mSpatializer->updateActiveTracks(1);
+ requestedLatencyMode = mSpatializer->getRequestedLatencyMode();
+ ASSERT_EQ(requestedLatencyMode, AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE);
+
+ mSpatializer->onSupportedLatencyModesChangedMsg(sTestOutput,
+ { AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE,
+ AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE,
+ AUDIO_LATENCY_MODE_FREE });
+
+ requestedLatencyMode = mSpatializer->getRequestedLatencyMode();
+ HeadTracking::ConnectionMode connectionMode = mSpatializer->getHeadtrackingConnectionMode();
+
+ // If low hardware mode is used, the spatializer must use either use one of the sensor
+ // connection tunneled modes.
+ // Otherwise, low software mode must be used
+ if (requestedLatencyMode == AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
+ ASSERT_TRUE(connectionMode == HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_TUNNEL
+ || connectionMode == HeadTracking::ConnectionMode::DIRECT_TO_SENSOR_SW);
+ } else {
+ ASSERT_EQ(requestedLatencyMode, AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE);
+ }
+
+ // requested latency mode must be free after stopping the last spatialized tracks
+ mSpatializer->updateActiveTracks(0);
+ requestedLatencyMode = mSpatializer->getRequestedLatencyMode();
+ ASSERT_EQ(requestedLatencyMode, AUDIO_LATENCY_MODE_FREE);
+}
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index b748888..c9e9090 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -263,7 +263,7 @@
"liblog",
"libutils",
"libxml2",
- "camera_platform_flags_c_lib"
+ "camera_platform_flags_c_lib",
],
include_dirs: [
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index ebe771e..78c14b2 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -155,17 +155,18 @@
CameraService::CameraService(
std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils) :
+ AttributionAndPermissionUtilsEncapsulator(attributionAndPermissionUtils == nullptr ?
+ std::make_shared<AttributionAndPermissionUtils>()\
+ : attributionAndPermissionUtils),
mCameraServiceProxyWrapper(cameraServiceProxyWrapper == nullptr ?
std::make_shared<CameraServiceProxyWrapper>() : cameraServiceProxyWrapper),
- mAttributionAndPermissionUtils(attributionAndPermissionUtils == nullptr ?
- std::make_shared<AttributionAndPermissionUtils>(this)\
- : attributionAndPermissionUtils),
mEventLog(DEFAULT_EVENT_LOG_LENGTH),
mNumberOfCameras(0),
mNumberOfCamerasWithoutSystemCamera(0),
mSoundRef(0), mInitialized(false),
mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) {
ALOGI("CameraService started (pid=%d)", getpid());
+ mAttributionAndPermissionUtils->setCameraService(this);
mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
mMemFd = memfd_create(sFileName, MFD_ALLOW_SEALING);
if (mMemFd == -1) {
@@ -707,14 +708,6 @@
broadcastTorchModeStatus(cameraId, newStatus, systemCameraKind);
}
-bool CameraService::isAutomotiveDevice() const {
- return mAttributionAndPermissionUtils->isAutomotiveDevice();
-}
-
-bool CameraService::isAutomotivePrivilegedClient(int32_t uid) const {
- return mAttributionAndPermissionUtils->isAutomotivePrivilegedClient(uid);
-}
-
bool CameraService::isAutomotiveExteriorSystemCamera(const std::string& cam_id) const {
// Returns false if this is not an automotive device type.
if (!isAutomotiveDevice())
@@ -760,49 +753,6 @@
return true;
}
-static AttributionSourceState attributionSourceFromPidAndUid(int callingPid, int callingUid) {
- AttributionSourceState attributionSource{};
- attributionSource.pid = callingPid;
- attributionSource.uid = callingUid;
- return attributionSource;
-}
-
-bool CameraService::hasPermissionsForCamera(int callingPid, int callingUid) const {
- return hasPermissionsForCamera(std::string(), callingPid, callingUid);
-}
-
-bool CameraService::hasPermissionsForCamera(const std::string& cameraId, int callingPid,
- int callingUid) const {
- auto attributionSource = attributionSourceFromPidAndUid(callingPid, callingUid);
- return mAttributionAndPermissionUtils->hasPermissionsForCamera(cameraId, attributionSource);
-}
-
-bool CameraService::hasPermissionsForSystemCamera(const std::string& cameraId, int callingPid,
- int callingUid, bool checkCameraPermissions) const {
- auto attributionSource = attributionSourceFromPidAndUid(callingPid, callingUid);
- return mAttributionAndPermissionUtils->hasPermissionsForSystemCamera(
- cameraId, attributionSource, checkCameraPermissions);
-}
-
-bool CameraService::hasPermissionsForCameraHeadlessSystemUser(const std::string& cameraId,
- int callingPid, int callingUid) const {
- auto attributionSource = attributionSourceFromPidAndUid(callingPid, callingUid);
- return mAttributionAndPermissionUtils->hasPermissionsForCameraHeadlessSystemUser(
- cameraId, attributionSource);
-}
-
-bool CameraService::hasPermissionsForCameraPrivacyAllowlist(int callingPid, int callingUid) const {
- auto attributionSource = attributionSourceFromPidAndUid(callingPid, callingUid);
- return mAttributionAndPermissionUtils->hasPermissionsForCameraPrivacyAllowlist(
- attributionSource);
-}
-
-bool CameraService::hasPermissionsForOpenCloseListener(int callingPid, int callingUid) const {
- auto attributionSource = attributionSourceFromPidAndUid(callingPid, callingUid);
- return mAttributionAndPermissionUtils->hasPermissionsForOpenCloseListener(
- attributionSource);
-}
-
Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) {
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
@@ -1353,6 +1303,7 @@
int32_t* torchStrength) {
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
+
const std::string cameraId = resolveCameraId(
unresolvedCameraId, CameraThreadState::getCallingUid());
if (!mInitialized) {
@@ -1681,16 +1632,6 @@
return STATUS_ERROR(ERROR_INVALID_OPERATION, "Unable to initialize legacy parameters");
}
-// Can camera service trust the caller based on the calling UID?
-bool CameraService::isTrustedCallingUid(uid_t uid) const {
- return mAttributionAndPermissionUtils->isTrustedCallingUid(uid);
-}
-
-status_t CameraService::getUidForPackage(const std::string &packageName, int userId,
- /*inout*/uid_t& uid, int err) const {
- return mAttributionAndPermissionUtils->getUidForPackage(packageName, userId, uid, err);
-}
-
Status CameraService::validateConnectLocked(const std::string& cameraId,
const std::string& clientName8, /*inout*/int& clientUid, /*inout*/int& clientPid,
/*out*/int& originalClientPid) const {
@@ -1755,7 +1696,7 @@
"Untrusted caller (calling PID %d, UID %d) trying to "
"forward camera access to camera %s for client %s (PID %d, UID %d)",
callingPid, callingUid, cameraId.c_str(),
- clientName.c_str(), clientUid, clientPid);
+ clientName.c_str(), clientPid, clientUid);
}
// Check if we can trust clientPid
@@ -1768,7 +1709,7 @@
"Untrusted caller (calling PID %d, UID %d) trying to "
"forward camera access to camera %s for client %s (PID %d, UID %d)",
callingPid, callingUid, cameraId.c_str(),
- clientName.c_str(), clientUid, clientPid);
+ clientName.c_str(), clientPid, clientUid);
}
if (shouldRejectSystemCameraConnection(cameraId)) {
@@ -1788,13 +1729,14 @@
// If it's not calling from cameraserver, check the permission if the
// device isn't a system only camera (shouldRejectSystemCameraConnection already checks for
// android.permission.SYSTEM_CAMERA for system only camera devices).
- bool checkPermissionForCamera = hasPermissionsForCamera(cameraId, clientPid, clientUid);
+ bool checkPermissionForCamera =
+ hasPermissionsForCamera(cameraId, clientPid, clientUid, clientName);
if (callingPid != getpid() &&
(deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) && !checkPermissionForCamera) {
ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", clientPid, clientUid);
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
"Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" without camera permission",
- clientName.c_str(), clientUid, clientPid, cameraId.c_str());
+ clientName.c_str(), clientPid, clientUid, cameraId.c_str());
}
// Make sure the UID is in an active state to use the camera
@@ -1805,7 +1747,7 @@
return STATUS_ERROR_FMT(ERROR_DISABLED,
"Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" from background ("
"calling UID %d proc state %" PRId32 ")",
- clientName.c_str(), clientUid, clientPid, cameraId.c_str(),
+ clientName.c_str(), clientPid, clientUid, cameraId.c_str(),
callingUid, procState);
}
@@ -1818,7 +1760,7 @@
ALOGE("Access Denial: cannot use the camera when sensor privacy is enabled");
return STATUS_ERROR_FMT(ERROR_DISABLED,
"Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" when sensor privacy "
- "is enabled", clientName.c_str(), clientUid, clientPid, cameraId.c_str());
+ "is enabled", clientName.c_str(), clientPid, clientUid, cameraId.c_str());
}
// Only use passed in clientPid to check permission. Use calling PID as the client PID that's
@@ -1844,14 +1786,14 @@
// If the System User tries to access the camera when the device is running in
// headless system user mode, ensure that client has the required permission
// CAMERA_HEADLESS_SYSTEM_USER.
- if (mAttributionAndPermissionUtils->isHeadlessSystemUserMode()
+ if (isHeadlessSystemUserMode()
&& (clientUserId == USER_SYSTEM)
&& !hasPermissionsForCameraHeadlessSystemUser(cameraId, callingPid, callingUid)) {
ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", clientPid, clientUid);
return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
"Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" as Headless System \
User without camera headless system user permission",
- clientName.c_str(), clientUid, clientPid, cameraId.c_str());
+ clientName.c_str(), clientPid, clientUid, cameraId.c_str());
}
}
@@ -2212,7 +2154,7 @@
}
// (1) Cameraserver trying to connect, accept.
- if (mAttributionAndPermissionUtils->isCallerCameraServerNotDelegating()) {
+ if (isCallerCameraServerNotDelegating()) {
return false;
}
// (2)
@@ -2249,16 +2191,17 @@
sp<CameraDeviceClient> client = nullptr;
std::string clientPackageNameAdj = clientPackageName;
int callingPid = CameraThreadState::getCallingPid();
+ int callingUid = CameraThreadState::getCallingUid();
bool systemNativeClient = false;
if (doesClientHaveSystemUid() && (clientPackageNameAdj.size() == 0)) {
- std::string systemClient =
- fmt::sprintf("client.pid<%d>", CameraThreadState::getCallingPid());
+ std::string systemClient = fmt::sprintf("client.pid<%d>", callingPid);
clientPackageNameAdj = systemClient;
systemNativeClient = true;
}
+
const std::string cameraId = resolveCameraId(
unresolvedCameraId,
- CameraThreadState::getCallingUid(),
+ callingUid,
clientPackageNameAdj);
if (oomScoreOffset < 0) {
@@ -2271,7 +2214,6 @@
}
userid_t clientUserId = multiuser_get_user_id(clientUid);
- int callingUid = CameraThreadState::getCallingUid();
if (clientUid == USE_CALLING_UID) {
clientUserId = multiuser_get_user_id(callingUid);
}
@@ -2288,8 +2230,8 @@
// enforce system camera permissions
if (oomScoreOffset > 0
&& !hasPermissionsForSystemCamera(cameraId, callingPid,
- CameraThreadState::getCallingUid())
- && !isTrustedCallingUid(CameraThreadState::getCallingUid())) {
+ callingUid)
+ && !isTrustedCallingUid(callingUid)) {
std::string msg = fmt::sprintf("Cannot change the priority of a client %s pid %d for "
"camera id %s without SYSTEM_CAMERA permissions",
clientPackageNameAdj.c_str(), callingPid, cameraId.c_str());
@@ -2329,8 +2271,8 @@
const auto& mActivityManager = getActivityManager();
if (mActivityManager) {
mActivityManager->logFgsApiBegin(LOG_FGS_CAMERA_API,
- CameraThreadState::getCallingUid(),
- CameraThreadState::getCallingPid());
+ callingUid,
+ callingPid);
}
return ret;
}
@@ -2353,12 +2295,8 @@
return true;
} else if (mSensorPrivacyPolicy->getCameraPrivacyState() == SensorPrivacyManager::DISABLED) {
return false;
- } else if ((mSensorPrivacyPolicy->getCameraPrivacyState()
- == SensorPrivacyManager::AUTOMOTIVE_DRIVER_ASSISTANCE_HELPFUL_APPS) ||
- (mSensorPrivacyPolicy->getCameraPrivacyState()
- == SensorPrivacyManager::AUTOMOTIVE_DRIVER_ASSISTANCE_REQUIRED_APPS) ||
- (mSensorPrivacyPolicy->getCameraPrivacyState() ==
- SensorPrivacyManager::AUTOMOTIVE_DRIVER_ASSISTANCE_APPS)) {
+ } else if (mSensorPrivacyPolicy->getCameraPrivacyState()
+ == SensorPrivacyManager::ENABLED_EXCEPT_ALLOWLISTED_APPS) {
if (hasPermissionsForCameraPrivacyAllowlist(callingPid, callingUid)) {
return false;
} else {
@@ -4015,7 +3953,7 @@
const std::optional<std::string>& clientFeatureId, const std::string& cameraIdStr,
int cameraFacing, int sensorOrientation, int clientPid, uid_t clientUid,
int servicePid, bool overrideToPortrait):
- mAttributionAndPermissionUtils(attributionAndPermissionUtils),
+ AttributionAndPermissionUtilsEncapsulator(attributionAndPermissionUtils),
mDestructionStarted(false),
mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing), mOrientation(sensorOrientation),
mClientPackageName(clientPackageName), mSystemNativeClient(nativeClient),
@@ -4048,7 +3986,7 @@
mAppOpsManager = std::make_unique<AppOpsManager>();
}
- mUidIsTrusted = mAttributionAndPermissionUtils->isTrustedCallingUid(mClientUid);
+ mUidIsTrusted = isTrustedCallingUid(mClientUid);
}
CameraService::BasicClient::~BasicClient() {
@@ -4787,7 +4725,7 @@
}
hasCameraPrivacyFeature(); // Called so the result is cached
mSpm.addSensorPrivacyListener(this);
- if (mAttributionAndPermissionUtils->isAutomotiveDevice()) {
+ if (isAutomotiveDevice()) {
mSpm.addToggleSensorPrivacyListener(this);
}
mSensorPrivacyEnabled = mSpm.isSensorPrivacyEnabled();
@@ -4827,7 +4765,7 @@
void CameraService::SensorPrivacyPolicy::unregisterSelf() {
Mutex::Autolock _l(mSensorPrivacyLock);
mSpm.removeSensorPrivacyListener(this);
- if (mAttributionAndPermissionUtils->isAutomotiveDevice()) {
+ if (isAutomotiveDevice()) {
mSpm.removeToggleSensorPrivacyListener(this);
}
mSpm.unlinkToDeath(this);
@@ -4903,9 +4841,7 @@
// if sensor privacy is enabled then block all clients from accessing the camera
if (state == SensorPrivacyManager::ENABLED) {
service->blockAllClients();
- } else if ((state == SensorPrivacyManager::AUTOMOTIVE_DRIVER_ASSISTANCE_APPS)
- || (state == SensorPrivacyManager::AUTOMOTIVE_DRIVER_ASSISTANCE_HELPFUL_APPS)
- || (state == SensorPrivacyManager::AUTOMOTIVE_DRIVER_ASSISTANCE_REQUIRED_APPS)) {
+ } else if (state == SensorPrivacyManager::ENABLED_EXCEPT_ALLOWLISTED_APPS) {
service->blockPrivacyEnabledClients();
}
return binder::Status::ok();
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 11cf1a1..1a887a1 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -78,7 +78,8 @@
public virtual ::android::hardware::BnCameraService,
public virtual IBinder::DeathRecipient,
public virtual CameraProviderManager::StatusListener,
- public virtual IServiceManager::LocalRegistrationCallback
+ public virtual IServiceManager::LocalRegistrationCallback,
+ public AttributionAndPermissionUtilsEncapsulator
{
friend class BinderService<CameraService>;
friend class CameraOfflineSessionClient;
@@ -317,13 +318,6 @@
// Shared utilities
static binder::Status filterGetInfoErrorCode(status_t err);
- bool isAutomotiveDevice() const;
-
- /**
- * Returns true if the client has uid AID_AUTOMOTIVE_EVS and the device is an automotive device.
- */
- bool isAutomotivePrivilegedClient(int32_t uid) const;
-
/**
* Returns true if the device is an automotive device and cameraId is system
* only camera which has characteristic AUTOMOTIVE_LOCATION value as either
@@ -335,7 +329,9 @@
/////////////////////////////////////////////////////////////////////
// CameraClient functionality
- class BasicClient : public virtual RefBase {
+ class BasicClient :
+ public virtual RefBase,
+ public AttributionAndPermissionUtilsEncapsulator {
friend class CameraService;
public:
virtual status_t initialize(sp<CameraProviderManager> manager,
@@ -460,8 +456,6 @@
virtual ~BasicClient();
- std::shared_ptr<AttributionAndPermissionUtils> mAttributionAndPermissionUtils;
-
// the instance is in the middle of destruction. When this is set,
// the instance should not be accessed from callback.
// CameraService's mClientLock should be acquired to access this.
@@ -681,20 +675,6 @@
return activityManager;
}
- bool hasPermissionsForCamera(int callingPid, int callingUid) const;
-
- bool hasPermissionsForCamera(const std::string& cameraId, int callingPid, int callingUid) const;
-
- bool hasPermissionsForSystemCamera(const std::string& cameraId, int callingPid, int callingUid,
- bool checkCameraPermissions = true) const;
-
- bool hasPermissionsForCameraHeadlessSystemUser(const std::string& cameraId, int callingPid,
- int callingUid) const;
-
- bool hasPermissionsForCameraPrivacyAllowlist(int callingPid, int callingUid) const;
-
- bool hasPermissionsForOpenCloseListener(int callingPid, int callingUid) const;
-
/**
* Typesafe version of device status, containing both the HAL-layer and the service interface-
* layer values.
@@ -879,12 +859,13 @@
// prevented from accessing the camera.
class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener,
public virtual IBinder::DeathRecipient,
- public virtual IServiceManager::LocalRegistrationCallback {
+ public virtual IServiceManager::LocalRegistrationCallback,
+ public AttributionAndPermissionUtilsEncapsulator {
public:
explicit SensorPrivacyPolicy(wp<CameraService> service,
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils)
- : mService(service),
- mAttributionAndPermissionUtils(attributionAndPermissionUtils),
+ : AttributionAndPermissionUtilsEncapsulator(attributionAndPermissionUtils),
+ mService(service),
mSensorPrivacyEnabled(false),
mCameraPrivacyState(SensorPrivacyManager::DISABLED), mRegistered(false) {}
@@ -909,7 +890,6 @@
private:
SensorPrivacyManager mSpm;
wp<CameraService> mService;
- std::shared_ptr<AttributionAndPermissionUtils> mAttributionAndPermissionUtils;
Mutex mSensorPrivacyLock;
bool mSensorPrivacyEnabled;
int mCameraPrivacyState;
@@ -924,7 +904,6 @@
sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper;
- std::shared_ptr<AttributionAndPermissionUtils> mAttributionAndPermissionUtils;
// Delay-load the Camera HAL module
virtual void onFirstRef();
@@ -937,11 +916,6 @@
void addStates(const std::string& id);
void removeStates(const std::string& id);
- bool isTrustedCallingUid(uid_t uid) const;
-
- status_t getUidForPackage(const std::string &packageName, int userId,
- /*inout*/uid_t& uid, int err) const;
-
// Check if we can connect, before we acquire the service lock.
// The returned originalClientPid is the PID of the original process that wants to connect to
// camera.
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index ac4b039..fa063b8 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1060,7 +1060,7 @@
static const nsecs_t kRequestTimeout = 50e6; // 50 ms
// TODO: does this need to be adjusted for long exposure requests?
- static const nsecs_t kRequestSubmitTimeout = 200e6; // 200 ms
+ static const nsecs_t kRequestSubmitTimeout = 500e6; // 500 ms
// Used to prepare a batch of requests.
struct NextRequest {
diff --git a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
index dc4cfb1..7f4a1bd 100644
--- a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
+++ b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
@@ -33,10 +33,13 @@
*/
class AttributionAndPermissionUtils {
public:
- AttributionAndPermissionUtils(wp<CameraService> cameraService) : mCameraService(cameraService)
- {}
+ AttributionAndPermissionUtils() { }
virtual ~AttributionAndPermissionUtils() {}
+ void setCameraService(wp<CameraService> cameraService) {
+ mCameraService = cameraService;
+ }
+
/**
* Pre-grants the permission if the attribution source uid is for an automotive
* privileged client. Otherwise uses system service permission checker to check
@@ -49,10 +52,18 @@
virtual bool checkPermissionForPreflight(const std::string &cameraId,
const std::string &permission, const AttributionSourceState& attributionSource,
const std::string& message, int32_t attributedOpCode);
+
+ // Can camera service trust the caller based on the calling UID?
virtual bool isTrustedCallingUid(uid_t uid);
+
virtual bool isAutomotiveDevice();
virtual bool isHeadlessSystemUserMode();
+
+ /**
+ * Returns true if the client has uid AID_AUTOMOTIVE_EVS and the device is an automotive device.
+ */
virtual bool isAutomotivePrivilegedClient(int32_t uid);
+
virtual status_t getUidForPackage(const std::string &packageName, int userId,
/*inout*/uid_t& uid, int err);
virtual bool isCallerCameraServerNotDelegating();
@@ -86,6 +97,107 @@
const AttributionSourceState &attributionSource);
};
+/**
+ * Class to be inherited by classes encapsulating AttributionAndPermissionUtils. Provides an
+ * additional utility layer above AttributionAndPermissionUtils calls, and avoids verbosity
+ * in the encapsulating class's methods.
+ */
+class AttributionAndPermissionUtilsEncapsulator {
+protected:
+ std::shared_ptr<AttributionAndPermissionUtils> mAttributionAndPermissionUtils;
+
+public:
+ AttributionAndPermissionUtilsEncapsulator(
+ std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils)
+ : mAttributionAndPermissionUtils(attributionAndPermissionUtils) { }
+
+ static AttributionSourceState buildAttributionSource(int callingPid, int callingUid) {
+ AttributionSourceState attributionSource{};
+ attributionSource.pid = callingPid;
+ attributionSource.uid = callingUid;
+ return attributionSource;
+ }
+
+ static AttributionSourceState buildAttributionSource(int callingPid, int callingUid,
+ const std::string& packageName) {
+ AttributionSourceState attributionSource = buildAttributionSource(callingPid, callingUid);
+ attributionSource.packageName = packageName;
+ return attributionSource;
+ }
+
+ bool hasPermissionsForCamera(int callingPid, int callingUid) const {
+ return hasPermissionsForCamera(std::string(), callingPid, callingUid);
+ }
+
+ bool hasPermissionsForCamera(int callingPid, int callingUid,
+ const std::string& packageName) const {
+ return hasPermissionsForCamera(std::string(), callingPid, callingUid, packageName);
+ }
+
+ bool hasPermissionsForCamera(const std::string& cameraId, int callingPid,
+ int callingUid) const {
+ auto attributionSource = buildAttributionSource(callingPid, callingUid);
+ return mAttributionAndPermissionUtils->hasPermissionsForCamera(cameraId, attributionSource);
+ }
+
+ bool hasPermissionsForCamera(const std::string& cameraId, int callingPid, int callingUid,
+ const std::string& packageName) const {
+ auto attributionSource = buildAttributionSource(callingPid, callingUid, packageName);
+ return mAttributionAndPermissionUtils->hasPermissionsForCamera(cameraId, attributionSource);
+ }
+
+ bool hasPermissionsForSystemCamera(const std::string& cameraId, int callingPid, int callingUid,
+ bool checkCameraPermissions = true) const {
+ auto attributionSource = buildAttributionSource(callingPid, callingUid);
+ return mAttributionAndPermissionUtils->hasPermissionsForSystemCamera(
+ cameraId, attributionSource, checkCameraPermissions);
+ }
+
+ bool hasPermissionsForCameraHeadlessSystemUser(const std::string& cameraId, int callingPid,
+ int callingUid) const {
+ auto attributionSource = buildAttributionSource(callingPid, callingUid);
+ return mAttributionAndPermissionUtils->hasPermissionsForCameraHeadlessSystemUser(
+ cameraId, attributionSource);
+ }
+
+ bool hasPermissionsForCameraPrivacyAllowlist(int callingPid, int callingUid) const {
+ auto attributionSource = buildAttributionSource(callingPid, callingUid);
+ return mAttributionAndPermissionUtils->hasPermissionsForCameraPrivacyAllowlist(
+ attributionSource);
+ }
+
+ bool hasPermissionsForOpenCloseListener(int callingPid, int callingUid) const {
+ auto attributionSource = buildAttributionSource(callingPid, callingUid);
+ return mAttributionAndPermissionUtils->hasPermissionsForOpenCloseListener(
+ attributionSource);
+ }
+
+ bool isAutomotiveDevice() const {
+ return mAttributionAndPermissionUtils->isAutomotiveDevice();
+ }
+
+ bool isAutomotivePrivilegedClient(int32_t uid) const {
+ return mAttributionAndPermissionUtils->isAutomotivePrivilegedClient(uid);
+ }
+
+ bool isTrustedCallingUid(uid_t uid) const {
+ return mAttributionAndPermissionUtils->isTrustedCallingUid(uid);
+ }
+
+ bool isHeadlessSystemUserMode() const {
+ return mAttributionAndPermissionUtils->isHeadlessSystemUserMode();
+ }
+
+ status_t getUidForPackage(const std::string &packageName, int userId,
+ /*inout*/uid_t& uid, int err) const {
+ return mAttributionAndPermissionUtils->getUidForPackage(packageName, userId, uid, err);
+ }
+
+ bool isCallerCameraServerNotDelegating() const {
+ return mAttributionAndPermissionUtils->isCallerCameraServerNotDelegating();
+ }
+};
+
} // namespace android
#endif // ANDROID_SERVERS_CAMERA_ATTRIBUTION_AND_PERMISSION_UTILS_H
diff --git a/services/camera/virtualcamera/VirtualCameraDevice.cc b/services/camera/virtualcamera/VirtualCameraDevice.cc
index 7636cbd..ddb245a 100644
--- a/services/camera/virtualcamera/VirtualCameraDevice.cc
+++ b/services/camera/virtualcamera/VirtualCameraDevice.cc
@@ -124,9 +124,9 @@
kOutputFormats.end();
}
-std::vector<MetadataBuilder::FpsRange> fpsRangesForInputConfig(
+std::vector<FpsRange> fpsRangesForInputConfig(
const std::vector<SupportedStreamConfiguration>& configs) {
- std::set<MetadataBuilder::FpsRange> availableRanges;
+ std::set<FpsRange> availableRanges;
for (const SupportedStreamConfiguration& config : configs) {
availableRanges.insert({.minFps = kMinFps, .maxFps = config.maxFps});
@@ -141,8 +141,7 @@
availableRanges.insert({.minFps = 30, .maxFps = 30});
}
- return std::vector<MetadataBuilder::FpsRange>(availableRanges.begin(),
- availableRanges.end());
+ return std::vector<FpsRange>(availableRanges.begin(), availableRanges.end());
}
std::optional<Resolution> getMaxResolution(
@@ -301,14 +300,41 @@
ANDROID_JPEG_THUMBNAIL_QUALITY,
ANDROID_NOISE_REDUCTION_MODE,
ANDROID_STATISTICS_FACE_DETECT_MODE})
- .setAvailableResultKeys(
- {ANDROID_COLOR_CORRECTION_ABERRATION_MODE, ANDROID_CONTROL_AE_MODE,
- ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, ANDROID_CONTROL_AF_MODE,
- ANDROID_CONTROL_AWB_MODE, ANDROID_CONTROL_EFFECT_MODE,
- ANDROID_CONTROL_MODE, ANDROID_FLASH_MODE, ANDROID_FLASH_STATE,
- ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, ANDROID_JPEG_QUALITY,
- ANDROID_JPEG_THUMBNAIL_QUALITY, ANDROID_LENS_FOCAL_LENGTH,
- ANDROID_SENSOR_TIMESTAMP, ANDROID_NOISE_REDUCTION_MODE})
+ .setAvailableResultKeys({
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+ ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+ ANDROID_CONTROL_AE_LOCK,
+ ANDROID_CONTROL_AE_MODE,
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+ ANDROID_CONTROL_AE_STATE,
+ ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+ ANDROID_CONTROL_AF_MODE,
+ ANDROID_CONTROL_AF_STATE,
+ ANDROID_CONTROL_AF_TRIGGER,
+ ANDROID_CONTROL_AWB_LOCK,
+ ANDROID_CONTROL_AWB_MODE,
+ ANDROID_CONTROL_AWB_STATE,
+ ANDROID_CONTROL_CAPTURE_INTENT,
+ ANDROID_CONTROL_EFFECT_MODE,
+ ANDROID_CONTROL_MODE,
+ ANDROID_CONTROL_SCENE_MODE,
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+ ANDROID_STATISTICS_FACE_DETECT_MODE,
+ ANDROID_FLASH_MODE,
+ ANDROID_FLASH_STATE,
+ ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+ ANDROID_JPEG_QUALITY,
+ ANDROID_JPEG_THUMBNAIL_QUALITY,
+ ANDROID_LENS_FOCAL_LENGTH,
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+ ANDROID_NOISE_REDUCTION_MODE,
+ ANDROID_REQUEST_PIPELINE_DEPTH,
+ ANDROID_SENSOR_TIMESTAMP,
+ ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+ ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+ ANDROID_STATISTICS_SCENE_FLICKER,
+ })
.setAvailableCapabilities(
{ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE});
diff --git a/services/camera/virtualcamera/VirtualCameraDevice.h b/services/camera/virtualcamera/VirtualCameraDevice.h
index c274dc9..4c50041 100644
--- a/services/camera/virtualcamera/VirtualCameraDevice.h
+++ b/services/camera/virtualcamera/VirtualCameraDevice.h
@@ -24,6 +24,7 @@
#include "aidl/android/companion/virtualcamera/SupportedStreamConfiguration.h"
#include "aidl/android/companion/virtualcamera/VirtualCameraConfiguration.h"
#include "aidl/android/hardware/camera/device/BnCameraDevice.h"
+#include "system/camera_metadata.h"
#include "util/Util.h"
namespace android {
@@ -121,6 +122,9 @@
// Default JPEG compression quality.
static constexpr uint8_t kDefaultJpegQuality = 80;
+ static constexpr camera_metadata_enum_android_control_capture_intent_t
+ kDefaultCaptureIntent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+
private:
std::shared_ptr<VirtualCameraDevice> sharedFromThis();
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
index 9b0fc07..6e89b5f 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
@@ -92,30 +92,62 @@
const std::chrono::nanoseconds timestamp,
const RequestSettings& requestSettings,
const Resolution reportedSensorSize) {
- std::unique_ptr<CameraMetadata> metadata =
+ // All of the keys used in the response needs to be referenced in
+ // availableResultKeys in CameraCharacteristics (see initCameraCharacteristics
+ // in VirtualCameraDevice.cc).
+ MetadataBuilder builder =
MetadataBuilder()
.setAberrationCorrectionMode(
ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF)
+ .setControlAeAvailableAntibandingModes(
+ {ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF})
+ .setControlAeAntibandingMode(ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF)
+ .setControlAeExposureCompensation(0)
+ .setControlAeLockAvailable(false)
+ .setControlAeLock(ANDROID_CONTROL_AE_LOCK_OFF)
.setControlAeMode(ANDROID_CONTROL_AE_MODE_ON)
.setControlAePrecaptureTrigger(
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE)
+ .setControlAeState(ANDROID_CONTROL_AE_STATE_INACTIVE)
.setControlAfMode(ANDROID_CONTROL_AF_MODE_OFF)
+ .setControlAfTrigger(ANDROID_CONTROL_AF_TRIGGER_IDLE)
+ .setControlAfState(ANDROID_CONTROL_AF_STATE_INACTIVE)
.setControlAwbMode(ANDROID_CONTROL_AWB_MODE_AUTO)
+ .setControlAwbLock(ANDROID_CONTROL_AWB_LOCK_OFF)
+ .setControlAwbState(ANDROID_CONTROL_AWB_STATE_INACTIVE)
+ .setControlCaptureIntent(requestSettings.captureIntent)
.setControlEffectMode(ANDROID_CONTROL_EFFECT_MODE_OFF)
.setControlMode(ANDROID_CONTROL_MODE_AUTO)
+ .setControlSceneMode(ANDROID_CONTROL_SCENE_MODE_DISABLED)
+ .setControlVideoStabilizationMode(
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF)
.setCropRegion(0, 0, reportedSensorSize.width,
reportedSensorSize.height)
.setFaceDetectMode(ANDROID_STATISTICS_FACE_DETECT_MODE_OFF)
.setFlashState(ANDROID_FLASH_STATE_UNAVAILABLE)
+ .setFlashMode(ANDROID_FLASH_MODE_OFF)
.setFocalLength(VirtualCameraDevice::kFocalLength)
.setJpegQuality(requestSettings.jpegQuality)
.setJpegThumbnailSize(requestSettings.thumbnailResolution.width,
requestSettings.thumbnailResolution.height)
.setJpegThumbnailQuality(requestSettings.thumbnailJpegQuality)
+ .setLensOpticalStabilizationMode(
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF)
.setNoiseReductionMode(ANDROID_NOISE_REDUCTION_MODE_OFF)
.setPipelineDepth(kPipelineDepth)
.setSensorTimestamp(timestamp)
- .build();
+ .setStatisticsHotPixelMapMode(
+ ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF)
+ .setStatisticsLensShadingMapMode(
+ ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF)
+ .setStatisticsSceneFlicker(ANDROID_STATISTICS_SCENE_FLICKER_NONE);
+
+ if (requestSettings.fpsRange.has_value()) {
+ builder.setControlAeTargetFpsRange(requestSettings.fpsRange.value());
+ }
+
+ std::unique_ptr<CameraMetadata> metadata = builder.build();
+
if (metadata == nullptr) {
ALOGE("%s: Failed to build capture result metadata", __func__);
return CameraMetadata();
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.h b/services/camera/virtualcamera/VirtualCameraRenderThread.h
index 86dad0b..e8e0bd4 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.h
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.h
@@ -33,6 +33,7 @@
#include "util/EglFramebuffer.h"
#include "util/EglProgram.h"
#include "util/EglSurfaceTexture.h"
+#include "util/MetadataUtil.h"
#include "util/Util.h"
namespace android {
@@ -58,6 +59,9 @@
int jpegQuality = VirtualCameraDevice::kDefaultJpegQuality;
Resolution thumbnailResolution = Resolution(0, 0);
int thumbnailJpegQuality = VirtualCameraDevice::kDefaultJpegQuality;
+ std::optional<FpsRange> fpsRange = {};
+ camera_metadata_enum_android_control_capture_intent_t captureIntent =
+ VirtualCameraDevice::kDefaultCaptureIntent;
};
// Represents single capture request to fill set of buffers.
diff --git a/services/camera/virtualcamera/VirtualCameraSession.cc b/services/camera/virtualcamera/VirtualCameraSession.cc
index 2a691c1..a0bb72e 100644
--- a/services/camera/virtualcamera/VirtualCameraSession.cc
+++ b/services/camera/virtualcamera/VirtualCameraSession.cc
@@ -148,7 +148,7 @@
.setControlMode(ANDROID_CONTROL_MODE_AUTO)
.setControlAeMode(ANDROID_CONTROL_AE_MODE_ON)
.setControlAeExposureCompensation(0)
- .setControlAeTargetFpsRange(maxFps, maxFps)
+ .setControlAeTargetFpsRange(FpsRange{maxFps, maxFps})
.setControlAeAntibandingMode(ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO)
.setControlAePrecaptureTrigger(
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE)
@@ -260,7 +260,10 @@
.thumbnailResolution =
getJpegThumbnailSize(metadata).value_or(Resolution(0, 0)),
.thumbnailJpegQuality = getJpegThumbnailQuality(metadata).value_or(
- VirtualCameraDevice::kDefaultJpegQuality)};
+ VirtualCameraDevice::kDefaultJpegQuality),
+ .fpsRange = getFpsRange(metadata),
+ .captureIntent = getCaptureIntent(metadata).value_or(
+ ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW)};
}
} // namespace
diff --git a/services/camera/virtualcamera/util/MetadataUtil.cc b/services/camera/virtualcamera/util/MetadataUtil.cc
index e3d9e28..119260f 100644
--- a/services/camera/virtualcamera/util/MetadataUtil.cc
+++ b/services/camera/virtualcamera/util/MetadataUtil.cc
@@ -23,6 +23,7 @@
#include <cstdint>
#include <iterator>
#include <memory>
+#include <optional>
#include <utility>
#include <variant>
#include <vector>
@@ -59,7 +60,7 @@
} // namespace
MetadataBuilder& MetadataBuilder::setSupportedHardwareLevel(
- camera_metadata_enum_android_info_supported_hardware_level_t hwLevel) {
+ const camera_metadata_enum_android_info_supported_hardware_level_t hwLevel) {
mEntryMap[ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL] =
asVectorOf<uint8_t>(hwLevel);
return *this;
@@ -86,7 +87,7 @@
}
MetadataBuilder& MetadataBuilder::setLensFacing(
- camera_metadata_enum_android_lens_facing lensFacing) {
+ const camera_metadata_enum_android_lens_facing lensFacing) {
mEntryMap[ANDROID_LENS_FACING] = asVectorOf<uint8_t>(lensFacing);
return *this;
}
@@ -175,6 +176,12 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlSceneMode(
+ const camera_metadata_enum_android_control_scene_mode sceneMode) {
+ mEntryMap[ANDROID_CONTROL_SCENE_MODE] = asVectorOf<uint8_t>(sceneMode);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlAvailableEffects(
const std::vector<camera_metadata_enum_android_control_effect_mode>&
availableEffects) {
@@ -198,6 +205,14 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlVideoStabilizationMode(
+ const camera_metadata_enum_android_control_video_stabilization_mode
+ stabilizationMode) {
+ mEntryMap[ANDROID_CONTROL_VIDEO_STABILIZATION_MODE] =
+ asVectorOf<uint8_t>(stabilizationMode);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlAfAvailableModes(
const std::vector<camera_metadata_enum_android_control_af_mode_t>&
availableModes) {
@@ -212,6 +227,12 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlAfState(
+ const camera_metadata_enum_android_control_af_state afState) {
+ mEntryMap[ANDROID_CONTROL_AF_STATE] = asVectorOf<uint8_t>(afState);
+ return *this;
+}
+
// See ANDROID_CONTROL_AF_TRIGGER_MODE in CameraMetadataTag.aidl.
MetadataBuilder& MetadataBuilder::setControlAfTrigger(
const camera_metadata_enum_android_control_af_trigger_t trigger) {
@@ -232,14 +253,14 @@
}
MetadataBuilder& MetadataBuilder::setControlAeTargetFpsRange(
- const int32_t minFps, const int32_t maxFps) {
+ const FpsRange fpsRange) {
mEntryMap[ANDROID_CONTROL_AE_TARGET_FPS_RANGE] =
- std::vector<int32_t>({minFps, maxFps});
+ std::vector<int32_t>({fpsRange.minFps, fpsRange.maxFps});
return *this;
}
MetadataBuilder& MetadataBuilder::setControlAeMode(
- camera_metadata_enum_android_control_ae_mode_t mode) {
+ const camera_metadata_enum_android_control_ae_mode_t mode) {
mEntryMap[ANDROID_CONTROL_AE_MODE] = asVectorOf<uint8_t>(mode);
return *this;
}
@@ -277,6 +298,12 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlAwbState(
+ const camera_metadata_enum_android_control_awb_state awbState) {
+ mEntryMap[ANDROID_CONTROL_AWB_STATE] = asVectorOf<uint8_t>(awbState);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlAwbLockAvailable(
const bool awbLockAvailable) {
const uint8_t lockAvailable = awbLockAvailable
@@ -287,6 +314,12 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlAwbLock(
+ const camera_metadata_enum_android_control_awb_lock awbLock) {
+ mEntryMap[ANDROID_CONTROL_AWB_LOCK] = asVectorOf<uint8_t>(awbLock);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlAeAvailableAntibandingModes(
const std::vector<camera_metadata_enum_android_control_ae_antibanding_mode_t>&
antibandingModes) {
@@ -313,6 +346,12 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlAeLock(
+ const camera_metadata_enum_android_control_ae_lock aeLock) {
+ mEntryMap[ANDROID_CONTROL_AE_LOCK] = asVectorOf<uint8_t>(aeLock);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setControlAeRegions(
const std::vector<ControlRegion>& aeRegions) {
std::vector<int32_t> regions;
@@ -421,7 +460,7 @@
}
MetadataBuilder& MetadataBuilder::setSyncMaxLatency(
- camera_metadata_enum_android_sync_max_latency latency) {
+ const camera_metadata_enum_android_sync_max_latency latency) {
mEntryMap[ANDROID_SYNC_MAX_LATENCY] = asVectorOf<int32_t>(latency);
return *this;
}
@@ -506,7 +545,7 @@
}
MetadataBuilder& MetadataBuilder::setNoiseReductionMode(
- camera_metadata_enum_android_noise_reduction_mode noiseReductionMode) {
+ const camera_metadata_enum_android_noise_reduction_mode noiseReductionMode) {
mEntryMap[ANDROID_NOISE_REDUCTION_MODE] =
asVectorOf<uint8_t>(noiseReductionMode);
return *this;
@@ -585,6 +624,43 @@
return *this;
}
+MetadataBuilder& MetadataBuilder::setControlAeState(
+ const camera_metadata_enum_android_control_ae_state aeState) {
+ mEntryMap[ANDROID_CONTROL_AE_STATE] = asVectorOf<uint8_t>(aeState);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setStatisticsSceneFlicker(
+ const camera_metadata_enum_android_statistics_scene_flicker sceneFlicker) {
+ mEntryMap[ANDROID_STATISTICS_SCENE_FLICKER] =
+ asVectorOf<uint8_t>(sceneFlicker);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setStatisticsHotPixelMapMode(
+ const camera_metadata_enum_android_statistics_hot_pixel_map_mode
+ hotPixelMapMode) {
+ mEntryMap[ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE] =
+ asVectorOf<uint8_t>(hotPixelMapMode);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setStatisticsLensShadingMapMode(
+ const camera_metadata_enum_android_statistics_lens_shading_map_mode
+ lensShadingMapMode) {
+ mEntryMap[ANDROID_STATISTICS_LENS_SHADING_MAP_MODE] =
+ asVectorOf<uint8_t>(lensShadingMapMode);
+ return *this;
+}
+
+MetadataBuilder& MetadataBuilder::setLensOpticalStabilizationMode(
+ const camera_metadata_enum_android_lens_optical_stabilization_mode_t
+ opticalStabilizationMode) {
+ mEntryMap[ANDROID_LENS_OPTICAL_STABILIZATION_MODE] =
+ asVectorOf<uint8_t>(opticalStabilizationMode);
+ return *this;
+}
+
MetadataBuilder& MetadataBuilder::setAvailableRequestKeys(
const std::vector<int32_t>& keys) {
mEntryMap[ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS] = keys;
@@ -724,6 +800,38 @@
return thumbnailSizes;
}
+std::optional<FpsRange> getFpsRange(
+ const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata) {
+ auto metadata =
+ reinterpret_cast<const camera_metadata_t*>(cameraMetadata.metadata.data());
+
+ camera_metadata_ro_entry_t entry;
+ if (find_camera_metadata_ro_entry(
+ metadata, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, &entry) != OK ||
+ entry.count != 2) {
+ return {};
+ }
+
+ FpsRange range{.minFps = entry.data.i32[0], .maxFps = entry.data.i32[1]};
+ return range;
+}
+
+std::optional<camera_metadata_enum_android_control_capture_intent>
+getCaptureIntent(const aidl::android::hardware::camera::device::CameraMetadata&
+ cameraMetadata) {
+ auto metadata =
+ reinterpret_cast<const camera_metadata_t*>(cameraMetadata.metadata.data());
+
+ camera_metadata_ro_entry_t entry;
+ if (find_camera_metadata_ro_entry(metadata, ANDROID_CONTROL_CAPTURE_INTENT,
+ &entry) != OK) {
+ return {};
+ }
+
+ return static_cast<camera_metadata_enum_android_control_capture_intent>(
+ entry.data.u8[0]);
+}
+
} // namespace virtualcamera
} // namespace companion
} // namespace android
diff --git a/services/camera/virtualcamera/util/MetadataUtil.h b/services/camera/virtualcamera/util/MetadataUtil.h
index b4d60cb..f6848cd 100644
--- a/services/camera/virtualcamera/util/MetadataUtil.h
+++ b/services/camera/virtualcamera/util/MetadataUtil.h
@@ -59,16 +59,6 @@
int32_t weight = 0;
};
- struct FpsRange {
- int32_t minFps;
- int32_t maxFps;
-
- bool operator<(const FpsRange& other) const {
- return maxFps == other.maxFps ? minFps < other.minFps
- : maxFps < other.maxFps;
- }
- };
-
MetadataBuilder() = default;
~MetadataBuilder() = default;
@@ -193,6 +183,10 @@
const std::vector<camera_metadata_enum_android_control_scene_mode>&
availableSceneModes);
+ // See ANDROID_CONTROL_SCENE_MODE in CameraMetadataTag.aidl
+ MetadataBuilder& setControlSceneMode(
+ camera_metadata_enum_android_control_scene_mode sceneMode);
+
// See ANDROID_CONTROL_AVAILABLE_EFFECTS in CameraMetadataTag.aidl.
MetadataBuilder& setControlAvailableEffects(
const std::vector<camera_metadata_enum_android_control_effect_mode>&
@@ -202,12 +196,17 @@
MetadataBuilder& setControlEffectMode(
camera_metadata_enum_android_control_effect_mode_t effectMode);
- // See ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES
+ // See ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES in CameraMetadataTag.aidl.
MetadataBuilder& setControlAvailableVideoStabilizationModes(
const std::vector<
camera_metadata_enum_android_control_video_stabilization_mode_t>&
videoStabilizationModes);
+ // See ANDROID_CONTROL_VIDEO_STABILIZATION_MODE in CameraMetadataTag.aidl.
+ MetadataBuilder& setControlVideoStabilizationMode(
+ camera_metadata_enum_android_control_video_stabilization_mode
+ stabilizationMode);
+
// See CONTROL_AE_AVAILABLE_ANTIBANDING_MODES in CameraCharacteristics.java.
MetadataBuilder& setControlAeAvailableAntibandingModes(
const std::vector<camera_metadata_enum_android_control_ae_antibanding_mode_t>&
@@ -256,7 +255,7 @@
const std::vector<FpsRange>& fpsRanges);
// See ANDROID_CONTROL_AE_TARGET_FPS_RANGE in CaptureRequest.java.
- MetadataBuilder& setControlAeTargetFpsRange(int32_t min, int32_t max);
+ MetadataBuilder& setControlAeTargetFpsRange(FpsRange fpsRange);
// See ANDROID_CONTROL_CAPTURE_INTENT in CameraMetadataTag.aidl.
MetadataBuilder& setControlCaptureIntent(
@@ -278,9 +277,21 @@
// See CONTROL_AWB_LOCK_AVAILABLE in CameraMetadataTag.aidl.
MetadataBuilder& setControlAwbLockAvailable(bool awbLockAvailable);
+ // See CONTROL_AWB_LOCK in CameraMetadataTag.aidl
+ MetadataBuilder& setControlAwbLock(
+ camera_metadata_enum_android_control_awb_lock awbLock);
+
// See CONTROL_AE_LOCK_AVAILABLE in CameraMetadataTag.aidl.
MetadataBuilder& setControlAeLockAvailable(bool aeLockAvailable);
+ // See CONTROL_AE_LOCK in CameraMetadataTag.aidl.
+ MetadataBuilder& setControlAeLock(
+ camera_metadata_enum_android_control_ae_lock aeLock);
+
+ // See CONTROL_AE_STATE in CameraMetadataTag.aidl
+ MetadataBuilder& setControlAeState(
+ camera_metadata_enum_android_control_ae_state aeState);
+
// See ANDROID_CONTROL_AE_REGIONS in CameraMetadataTag.aidl.
MetadataBuilder& setControlAeRegions(
const std::vector<ControlRegion>& aeRegions);
@@ -289,6 +300,10 @@
MetadataBuilder& setControlAwbRegions(
const std::vector<ControlRegion>& awbRegions);
+ // See ANDROID_CONTROL_AWB_STATE in CameraMetadataTag.aidl.
+ MetadataBuilder& setControlAwbState(
+ camera_metadata_enum_android_control_awb_state awbState);
+
// See ANDROID_SCALER_CROP_REGION in CaptureRequest.java.
MetadataBuilder& setCropRegion(int32_t x, int32_t y, int32_t width,
int32_t height);
@@ -297,6 +312,10 @@
MetadataBuilder& setControlAfRegions(
const std::vector<ControlRegion>& afRegions);
+ // See ANDROID_CONTROL_AF_STATE in CameraMetadataTag.aidl.
+ MetadataBuilder& setControlAfState(
+ camera_metadata_enum_android_control_af_state aeftate);
+
// The size of the compressed JPEG image, in bytes.
//
// See ANDROID_JPEG_SIZE in CameraMetadataTag.aidl.
@@ -342,6 +361,24 @@
// See ANDROID_CONTROL_ZOOM_RATIO_RANGE in CameraMetadataTag.aidl.
MetadataBuilder& setControlZoomRatioRange(float min, float max);
+ // See ANDROID_STATISTICS_SCENE_FLICKER in CameraMetadataTag.aidl.
+ MetadataBuilder& setStatisticsSceneFlicker(
+ camera_metadata_enum_android_statistics_scene_flicker sceneFlicker);
+
+ // See ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE in CameraMetadataTag.aidl.
+ MetadataBuilder& setStatisticsHotPixelMapMode(
+ camera_metadata_enum_android_statistics_hot_pixel_map_mode mode);
+
+ // See ANDROID_STATISTICS_LENS_SHADING_MAP_MODE in CameraMetadataTag.aidl.
+ MetadataBuilder& setStatisticsLensShadingMapMode(
+ camera_metadata_enum_android_statistics_lens_shading_map_mode
+ lensShadingMapMode);
+
+ // See ANDROID_LENS_OPTICAL_STABILIZATION_MODE in CameraMetadataTag.aidl.
+ MetadataBuilder& setLensOpticalStabilizationMode(
+ camera_metadata_enum_android_lens_optical_stabilization_mode_t
+ opticalStabilizationMode);
+
// See ANDROID_REQUEST_AVAILABLE_CAPABILITIES in CameraMetadataTag.aidl.
MetadataBuilder& setAvailableRequestCapabilities(
const std::vector<
@@ -410,6 +447,12 @@
std::vector<Resolution> getJpegAvailableThumbnailSizes(
const aidl::android::hardware::camera::device::CameraMetadata& metadata);
+std::optional<FpsRange> getFpsRange(
+ const aidl::android::hardware::camera::device::CameraMetadata& metadata);
+
+std::optional<camera_metadata_enum_android_control_capture_intent> getCaptureIntent(
+ const aidl::android::hardware::camera::device::CameraMetadata& metadata);
+
} // namespace virtualcamera
} // namespace companion
} // namespace android
diff --git a/services/camera/virtualcamera/util/Util.h b/services/camera/virtualcamera/util/Util.h
index faae010..f08eb1c 100644
--- a/services/camera/virtualcamera/util/Util.h
+++ b/services/camera/virtualcamera/util/Util.h
@@ -142,6 +142,16 @@
int height = 0;
};
+struct FpsRange {
+ int32_t minFps;
+ int32_t maxFps;
+
+ bool operator<(const FpsRange& other) const {
+ return maxFps == other.maxFps ? minFps < other.minFps
+ : maxFps < other.maxFps;
+ }
+};
+
inline bool isApproximatellySameAspectRatio(const Resolution r1,
const Resolution r2) {
static constexpr float kAspectRatioEpsilon = 0.05;