Merge "Use test policy engine configuration file." into main
diff --git a/camera/camera2/SessionConfiguration.cpp b/camera/camera2/SessionConfiguration.cpp
index 2f1f22d..065d283 100644
--- a/camera/camera2/SessionConfiguration.cpp
+++ b/camera/camera2/SessionConfiguration.cpp
@@ -72,17 +72,15 @@
bool hasSessionParameters = false;
CameraMetadata settings;
- if (flags::feature_combination_query()) {
- if ((err = parcel->readBool(&hasSessionParameters)) != OK) {
- ALOGE("%s: Failed to read hasSessionParameters flag from parcel", __FUNCTION__);
- return err;
- }
+ if ((err = parcel->readBool(&hasSessionParameters)) != OK) {
+ ALOGE("%s: Failed to read hasSessionParameters flag from parcel", __FUNCTION__);
+ return err;
+ }
- if (hasSessionParameters) {
- if ((err = settings.readFromParcel(parcel)) != OK) {
- ALOGE("%s: Failed to read metadata flag from parcel", __FUNCTION__);
- return err;
- }
+ if (hasSessionParameters) {
+ if ((err = settings.readFromParcel(parcel)) != OK) {
+ ALOGE("%s: Failed to read metadata flag from parcel", __FUNCTION__);
+ return err;
}
}
@@ -94,10 +92,8 @@
for (auto& stream : outputStreams) {
mOutputStreams.push_back(stream);
}
- if (flags::feature_combination_query()) {
- mHasSessionParameters = hasSessionParameters;
- mSessionParameters = std::move(settings);
- }
+ mHasSessionParameters = hasSessionParameters;
+ mSessionParameters = std::move(settings);
return err;
}
@@ -125,14 +121,12 @@
err = parcel->writeParcelableVector(mOutputStreams);
if (err != OK) return err;
- if (flags::feature_combination_query()) {
- err = parcel->writeBool(mHasSessionParameters);
- if (err != OK) return err;
+ err = parcel->writeBool(mHasSessionParameters);
+ if (err != OK) return err;
- if (mHasSessionParameters) {
- err = mSessionParameters.writeToParcel(parcel);
- if (err != OK) return err;
- }
+ if (mHasSessionParameters) {
+ err = mSessionParameters.writeToParcel(parcel);
+ if (err != OK) return err;
}
return OK;
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index 471bfdf..c46c4fa 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -27,20 +27,6 @@
flag {
namespace: "camera_platform"
- name: "watch_foreground_changes"
- description: "Request AppOps to notify changes in the foreground status of the client"
- bug: "290086710"
-}
-
-flag {
- namespace: "camera_platform"
- name: "log_ultrawide_usage"
- description: "Enable measuring how much usage there is for ultrawide-angle cameras"
- bug: "300515796"
-}
-
-flag {
- namespace: "camera_platform"
name: "camera_manual_flash_strength_control"
is_exported: true
description: "Flash brightness level control in manual flash mode"
@@ -56,13 +42,6 @@
flag {
namespace: "camera_platform"
- name: "log_zoom_override_usage"
- description: "Enable measuring how much usage there is for zoom settings overrde"
- bug: "307409002"
-}
-
-flag {
- namespace: "camera_platform"
name: "session_hal_buf_manager"
description: "Enable or disable HAL buffer manager as requested by the camera HAL"
bug: "311263114"
@@ -137,16 +116,6 @@
flag {
namespace: "camera_platform"
- name: "surface_ipc"
- description: "Optimize Surface binder IPC"
- bug: "323292530"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
- namespace: "camera_platform"
name: "extension_10_bit"
is_exported: true
description: "Enables 10-bit support in the camera extensions."
@@ -286,4 +255,11 @@
metadata {
purpose: PURPOSE_BUGFIX
}
-}
\ No newline at end of file
+}
+
+flag {
+ namespace: "camera_platform"
+ name: "enable_hal_abort_from_cameraservicewatchdog"
+ description: "Enable CameraServiceWatchdog to abort camera HAL to generate HAL tombstones"
+ bug: "349652177"
+}
diff --git a/media/aconfig/codec_fwk.aconfig b/media/aconfig/codec_fwk.aconfig
index 362e98e..2bf53f9 100644
--- a/media/aconfig/codec_fwk.aconfig
+++ b/media/aconfig/codec_fwk.aconfig
@@ -13,6 +13,16 @@
}
flag {
+ name: "dataspace_v0_partial"
+ namespace: "codec_fwk"
+ description: "Bugfix flag for using V0 dataspace in some cases"
+ bug: "313827126"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "dynamic_color_aspects"
is_exported: true
namespace: "codec_fwk"
@@ -98,6 +108,16 @@
}
flag {
+ name: "secure_codecs_require_crypto"
+ namespace: "codec_fwk"
+ description: "Bugfix flag for requiring setting crypto for secure codecs"
+ bug: "365162324"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "set_callback_stall"
namespace: "codec_fwk"
description: "Bugfix flag for setCallback stall"
diff --git a/media/audio/aconfig/audio_framework.aconfig b/media/audio/aconfig/audio_framework.aconfig
index 0209e28..b8555df 100644
--- a/media/audio/aconfig/audio_framework.aconfig
+++ b/media/audio/aconfig/audio_framework.aconfig
@@ -22,6 +22,13 @@
bug: "302323921"
}
+flag{
+ name: "enable_ringtone_haptics_customization"
+ namespace: "media_audio"
+ description: "Enables haptic customization for playing ringtone."
+ bug: "351974934"
+}
+
flag {
name: "feature_spatial_audio_headtracking_low_latency"
is_exported: true
@@ -86,6 +93,13 @@
}
flag {
+ name: "muted_by_port_volume_api"
+ namespace: "media_audio"
+ description: "Playback monitoring flag used when player muted by port volume"
+ bug: "319515324"
+}
+
+flag {
name: "sco_managed_by_audio"
is_exported: true
namespace: "media_audio"
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 9eaddce..01b6e42 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -76,6 +76,8 @@
using media::audio::common::AudioOffloadInfo;
using media::audio::common::AudioOutputFlags;
using media::audio::common::AudioPlaybackRate;
+using media::audio::common::AudioPolicyForcedConfig;
+using media::audio::common::AudioPolicyForceUse;
using media::audio::common::AudioPort;
using media::audio::common::AudioPortConfig;
using media::audio::common::AudioPortDeviceExt;
@@ -3301,6 +3303,138 @@
return OK;
}
+ConversionResult<audio_policy_force_use_t>
+aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(AudioPolicyForceUse aidl) {
+ switch (aidl) {
+ case AudioPolicyForceUse::COMMUNICATION:
+ return AUDIO_POLICY_FORCE_FOR_COMMUNICATION;
+ case AudioPolicyForceUse::MEDIA:
+ return AUDIO_POLICY_FORCE_FOR_MEDIA;
+ case AudioPolicyForceUse::RECORD:
+ return AUDIO_POLICY_FORCE_FOR_RECORD;
+ case AudioPolicyForceUse::DOCK:
+ return AUDIO_POLICY_FORCE_FOR_DOCK;
+ case AudioPolicyForceUse::SYSTEM:
+ return AUDIO_POLICY_FORCE_FOR_SYSTEM;
+ case AudioPolicyForceUse::HDMI_SYSTEM_AUDIO:
+ return AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO;
+ case AudioPolicyForceUse::ENCODED_SURROUND:
+ return AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND;
+ case AudioPolicyForceUse::VIBRATE_RINGING:
+ return AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPolicyForceUse>
+legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(audio_policy_force_use_t legacy) {
+ switch (legacy) {
+ case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
+ return AudioPolicyForceUse::COMMUNICATION;
+ case AUDIO_POLICY_FORCE_FOR_MEDIA:
+ return AudioPolicyForceUse::MEDIA;
+ case AUDIO_POLICY_FORCE_FOR_RECORD:
+ return AudioPolicyForceUse::RECORD;
+ case AUDIO_POLICY_FORCE_FOR_DOCK:
+ return AudioPolicyForceUse::DOCK;
+ case AUDIO_POLICY_FORCE_FOR_SYSTEM:
+ return AudioPolicyForceUse::SYSTEM;
+ case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
+ return AudioPolicyForceUse::HDMI_SYSTEM_AUDIO;
+ case AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:
+ return AudioPolicyForceUse::ENCODED_SURROUND;
+ case AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING:
+ return AudioPolicyForceUse::VIBRATE_RINGING;
+ case AUDIO_POLICY_FORCE_USE_CNT:
+ break;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_policy_forced_cfg_t>
+aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(AudioPolicyForcedConfig aidl) {
+ switch (aidl) {
+ case AudioPolicyForcedConfig::NONE:
+ return AUDIO_POLICY_FORCE_NONE;
+ case AudioPolicyForcedConfig::SPEAKER:
+ return AUDIO_POLICY_FORCE_SPEAKER;
+ case AudioPolicyForcedConfig::HEADPHONES:
+ return AUDIO_POLICY_FORCE_HEADPHONES;
+ case AudioPolicyForcedConfig::BT_SCO:
+ return AUDIO_POLICY_FORCE_BT_SCO;
+ case AudioPolicyForcedConfig::BT_A2DP:
+ return AUDIO_POLICY_FORCE_BT_A2DP;
+ case AudioPolicyForcedConfig::WIRED_ACCESSORY:
+ return AUDIO_POLICY_FORCE_WIRED_ACCESSORY;
+ case AudioPolicyForcedConfig::BT_CAR_DOCK:
+ return AUDIO_POLICY_FORCE_BT_CAR_DOCK;
+ case AudioPolicyForcedConfig::BT_DESK_DOCK:
+ return AUDIO_POLICY_FORCE_BT_DESK_DOCK;
+ case AudioPolicyForcedConfig::ANALOG_DOCK:
+ return AUDIO_POLICY_FORCE_ANALOG_DOCK;
+ case AudioPolicyForcedConfig::DIGITAL_DOCK:
+ return AUDIO_POLICY_FORCE_DIGITAL_DOCK;
+ case AudioPolicyForcedConfig::NO_BT_A2DP:
+ return AUDIO_POLICY_FORCE_NO_BT_A2DP;
+ case AudioPolicyForcedConfig::SYSTEM_ENFORCED:
+ return AUDIO_POLICY_FORCE_SYSTEM_ENFORCED;
+ case AudioPolicyForcedConfig::HDMI_SYSTEM_AUDIO_ENFORCED:
+ return AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED;
+ case AudioPolicyForcedConfig::ENCODED_SURROUND_NEVER:
+ return AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER;
+ case AudioPolicyForcedConfig::ENCODED_SURROUND_ALWAYS:
+ return AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS;
+ case AudioPolicyForcedConfig::ENCODED_SURROUND_MANUAL:
+ return AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL;
+ case AudioPolicyForcedConfig::BT_BLE:
+ return AUDIO_POLICY_FORCE_BT_BLE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPolicyForcedConfig>
+legacy2aidl_audio_policy_forced_cfg_t_AudioPolicyForcedConfig(audio_policy_forced_cfg_t legacy) {
+ switch (legacy) {
+ case AUDIO_POLICY_FORCE_NONE:
+ return AudioPolicyForcedConfig::NONE;
+ case AUDIO_POLICY_FORCE_SPEAKER:
+ return AudioPolicyForcedConfig::SPEAKER;
+ case AUDIO_POLICY_FORCE_HEADPHONES:
+ return AudioPolicyForcedConfig::HEADPHONES;
+ case AUDIO_POLICY_FORCE_BT_SCO:
+ return AudioPolicyForcedConfig::BT_SCO;
+ case AUDIO_POLICY_FORCE_BT_A2DP:
+ return AudioPolicyForcedConfig::BT_A2DP;
+ case AUDIO_POLICY_FORCE_WIRED_ACCESSORY:
+ return AudioPolicyForcedConfig::WIRED_ACCESSORY;
+ case AUDIO_POLICY_FORCE_BT_CAR_DOCK:
+ return AudioPolicyForcedConfig::BT_CAR_DOCK;
+ case AUDIO_POLICY_FORCE_BT_DESK_DOCK:
+ return AudioPolicyForcedConfig::BT_DESK_DOCK;
+ case AUDIO_POLICY_FORCE_ANALOG_DOCK:
+ return AudioPolicyForcedConfig::ANALOG_DOCK;
+ case AUDIO_POLICY_FORCE_DIGITAL_DOCK:
+ return AudioPolicyForcedConfig::DIGITAL_DOCK;
+ case AUDIO_POLICY_FORCE_NO_BT_A2DP:
+ return AudioPolicyForcedConfig::NO_BT_A2DP;
+ case AUDIO_POLICY_FORCE_SYSTEM_ENFORCED:
+ return AudioPolicyForcedConfig::SYSTEM_ENFORCED;
+ case AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED:
+ return AudioPolicyForcedConfig::HDMI_SYSTEM_AUDIO_ENFORCED;
+ case AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER:
+ return AudioPolicyForcedConfig::ENCODED_SURROUND_NEVER;
+ case AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS:
+ return AudioPolicyForcedConfig::ENCODED_SURROUND_ALWAYS;
+ case AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL:
+ return AudioPolicyForcedConfig::ENCODED_SURROUND_MANUAL;
+ case AUDIO_POLICY_FORCE_BT_BLE:
+ return AudioPolicyForcedConfig::BT_BLE;
+ case AUDIO_POLICY_FORCE_CFG_CNT:
+ break;
+ }
+ return unexpected(BAD_VALUE);
+}
+
} // namespace android
#undef GET_DEVICE_DESC_CONNECTION
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
index 7268464..9dfb7e7 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -58,6 +58,8 @@
#include PREFIX(android/media/audio/common/AudioMode.h)
#include PREFIX(android/media/audio/common/AudioOffloadInfo.h)
#include PREFIX(android/media/audio/common/AudioOutputFlags.h)
+#include PREFIX(android/media/audio/common/AudioPolicyForceUse.h)
+#include PREFIX(android/media/audio/common/AudioPolicyForcedConfig.h)
#include PREFIX(android/media/audio/common/AudioPort.h)
#include PREFIX(android/media/audio/common/AudioPortConfig.h)
#include PREFIX(android/media/audio/common/AudioPortExt.h)
@@ -76,6 +78,7 @@
#include <system/audio.h>
#include <system/audio_effect.h>
+#include <system/audio_policy.h>
#if defined(BACKEND_NDK_IMPL)
namespace aidl {
@@ -454,6 +457,18 @@
media::audio::common::MicrophoneInfo* aidlInfo,
media::audio::common::MicrophoneDynamicInfo* aidlDynamic);
+ConversionResult<audio_policy_forced_cfg_t>
+aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(
+ media::audio::common::AudioPolicyForcedConfig aidl);
+ConversionResult<media::audio::common::AudioPolicyForcedConfig>
+legacy2aidl_audio_policy_forced_cfg_t_AudioPolicyForcedConfig(audio_policy_forced_cfg_t legacy);
+
+ConversionResult<audio_policy_force_use_t>
+aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(
+ media::audio::common::AudioPolicyForceUse aidl);
+ConversionResult<media::audio::common::AudioPolicyForceUse>
+legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(audio_policy_force_use_t legacy);
+
} // namespace android
#if defined(BACKEND_NDK_IMPL)
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
index ea4d045..356bf72 100644
--- a/media/codec2/hal/aidl/ComponentStore.cpp
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -212,12 +212,20 @@
if (c2interface == nullptr) {
return nullptr;
}
+ // Framework support for Large audio frame feature depends on:
+ // 1. All feature flags enabled on platform
+ // 2. The capability of the implementation to use the same input buffer
+ // for different C2Work (C2Config::api_feature_t::API_SAME_INPUT_BUFFER)
+ // 3. Implementation does not inherently support C2LargeFrame::output::PARAM_TYPE param.
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)) {
+ C2ApiFeaturesSetting features = (C2Config::api_feature_t)0;
+ err = c2interface->query_vb({&domain, &features}, {}, C2_MAY_BLOCK, &heapParams);
+ if (err == C2_OK
+ && (domain.value == C2Component::DOMAIN_AUDIO)
+ && ((features.value & C2Config::api_feature_t::API_SAME_INPUT_BUFFER) != 0)) {
std::vector<std::shared_ptr<C2ParamDescriptor>> params;
bool isComponentSupportsLargeAudioFrame = false;
c2interface->querySupportedParams_nb(¶ms);
@@ -232,9 +240,11 @@
// param reflectors. Currently filters work on video domain only,
// and the MultiAccessUnitHelper is only enabled on audio domain;
// thus we pass the component's param reflector, which is mParamReflectors[0].
+ std::shared_ptr<C2ReflectorHelper> multiAccessReflector(new C2ReflectorHelper());
multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
c2interface,
- std::static_pointer_cast<C2ReflectorHelper>(mParamReflectors[0]));
+ multiAccessReflector);
+ mParamReflectors.push_back(multiAccessReflector);
}
}
}
diff --git a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp
index 1ba1889..f09e232 100644
--- a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp
@@ -207,12 +207,20 @@
if (c2interface == nullptr) {
return nullptr;
}
+ // Framework support for Large audio frame feature depends on:
+ // 1. All feature flags enabled on platform
+ // 2. The capability of the implementation to use the same input buffer
+ // for different C2Work (C2Config::api_feature_t::API_SAME_INPUT_BUFFER)
+ // 3. Implementation does not inherently support C2LargeFrame::output::PARAM_TYPE param.
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)) {
+ C2ApiFeaturesSetting features = (C2Config::api_feature_t)0;
+ err = c2interface->query_vb({&domain, &features}, {}, C2_MAY_BLOCK, &heapParams);
+ if (err == C2_OK
+ && (domain.value == C2Component::DOMAIN_AUDIO)
+ && ((features.value & C2Config::api_feature_t::API_SAME_INPUT_BUFFER) != 0)) {
std::vector<std::shared_ptr<C2ParamDescriptor>> params;
bool isComponentSupportsLargeAudioFrame = false;
c2interface->querySupportedParams_nb(¶ms);
@@ -223,9 +231,12 @@
}
}
if (!isComponentSupportsLargeAudioFrame) {
+ std::shared_ptr<C2ReflectorHelper> multiAccessReflector(new C2ReflectorHelper());
multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
c2interface,
- std::static_pointer_cast<C2ReflectorHelper>(mParamReflectors[0]));
+ multiAccessReflector);
+ mParamReflectors.push_back(multiAccessReflector);
+
}
}
}
diff --git a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp
index 1b86958..009a326 100644
--- a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp
+++ b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp
@@ -207,12 +207,20 @@
if (c2interface == nullptr) {
return nullptr;
}
+ // Framework support for Large audio frame feature depends on:
+ // 1. All feature flags enabled on platform
+ // 2. The capability of the implementation to use the same input buffer
+ // for different C2Work (C2Config::api_feature_t::API_SAME_INPUT_BUFFER)
+ // 3. Implementation does not inherently support C2LargeFrame::output::PARAM_TYPE param.
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)) {
+ C2ApiFeaturesSetting features = (C2Config::api_feature_t)0;
+ err = c2interface->query_vb({&domain, &features}, {}, C2_MAY_BLOCK, &heapParams);
+ if (err == C2_OK
+ && (domain.value == C2Component::DOMAIN_AUDIO)
+ && ((features.value & C2Config::api_feature_t::API_SAME_INPUT_BUFFER) != 0)) {
std::vector<std::shared_ptr<C2ParamDescriptor>> params;
bool isComponentSupportsLargeAudioFrame = false;
c2interface->querySupportedParams_nb(¶ms);
@@ -224,9 +232,11 @@
}
if (!isComponentSupportsLargeAudioFrame) {
+ std::shared_ptr<C2ReflectorHelper> multiAccessReflector(new C2ReflectorHelper());
multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
c2interface,
- std::static_pointer_cast<C2ReflectorHelper>(mParamReflectors[0]));
+ multiAccessReflector);
+ mParamReflectors.push_back(multiAccessReflector);
}
}
}
diff --git a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp
index 2e0386f..89f71a9 100644
--- a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp
+++ b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp
@@ -207,12 +207,20 @@
if (c2interface == nullptr) {
return nullptr;
}
+ // Framework support for Large audio frame feature depends on:
+ // 1. All feature flags enabled on platform
+ // 2. The capability of the implementation to use the same input buffer
+ // for different C2Work (C2Config::api_feature_t::API_SAME_INPUT_BUFFER)
+ // 3. Implementation does not inherently support C2LargeFrame::output::PARAM_TYPE param.
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)) {
+ C2ApiFeaturesSetting features = (C2Config::api_feature_t)0;
+ err = c2interface->query_vb({&domain, &features}, {}, C2_MAY_BLOCK, &heapParams);
+ if (err == C2_OK
+ && (domain.value == C2Component::DOMAIN_AUDIO)
+ && ((features.value & C2Config::api_feature_t::API_SAME_INPUT_BUFFER) != 0)) {
std::vector<std::shared_ptr<C2ParamDescriptor>> params;
bool isComponentSupportsLargeAudioFrame = false;
c2interface->querySupportedParams_nb(¶ms);
@@ -223,9 +231,11 @@
}
}
if (!isComponentSupportsLargeAudioFrame) {
+ std::shared_ptr<C2ReflectorHelper> multiAccessReflector(new C2ReflectorHelper());
multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
c2interface,
- std::static_pointer_cast<C2ReflectorHelper>(mParamReflectors[0]));
+ multiAccessReflector);
+ mParamReflectors.push_back(multiAccessReflector);
}
}
}
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 68f1dda..632eaed 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -512,9 +512,14 @@
uint64_t usage = mConfig.mUsage;
(void)(*node)->setConsumerUsage((int64_t)usage);
+ // AIDL does not define legacy dataspace.
+ android_dataspace_t dataspace = mDataSpace;
+ if (android::media::codec::provider_->dataspace_v0_partial()) {
+ ColorUtils::convertDataSpaceToV0(dataspace);
+ }
return fromAidlStatus(mSource->configure(
(*node), static_cast<::aidl::android::hardware::graphics::common::Dataspace>(
- mDataSpace)));
+ dataspace)));
}
void disconnect() override {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index d829523..3e74d8f 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -2625,8 +2625,8 @@
bufferMetadata->m.values[nMeta];
flag = convertFlags(bufferMetadataStruct.flags, false);
accessUnitInfos.emplace_back(flag,
- static_cast<size_t>(bufferMetadataStruct.size),
- static_cast<size_t>(bufferMetadataStruct.timestamp));
+ bufferMetadataStruct.size,
+ bufferMetadataStruct.timestamp);
}
sp<WrapperObject<std::vector<AccessUnitInfo>>> obj{
new WrapperObject<std::vector<AccessUnitInfo>>{accessUnitInfos}};
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 164a1e0..7d4e8ab 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -20,6 +20,8 @@
#include <utils/Log.h>
#include <utils/Trace.h>
+#include <android_media_codec.h>
+
#include <aidl/android/hardware/graphics/common/Cta861_3.h>
#include <aidl/android/hardware/graphics/common/Smpte2086.h>
#include <android-base/no_destructor.h>
@@ -33,6 +35,7 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <mediadrm/ICrypto.h>
#include <nativebase/nativebase.h>
#include <ui/GraphicBufferMapper.h>
@@ -735,6 +738,10 @@
// Gralloc4 not supported; nothing to do
return err;
}
+ // Use V0 dataspaces for Gralloc4+
+ if (android::media::codec::provider_->dataspace_v0_partial()) {
+ ColorUtils::convertDataSpaceToV0(dataSpace);
+ }
status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
if (status != OK) {
err = C2_CORRUPTED;
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 5785537..b1517bb 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -358,8 +358,6 @@
"aidl/android/media/AudioMixerBehavior.aidl",
"aidl/android/media/AudioOffloadMode.aidl",
"aidl/android/media/AudioPolicyDeviceState.aidl",
- "aidl/android/media/AudioPolicyForceUse.aidl",
- "aidl/android/media/AudioPolicyForcedConfig.aidl",
"aidl/android/media/AudioProductStrategy.aidl",
"aidl/android/media/AudioVolumeGroup.aidl",
"aidl/android/media/DeviceRole.aidl",
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 55f74e1..ee44074 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -60,6 +60,8 @@
using media::audio::common::AudioMMapPolicyInfo;
using media::audio::common::AudioMMapPolicyType;
using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioPolicyForceUse;
+using media::audio::common::AudioPolicyForcedConfig;
using media::audio::common::AudioSource;
using media::audio::common::AudioStreamType;
using media::audio::common::AudioUsage;
@@ -1054,9 +1056,9 @@
if (aps == 0) return AUDIO_POLICY_FORCE_NONE;
auto result = [&]() -> ConversionResult<audio_policy_forced_cfg_t> {
- media::AudioPolicyForceUse usageAidl = VALUE_OR_RETURN(
+ AudioPolicyForceUse usageAidl = VALUE_OR_RETURN(
legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(usage));
- media::AudioPolicyForcedConfig configAidl;
+ AudioPolicyForcedConfig configAidl;
RETURN_IF_ERROR(statusTFromBinderStatus(
aps->getForceUse(usageAidl, &configAidl)));
return aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(configAidl);
diff --git a/media/libaudioclient/PolicyAidlConversion.cpp b/media/libaudioclient/PolicyAidlConversion.cpp
index 163a359..a414cb7 100644
--- a/media/libaudioclient/PolicyAidlConversion.cpp
+++ b/media/libaudioclient/PolicyAidlConversion.cpp
@@ -296,138 +296,6 @@
return unexpected(BAD_VALUE);
}
-ConversionResult<audio_policy_force_use_t>
-aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(media::AudioPolicyForceUse aidl) {
- switch (aidl) {
- case media::AudioPolicyForceUse::COMMUNICATION:
- return AUDIO_POLICY_FORCE_FOR_COMMUNICATION;
- case media::AudioPolicyForceUse::MEDIA:
- return AUDIO_POLICY_FORCE_FOR_MEDIA;
- case media::AudioPolicyForceUse::RECORD:
- return AUDIO_POLICY_FORCE_FOR_RECORD;
- case media::AudioPolicyForceUse::DOCK:
- return AUDIO_POLICY_FORCE_FOR_DOCK;
- case media::AudioPolicyForceUse::SYSTEM:
- return AUDIO_POLICY_FORCE_FOR_SYSTEM;
- case media::AudioPolicyForceUse::HDMI_SYSTEM_AUDIO:
- return AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO;
- case media::AudioPolicyForceUse::ENCODED_SURROUND:
- return AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND;
- case media::AudioPolicyForceUse::VIBRATE_RINGING:
- return AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioPolicyForceUse>
-legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(audio_policy_force_use_t legacy) {
- switch (legacy) {
- case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
- return media::AudioPolicyForceUse::COMMUNICATION;
- case AUDIO_POLICY_FORCE_FOR_MEDIA:
- return media::AudioPolicyForceUse::MEDIA;
- case AUDIO_POLICY_FORCE_FOR_RECORD:
- return media::AudioPolicyForceUse::RECORD;
- case AUDIO_POLICY_FORCE_FOR_DOCK:
- return media::AudioPolicyForceUse::DOCK;
- case AUDIO_POLICY_FORCE_FOR_SYSTEM:
- return media::AudioPolicyForceUse::SYSTEM;
- case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
- return media::AudioPolicyForceUse::HDMI_SYSTEM_AUDIO;
- case AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:
- return media::AudioPolicyForceUse::ENCODED_SURROUND;
- case AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING:
- return media::AudioPolicyForceUse::VIBRATE_RINGING;
- case AUDIO_POLICY_FORCE_USE_CNT:
- break;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_policy_forced_cfg_t>
-aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(media::AudioPolicyForcedConfig aidl) {
- switch (aidl) {
- case media::AudioPolicyForcedConfig::NONE:
- return AUDIO_POLICY_FORCE_NONE;
- case media::AudioPolicyForcedConfig::SPEAKER:
- return AUDIO_POLICY_FORCE_SPEAKER;
- case media::AudioPolicyForcedConfig::HEADPHONES:
- return AUDIO_POLICY_FORCE_HEADPHONES;
- case media::AudioPolicyForcedConfig::BT_SCO:
- return AUDIO_POLICY_FORCE_BT_SCO;
- case media::AudioPolicyForcedConfig::BT_A2DP:
- return AUDIO_POLICY_FORCE_BT_A2DP;
- case media::AudioPolicyForcedConfig::WIRED_ACCESSORY:
- return AUDIO_POLICY_FORCE_WIRED_ACCESSORY;
- case media::AudioPolicyForcedConfig::BT_CAR_DOCK:
- return AUDIO_POLICY_FORCE_BT_CAR_DOCK;
- case media::AudioPolicyForcedConfig::BT_DESK_DOCK:
- return AUDIO_POLICY_FORCE_BT_DESK_DOCK;
- case media::AudioPolicyForcedConfig::ANALOG_DOCK:
- return AUDIO_POLICY_FORCE_ANALOG_DOCK;
- case media::AudioPolicyForcedConfig::DIGITAL_DOCK:
- return AUDIO_POLICY_FORCE_DIGITAL_DOCK;
- case media::AudioPolicyForcedConfig::NO_BT_A2DP:
- return AUDIO_POLICY_FORCE_NO_BT_A2DP;
- case media::AudioPolicyForcedConfig::SYSTEM_ENFORCED:
- return AUDIO_POLICY_FORCE_SYSTEM_ENFORCED;
- case media::AudioPolicyForcedConfig::HDMI_SYSTEM_AUDIO_ENFORCED:
- return AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED;
- case media::AudioPolicyForcedConfig::ENCODED_SURROUND_NEVER:
- return AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER;
- case media::AudioPolicyForcedConfig::ENCODED_SURROUND_ALWAYS:
- return AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS;
- case media::AudioPolicyForcedConfig::ENCODED_SURROUND_MANUAL:
- return AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL;
- case media::AudioPolicyForcedConfig::BT_BLE:
- return AUDIO_POLICY_FORCE_BT_BLE;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioPolicyForcedConfig>
-legacy2aidl_audio_policy_forced_cfg_t_AudioPolicyForcedConfig(audio_policy_forced_cfg_t legacy) {
- switch (legacy) {
- case AUDIO_POLICY_FORCE_NONE:
- return media::AudioPolicyForcedConfig::NONE;
- case AUDIO_POLICY_FORCE_SPEAKER:
- return media::AudioPolicyForcedConfig::SPEAKER;
- case AUDIO_POLICY_FORCE_HEADPHONES:
- return media::AudioPolicyForcedConfig::HEADPHONES;
- case AUDIO_POLICY_FORCE_BT_SCO:
- return media::AudioPolicyForcedConfig::BT_SCO;
- case AUDIO_POLICY_FORCE_BT_A2DP:
- return media::AudioPolicyForcedConfig::BT_A2DP;
- case AUDIO_POLICY_FORCE_WIRED_ACCESSORY:
- return media::AudioPolicyForcedConfig::WIRED_ACCESSORY;
- case AUDIO_POLICY_FORCE_BT_CAR_DOCK:
- return media::AudioPolicyForcedConfig::BT_CAR_DOCK;
- case AUDIO_POLICY_FORCE_BT_DESK_DOCK:
- return media::AudioPolicyForcedConfig::BT_DESK_DOCK;
- case AUDIO_POLICY_FORCE_ANALOG_DOCK:
- return media::AudioPolicyForcedConfig::ANALOG_DOCK;
- case AUDIO_POLICY_FORCE_DIGITAL_DOCK:
- return media::AudioPolicyForcedConfig::DIGITAL_DOCK;
- case AUDIO_POLICY_FORCE_NO_BT_A2DP:
- return media::AudioPolicyForcedConfig::NO_BT_A2DP;
- case AUDIO_POLICY_FORCE_SYSTEM_ENFORCED:
- return media::AudioPolicyForcedConfig::SYSTEM_ENFORCED;
- case AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED:
- return media::AudioPolicyForcedConfig::HDMI_SYSTEM_AUDIO_ENFORCED;
- case AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER:
- return media::AudioPolicyForcedConfig::ENCODED_SURROUND_NEVER;
- case AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS:
- return media::AudioPolicyForcedConfig::ENCODED_SURROUND_ALWAYS;
- case AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL:
- return media::AudioPolicyForcedConfig::ENCODED_SURROUND_MANUAL;
- case AUDIO_POLICY_FORCE_BT_BLE:
- return media::AudioPolicyForcedConfig::BT_BLE;
- case AUDIO_POLICY_FORCE_CFG_CNT:
- break;
- }
- return unexpected(BAD_VALUE);
-}
-
ConversionResult<device_role_t>
aidl2legacy_DeviceRole_device_role_t(media::DeviceRole aidl) {
switch (aidl) {
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index 79fcea8..e723926 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -1323,7 +1323,7 @@
audio_attributes_t attr;
audio_stream_type_t streamType = mStreamType;
- if (mStreamType == AUDIO_STREAM_VOICE_CALL) {
+ if (mStreamType == AUDIO_STREAM_VOICE_CALL || mStreamType == AUDIO_STREAM_BLUETOOTH_SCO) {
streamType = AUDIO_STREAM_DTMF;
}
attr = AudioSystem::streamTypeToAttributes(streamType);
diff --git a/media/libaudioclient/aidl/android/media/AudioPolicyForceUse.aidl b/media/libaudioclient/aidl/android/media/AudioPolicyForceUse.aidl
deleted file mode 100644
index 9bb0605..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPolicyForceUse.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioPolicyForceUse {
- COMMUNICATION = 0,
- MEDIA = 1,
- RECORD = 2,
- DOCK = 3,
- SYSTEM = 4,
- HDMI_SYSTEM_AUDIO = 5,
- ENCODED_SURROUND = 6,
- VIBRATE_RINGING = 7,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPolicyForcedConfig.aidl b/media/libaudioclient/aidl/android/media/AudioPolicyForcedConfig.aidl
deleted file mode 100644
index 111bb2f..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPolicyForcedConfig.aidl
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioPolicyForcedConfig {
- NONE = 0,
- SPEAKER = 1,
- HEADPHONES = 2,
- BT_SCO = 3,
- BT_A2DP = 4,
- WIRED_ACCESSORY = 5,
- BT_CAR_DOCK = 6,
- BT_DESK_DOCK = 7,
- ANALOG_DOCK = 8,
- DIGITAL_DOCK = 9,
- NO_BT_A2DP = 10, /* A2DP sink is not preferred to speaker or wired HS */
- SYSTEM_ENFORCED = 11,
- HDMI_SYSTEM_AUDIO_ENFORCED = 12,
- ENCODED_SURROUND_NEVER = 13,
- ENCODED_SURROUND_ALWAYS = 14,
- ENCODED_SURROUND_MANUAL = 15,
- BT_BLE = 16,
-}
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index ac42ea9..7f5e8e2 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -25,8 +25,6 @@
import android.media.AudioOffloadMode;
import android.media.AudioPatchFw;
import android.media.AudioPolicyDeviceState;
-import android.media.AudioPolicyForcedConfig;
-import android.media.AudioPolicyForceUse;
import android.media.AudioPortFw;
import android.media.AudioPortConfigFw;
import android.media.AudioPortRole;
@@ -49,6 +47,8 @@
import android.media.audio.common.AudioDeviceDescription;
import android.media.audio.common.AudioFormatDescription;
import android.media.audio.common.AudioMode;
+import android.media.audio.common.AudioPolicyForcedConfig;
+import android.media.audio.common.AudioPolicyForceUse;
import android.media.audio.common.AudioProfile;
import android.media.audio.common.AudioOffloadInfo;
import android.media.audio.common.AudioPort;
diff --git a/media/libaudioclient/include/media/PolicyAidlConversion.h b/media/libaudioclient/include/media/PolicyAidlConversion.h
index ed9ddd6..1b90d6b 100644
--- a/media/libaudioclient/include/media/PolicyAidlConversion.h
+++ b/media/libaudioclient/include/media/PolicyAidlConversion.h
@@ -28,8 +28,6 @@
#include <android/media/AudioMixRouteFlag.h>
#include <android/media/AudioMixType.h>
#include <android/media/AudioOffloadMode.h>
-#include <android/media/AudioPolicyForceUse.h>
-#include <android/media/AudioPolicyForcedConfig.h>
#include <android/media/DeviceRole.h>
#include <media/AidlConversionUtil.h>
@@ -84,16 +82,6 @@
ConversionResult<media::AudioPolicyDeviceState>
legacy2aidl_audio_policy_dev_state_t_AudioPolicyDeviceState(audio_policy_dev_state_t legacy);
-ConversionResult<audio_policy_force_use_t>
-aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(media::AudioPolicyForceUse aidl);
-ConversionResult<media::AudioPolicyForceUse>
-legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(audio_policy_force_use_t legacy);
-
-ConversionResult<audio_policy_forced_cfg_t>
-aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(media::AudioPolicyForcedConfig aidl);
-ConversionResult<media::AudioPolicyForcedConfig>
-legacy2aidl_audio_policy_forced_cfg_t_AudioPolicyForcedConfig(audio_policy_forced_cfg_t legacy);
-
ConversionResult<device_role_t>
aidl2legacy_DeviceRole_device_role_t(media::DeviceRole aidl);
ConversionResult<media::DeviceRole>
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 893b442..cc78510 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -654,7 +654,9 @@
mReadOptions.clearSeekTo();
if (err != OK) {
ALOGW("Input Error: err=%d", err);
- mediaBuffer->release();
+ if (mediaBuffer) {
+ mediaBuffer->release();
+ }
return err;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 1422868..8b50359 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2462,7 +2462,12 @@
mediametrics_setInt32(nextMetricsHandle, kCodecCrypto, 1);
}
} else if (mFlags & kFlagIsSecure) {
- ALOGW("Crypto or descrambler should be given for secure codec");
+ if (android::media::codec::provider_->secure_codecs_require_crypto()) {
+ mErrorLog.log(LOG_TAG, "Crypto or descrambler must be given for secure codec");
+ return INVALID_OPERATION;
+ } else {
+ ALOGW("Crypto or descrambler should be given for secure codec");
+ }
}
if (mConfigureMsg != nullptr) {
diff --git a/media/tests/benchmark/MediaBenchmarkTest/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
index d41a7f9..1049d5e 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/Android.bp
+++ b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
@@ -36,8 +36,8 @@
resource_dirs: ["res"],
libs: [
- "android.test.runner",
- "android.test.base",
+ "android.test.runner.stubs.system",
+ "android.test.base.stubs.system",
],
jni_libs: [
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index ee6af4c..3b7cae3 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -26,6 +26,25 @@
using StreamTypeVector = std::vector<audio_stream_type_t>;
+/**
+ * Legacy audio policy product strategies IDs. These strategies are supported by the default
+ * policy engine.
+ */
+enum legacy_strategy {
+ STRATEGY_NONE = -1,
+ STRATEGY_MEDIA,
+ STRATEGY_PHONE,
+ STRATEGY_SONIFICATION,
+ STRATEGY_SONIFICATION_RESPECTFUL,
+ STRATEGY_DTMF,
+ STRATEGY_ENFORCED_AUDIBLE,
+ STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
+ STRATEGY_ACCESSIBILITY,
+ STRATEGY_REROUTING,
+ STRATEGY_CALL_ASSISTANT,
+ STRATEGY_PATCH,
+};
+
static const audio_attributes_t defaultAttr = AUDIO_ATTRIBUTES_INITIALIZER;
static const std::set<audio_usage_t > gHighPriorityUseCases = {
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 1f6002f..794c7c0 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -49,6 +49,7 @@
static const constexpr char* const kDefaultConfigSource = "AudioPolicyConfig::setDefault";
// The suffix of the "engine default" implementation shared library name.
static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
+ static const constexpr char* const kCapEngineLibraryNameSuffix = "configurable";
// Creates the default (fallback) configuration.
static sp<const AudioPolicyConfig> createDefault();
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
index 4edd11f..abeaaf8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -269,6 +269,9 @@
mSurroundFormats = VALUE_OR_RETURN_STATUS(
aidl2legacy_SurroundSoundConfig_SurroundFormats(aidl.surroundSoundConfig));
mSource = kAidlConfigSource;
+ if (aidl.engineConfig.capSpecificConfig.has_value()) {
+ setEngineLibraryNameSuffix(kCapEngineLibraryNameSuffix);
+ }
// No need to augmentData() as AIDL HAL must provide correct mic addresses.
return NO_ERROR;
}
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index d8aac37..7daa064 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -64,5 +64,6 @@
],
defaults: [
"aconfig_lib_cc_static_link.defaults",
+ "latest_android_media_audio_common_types_cpp_static",
],
}
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index b9c94a4..edb2e29 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -129,6 +129,8 @@
product_strategy_t getProductStrategyByName(const std::string &name) const;
+ std::string getProductStrategyName(product_strategy_t id) const;
+
AudioPolicyManagerObserver *getApmObserver() const { return mApmObserver; }
inline bool isInCall() const
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 1593be0..8162720 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -46,7 +46,7 @@
using VolumeGroupAttributesVector = std::vector<VolumeGroupAttributes>;
public:
- ProductStrategy(const std::string &name);
+ ProductStrategy(const std::string &name, int id = PRODUCT_STRATEGY_NONE);
void addAttributes(const VolumeGroupAttributes &volumeGroupAttributes);
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index e259e6e..976791f 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -116,6 +116,15 @@
return PRODUCT_STRATEGY_NONE;
}
+std::string EngineBase::getProductStrategyName(product_strategy_t id) const {
+ for (const auto &iter : mProductStrategies) {
+ if (iter.second->getId() == id) {
+ return iter.second->getName();
+ }
+ }
+ return "";
+}
+
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
const media::audio::common::AudioHalEngineConfig& aidlConfig)
{
@@ -240,7 +249,7 @@
loadVolumeConfig(mVolumeGroups, volumeConfig);
}
for (auto& strategyConfig : result.parsedConfig->productStrategies) {
- sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
+ sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name, strategyConfig.id);
for (const auto &group : strategyConfig.attributesGroups) {
const auto &iter = std::find_if(begin(mVolumeGroups), end(mVolumeGroups),
[&group](const auto &volumeGroup) {
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index 548a20d..c4bf64a 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -18,14 +18,17 @@
#include <EngineConfig.h>
+#include <media/AudioProductStrategy.h>
+#include <policy.h>
#include <system/audio.h>
namespace android {
+
/**
* @brief AudioProductStrategies hard coded array of strategies to fill new engine API contract.
*/
const engineConfig::ProductStrategies gOrderedStrategies = {
- {"STRATEGY_PHONE",
+ {"STRATEGY_PHONE", STRATEGY_PHONE,
{
{AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT,
@@ -37,7 +40,7 @@
}
},
},
- {"STRATEGY_SONIFICATION",
+ {"STRATEGY_SONIFICATION", STRATEGY_SONIFICATION,
{
{AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
@@ -49,7 +52,7 @@
}
},
},
- {"STRATEGY_ENFORCED_AUDIBLE",
+ {"STRATEGY_ENFORCED_AUDIBLE", STRATEGY_ENFORCED_AUDIBLE,
{
{AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
@@ -57,7 +60,7 @@
}
},
},
- {"STRATEGY_ACCESSIBILITY",
+ {"STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY,
{
{AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
@@ -65,7 +68,7 @@
}
},
},
- {"STRATEGY_SONIFICATION_RESPECTFUL",
+ {"STRATEGY_SONIFICATION_RESPECTFUL", STRATEGY_SONIFICATION_RESPECTFUL,
{
{AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
{
@@ -77,7 +80,7 @@
}
},
},
- {"STRATEGY_MEDIA",
+ {"STRATEGY_MEDIA", STRATEGY_MEDIA,
{
{AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
{{AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
@@ -103,7 +106,7 @@
}
},
},
- {"STRATEGY_DTMF",
+ {"STRATEGY_DTMF", STRATEGY_DTMF,
{
{AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
{
@@ -113,7 +116,7 @@
}
},
},
- {"STRATEGY_CALL_ASSISTANT",
+ {"STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT,
{
{AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT,
@@ -121,7 +124,7 @@
}
},
},
- {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
+ {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
{
{AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
{
@@ -140,7 +143,7 @@
* For compatibility reason why apm volume config file, volume group name is the stream type.
*/
const engineConfig::ProductStrategies gOrderedSystemStrategies = {
- {"STRATEGY_REROUTING",
+ {"STRATEGY_REROUTING", STRATEGY_REROUTING,
{
{AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT,
@@ -148,7 +151,7 @@
}
},
},
- {"STRATEGY_PATCH",
+ {"STRATEGY_PATCH", STRATEGY_PATCH,
{
{AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index 0d25955..8ed7403 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -19,6 +19,7 @@
#include "ProductStrategy.h"
+#include <android/media/audio/common/AudioHalProductStrategy.h>
#include <media/AudioProductStrategy.h>
#include <media/TypeConverter.h>
#include <utils/String8.h>
@@ -30,11 +31,20 @@
namespace android {
-ProductStrategy::ProductStrategy(const std::string &name) :
+using media::audio::common::AudioHalProductStrategy;
+
+/*
+ * Note on the id: either is provided (legacy strategies have hard coded id, aidl have
+ * own id, enforced to be started from VENDOR_STRATEGY_ID_START.
+ * REROUTING & PATCH system strategies are added.
+ * To prevent from collision, generate from VENDOR_STRATEGY_ID_START when id is not provided.
+ */
+ProductStrategy::ProductStrategy(const std::string &name, int id) :
mName(name),
- mId(static_cast<product_strategy_t>(HandleGenerator<uint32_t>::getNextHandle()))
-{
-}
+ mId((static_cast<product_strategy_t>(id) != PRODUCT_STRATEGY_NONE) ?
+ static_cast<product_strategy_t>(id) :
+ static_cast<product_strategy_t>(AudioHalProductStrategy::VENDOR_STRATEGY_ID_START +
+ HandleGenerator<uint32_t>::getNextHandle())) {}
void ProductStrategy::addAttributes(const VolumeGroupAttributes &volumeGroupAttributes)
{
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index ab2c134..d771605 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -10,6 +10,9 @@
cc_library {
name: "libaudiopolicyengine_config",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
export_include_dirs: ["include"],
include_dirs: [
"external/libxml2/include",
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index 119dbd6..054bdae 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -71,6 +71,7 @@
struct ProductStrategy {
std::string name;
+ int id;
AttributesGroups attributesGroups;
};
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 3f9ae19..714ab78 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -20,7 +20,6 @@
#include <sstream>
#include <stdarg.h>
#include <string>
-#include <string>
#include <vector>
#include <unordered_map>
@@ -42,6 +41,7 @@
namespace android {
+using media::audio::common::AudioStreamType;
using utilities::convertTo;
namespace engineConfig {
@@ -66,6 +66,9 @@
STRATEGY_ENTRY(ACCESSIBILITY)};
#undef STRATEGY_ENTRY
+ if (id >= media::audio::common::AudioHalProductStrategy::VENDOR_STRATEGY_ID_START) {
+ return std::to_string(id);
+ }
auto it = productStrategyMap.find(id);
if (it == productStrategyMap.end()) {
return base::unexpected(BAD_VALUE);
@@ -76,8 +79,12 @@
ConversionResult<AttributesGroup> aidl2legacy_AudioHalAttributeGroup_AttributesGroup(
const media::audio::common::AudioHalAttributesGroup& aidl) {
AttributesGroup legacy;
- legacy.stream = VALUE_OR_RETURN(
- aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+ // StreamType may only be set to AudioStreamType.INVALID when using the
+ // Configurable Audio Policy (CAP) engine. An AudioHalAttributesGroup with
+ // AudioStreamType.INVALID is used when the volume group and attributes are
+ // not associated to any AudioStreamType.
+ legacy.stream = ((aidl.streamType == AudioStreamType::INVALID) ? AUDIO_STREAM_DEFAULT :
+ VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType)));
legacy.volumeGroup = aidl.volumeGroupName;
legacy.attributesVect = VALUE_OR_RETURN(convertContainer<AttributesVector>(
aidl.attributes, aidl2legacy_AudioAttributes_audio_attributes_t));
@@ -87,8 +94,9 @@
ConversionResult<ProductStrategy> aidl2legacy_AudioHalProductStrategy_ProductStrategy(
const media::audio::common::AudioHalProductStrategy& aidl) {
ProductStrategy legacy;
- legacy.name = VALUE_OR_RETURN(
- aidl2legacy_AudioHalProductStrategy_ProductStrategyType(aidl.id));
+ legacy.name = aidl.name.value_or(VALUE_OR_RETURN(
+ aidl2legacy_AudioHalProductStrategy_ProductStrategyType(aidl.id)));
+ legacy.id = aidl.id;
legacy.attributesGroups = VALUE_OR_RETURN(convertContainer<AttributesGroups>(
aidl.attributesGroups,
aidl2legacy_AudioHalAttributeGroup_AttributesGroup));
@@ -148,7 +156,6 @@
aidl.volumeCurves, aidl2legacy_AudioHalVolumeCurve_VolumeCurve));
return legacy;
}
-
} // namespace
template<typename E, typename C>
@@ -175,6 +182,7 @@
struct Attributes {
static constexpr const char *name = "name";
+ static constexpr const char *id = "id";
};
static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root, Collection &ps);
};
@@ -533,13 +541,21 @@
ALOGE("ProductStrategyTraits No attribute %s found", Attributes::name);
return BAD_VALUE;
}
+ int id = PRODUCT_STRATEGY_NONE;
+ std::string idLiteral = getXmlAttribute(child, Attributes::id);
+ if (!idLiteral.empty()) {
+ if (!convertTo(idLiteral, id)) {
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s, %s = %d", __FUNCTION__, name.c_str(), Attributes::id, id);
+ }
ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
size_t skipped = 0;
AttributesGroups attrGroups;
deserializeCollection<AttributesGroupTraits>(doc, child, attrGroups, skipped);
- strategies.push_back({name, attrGroups});
+ strategies.push_back({name, id, attrGroups});
return NO_ERROR;
}
diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp
index a0a4bdf..1c98faf 100644
--- a/services/audiopolicy/engineconfigurable/Android.bp
+++ b/services/audiopolicy/engineconfigurable/Android.bp
@@ -36,10 +36,10 @@
"libbase_headers",
],
static_libs: [
+ "libaudiopolicycapengine_config",
"libaudiopolicyengine_common",
"libaudiopolicyengine_config",
"libaudiopolicyengineconfigurable_pfwwrapper",
-
],
shared_libs: [
"libaudio_aidl_conversion_common_cpp",
@@ -56,5 +56,13 @@
],
defaults: [
"aconfig_lib_cc_static_link.defaults",
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+ required: [
+ "CapClass.xml",
+ "CapProductStrategies.xml",
+ "CapSubsystem-CommonTypes.xml",
+ "CapSubsystem.xml",
+ "ParameterFrameworkConfigurationCap.xml",
],
}
diff --git a/services/audiopolicy/engineconfigurable/config/Android.bp b/services/audiopolicy/engineconfigurable/config/Android.bp
index 8dd13e8..95a7cf8 100644
--- a/services/audiopolicy/engineconfigurable/config/Android.bp
+++ b/services/audiopolicy/engineconfigurable/config/Android.bp
@@ -38,6 +38,53 @@
}
filegroup {
+ name: "audio_policy_engine_aidl_criterion_types_template",
+ srcs: ["example/common/audio_policy_engine_criterion_types_aidl.xml.in"],
+}
+
+filegroup {
name: "audio_policy_engine_criteria",
srcs: ["example/common/audio_policy_engine_criteria.xml"],
}
+
+cc_library_headers {
+ name: "libaudiopolicycapengine_config_headers",
+ export_include_dirs: ["include"],
+}
+
+cc_library {
+ name: "libaudiopolicycapengine_config",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+ export_header_lib_headers: [
+ "libaudiopolicycapengine_config_headers",
+ ],
+ include_dirs: [
+ "external/libxml2/include",
+ ],
+ srcs: [
+ "src/CapEngineConfig.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ shared_libs: [
+ "libaudio_aidl_conversion_common_cpp",
+ "libaudiopolicycomponents",
+ "libaudiopolicyengine_config",
+ "libcutils",
+ "liblog",
+ "libmedia_helper",
+ "libutils",
+ "libxml2",
+ ],
+ header_libs: [
+ "libaudio_system_headers",
+ "libaudioclient_headers",
+ "libaudiopolicycapengine_config_headers",
+ "libmedia_headers",
+ ],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types_aidl.xml.in b/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types_aidl.xml.in
new file mode 100644
index 0000000..dc2517b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types_aidl.xml.in
@@ -0,0 +1,96 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<criterion_types>
+ <criterion_type name="OutputDevicesMaskType" type="inclusive"/>
+ <criterion_type name="InputDevicesMaskType" type="inclusive"/>
+ <criterion_type name="OutputDevicesAddressesType" type="inclusive">
+ <values>
+ <!-- legacy remote submix -->
+ <value literal="0" numerical="1"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="InputDevicesAddressesType" type="inclusive">
+ <values>
+ <!-- legacy remote submix -->
+ <value literal="0" numerical="1"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="AndroidModeType" type="exclusive"/>
+ <criterion_type name="ForceUseForCommunicationType" type="exclusive">
+ <values>
+ <value literal="NONE" numerical="0"/>
+ <value literal="SPEAKER" numerical="1"/>
+ <value literal="BT_SCO" numerical="3"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForMediaType" type="exclusive">
+ <values>
+ <value literal="NONE" numerical="0"/>
+ <value literal="SPEAKER" numerical="1"/>
+ <value literal="HEADPHONES" numerical="2"/>
+ <value literal="BT_A2DP" numerical="4"/>
+ <value literal="WIRED_ACCESSORY" numerical="5"/>
+ <value literal="ANALOG_DOCK" numerical="8"/>
+ <value literal="DIGITAL_DOCK" numerical="9"/>
+ <value literal="NO_BT_A2DP" numerical="10"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForRecordType" type="exclusive">
+ <values>
+ <value literal="NONE" numerical="0"/>
+ <value literal="BT_SCO" numerical="3"/>
+ <value literal="WIRED_ACCESSORY" numerical="5"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForDockType" type="exclusive">
+ <values>
+ <value literal="NONE" numerical="0"/>
+ <value literal="WIRED_ACCESSORY" numerical="5"/>
+ <value literal="BT_CAR_DOCK" numerical="6"/>
+ <value literal="BT_DESK_DOCK" numerical="7"/>
+ <value literal="ANALOG_DOCK" numerical="8"/>
+ <value literal="DIGITAL_DOCK" numerical="9"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForSystemType" type="exclusive" >
+ <values>
+ <value literal="NONE" numerical="0"/>
+ <value literal="SYSTEM_ENFORCED" numerical="11"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForHdmiSystemAudioType" type="exclusive">
+ <values>
+ <value literal="NONE" numerical="0"/>
+ <value literal="HDMI_SYSTEM_AUDIO_ENFORCED" numerical="12"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForEncodedSurroundType" type="exclusive">
+ <values>
+ <value literal="NONE" numerical="0"/>
+ <value literal="ENCODED_SURROUND_NEVER" numerical="13"/>
+ <value literal="ENCODED_SURROUND_ALWAYS" numerical="14"/>
+ <value literal="ENCODED_SURROUND_MANUAL" numerical="15"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForVibrateRingingType" type="exclusive">
+ <values>
+ <value literal="NONE" numerical="0"/>
+ <value literal="BT_SCO" numerical="3"/>
+ </values>
+ </criterion_type>
+</criterion_types>
+
+
diff --git a/services/audiopolicy/engineconfigurable/config/include/CapEngineConfig.h b/services/audiopolicy/engineconfigurable/config/include/CapEngineConfig.h
new file mode 100644
index 0000000..6c55a49
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/include/CapEngineConfig.h
@@ -0,0 +1,109 @@
+/*
+ * 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 <EngineConfig.h>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio_policy.h>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace capEngineConfig {
+
+static const char *const gCriterionTypeSuffix = "Type";
+static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
+static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
+static const char *const gPhoneStateCriterionName = "TelephonyMode";
+static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
+static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
+
+/**
+* Order MUST be aligned with definition of audio_policy_force_use_t within audio_policy.h
+*/
+static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
+{
+ [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] = "ForceUseForCommunication",
+ [AUDIO_POLICY_FORCE_FOR_MEDIA] = "ForceUseForMedia",
+ [AUDIO_POLICY_FORCE_FOR_RECORD] = "ForceUseForRecord",
+ [AUDIO_POLICY_FORCE_FOR_DOCK] = "ForceUseForDock",
+ [AUDIO_POLICY_FORCE_FOR_SYSTEM] = "ForceUseForSystem",
+ [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] = "ForceUseForHdmiSystemAudio",
+ [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround",
+ [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] = "ForceUseForVibrateRinging"
+};
+
+using ParameterValues = std::vector<std::string>;
+
+struct ConfigurableElement {
+ std::string path;
+};
+
+struct ConfigurableElementValue {
+ ConfigurableElement configurableElement;
+ std::string value;
+};
+using ConfigurableElementValues = std::vector<ConfigurableElementValue>;
+
+struct CapSetting {
+ std::string configurationName;
+ ConfigurableElementValues configurableElementValues;
+};
+using CapSettings = std::vector<CapSetting>;
+
+struct CapConfiguration {
+ std::string name;
+ std::string rule;
+};
+
+using ConfigurableElementPaths = std::vector<std::string>;
+using CapConfigurations = std::vector<CapConfiguration>;
+
+struct CapConfigurableDomain {
+ std::string name;
+ CapConfigurations configurations;
+ CapSettings settings;
+};
+
+struct CapCriterion {
+ engineConfig::Criterion criterion;
+ engineConfig::CriterionType criterionType;
+};
+
+using CapCriteria = std::vector<CapCriterion>;
+using CapConfigurableDomains = std::vector<CapConfigurableDomain>;
+
+struct CapConfig {
+ CapCriteria capCriteria;
+ CapConfigurableDomains capConfigurableDomains;
+};
+
+/** Result of `parse(const char*)` */
+struct ParsingResult {
+ /** Parsed config, nullptr if the xml lib could not load the file */
+ std::unique_ptr<CapConfig> parsedConfig;
+ size_t nbSkippedElement; //< Number of skipped invalid product strategies
+};
+
+/** Convert the provided Cap Settings configuration.
+ * @return audio policy usage @see Config
+ */
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig);
+
+}
+}
diff --git a/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp b/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp
new file mode 100644
index 0000000..a1b4470
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp
@@ -0,0 +1,500 @@
+/*
+ * 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.
+ */
+
+#include <cinttypes>
+#include <cstdint>
+#include <istream>
+#include <map>
+#include <sstream>
+#include <stdarg.h>
+#include <string>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "APM::AudioPolicyEngine/CapConfig"
+//#define LOG_NDEBUG 0
+
+#include "CapEngineConfig.h"
+#include <TypeConverter.h>
+#include <Volume.h>
+#include <cutils/properties.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionUtil.h>
+#include <media/TypeConverter.h>
+#include <media/convert.h>
+#include <system/audio_config.h>
+#include <utils/Log.h>
+
+namespace android {
+
+using utilities::convertTo;
+using media::audio::common::AudioDeviceAddress;
+using media::audio::common::AudioDeviceDescription;
+using media::audio::common::AudioHalCapCriterion;
+using media::audio::common::AudioHalCapParameter;
+using media::audio::common::AudioHalCapRule;
+using media::audio::common::AudioSource;
+using media::audio::common::AudioStreamType;
+using media::audio::common::AudioHalCapCriterionV2;
+using ::android::base::unexpected;
+
+namespace capEngineConfig {
+
+static constexpr const char *gLegacyOutputDevicePrefix = "AUDIO_DEVICE_OUT_";
+static constexpr const char *gLegacyInputDevicePrefix = "AUDIO_DEVICE_IN_";
+static constexpr const char *gLegacyStreamPrefix = "AUDIO_STREAM_";
+static constexpr const char *gLegacySourcePrefix = "AUDIO_SOURCE_";
+static constexpr const char *gPolicyParamPrefix = "/Policy/policy/";
+
+namespace {
+
+ConversionResult<std::string> truncatePrefixToLower(const std::string& legacyName,
+ const std::string& legacyPrefix) {
+ std::size_t pos = legacyName.find(legacyPrefix);
+ if (pos == std::string::npos) {
+ return unexpected(BAD_VALUE);
+ }
+ std::string capName = legacyName.substr(pos + legacyPrefix.length());
+ std::transform(capName.begin(), capName.end(), capName.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+ return capName;
+}
+
+ConversionResult<std::string> truncatePrefix(const std::string& name, const std::string& prefix) {
+ std::size_t pos = name.find(prefix);
+ if (pos == std::string::npos) {
+ return unexpected(BAD_VALUE);
+ }
+ std::string capName = name.substr(pos + prefix.length());
+ return capName;
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2_CapName(
+ const AudioHalCapCriterionV2& aidl) {
+ switch (aidl.getTag()) {
+ case AudioHalCapCriterionV2::availableInputDevices:
+ return gInputDeviceCriterionName;
+ case AudioHalCapCriterionV2::availableOutputDevices:
+ return gOutputDeviceCriterionName;
+ case AudioHalCapCriterionV2::availableInputDevicesAddresses:
+ return gInputDeviceAddressCriterionName;
+ case AudioHalCapCriterionV2::availableOutputDevicesAddresses:
+ return gOutputDeviceAddressCriterionName;
+ case AudioHalCapCriterionV2::telephonyMode:
+ return gPhoneStateCriterionName;
+ case AudioHalCapCriterionV2::forceConfigForUse: {
+ auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::forceConfigForUse>();
+ return gForceUseCriterionTag[VALUE_OR_RETURN(
+ aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(
+ aidlCriterion.forceUse))];
+ }
+ default:
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(
+ const AudioDeviceDescription& aidl) {
+ audio_devices_t legacyDeviceType = VALUE_OR_RETURN(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl));
+ bool isOut = audio_is_output_devices(legacyDeviceType);
+ std::string legacyTypeLiteral;
+ if (!::android::DeviceConverter::toString(legacyDeviceType, legacyTypeLiteral)) {
+ ALOGE("%s Invalid strategy device type %d", __func__, legacyDeviceType);
+ return unexpected(BAD_VALUE);
+ }
+ return truncatePrefix(legacyTypeLiteral,
+ isOut ? gLegacyOutputDevicePrefix : gLegacyInputDevicePrefix);
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2Type_CapCriterionValue(
+ const AudioHalCapCriterionV2::Type& aidl) {
+ switch (aidl.getTag()) {
+ case AudioHalCapCriterionV2::Type::availableDevicesType:
+ return aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(
+ aidl.get<AudioHalCapCriterionV2::Type::availableDevicesType>());
+ case AudioHalCapCriterionV2::Type::availableDevicesAddressesType:
+ return aidl.get<AudioHalCapCriterionV2::Type::availableDevicesAddressesType>().template
+ get<AudioDeviceAddress::id>();
+ case AudioHalCapCriterionV2::Type::telephonyModeType:
+ return toString(aidl.get<AudioHalCapCriterionV2::Type::telephonyModeType>());
+ case AudioHalCapCriterionV2::Type::forcedConfigType:
+ return toString(aidl.get<AudioHalCapCriterionV2::Type::forcedConfigType>());
+ default:
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapRule_CapRule(
+ const AudioHalCapRule& aidlRule) {
+ std::string rule;
+ switch (aidlRule.compoundRule) {
+ case AudioHalCapRule::CompoundRule::ANY:
+ rule += "Any";
+ break;
+ case AudioHalCapRule::CompoundRule::ALL:
+ rule += "All";
+ break;
+ default:
+ return unexpected(BAD_VALUE);
+ }
+ rule += "{";
+ if (!aidlRule.nestedRules.empty()) {
+ for (const auto& nestedRule: aidlRule.nestedRules) {
+ rule += VALUE_OR_FATAL(aidl2legacy_AudioHalCapRule_CapRule(nestedRule));
+ }
+ if (!aidlRule.criterionRules.empty()) {
+ rule += ",";
+ }
+ }
+ bool isFirstCriterionRule = true;
+ for (const auto& criterionRule: aidlRule.criterionRules) {
+ if (!isFirstCriterionRule) {
+ rule += ",";
+ }
+ isFirstCriterionRule = false;
+ std::string selectionCriterion = VALUE_OR_RETURN(
+ aidl2legacy_AudioHalCapCriterionV2_CapName(criterionRule.criterion));
+ std::string matchesWhen;
+ std::string value = VALUE_OR_RETURN(
+ aidl2legacy_AudioHalCapCriterionV2Type_CapCriterionValue(
+ criterionRule.criterionTypeValue));
+
+ switch (criterionRule.matchingRule) {
+ case AudioHalCapRule::MatchingRule::IS:
+ matchesWhen = "Is";
+ break;
+ case AudioHalCapRule::MatchingRule::IS_NOT:
+ matchesWhen = "IsNot";
+ break;
+ case AudioHalCapRule::MatchingRule::INCLUDES:
+ matchesWhen = "Includes";
+ break;
+ case AudioHalCapRule::MatchingRule::EXCLUDES:
+ matchesWhen = "Excludes";
+ break;
+ default:
+ return unexpected(BAD_VALUE);
+ }
+ rule += selectionCriterion + " " + matchesWhen + " " + value;
+ }
+ rule += "}";
+ return rule;
+}
+
+ConversionResult<CapConfiguration> aidl2legacy_AudioHalCapConfiguration_CapConfiguration(
+ const media::audio::common::AudioHalCapConfiguration& aidl) {
+ CapConfiguration legacy;
+ legacy.name = aidl.name;
+ legacy.rule = VALUE_OR_FATAL(aidl2legacy_AudioHalCapRule_CapRule(aidl.rule));
+ return legacy;
+}
+
+ConversionResult<ConfigurableElementValue> aidl2legacy_ParameterSetting_ConfigurableElementValue(
+ const AudioHalCapParameter& aidl) {
+ ConfigurableElementValue legacy;
+ std::string literalValue;
+ switch (aidl.getTag()) {
+ case AudioHalCapParameter::selectedStrategyDevice: {
+ auto strategyDevice = aidl.get<AudioHalCapParameter::selectedStrategyDevice>();
+ literalValue = std::to_string(strategyDevice.isSelected);
+ audio_devices_t legacyType = VALUE_OR_RETURN(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(strategyDevice.device));
+ std::string legacyTypeLiteral;
+ if (!::android::OutputDeviceConverter::toString(legacyType, legacyTypeLiteral)) {
+ ALOGE("%s Invalid device type %d", __func__, legacyType);
+ return unexpected(BAD_VALUE);
+ }
+ std::string deviceLiteral = VALUE_OR_RETURN(
+ truncatePrefixToLower(legacyTypeLiteral, gLegacyOutputDevicePrefix));
+ if (deviceLiteral == "default") {
+ deviceLiteral = "stub";
+ }
+ legacy.configurableElement.path = std::string(gPolicyParamPrefix)
+ + "product_strategies/vx_" + std::to_string(strategyDevice.id)
+ + "/selected_output_devices/mask/" + deviceLiteral;
+ break;
+ }
+ case AudioHalCapParameter::strategyDeviceAddress: {
+ auto strategyAddress = aidl.get<AudioHalCapParameter::strategyDeviceAddress>();
+ legacy.configurableElement.path = std::string(gPolicyParamPrefix)
+ + "product_strategies/vx_" + std::to_string(strategyAddress.id)
+ + "/device_address";
+ literalValue = strategyAddress.deviceAddress.get<AudioDeviceAddress::id>();
+ break;
+ }
+ case AudioHalCapParameter::selectedInputSourceDevice: {
+ auto inputSourceDevice = aidl.get<AudioHalCapParameter::selectedInputSourceDevice>();
+ literalValue = std::to_string(inputSourceDevice.isSelected);
+ audio_devices_t legacyType = VALUE_OR_RETURN(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(inputSourceDevice.device));
+ std::string legacyTypeLiteral;
+ if (!::android::InputDeviceConverter::toString(legacyType, legacyTypeLiteral)) {
+ ALOGE("%s Invalid input source device type %d", __func__, legacyType);
+ return unexpected(BAD_VALUE);
+ }
+ std::string deviceLiteral = VALUE_OR_RETURN(
+ truncatePrefixToLower(legacyTypeLiteral, gLegacyInputDevicePrefix));
+ if (deviceLiteral == "default") {
+ deviceLiteral = "stub";
+ }
+ audio_source_t legacySource = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
+ inputSourceDevice.inputSource));
+ std::string inputSourceLiteral;
+ if (!::android::SourceTypeConverter::toString(legacySource, inputSourceLiteral)) {
+ ALOGE("%s Invalid input source %d", __func__, legacySource);
+ return unexpected(BAD_VALUE);
+ }
+ inputSourceLiteral = VALUE_OR_RETURN(
+ truncatePrefixToLower(inputSourceLiteral, gLegacySourcePrefix));
+ legacy.configurableElement.path = std::string(gPolicyParamPrefix) + "input_sources/"
+ + inputSourceLiteral + "/applicable_input_device/mask/" + deviceLiteral;
+ break;
+ }
+ case AudioHalCapParameter::streamVolumeProfile: {
+ auto streamVolumeProfile = aidl.get<AudioHalCapParameter::streamVolumeProfile>();
+ audio_stream_type_t legacyStreamType = VALUE_OR_RETURN(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(streamVolumeProfile.stream));
+ std::string legacyStreamLiteral;
+ if (!::android::StreamTypeConverter::toString(legacyStreamType, legacyStreamLiteral)) {
+ ALOGE("%s Invalid stream type %d", __func__, legacyStreamType);
+ return unexpected(BAD_VALUE);
+ }
+ legacyStreamLiteral = VALUE_OR_RETURN(
+ truncatePrefixToLower(legacyStreamLiteral, gLegacyStreamPrefix));
+
+ audio_stream_type_t legacyProfile = VALUE_OR_RETURN(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(streamVolumeProfile.profile));
+ std::string legacyProfileLiteral;
+ if (!::android::StreamTypeConverter::toString(legacyProfile, legacyProfileLiteral)) {
+ ALOGE("%s Invalid profile %d", __func__, legacyProfile);
+ return unexpected(BAD_VALUE);
+ }
+ literalValue = VALUE_OR_RETURN(
+ truncatePrefixToLower(legacyProfileLiteral, gLegacyStreamPrefix));
+ legacy.configurableElement.path = std::string(gPolicyParamPrefix) + "streams/"
+ + legacyStreamLiteral + "/applicable_volume_profile/volume_profile";
+ break;
+ }
+ default:
+ return unexpected(BAD_VALUE);
+ }
+ legacy.value = literalValue;
+ return legacy;
+}
+
+ConversionResult<CapSetting> aidl2legacy_AudioHalCapConfiguration_CapSetting(
+ const media::audio::common::AudioHalCapConfiguration& aidl) {
+ CapSetting legacy;
+ legacy.configurationName = aidl.name;
+ legacy.configurableElementValues = VALUE_OR_RETURN(convertContainer<ConfigurableElementValues>(
+ aidl.parameterSettings, aidl2legacy_ParameterSetting_ConfigurableElementValue));
+ return legacy;
+}
+
+ConversionResult<CapConfigurableDomain> aidl2legacy_AudioHalCapDomain_CapConfigurableDomain(
+ const media::audio::common::AudioHalCapDomain& aidl) {
+ CapConfigurableDomain legacy;
+ legacy.name = aidl.name;
+ legacy.configurations = VALUE_OR_RETURN(convertContainer<CapConfigurations>(
+ aidl.configurations,
+ aidl2legacy_AudioHalCapConfiguration_CapConfiguration));
+ legacy.settings = VALUE_OR_RETURN(convertContainer<CapSettings>(
+ aidl.configurations,
+ aidl2legacy_AudioHalCapConfiguration_CapSetting));
+ return legacy;
+}
+
+ConversionResult<CapCriterion> aidl2legacy_AudioHalCapCriterionV2_Criterion(
+ const AudioHalCapCriterionV2& aidl) {
+ CapCriterion capCriterion;
+ engineConfig::Criterion& criterion = capCriterion.criterion;
+ engineConfig::CriterionType& criterionType = capCriterion.criterionType;
+
+ auto loadForceUseCriterion = [](const auto &aidlCriterion, auto &criterion,
+ auto &criterionType) -> status_t {
+ uint32_t legacyForceUse = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(
+ aidlCriterion.forceUse));
+ criterion.typeName = criterionType.name;
+ criterionType.name = criterion.typeName + gCriterionTypeSuffix;
+ criterionType.isInclusive =
+ (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+ criterion.name = gForceUseCriterionTag[legacyForceUse];
+ criterion.defaultLiteralValue = toString(aidlCriterion.defaultValue);
+ if (aidlCriterion.values.empty()) {
+ return BAD_VALUE;
+ }
+ for (auto &value : aidlCriterion.values) {
+ uint32_t legacyForcedConfig = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(value));
+ criterionType.valuePairs.push_back({legacyForcedConfig, 0, toString(value)});
+ }
+ return NO_ERROR;
+ };
+
+ auto loadDevicesCriterion = [](const auto &aidlCriterion, auto &criterion,
+ auto &criterionType) -> status_t {
+ criterionType.name = criterion.name + gCriterionTypeSuffix;
+ criterionType.isInclusive =
+ (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+ criterion.typeName = criterionType.name;
+ int shift = 0;
+ if (aidlCriterion.values.empty()) {
+ return BAD_VALUE;
+ }
+ for (const auto &value : aidlCriterion.values) {
+ audio_devices_t legacyDeviceType = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioDeviceDescription_audio_devices_t(value));
+ bool isOut = audio_is_output_devices(legacyDeviceType);
+ std::string legacyTypeLiteral;
+ if (!::android::DeviceConverter::toString(legacyDeviceType, legacyTypeLiteral)) {
+ ALOGE("%s Invalid device type %d", __func__, legacyDeviceType);
+ return BAD_VALUE;
+ }
+ std::string deviceLiteral = VALUE_OR_RETURN_STATUS(truncatePrefix(legacyTypeLiteral,
+ isOut ? gLegacyOutputDevicePrefix : gLegacyInputDevicePrefix));
+ uint64_t pfwCriterionValue = 1 << shift++;
+ criterionType.valuePairs.push_back(
+ {pfwCriterionValue, static_cast<int32_t>(legacyDeviceType), deviceLiteral});
+ ALOGV("%s: adding %" PRIu64 " %d %s %s", __func__, pfwCriterionValue, legacyDeviceType,
+ toString(value.type).c_str(), deviceLiteral.c_str());
+ }
+ return NO_ERROR;
+ };
+
+ auto loadDeviceAddressesCriterion = [](const auto &aidlCriterion, auto &criterion,
+ auto &criterionType) -> status_t {
+ criterionType.name = criterion.name + gCriterionTypeSuffix;
+ criterionType.isInclusive =
+ (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+ criterion.typeName = criterionType.name;
+ int shift = 0;
+ for (auto &value : aidlCriterion.values) {
+ uint64_t pfwCriterionValue = 1 << shift++;
+ if (value.getTag() != AudioDeviceAddress::id) {
+ return BAD_VALUE;
+ }
+ std::string address = value.template get<AudioDeviceAddress::id>();
+ criterionType.valuePairs.push_back({pfwCriterionValue, 0, address});
+ }
+ return NO_ERROR;
+ };
+
+ switch (aidl.getTag()) {
+ case AudioHalCapCriterionV2::availableInputDevices: {
+ auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::availableInputDevices>();
+ criterion.name = gInputDeviceCriterionName;
+ if (loadDevicesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+ return unexpected(BAD_VALUE);
+ }
+ break;
+ }
+ case AudioHalCapCriterionV2::availableOutputDevices: {
+ auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::availableOutputDevices>();
+ criterion.name = gOutputDeviceCriterionName;
+ if (loadDevicesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+ return unexpected(BAD_VALUE);
+ }
+ break;
+ }
+ case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
+ auto aidlCriterion =
+ aidl.get<AudioHalCapCriterionV2::availableInputDevicesAddresses>();
+ criterion.name = gInputDeviceAddressCriterionName;
+ if (loadDeviceAddressesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+ return unexpected(BAD_VALUE);
+ }
+ break;
+ }
+ case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
+ auto aidlCriterion =
+ aidl.get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>();
+ criterion.name = gOutputDeviceAddressCriterionName;
+ if (loadDeviceAddressesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+ return unexpected(BAD_VALUE);
+ }
+ break;
+ }
+ case AudioHalCapCriterionV2::telephonyMode: {
+ auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::telephonyMode>();
+ criterion.name = gPhoneStateCriterionName;
+ criterionType.name = criterion.name + gCriterionTypeSuffix;
+ criterionType.isInclusive =
+ (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+ criterion.typeName = criterionType.name;
+ criterion.defaultLiteralValue = toString( aidlCriterion.defaultValue);
+ if (aidlCriterion.values.empty()) {
+ return unexpected(BAD_VALUE);
+ }
+ for (auto &value : aidlCriterion.values) {
+ uint32_t legacyMode =
+ VALUE_OR_RETURN(aidl2legacy_AudioMode_audio_mode_t(value));
+ criterionType.valuePairs.push_back({legacyMode, 0, toString(value)});
+ }
+ break;
+ }
+ case AudioHalCapCriterionV2::forceConfigForUse: {
+ auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::forceConfigForUse>();
+ if (loadForceUseCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+ return unexpected(BAD_VALUE);
+ }
+ break;
+ }
+ default:
+ return unexpected(BAD_VALUE);
+ }
+ return capCriterion;
+}
+
+} // namespace
+
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig) {
+ auto config = std::make_unique<capEngineConfig::CapConfig>();
+
+ if (!aidlConfig.capSpecificConfig.has_value() ||
+ !aidlConfig.capSpecificConfig.value().domains.has_value()) {
+ ALOGE("%s: no Cap Engine config", __func__);
+ return ParsingResult{};
+ }
+ for (auto& aidlCriteria: aidlConfig.capSpecificConfig.value().criteriaV2.value()) {
+ if (aidlCriteria.has_value()) {
+ if (auto conv = aidl2legacy_AudioHalCapCriterionV2_Criterion(aidlCriteria.value());
+ conv.ok()) {
+ config->capCriteria.push_back(std::move(conv.value()));
+ } else {
+ return ParsingResult{};
+ }
+ }
+ }
+ size_t skippedElement = 0;
+ for (auto& aidlDomain: aidlConfig.capSpecificConfig.value().domains.value()) {
+ if (aidlDomain.has_value()) {
+ if (auto conv = aidl2legacy_AudioHalCapDomain_CapConfigurableDomain(aidlDomain.value());
+ conv.ok()) {
+ config->capConfigurableDomains.push_back(std::move(conv.value()));
+ } else {
+ return ParsingResult{};
+ }
+ } else {
+ skippedElement += 1;
+ }
+ }
+ return {.parsedConfig=std::move(config), .nbSkippedElement=skippedElement};
+}
+} // namespace capEngineConfig
+} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/data/Android.bp b/services/audiopolicy/engineconfigurable/data/Android.bp
new file mode 100644
index 0000000..303cabc
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/Android.bp
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_license"],
+}
+
+prebuilt_etc {
+ name: "CapClass.xml",
+ src: ":CapClass",
+ sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+ name: "CapSubsystem.xml",
+ src: ":CapSubsystem",
+ sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+ name: "CapSubsystem-CommonTypes.xml",
+ src: ":buildaidlcommontypesstructure_gen",
+ sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+ name: "CapProductStrategies.xml",
+ src: ":cap_product_strategies_structure",
+ sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+ name: "ParameterFrameworkConfigurationCap.xml",
+ src: ":ParameterFrameworkConfigurationCapSrc_gen",
+ sub_dir: "parameter-framework",
+}
+
+genrule {
+ name: "ParameterFrameworkConfigurationCapSrc_gen",
+ out: ["ParameterFrameworkConfigurationCap.xml"],
+ srcs: [":ParameterFrameworkConfigurationCapSrc"],
+ product_variables: {
+ debuggable: {
+ cmd: "sed -e 's|TuningAllowed=\"false\"|TuningAllowed=\"true\" ServerPort=\"unix:///dev/socket/audioserver/policy_debug\"|g' <$(in) > $(out)",
+ },
+ },
+ cmd: "cp -f $(in) $(out)",
+}
+
+genrule {
+ name: "buildaidlcommontypesstructure_gen",
+ defaults: ["buildcommontypesstructurerule"],
+ out: ["CapSubsystem-CommonTypes.xml"],
+}
+
+filegroup {
+ name: "ParameterFrameworkConfigurationCapSrc",
+ srcs: ["etc/ParameterFrameworkConfigurationCap.xml"],
+}
+
+filegroup {
+ name: "cap_product_strategies_structure",
+ srcs: ["etc/Structure/CapProductStrategies.xml"],
+}
+
+filegroup {
+ name: "CapSubsystem",
+ srcs: ["etc/Structure/CapSubsystem.xml"],
+}
+
+filegroup {
+ name: "aidl_common_types_structure_template",
+ srcs: ["etc/Structure/CapSubsystem-CommonTypes.xml.in"],
+}
+
+filegroup {
+ name: "CapClass",
+ srcs: ["etc/Structure/CapClass.xml"],
+}
diff --git a/services/audiopolicy/engineconfigurable/data/etc/ParameterFrameworkConfigurationCap.xml b/services/audiopolicy/engineconfigurable/data/etc/ParameterFrameworkConfigurationCap.xml
new file mode 100644
index 0000000..bac7a25
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/ParameterFrameworkConfigurationCap.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ SystemClassName="Policy" TuningAllowed="false">
+
+ <SubsystemPlugins>
+ <Location Folder="">
+ <Plugin Name="libpolicy-subsystem.so"/>
+ </Location>
+ </SubsystemPlugins>
+ <StructureDescriptionFileLocation Path="Structure/Policy/CapClass.xml"/>
+</ParameterFrameworkConfiguration>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapClass.xml b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapClass.xml
new file mode 100644
index 0000000..e233673
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapClass.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<SystemClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../../Schemas/SystemClass.xsd" Name="Policy">
+ <SubsystemInclude Path="CapSubsystem.xml"/>
+</SystemClass>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapProductStrategies.xml b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapProductStrategies.xml
new file mode 100644
index 0000000..61f056a
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapProductStrategies.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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.
+-->
+<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
+ <!-- This structure is expected to be in the system partition and provisionned a maximum
+ allowed strategies to be used by vendor. -->
+ <ComponentType Name="ProductStrategies" Description="">
+ <Component Name="vx_1000" Type="ProductStrategy" Mapping="Identifier:1000,Name:vx_1000"/>
+ <Component Name="vx_1001" Type="ProductStrategy" Mapping="Identifier:1001,Name:vx_1001"/>
+ <Component Name="vx_1002" Type="ProductStrategy" Mapping="Identifier:1002,Name:vx_1002"/>
+ <Component Name="vx_1003" Type="ProductStrategy" Mapping="Identifier:1003,Name:vx_1003"/>
+ <Component Name="vx_1004" Type="ProductStrategy" Mapping="Identifier:1004,Name:vx_1004"/>
+ <Component Name="vx_1005" Type="ProductStrategy" Mapping="Identifier:1005,Name:vx_1005"/>
+ <Component Name="vx_1006" Type="ProductStrategy" Mapping="Identifier:1006,Name:vx_1006"/>
+ <Component Name="vx_1007" Type="ProductStrategy" Mapping="Identifier:1007,Name:vx_1007"/>
+ <Component Name="vx_1008" Type="ProductStrategy" Mapping="Identifier:1008,Name:vx_1008"/>
+ <Component Name="vx_1009" Type="ProductStrategy" Mapping="Identifier:1009,Name:vx_1009"/>
+ <Component Name="vx_1010" Type="ProductStrategy" Mapping="Identifier:1010,Name:vx_1010"/>
+ <Component Name="vx_1011" Type="ProductStrategy" Mapping="Identifier:1011,Name:vx_1011"/>
+ <Component Name="vx_1012" Type="ProductStrategy" Mapping="Identifier:1012,Name:vx_1012"/>
+ <Component Name="vx_1013" Type="ProductStrategy" Mapping="Identifier:1013,Name:vx_1013"/>
+ <Component Name="vx_1014" Type="ProductStrategy" Mapping="Identifier:1014,Name:vx_1014"/>
+ <Component Name="vx_1015" Type="ProductStrategy" Mapping="Identifier:1015,Name:vx_1015"/>
+ <Component Name="vx_1016" Type="ProductStrategy" Mapping="Identifier:1016,Name:vx_1016"/>
+ <Component Name="vx_1017" Type="ProductStrategy" Mapping="Identifier:1017,Name:vx_1017"/>
+ <Component Name="vx_1018" Type="ProductStrategy" Mapping="Identifier:1018,Name:vx_1018"/>
+ <Component Name="vx_1019" Type="ProductStrategy" Mapping="Identifier:1019,Name:vx_1019"/>
+ <Component Name="vx_1020" Type="ProductStrategy" Mapping="Identifier:1020,Name:vx_1020"/>
+ <Component Name="vx_1021" Type="ProductStrategy" Mapping="Identifier:1021,Name:vx_1021"/>
+ <Component Name="vx_1022" Type="ProductStrategy" Mapping="Identifier:1022,Name:vx_1022"/>
+ <Component Name="vx_1023" Type="ProductStrategy" Mapping="Identifier:1023,Name:vx_1023"/>
+ <Component Name="vx_1024" Type="ProductStrategy" Mapping="Identifier:1024,Name:vx_1024"/>
+ <Component Name="vx_1025" Type="ProductStrategy" Mapping="Identifier:1025,Name:vx_1025"/>
+ <Component Name="vx_1026" Type="ProductStrategy" Mapping="Identifier:1026,Name:vx_1026"/>
+ <Component Name="vx_1027" Type="ProductStrategy" Mapping="Identifier:1027,Name:vx_1027"/>
+ <Component Name="vx_1028" Type="ProductStrategy" Mapping="Identifier:1028,Name:vx_1028"/>
+ <Component Name="vx_1029" Type="ProductStrategy" Mapping="Identifier:1029,Name:vx_1029"/>
+ <Component Name="vx_1030" Type="ProductStrategy" Mapping="Identifier:1030,Name:vx_1030"/>
+ <Component Name="vx_1031" Type="ProductStrategy" Mapping="Identifier:1031,Name:vx_1031"/>
+ <Component Name="vx_1032" Type="ProductStrategy" Mapping="Identifier:1032,Name:vx_1032"/>
+ <Component Name="vx_1033" Type="ProductStrategy" Mapping="Identifier:1033,Name:vx_1033"/>
+ <Component Name="vx_1034" Type="ProductStrategy" Mapping="Identifier:1034,Name:vx_1034"/>
+ <Component Name="vx_1035" Type="ProductStrategy" Mapping="Identifier:1035,Name:vx_1035"/>
+ <Component Name="vx_1036" Type="ProductStrategy" Mapping="Identifier:1036,Name:vx_1036"/>
+ <Component Name="vx_1037" Type="ProductStrategy" Mapping="Identifier:1037,Name:vx_1037"/>
+ <Component Name="vx_1038" Type="ProductStrategy" Mapping="Identifier:1038,Name:vx_1038"/>
+ <Component Name="vx_1039" Type="ProductStrategy" Mapping="Identifier:1039,Name:vx_1039"/>
+ </ComponentType>
+</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem-CommonTypes.xml.in b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem-CommonTypes.xml.in
new file mode 100644
index 0000000..2c4c7b5
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem-CommonTypes.xml.in
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
+ <!-- Output devices definition as a bitfield for the supported devices per output
+ profile. It must match with the output device enum parameter.
+ -->
+ <!--#################### GLOBAL COMPONENTS BEGIN ####################-->
+
+ <!--#################### GLOBAL COMPONENTS END ####################-->
+
+ <!-- Automatically filled from audio-base.h file -->
+ <ComponentType Name="OutputDevicesMask" Description="64bit representation of devices">
+ <BitParameterBlock Name="mask" Size="64">
+ </BitParameterBlock>
+ </ComponentType>
+
+ <!-- Input devices definition as a bitfield for the supported devices per Input
+ profile. It must match with the Input device enum parameter.
+ -->
+ <!-- Automatically filled from audio-base.h file -->
+ <ComponentType Name="InputDevicesMask" Description="64bit representation of devices">
+ <BitParameterBlock Name="mask" Size="64">
+ </BitParameterBlock>
+ </ComponentType>
+
+ <!--#################### STREAM COMMON TYPES BEGIN ####################-->
+ <!-- Automatically filled from audio-base.h file. VolumeProfileType is associated to stream type -->
+ <ComponentType Name="VolumeProfileType">
+ <EnumParameter Name="volume_profile" Size="32">
+ </EnumParameter>
+ </ComponentType>
+
+ <ComponentType Name="Stream" Mapping="Stream">
+ <Component Name="applicable_volume_profile" Type="VolumeProfileType"
+ Description="Volume profile followed by a given stream type."/>
+ </ComponentType>
+
+ <!--#################### STREAM COMMON TYPES END ####################-->
+
+ <!--#################### INPUT SOURCE COMMON TYPES BEGIN ####################-->
+
+ <ComponentType Name="InputSource">
+ <Component Name="applicable_input_device" Type="InputDevicesMask"
+ Mapping="InputSource" Description="Selected Input device"/>
+ </ComponentType>
+
+ <!--#################### INPUT SOURCE COMMON TYPES END ####################-->
+
+ <!--#################### PRODUCT STRATEGY COMMON TYPES BEGIN ####################-->
+
+ <ComponentType Name="ProductStrategy" Mapping="ProductStrategy">
+ <Component Name="selected_output_devices" Type="OutputDevicesMask"/>
+ <StringParameter Name="device_address" MaxLength="256"
+ Description="if any, device address associated"/>
+ </ComponentType>
+
+ <!--#################### PRODUCT STRATEGY COMMON TYPES END ####################-->
+
+</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem.xml b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem.xml
new file mode 100644
index 0000000..45a0bd4
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<Subsystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xsi:noNamespaceSchemaLocation="Schemas/Subsystem.xsd"
+ Name="policy" Type="Policy">
+
+ <ComponentLibrary>
+ <!--#################### GLOBAL COMPONENTS BEGIN ####################-->
+ <!-- Common Types definition -->
+ <xi:include href="CapSubsystem-CommonTypes.xml"/>
+ <xi:include href="CapProductStrategies.xml"/>
+
+
+ <!--#################### GLOBAL COMPONENTS END ####################-->
+
+ <!--#################### STREAM BEGIN ####################-->
+
+ <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition">
+ <Component Name="voice_call" Type="Stream" Mapping="Name:AUDIO_STREAM_VOICE_CALL"/>
+ <Component Name="system" Type="Stream" Mapping="Name:AUDIO_STREAM_SYSTEM"/>
+ <Component Name="ring" Type="Stream" Mapping="Name:AUDIO_STREAM_RING"/>
+ <Component Name="music" Type="Stream" Mapping="Name:AUDIO_STREAM_MUSIC"/>
+ <Component Name="alarm" Type="Stream" Mapping="Name:AUDIO_STREAM_ALARM"/>
+ <Component Name="notification" Type="Stream" Mapping="Name:AUDIO_STREAM_NOTIFICATION"/>
+ <Component Name="bluetooth_sco" Type="Stream" Mapping="Name:AUDIO_STREAM_BLUETOOTH_SCO"/>
+ <Component Name="enforced_audible" Type="Stream" Mapping="Name:AUDIO_STREAM_ENFORCED_AUDIBLE"
+ Description="Sounds that cannot be muted by user and must be routed to speaker"/>
+ <Component Name="dtmf" Type="Stream" Mapping="Name:AUDIO_STREAM_DTMF"/>
+ <Component Name="tts" Type="Stream" Mapping="Name:AUDIO_STREAM_TTS"
+ Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
+ <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
+ Description="For accessibility talk back prompts"/>
+ <Component Name="assistant" Type="Stream" Mapping="Name:AUDIO_STREAM_ASSISTANT"
+ Description="used by a virtual assistant like Google Assistant, Bixby, etc."/>
+ <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
+ Description="For dynamic policy output mixes"/>
+ <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
+ Description="For internal audio flinger tracks. Fixed volume"/>
+ </ComponentType>
+
+ <!--#################### STREAM END ####################-->
+
+ <!--#################### INPUT SOURCE BEGIN ####################-->
+
+ <ComponentType Name="InputSources" Description="associated to audio_source_t definition,
+ identifier mapping must match the value of the enum">
+ <Component Name="default" Type="InputSource" Mapping="Name:AUDIO_SOURCE_DEFAULT"/>
+ <Component Name="mic" Type="InputSource" Mapping="Name:AUDIO_SOURCE_MIC"/>
+ <Component Name="voice_uplink" Type="InputSource"
+ Mapping="Name:AUDIO_SOURCE_VOICE_UPLINK"/>
+ <Component Name="voice_downlink" Type="InputSource"
+ Mapping="Name:AUDIO_SOURCE_VOICE_DOWNLINK"/>
+ <Component Name="voice_call" Type="InputSource"
+ Mapping="Name:AUDIO_SOURCE_VOICE_CALL"/>
+ <Component Name="camcorder" Type="InputSource" Mapping="Name:AUDIO_SOURCE_CAMCORDER"/>
+ <Component Name="voice_recognition" Type="InputSource"
+ Mapping="Name:AUDIO_SOURCE_VOICE_RECOGNITION"/>
+ <Component Name="voice_communication" Type="InputSource"
+ Mapping="Name:AUDIO_SOURCE_VOICE_COMMUNICATION"/>
+ <Component Name="remote_submix" Type="InputSource"
+ Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
+ <Component Name="unprocessed" Type="InputSource"
+ Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
+ <Component Name="voice_performance" Type="InputSource"
+ Mapping="Name:AUDIO_SOURCE_VOICE_PERFORMANCE"/>
+ <Component Name="echo_reference" Type="InputSource"
+ Mapping="Name:AUDIO_SOURCE_ECHO_REFERENCE"/>
+ <Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
+ <Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
+ </ComponentType>
+ <!--#################### INPUT SOURCE END ####################-->
+ </ComponentLibrary>
+
+ <InstanceDefinition>
+ <Component Name="streams" Type="Streams"/>
+ <Component Name="input_sources" Type="InputSources"/>
+ <Component Name="product_strategies" Type="ProductStrategies"/>
+ </InstanceDefinition>
+</Subsystem>
diff --git a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
index 9fd8b8e..e0b7210 100644
--- a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
+++ b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
@@ -98,7 +98,8 @@
virtual bool setDeviceTypesForProductStrategy(product_strategy_t strategy,
uint64_t devices) = 0;
- virtual product_strategy_t getProductStrategyByName(const std::string &address) = 0;
+ virtual product_strategy_t getProductStrategyByName(const std::string &name) = 0;
+ virtual std::string getProductStrategyName(product_strategy_t id) const = 0;
protected:
virtual ~AudioPolicyPluginInterface() {}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
index 7fe111f..e4f44d5 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
@@ -50,6 +50,7 @@
genrule {
name: "buildcommontypesstructure_gen",
defaults: ["buildcommontypesstructurerule"],
+ out: ["PolicySubsystem-CommonTypes.xml"],
}
filegroup {
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
index 8bd7f66..bf5767d 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
@@ -72,7 +72,7 @@
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<ProductStrategy>(
- mProductStrategyComponentName, (1 << MappingKeyName))
+ mProductStrategyComponentName, (1 << MappingKeyName) | (1 << MappingKeyIdentifier))
);
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
index ebd9456..06efbf28 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
@@ -18,10 +18,7 @@
#include "PolicyMappingKeys.h"
#include "PolicySubsystem.h"
-using std::string;
-using android::product_strategy_t;
-
-ProductStrategy::ProductStrategy(const string &mappingValue,
+ProductStrategy::ProductStrategy(const std::string &mappingValue,
CInstanceConfigurableElement *instanceConfigurableElement,
const CMappingContext &context,
core::log::Logger& logger)
@@ -30,26 +27,32 @@
mappingValue,
MappingKeyAmend1,
(MappingKeyAmendEnd - MappingKeyAmend1 + 1),
- context)
-{
- std::string name(context.getItem(MappingKeyName));
+ context) {
+
+ size_t id = context.getItemAsInteger(MappingKeyIdentifier);
+ std::string nameFromStructure(context.getItem(MappingKeyName));
ALOG_ASSERT(instanceConfigurableElement != nullptr, "Invalid Configurable Element");
mPolicySubsystem = static_cast<const PolicySubsystem *>(
- instanceConfigurableElement->getBelongingSubsystem());
+ instanceConfigurableElement->getBelongingSubsystem());
ALOG_ASSERT(mPolicySubsystem != nullptr, "Invalid Policy Subsystem");
mPolicyPluginInterface = mPolicySubsystem->getPolicyPluginInterface();
ALOG_ASSERT(mPolicyPluginInterface != nullptr, "Invalid Policy Plugin Interface");
- mId = mPolicyPluginInterface->getProductStrategyByName(name);
+ mId = static_cast<android::product_strategy_t>(id);
+ std::string name = mPolicyPluginInterface->getProductStrategyName(mId);
+ if (name.empty()) {
+ name = nameFromStructure;
+ mId = mPolicyPluginInterface->getProductStrategyByName(name);
+ }
ALOG_ASSERT(mId != PRODUCT_STRATEGY_INVALID, "Product Strategy %s not found", name.c_str());
ALOGE("Product Strategy %s added", name.c_str());
}
-bool ProductStrategy::sendToHW(string & /*error*/)
+bool ProductStrategy::sendToHW(std::string & /*error*/)
{
Device deviceParams;
blackboardRead(&deviceParams, sizeof(deviceParams));
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index ccd4316..45da7b0 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -71,27 +71,75 @@
}
status_t Engine::loadFromHalConfigWithFallback(
- const media::audio::common::AudioHalEngineConfig& config __unused) {
- // b/242678729. Need to implement for the configurable engine.
- return INVALID_OPERATION;
-}
+ const media::audio::common::AudioHalEngineConfig& aidlConfig) {
-status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
-{
- status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
- if (loadResult < 0) {
- ALOGE("Policy Engine configuration is invalid.");
+ auto capResult = capEngineConfig::convert(aidlConfig);
+ if (capResult.parsedConfig == nullptr) {
+ ALOGE("%s CapEngine Config invalid", __func__);
+ return BAD_VALUE;
}
- return loadResult;
-}
-
-status_t Engine::initCheck()
-{
+ status_t ret = loadWithFallback(aidlConfig);
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+ auto loadCriteria= [this](const auto& capCriteria) {
+ for (auto& capCriterion : capCriteria) {
+ mPolicyParameterMgr->addCriterion(capCriterion.criterion.name,
+ capCriterion.criterionType.isInclusive,
+ capCriterion.criterionType.valuePairs,
+ capCriterion.criterion.defaultLiteralValue);
+ }
+ };
+ loadCriteria(capResult.parsedConfig->capCriteria);
std::string error;
if (mPolicyParameterMgr == nullptr || mPolicyParameterMgr->start(error) != NO_ERROR) {
ALOGE("%s: could not start Policy PFW: %s", __FUNCTION__, error.c_str());
return NO_INIT;
}
+ return mPolicyParameterMgr->setConfiguration(capResult);
+}
+
+status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
+{
+ status_t status = loadWithFallback(xmlFilePath);
+ std::string error;
+ if (mPolicyParameterMgr == nullptr || mPolicyParameterMgr->start(error) != NO_ERROR) {
+ ALOGE("%s: could not start Policy PFW: %s", __FUNCTION__, error.c_str());
+ return NO_INIT;
+ }
+ return status;
+}
+
+template<typename T>
+status_t Engine::loadWithFallback(const T& configSource) {
+ auto result = EngineBase::loadAudioPolicyEngineConfig(configSource);
+ ALOGE_IF(result.nbSkippedElement != 0,
+ "Policy Engine configuration is partially invalid, skipped %zu elements",
+ result.nbSkippedElement);
+
+ auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
+ for (auto& criterion : configCriteria) {
+ engineConfig::CriterionType criterionType;
+ for (auto &configCriterionType : configCriterionTypes) {
+ if (configCriterionType.name == criterion.typeName) {
+ criterionType = configCriterionType;
+ break;
+ }
+ }
+ ALOG_ASSERT(not criterionType.name.empty(), "Invalid criterion type for %s",
+ criterion.name.c_str());
+ mPolicyParameterMgr->addCriterion(criterion.name, criterionType.isInclusive,
+ criterionType.valuePairs,
+ criterion.defaultLiteralValue);
+ }
+ };
+
+ loadCriteria(result.parsedConfig->criteria, result.parsedConfig->criterionTypes);
+ return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
+}
+
+status_t Engine::initCheck()
+{
return EngineBase::initCheck();
}
@@ -199,32 +247,6 @@
return EngineBase::setDeviceConnectionState(device, state);
}
-status_t Engine::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
-{
- auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
-
- // Custom XML Parsing
- auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
- for (auto& criterion : configCriteria) {
- engineConfig::CriterionType criterionType;
- for (auto &configCriterionType : configCriterionTypes) {
- if (configCriterionType.name == criterion.typeName) {
- criterionType = configCriterionType;
- break;
- }
- }
- ALOG_ASSERT(not criterionType.name.empty(), "Invalid criterion type for %s",
- criterion.name.c_str());
- mPolicyParameterMgr->addCriterion(criterion.name, criterionType.isInclusive,
- criterionType.valuePairs,
- criterion.defaultLiteralValue);
- }
- };
-
- loadCriteria(result.parsedConfig->criteria, result.parsedConfig->criterionTypes);
- return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
-}
-
status_t Engine::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
const AudioDeviceTypeAddrVector &devices)
{
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 4f3e620..d9ebbe7 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -16,10 +16,11 @@
#pragma once
-#include "EngineBase.h"
-#include <EngineInterface.h>
-#include <AudioPolicyPluginInterface.h>
#include "Collection.h"
+#include "EngineBase.h"
+#include <AudioPolicyPluginInterface.h>
+#include <CapEngineConfig.h>
+#include <EngineInterface.h>
namespace android {
class AudioPolicyManagerObserver;
@@ -107,8 +108,14 @@
{
return EngineBase::getProductStrategyByName(name);
}
+ std::string getProductStrategyName(product_strategy_t id) const override {
+ return EngineBase::getProductStrategyName(id);
+ }
private:
+ template<typename T>
+ status_t loadWithFallback(const T& configSource);
+
android::status_t disableDevicesForStrategy(product_strategy_t strategy,
const DeviceVector &devicesToDisable);
void enableDevicesForStrategy(product_strategy_t strategy, const DeviceVector &devicesToEnable);
@@ -140,8 +147,6 @@
template <typename Property, typename Key>
bool setPropertyForKey(const Property &property, const Key &key);
- status_t loadAudioPolicyEngineConfig(const std::string& xmlFilePath);
-
DeviceVector getCachedDevices(product_strategy_t ps) const;
///
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index d1fb2fb..7ae124c 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -23,7 +23,7 @@
}
//##################################################################################################
-// Tools for audio policy engine criterion type configuration file
+// Legacy tools for audio policy engine criterion type configuration file
//
python_binary_host {
name: "buildPolicyCriterionTypes",
@@ -57,6 +57,40 @@
}
//##################################################################################################
+// Tools for audio policy engine criterion type configuration file
+//
+python_binary_host {
+ name: "capBuildPolicyCriterionTypes",
+ main: "capBuildPolicyCriterionTypes.py",
+ srcs: [
+ "capBuildPolicyCriterionTypes.py",
+ ],
+}
+
+genrule_defaults {
+ name: "capbuildpolicycriteriontypesrule",
+ tools: ["capBuildPolicyCriterionTypes"],
+ cmd: "cp $(locations :audio_policy_configuration_files) $(genDir)/. && " +
+ "cp $(location :audio_policy_configuration_top_file) $(genDir)/audio_policy_configuration.xml && " +
+ "$(location capBuildPolicyCriterionTypes) " +
+ " --androidaudiobaseheader $(location :libaudio_system_audio_base) " +
+ " --androidaudiocommonbaseheader $(location :libaudio_system_audio_common_base) " +
+ "--audiopolicyconfigurationfile $(genDir)/audio_policy_configuration.xml " +
+ "--criteriontypes $(location :audio_policy_engine_aidl_criterion_types_template) " +
+ "--outputfile $(out)",
+ srcs: [
+ // The commented inputs must be provided to use this genrule_defaults
+ // @todo uncomment if 1428659 is merged":android_audio_base_header_file",
+ ":audio_policy_engine_aidl_criterion_types_template",
+ ":libaudio_system_audio_base",
+ ":libaudio_system_audio_common_base",
+ // ":audio_policy_configuration_top_file",
+ // ":audio_policy_configuration_files",
+ ],
+ out: ["audio_policy_engine_criterion_types.xml"],
+}
+
+//##################################################################################################
// Tools for audio policy engine parameter framework configurable domains
//
python_binary_host {
@@ -84,6 +118,7 @@
cmd: "mkdir -p $(genDir)/Structure/Policy && " +
"cp $(locations :audio_policy_pfw_structure_files) $(genDir)/Structure/Policy && " +
"cp $(location :audio_policy_pfw_toplevel) $(genDir)/top_level && " +
+ "sed -i -e 's|TuningAllowed=\"false\"|TuningAllowed=\"true\" ServerPort=\"unix:///dev/socket/audioserver/policy_debug\"|g' $(genDir)/top_level &&" +
"$(location domainGeneratorPolicy) " +
"--validate " +
"--domain-generator-tool $(location domainGeneratorConnector) " +
@@ -106,7 +141,7 @@
}
//##################################################################################################
-// Tools for policy parameter-framework product strategies structure file generation
+// Legacy tools for policy parameter-framework product strategies structure file generation
//
python_binary_host {
name: "buildStrategiesStructureFile",
@@ -154,5 +189,4 @@
":common_types_structure_template",
":libaudio_system_audio_base",
],
- out: ["PolicySubsystem-CommonTypes.xml"],
}
diff --git a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
index f69d346..6eabc57 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
@@ -75,7 +75,7 @@
strategy_components = strategies_root.find('ComponentType')
for strategy_name in strategies:
- context_mapping = "".join(map(str, ["Name:", strategy_name]))
+ context_mapping = "".join(map(str, ["Identifier:-1,Name:", strategy_name]))
strategy_pfw_name = strategy_name.replace('STRATEGY_', '').lower()
ET.SubElement(strategy_components, "Component",
Name=strategy_pfw_name, Type="ProductStrategy",
diff --git a/services/audiopolicy/engineconfigurable/tools/capBuildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/capBuildPolicyCriterionTypes.py
new file mode 100755
index 0000000..b873830
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/capBuildPolicyCriterionTypes.py
@@ -0,0 +1,368 @@
+#!/usr/bin/python3
+
+#
+# Copyright 2018, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import argparse
+import re
+import sys
+import os
+import logging
+import xml.etree.ElementTree as ET
+import xml.etree.ElementInclude as EI
+import xml.dom.minidom as MINIDOM
+from collections import OrderedDict
+
+#
+# Helper script that helps to feed at build time the XML criterion types file used by
+# the engineconfigurable to start the parameter-framework.
+# It prevents to fill them manually and avoid divergences with android.
+#
+# The Device Types criterion types are fed from audio-base.h file with the option
+# --androidaudiobaseheader <path/to/android/audio/base/file/audio-base.h>
+#
+# The Device Addresses criterion types are fed from the audio policy configuration file
+# in order to discover all the devices for which the address matter.
+# --audiopolicyconfigurationfile <path/to/audio_policy_configuration.xml>
+#
+# The reference file of criterion types must also be set as an input of the script:
+# --criteriontypes <path/to/criterion/file/audio_criterion_types.xml.in>
+#
+# At last, the output of the script shall be set also:
+# --outputfile <path/to/out/vendor/etc/audio_criterion_types.xml>
+#
+
+def parseArgs():
+ argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+ audio criterion type file generator.\n\
+ Exit with the number of (recoverable or not) \
+ error that occurred.")
+ argparser.add_argument('--androidaudiobaseheader',
+ help="Android Audio Base C header file, Mandatory.",
+ metavar="ANDROID_AUDIO_BASE_HEADER",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--androidaudiocommonbaseheader',
+ help="Android Audio CommonBase C header file, Mandatory.",
+ metavar="ANDROID_AUDIO_COMMON_BASE_HEADER",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--audiopolicyconfigurationfile',
+ help="Android Audio Policy Configuration file, Mandatory.",
+ metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--criteriontypes',
+ help="Criterion types XML base file, in \
+ '<criterion_types> \
+ <criterion_type name="" type=<inclusive|exclusive> \
+ values=<value1,value2,...>/>' \
+ format. Mandatory.",
+ metavar="CRITERION_TYPE_FILE",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--outputfile',
+ help="Criterion types outputfile file. Mandatory.",
+ metavar="CRITERION_TYPE_OUTPUT_FILE",
+ type=argparse.FileType('w'),
+ required=True)
+ argparser.add_argument('--verbose',
+ action='store_true')
+
+ return argparser.parse_args()
+
+
+output_devices_type_value = {}
+input_devices_type_value = {}
+
+def generateXmlCriterionTypesFile(criterionTypes, addressCriteria, criterionTypesFile, outputFile):
+
+ logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+ criterion_types_in_tree = ET.parse(criterionTypesFile)
+
+ criterion_types_root = criterion_types_in_tree.getroot()
+
+ for criterion_name, values_dict in criterionTypes.items():
+ for criterion_type in criterion_types_root.findall('criterion_type'):
+ if criterion_type.get('name') == criterion_name:
+ values_node = ET.SubElement(criterion_type, "values")
+ ordered_values = OrderedDict(sorted(values_dict.items(), key=lambda x: x[1]))
+ for key, value in ordered_values.items():
+ value_node = ET.SubElement(values_node, "value")
+ value_node.set('numerical', str(value))
+ value_node.set('literal', key)
+
+ if criterion_type.get('name') == "OutputDevicesMaskType":
+ value_node.set('android_type', output_devices_type_value[key])
+ if criterion_type.get('name') == "InputDevicesMaskType":
+ value_node.set('android_type', input_devices_type_value[key])
+
+ if addressCriteria:
+ for criterion_name, values_list in addressCriteria.items():
+ for criterion_type in criterion_types_root.findall('criterion_type'):
+ if criterion_type.get('name') == criterion_name:
+ index = 0
+ existing_values_node = criterion_type.find("values")
+ if existing_values_node is not None:
+ for existing_value in existing_values_node.findall('value'):
+ if existing_value.get('numerical') == str(1 << index):
+ index += 1
+ values_node = existing_values_node
+ else:
+ values_node = ET.SubElement(criterion_type, "values")
+
+ for value in values_list:
+ value_node = ET.SubElement(values_node, "value", literal=value)
+ value_node.set('numerical', str(1 << index))
+ index += 1
+
+ xmlstr = ET.tostring(criterion_types_root, encoding='utf8', method='xml')
+ reparsed = MINIDOM.parseString(xmlstr)
+ prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
+ prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
+ outputFile.write(prettyXmlStr)
+
+def capitalizeLine(line):
+ return ' '.join((w.capitalize() for w in line.split(' ')))
+
+
+#
+# Parse the audio policy configuration file and output a dictionary of device criteria addresses
+#
+def parseAndroidAudioPolicyConfigurationFile(audiopolicyconfigurationfile):
+
+ logging.info("Checking Audio Policy Configuration file {}".format(audiopolicyconfigurationfile))
+ #
+ # extract all devices addresses from audio policy configuration file
+ #
+ address_criteria_mapping_table = {
+ 'sink' : "OutputDevicesAddressesType",
+ 'source' : "InputDevicesAddressesType"}
+
+ address_criteria = {
+ 'OutputDevicesAddressesType' : [],
+ 'InputDevicesAddressesType' : []}
+
+ old_working_dir = os.getcwd()
+ print("Current working directory %s" % old_working_dir)
+
+ new_dir = os.path.join(old_working_dir, audiopolicyconfigurationfile.name)
+
+ policy_in_tree = ET.parse(audiopolicyconfigurationfile)
+ os.chdir(os.path.dirname(os.path.normpath(new_dir)))
+
+ print("new working directory %s" % os.getcwd())
+
+ policy_root = policy_in_tree.getroot()
+ EI.include(policy_root)
+
+ os.chdir(old_working_dir)
+
+ for device in policy_root.iter('devicePort'):
+ for key in address_criteria_mapping_table.keys():
+ if device.get('role') == key and device.get('address'):
+ logging.info("{}: <{}>".format(key, device.get('address')))
+ address_criteria[address_criteria_mapping_table[key]].append(device.get('address'))
+
+ for criteria in address_criteria:
+ values = ','.join(address_criteria[criteria])
+ logging.info("{}: <{}>".format(criteria, values))
+
+ return address_criteria
+
+#
+# Parse the audio-base.h file and output a dictionary of android dependent criterion types:
+# -Android Mode
+# -Output devices type
+# -Input devices type
+#
+def parseAndroidAudioFile(androidaudiobaseheaderFile, androidaudiocommonbaseheaderFile):
+ #
+ # Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
+ #
+ criterion_mapping_table = {
+ 'HAL_AUDIO_MODE' : "AndroidModeType",
+ 'AUDIO_DEVICE_OUT' : "OutputDevicesMaskType",
+ 'AUDIO_DEVICE_IN' : "InputDevicesMaskType"}
+
+ all_criteria = {
+ 'AndroidModeType' : {},
+ 'OutputDevicesMaskType' : {},
+ 'InputDevicesMaskType' : {}}
+
+ #
+ # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
+ #
+ ignored_values = ['CNT', 'MAX', 'ALL', 'NONE']
+
+ multi_bit_outputdevice_shift = 32
+ multi_bit_inputdevice_shift = 32
+
+ criteria_pattern = re.compile(
+ r"\s*V\((?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+ r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*,\s*" \
+ r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
+
+ logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
+
+ for line_number, line in enumerate(androidaudiobaseheaderFile):
+ match = criteria_pattern.match(line)
+ if match:
+ logging.debug("The following line is VALID: {}:{}\n{}".format(
+ androidaudiobaseheaderFile.name, line_number, line))
+
+ criterion_name = criterion_mapping_table[match.groupdict()['type']]
+ criterion_literal = ''.join(match.groupdict()['literal'])
+ criterion_numerical_value = match.groupdict()['values']
+
+ if criterion_name == "InputDevicesMaskType":
+ # Remove ambient and in_communication since they were deprecated
+ logging.info("Remove deprecated device {}".format(criterion_literal))
+ if criterion_literal == "AMBIENT" or criterion_literal == "COMMUNICATION":
+ logging.info("Remove deprecated device {}".format(criterion_literal))
+ continue
+ # for AUDIO_DEVICE_IN: rename default to stub
+ elif criterion_literal == "DEFAULT":
+ criterion_numerical_value = str(int("0x40000000", 0))
+ input_devices_type_value[criterion_literal] = "0xC0000000"
+ else:
+ try:
+ string_int = int(criterion_numerical_value, 0)
+ # Append AUDIO_DEVICE_IN for android type tag
+ input_devices_type_value[criterion_literal] = hex(string_int | 2147483648)
+
+ num_bits = bin(string_int).count("1")
+ if num_bits > 1:
+ logging.info("The value {}:{} is for criterion {} binary rep {} has {} bits sets"
+ .format(criterion_numerical_value, criterion_literal, criterion_name, bin(string_int), num_bits))
+ string_int = 2**multi_bit_inputdevice_shift
+ logging.info("new val assigned is {} {}" .format(string_int, bin(string_int)))
+ multi_bit_inputdevice_shift += 1
+ criterion_numerical_value = str(string_int)
+
+ except ValueError:
+ # Handle the exception
+ logging.info("value {}:{} for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
+
+ if criterion_name == "OutputDevicesMaskType":
+ if criterion_literal == "DEFAULT":
+ criterion_numerical_value = str(int("0x40000000", 0))
+ output_devices_type_value[criterion_literal] = "0x40000000"
+ else:
+ try:
+ string_int = int(criterion_numerical_value, 0)
+ output_devices_type_value[criterion_literal] = criterion_numerical_value
+
+ num_bits = bin(string_int).count("1")
+ if num_bits > 1:
+ logging.info("The value {}:{} is for criterion {} binary rep {} has {} bits sets"
+ .format(criterion_numerical_value, criterion_literal, criterion_name, bin(string_int), num_bits))
+ string_int = 2**multi_bit_outputdevice_shift
+ logging.info("new val assigned is {} {}" .format(string_int, bin(string_int)))
+ multi_bit_outputdevice_shift += 1
+ criterion_numerical_value = str(string_int)
+
+ except ValueError:
+ # Handle the exception
+ logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
+
+ try:
+ string_int = int(criterion_numerical_value, 0)
+
+ except ValueError:
+ # Handle the exception
+ logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
+
+ # Remove duplicated numerical values
+ if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
+ logging.info("criterion {} duplicated values:".format(criterion_name))
+ logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
+ logging.info("KEEPING LATEST")
+ for key in list(all_criteria[criterion_name]):
+ if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
+ del all_criteria[criterion_name][key]
+
+ all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
+
+ logging.debug("type:{},".format(criterion_name))
+ logging.debug("iteral:{},".format(criterion_literal))
+ logging.debug("values:{}.".format(criterion_numerical_value))
+
+ logging.info("Checking Android Common Header file {}".format(androidaudiocommonbaseheaderFile))
+
+ criteria_pattern = re.compile(
+ r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+ r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
+ r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
+
+ for line_number, line in enumerate(androidaudiocommonbaseheaderFile):
+ match = criteria_pattern.match(line)
+ if match:
+ logging.debug("The following line is VALID: {}:{}\n{}".format(
+ androidaudiocommonbaseheaderFile.name, line_number, line))
+
+ criterion_name = criterion_mapping_table[match.groupdict()['type']]
+ criterion_literal = ''.join(match.groupdict()['literal'])
+ criterion_numerical_value = match.groupdict()['values']
+
+ try:
+ string_int = int(criterion_numerical_value, 0)
+ except ValueError:
+ # Handle the exception
+ logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+ .format(criterion_numerical_value, criterion_literal, criterion_name))
+ continue
+
+ # Remove duplicated numerical values
+ if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
+ logging.info("criterion {} duplicated values:".format(criterion_name))
+ logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
+ logging.info("KEEPING LATEST")
+ for key in list(all_criteria[criterion_name]):
+ if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
+ del all_criteria[criterion_name][key]
+
+ all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
+
+ logging.debug("type:{},".format(criterion_name))
+ logging.debug("iteral:{},".format(criterion_literal))
+ logging.debug("values:{}.".format(criterion_numerical_value))
+
+ return all_criteria
+
+
+def main():
+ logging.root.setLevel(logging.INFO)
+ args = parseArgs()
+
+ all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader,
+ args.androidaudiocommonbaseheader)
+
+ address_criteria = parseAndroidAudioPolicyConfigurationFile(args.audiopolicyconfigurationfile)
+
+ criterion_types = args.criteriontypes
+
+ generateXmlCriterionTypesFile(all_criteria, address_criteria, criterion_types, args.outputfile)
+
+# If this file is directly executed
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/services/audiopolicy/engineconfigurable/wrapper/Android.bp b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
index 78d5fa3..506b19b 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.bp
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
@@ -19,10 +19,12 @@
],
header_libs: [
"libaudiofoundation_headers",
+ "libaudiopolicycapengine_config_headers",
"libaudiopolicycommon",
"libbase_headers",
],
shared_libs: [
+ "libaudiopolicyengine_config",
"liblog",
"libmedia_helper",
"libparameter",
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 099d55d..0bcde8d 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -18,13 +18,13 @@
//#define LOG_NDEBUG 0
#include "ParameterManagerWrapper.h"
+#include <ParameterMgrFullConnector.h>
#include <ParameterMgrPlatformConnector.h>
#include <SelectionCriterionTypeInterface.h>
#include <SelectionCriterionInterface.h>
#include <media/convert.h>
#include <algorithm>
#include <cutils/bitops.h>
-#include <cutils/config_utils.h>
#include <cutils/misc.h>
#include <fstream>
#include <limits>
@@ -64,31 +64,10 @@
namespace audio_policy {
const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
- "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
+ "/etc/parameter-framework/ParameterFrameworkConfigurationCap.xml";
const char *const ParameterManagerWrapper::mPolicyPfwVendorConfFileName =
"/vendor/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
-static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
-static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
-static const char *const gPhoneStateCriterionName = "TelephonyMode";
-static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
-static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
-
-/**
- * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
- */
-static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
-{
- [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] = "ForceUseForCommunication",
- [AUDIO_POLICY_FORCE_FOR_MEDIA] = "ForceUseForMedia",
- [AUDIO_POLICY_FORCE_FOR_RECORD] = "ForceUseForRecord",
- [AUDIO_POLICY_FORCE_FOR_DOCK] = "ForceUseForDock",
- [AUDIO_POLICY_FORCE_FOR_SYSTEM] = "ForceUseForSystem",
- [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] = "ForceUseForHdmiSystemAudio",
- [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround",
- [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] = "ForceUseForVibrateRinging"
-};
-
template <>
struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
template <>
@@ -100,9 +79,9 @@
{
// Connector
if (access(mPolicyPfwVendorConfFileName, R_OK) == 0) {
- mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwVendorConfFileName);
+ mPfwConnector = new CParameterMgrFullConnector(mPolicyPfwVendorConfFileName);
} else {
- mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName);
+ mPfwConnector = new CParameterMgrFullConnector(mPolicyPfwDefaultConfFileName);
}
// Logger
@@ -130,13 +109,13 @@
std::get<2>(pair).c_str(), name.c_str());
criterionType->addValuePair(std::get<0>(pair), std::get<2>(pair), error);
- if (name == gOutputDeviceCriterionName) {
+ if (name == capEngineConfig::gOutputDeviceCriterionName) {
ALOGV("%s: Adding mOutputDeviceToCriterionTypeMap %d %" PRIu64" for criterionType %s",
__func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
mOutputDeviceToCriterionTypeMap[androidType] = std::get<0>(pair);
}
- if (name == gInputDeviceCriterionName) {
+ if (name == capEngineConfig::gInputDeviceCriterionName) {
ALOGV("%s: Adding mInputDeviceToCriterionTypeMap %d %" PRIu64" for criterionType %s",
__func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
@@ -207,10 +186,11 @@
status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
{
- ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
+ ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+ capEngineConfig::gPhoneStateCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
+ ALOGE("%s: no criterion found for %s", __FUNCTION__,
+ capEngineConfig::gPhoneStateCriterionName);
return BAD_VALUE;
}
if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
@@ -223,10 +203,11 @@
audio_mode_t ParameterManagerWrapper::getPhoneState() const
{
- const ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
+ const ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+ capEngineConfig::gPhoneStateCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
+ ALOGE("%s: no criterion found for %s", __FUNCTION__,
+ capEngineConfig::gPhoneStateCriterionName);
return AUDIO_MODE_NORMAL;
}
return static_cast<audio_mode_t>(criterion->getCriterionState());
@@ -240,10 +221,11 @@
return BAD_VALUE;
}
- ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
+ ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+ capEngineConfig::gForceUseCriterionTag[usage], mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
+ ALOGE("%s: no criterion found for %s", __FUNCTION__,
+ capEngineConfig::gForceUseCriterionTag[usage]);
return BAD_VALUE;
}
if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
@@ -260,10 +242,11 @@
if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
return AUDIO_POLICY_FORCE_NONE;
}
- const ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
+ const ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+ capEngineConfig::gForceUseCriterionTag[usage], mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
+ ALOGE("%s: no criterion found for %s", __FUNCTION__,
+ capEngineConfig::gForceUseCriterionTag[usage]);
return AUDIO_POLICY_FORCE_NONE;
}
return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
@@ -281,8 +264,8 @@
audio_devices_t type, const std::string &address, audio_policy_dev_state_t state)
{
std::string criterionName = audio_is_output_device(type) ?
- gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
-
+ capEngineConfig::gOutputDeviceAddressCriterionName :
+ capEngineConfig::gInputDeviceAddressCriterionName;
ALOGV("%s: device with address %s %s", __FUNCTION__, address.c_str(),
state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
ISelectionCriterionInterface *criterion =
@@ -311,12 +294,12 @@
return NO_ERROR;
}
-status_t ParameterManagerWrapper::setAvailableInputDevices(const DeviceTypeSet &types)
-{
- ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
+status_t ParameterManagerWrapper::setAvailableInputDevices(const DeviceTypeSet &types) {
+ ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+ capEngineConfig::gInputDeviceCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __func__, gInputDeviceCriterionName);
+ ALOGE("%s: no criterion found for %s", __func__,
+ capEngineConfig::gInputDeviceCriterionName);
return DEAD_OBJECT;
}
criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
@@ -324,12 +307,12 @@
return NO_ERROR;
}
-status_t ParameterManagerWrapper::setAvailableOutputDevices(const DeviceTypeSet &types)
-{
- ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
+status_t ParameterManagerWrapper::setAvailableOutputDevices(const DeviceTypeSet &types) {
+ ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+ capEngineConfig::gOutputDeviceCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __func__, gOutputDeviceCriterionName);
+ ALOGE("%s: no criterion found for %s", __func__,
+ capEngineConfig::gOutputDeviceCriterionName);
return DEAD_OBJECT;
}
criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
@@ -344,21 +327,15 @@
uint64_t ParameterManagerWrapper::convertDeviceTypeToCriterionValue(audio_devices_t type) const {
bool isOut = audio_is_output_devices(type);
- uint32_t typeMask = isOut ? type : (type & ~AUDIO_DEVICE_BIT_IN);
-
const auto &adapters = isOut ? mOutputDeviceToCriterionTypeMap : mInputDeviceToCriterionTypeMap;
- // Only multibit devices need adaptation.
- if (popcount(typeMask) > 1) {
- const auto &adapter = adapters.find(type);
- if (adapter != adapters.end()) {
- ALOGV("%s: multibit device %d converted to criterion %" PRIu64, __func__, type,
- adapter->second);
- return adapter->second;
- }
- ALOGE("%s: failed to find map for multibit device %d", __func__, type);
- return 0;
+ const auto &adapter = adapters.find(type);
+ if (adapter != adapters.end()) {
+ ALOGV("%s: multibit device %d converted to criterion %" PRIu64, __func__, type,
+ adapter->second);
+ return adapter->second;
}
- return typeMask;
+ ALOGE("%s: failed to find map for multibit device %d", __func__, type);
+ return 0;
}
uint64_t ParameterManagerWrapper::convertDeviceTypesToCriterionValue(
@@ -382,5 +359,88 @@
return deviceTypes;
}
+void ParameterManagerWrapper::createDomain(const std::string &domain)
+{
+ std::string error;
+ bool ret = mPfwConnector->createDomain(domain, error);
+ if (!ret) {
+ ALOGD("%s: failed to create domain %s (error=%s)", __func__, domain.c_str(),
+ error.c_str());
+ }
+}
+
+void ParameterManagerWrapper::addConfigurableElementToDomain(const std::string &domain,
+ const std::string &elementPath)
+{
+ std::string error;
+ bool ret = mPfwConnector->addConfigurableElementToDomain(domain, elementPath, error);
+ ALOGE_IF(!ret, "%s: failed to add parameter %s for domain %s (error=%s)",
+ __func__, elementPath.c_str(), domain.c_str(), error.c_str());
+}
+
+void ParameterManagerWrapper::createConfiguration(const std::string &domain,
+ const std::string &configurationName)
+{
+ std::string error;
+ bool ret = mPfwConnector->createConfiguration(domain, configurationName, error);
+ ALOGE_IF(!ret, "%s: failed to create configuration %s for domain %s (error=%s)",
+ __func__, configurationName.c_str(), domain.c_str(), error.c_str());
+}
+
+void ParameterManagerWrapper::setApplicationRule(
+ const std::string &domain, const std::string &configurationName, const std::string &rule)
+{
+ std::string error;
+ bool ret = mPfwConnector->setApplicationRule(domain, configurationName, rule, error);
+ ALOGE_IF(!ret, "%s: failed to set rule %s for domain %s and configuration %s (error=%s)",
+ __func__, rule.c_str(), domain.c_str(), configurationName.c_str(), error.c_str());
+}
+
+void ParameterManagerWrapper::accessConfigurationValue(const std::string &domain,
+ const std::string &configurationName, const std::string &elementPath,
+ std::string &value)
+{
+ std::string error;
+ bool ret = mPfwConnector->accessConfigurationValue(domain, configurationName, elementPath,
+ value, /*set=*/ true, error);
+ ALOGE_IF(!ret, "%s: failed to set value %s for parameter %s on domain %s and configuration %s "
+ "(error=%s)", __func__, value.c_str(), elementPath.c_str(), domain.c_str(),
+ configurationName.c_str(), error.c_str());
+}
+
+status_t ParameterManagerWrapper::setConfiguration(
+ const android::capEngineConfig::ParsingResult& capSettings)
+{
+ if (!isStarted()) {
+ return NO_INIT;
+ }
+ std::string error;
+ if (!mPfwConnector->setTuningMode(/* bOn= */ true, error)) {
+ ALOGD("%s: failed to set Tuning Mode error=%s", __FUNCTION__, error.c_str());
+ return DEAD_OBJECT;
+ }
+ for (auto &domain: capSettings.parsedConfig->capConfigurableDomains) {
+ createDomain(domain.name);
+ for (const auto &configurableElementValue : domain.settings[0].configurableElementValues) {
+ addConfigurableElementToDomain(domain.name,
+ configurableElementValue.configurableElement.path);
+ }
+ for (const auto &configuration : domain.configurations) {
+ createConfiguration(domain.name, configuration.name);
+ setApplicationRule(domain.name, configuration.name, configuration.rule);
+ }
+ for (const auto &setting : domain.settings) {
+ for (const auto &configurableElementValue : setting.configurableElementValues) {
+ std::string value = configurableElementValue.value;
+ accessConfigurationValue(domain.name, setting.configurationName,
+ configurableElementValue.configurableElement.path, value);
+ }
+
+ }
+ }
+ mPfwConnector->setTuningMode(/* bOn= */ false, error);
+ return OK;
+}
+
} // namespace audio_policy
} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
index fa4ae1e..0c45a60 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
+++ b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
@@ -16,6 +16,7 @@
#pragma once
+#include <CapEngineConfig.h>
#include <media/AudioContainers.h>
#include <system/audio.h>
#include <system/audio_policy.h>
@@ -27,7 +28,7 @@
#include <string>
#include <vector>
-class CParameterMgrPlatformConnector;
+class CParameterMgrFullConnector;
class ISelectionCriterionInterface;
struct cnode;
@@ -59,6 +60,9 @@
*/
status_t start(std::string &error);
+ status_t setConfiguration(const android::capEngineConfig::ParsingResult& capSettings);
+
+
/**
* The following API wrap policy action to criteria
*/
@@ -148,6 +152,14 @@
uint64_t criterionValue, bool isOut) const;
private:
+ void createDomain(const std::string &domain);
+ void addConfigurableElementToDomain(const std::string &domain, const std::string &elementPath);
+ void createConfiguration(const std::string &domain, const std::string &configurationName);
+ void setApplicationRule(const std::string &domain, const std::string &configurationName,
+ const std::string &rule);
+ void accessConfigurationValue(const std::string &domain, const std::string &configurationName,
+ const std::string &elementPath, std::string &value);
+
/**
* Apply the configuration of the platform on the policy parameter manager.
* Once all the criteria have been set, the client of the platform state must call
@@ -206,7 +218,7 @@
Criteria mPolicyCriteria; /**< Policy Criterion Map. */
- CParameterMgrPlatformConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
+ CParameterMgrFullConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
ParameterMgrPlatformConnectorLogger *mPfwConnectorLogger; /**< Policy PFW logger. */
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index daef691..7de6939 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -51,7 +51,7 @@
{ "STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER },
{ "STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY },
{ "STRATEGY_REROUTING", STRATEGY_REROUTING },
- { "STRATEGY_PATCH", STRATEGY_REROUTING }, // boiler to manage stream patch volume
+ { "STRATEGY_PATCH", STRATEGY_PATCH }, // boiler to manage stream patch volume
{ "STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT },
};
return legacyStrategy;
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index a6090cf..862b5fd 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -28,20 +28,6 @@
namespace audio_policy
{
-enum legacy_strategy {
- STRATEGY_NONE = -1,
- STRATEGY_MEDIA,
- STRATEGY_PHONE,
- STRATEGY_SONIFICATION,
- STRATEGY_SONIFICATION_RESPECTFUL,
- STRATEGY_DTMF,
- STRATEGY_ENFORCED_AUDIBLE,
- STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
- STRATEGY_ACCESSIBILITY,
- STRATEGY_REROUTING,
- STRATEGY_CALL_ASSISTANT,
-};
-
class Engine : public EngineBase
{
public:
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 718f958..1b53428 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -8427,6 +8427,9 @@
int delayMs,
bool force)
{
+ // APM is single threaded, and single instance.
+ static std::set<IVolumeCurves*> invalidCurvesReported;
+
// do not change actual attributes volume if the attributes is muted
if (outputDesc->isMuted(volumeSource)) {
ALOGVV("%s: volume source %d muted count %d active=%d", __func__, volumeSource,
@@ -8451,7 +8454,12 @@
}
if (curves.getVolumeIndexMin() < 0 || curves.getVolumeIndexMax() < 0) {
- ALOGE("invalid volume index range");
+ if (!invalidCurvesReported.count(&curves)) {
+ invalidCurvesReported.insert(&curves);
+ String8 dump;
+ curves.dump(&dump);
+ ALOGE("invalid volume index range in the curve:\n%s", dump.c_str());
+ }
return BAD_VALUE;
}
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index bb41d00..2f7d722 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -79,6 +79,8 @@
using media::audio::common::AudioFormatDescription;
using media::audio::common::AudioMode;
using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioPolicyForceUse;
+using media::audio::common::AudioPolicyForcedConfig;
using media::audio::common::AudioSource;
using media::audio::common::AudioStreamType;
using media::audio::common::AudioUsage;
@@ -284,8 +286,8 @@
return Status::ok();
}
-Status AudioPolicyService::setForceUse(media::AudioPolicyForceUse usageAidl,
- media::AudioPolicyForcedConfig configAidl)
+Status AudioPolicyService::setForceUse(AudioPolicyForceUse usageAidl,
+ AudioPolicyForcedConfig configAidl)
{
audio_policy_force_use_t usage = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(usageAidl));
@@ -316,8 +318,8 @@
return Status::ok();
}
-Status AudioPolicyService::getForceUse(media::AudioPolicyForceUse usageAidl,
- media::AudioPolicyForcedConfig* _aidl_return) {
+Status AudioPolicyService::getForceUse(AudioPolicyForceUse usageAidl,
+ AudioPolicyForcedConfig* _aidl_return) {
audio_policy_force_use_t usage = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(usageAidl));
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 2e0aa3c..74cfdbe 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -193,9 +193,7 @@
media::AudioPolicyConfig apmConfig;
if (status_t status = clientInterface->getAudioPolicyConfig(&apmConfig); status == OK) {
auto config = AudioPolicyConfig::loadFromApmAidlConfigWithFallback(apmConfig);
- LOG_ALWAYS_FATAL_IF(config->getEngineLibraryNameSuffix() !=
- AudioPolicyConfig::kDefaultEngineLibraryNameSuffix,
- "Only default engine is currently supported with the AIDL HAL");
+ ALOGD("%s loading APM engine %s", __func__, config->getEngineLibraryNameSuffix().c_str());
apm = new AudioPolicyManager(config,
loadApmEngineLibraryAndCreateEngine(
config->getEngineLibraryNameSuffix(), apmConfig.engineConfig),
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index d5d4f97..d74bc07 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -106,10 +106,10 @@
const std::string& deviceName,
const AudioFormatDescription& encodedFormat) override;
binder::Status setPhoneState(AudioMode state, int32_t uid) override;
- binder::Status setForceUse(media::AudioPolicyForceUse usage,
- media::AudioPolicyForcedConfig config) override;
- binder::Status getForceUse(media::AudioPolicyForceUse usage,
- media::AudioPolicyForcedConfig* _aidl_return) override;
+ binder::Status setForceUse(android::media::audio::common::AudioPolicyForceUse usage,
+ android::media::audio::common::AudioPolicyForcedConfig config) override;
+ binder::Status getForceUse(android::media::audio::common::AudioPolicyForceUse usage,
+ android::media::audio::common::AudioPolicyForcedConfig* _aidl_return) override;
binder::Status getOutput(AudioStreamType stream, int32_t* _aidl_return) override;
binder::Status getOutputForAttr(const media::audio::common::AudioAttributes& attr,
int32_t session,
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index c600fb6..154b063 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -53,7 +53,10 @@
"libaudiopolicymanager_interface_headers",
],
- srcs: ["audiopolicymanager_tests.cpp"],
+ srcs: [
+ "audiopolicymanager_tests.cpp",
+ "test_execution_tracer.cpp",
+ ],
data: [":audiopolicytest_configuration_files"],
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index cd70e95..fe9937f 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -43,6 +43,7 @@
#include "AudioPolicyManagerTestClient.h"
#include "AudioPolicyTestClient.h"
#include "AudioPolicyTestManager.h"
+#include "test_execution_tracer.h"
using namespace android;
using testing::UnorderedElementsAre;
@@ -3929,3 +3930,9 @@
EXPECT_EQ(1, mClient->getCloseInputCallsCount());
EXPECT_NE(input1, input2);
}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
+ return RUN_ALL_TESTS();
+}
diff --git a/services/audiopolicy/tests/test_execution_tracer.cpp b/services/audiopolicy/tests/test_execution_tracer.cpp
new file mode 100644
index 0000000..09de4a1
--- /dev/null
+++ b/services/audiopolicy/tests/test_execution_tracer.cpp
@@ -0,0 +1,43 @@
+/*
+ * 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 "TestExecutionTracer"
+
+#include "test_execution_tracer.h"
+
+#include <android-base/logging.h>
+
+void TestExecutionTracer::OnTestStart(const ::testing::TestInfo& test_info) {
+ TraceTestState("Started", test_info);
+}
+
+void TestExecutionTracer::OnTestEnd(const ::testing::TestInfo& test_info) {
+ TraceTestState("Finished", test_info);
+}
+
+void TestExecutionTracer::OnTestPartResult(const ::testing::TestPartResult& result) {
+ if (result.failed()) {
+ LOG(ERROR) << result;
+ } else {
+ LOG(INFO) << result;
+ }
+}
+
+// static
+void TestExecutionTracer::TraceTestState(const std::string& state,
+ const ::testing::TestInfo& test_info) {
+ LOG(INFO) << state << " " << test_info.test_suite_name() << "::" << test_info.name();
+}
diff --git a/services/audiopolicy/tests/test_execution_tracer.h b/services/audiopolicy/tests/test_execution_tracer.h
new file mode 100644
index 0000000..9031aaf
--- /dev/null
+++ b/services/audiopolicy/tests/test_execution_tracer.h
@@ -0,0 +1,29 @@
+/*
+ * 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 <gtest/gtest.h>
+
+class TestExecutionTracer : public ::testing::EmptyTestEventListener {
+ public:
+ void OnTestStart(const ::testing::TestInfo& test_info) override;
+ void OnTestEnd(const ::testing::TestInfo& test_info) override;
+ void OnTestPartResult(const ::testing::TestPartResult& result) override;
+
+ private:
+ static void TraceTestState(const std::string& state, const ::testing::TestInfo& test_info);
+};
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index f94300e..eb8708e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -828,10 +828,6 @@
hardware::camera2::impl::CameraMetadataNative* request) {
ATRACE_CALL();
- if (!flags::feature_combination_query()) {
- return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
- "Camera subsystem doesn't support this method!");
- }
if (!mInitialized) {
ALOGE("%s: Camera subsystem is not available", __FUNCTION__);
logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
@@ -891,10 +887,6 @@
/*out*/ bool* supported) {
ATRACE_CALL();
- if (!flags::feature_combination_query()) {
- return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
- "Camera subsystem doesn't support this method!");
- }
if (!mInitialized) {
ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
@@ -1612,11 +1604,12 @@
Status ret = Status::ok();
sp<Client> tmp = nullptr;
- logConnectionAttempt(getCallingPid(), kServiceName, cameraIdStr, API_1);
+ int callingPid = getCallingPid();
+ logConnectionAttempt(callingPid, kServiceName, cameraIdStr, API_1);
if (!(ret = connectHelper<ICameraClient,Client>(
sp<ICameraClient>{nullptr}, cameraIdStr, cameraId,
- kServiceName, /*systemNativeClient*/ false, {}, uid, USE_CALLING_PID,
+ kServiceName, /*systemNativeClient*/ false, {}, uid, callingPid,
API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0,
/*targetSdkVersion*/ __ANDROID_API_FUTURE__,
/*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT,
@@ -1690,7 +1683,7 @@
}
Status CameraService::validateConnectLocked(const std::string& cameraId,
- const std::string& clientName8, /*inout*/int& clientUid, /*inout*/int& clientPid) const {
+ const std::string& clientName8, int clientUid, int clientPid) const {
#ifdef __BRILLO__
UNUSED(clientName8);
@@ -1734,36 +1727,24 @@
return Status::ok();
}
-Status CameraService::validateClientPermissionsLocked(const std::string& cameraId,
- const std::string& clientName, int& clientUid, int& clientPid) const {
+Status CameraService::errorNotTrusted(int clientPid, int clientUid, const std::string& cameraId,
+ const std::string& clientName, bool isPid) const {
int callingPid = getCallingPid();
int callingUid = getCallingUid();
+ ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected "
+ "(don't trust %s %d)", callingPid, callingUid, isPid ? "clientPid" : "clientUid",
+ isPid ? clientPid : clientUid);
+ return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
+ "Untrusted caller (calling PID %d, UID %d) trying to "
+ "forward camera access to camera %s for client %s (PID %d, UID %d)",
+ getCallingPid(), getCallingUid(), cameraId.c_str(),
+ clientName.c_str(), clientPid, clientUid);
+}
- // Check if we can trust clientUid
- if (clientUid == USE_CALLING_UID) {
- clientUid = callingUid;
- } else if (!isTrustedCallingUid(callingUid)) {
- ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected "
- "(don't trust clientUid %d)", callingPid, callingUid, clientUid);
- return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
- "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(), clientPid, clientUid);
- }
-
- // Check if we can trust clientPid
- if (clientPid == USE_CALLING_PID) {
- clientPid = callingPid;
- } else if (!isTrustedCallingUid(callingUid)) {
- ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected "
- "(don't trust clientPid %d)", callingPid, callingUid, clientPid);
- return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
- "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(), clientPid, clientUid);
- }
+Status CameraService::validateClientPermissionsLocked(const std::string& cameraId,
+ const std::string& clientName, int clientUid, int clientPid) const {
+ int callingPid = getCallingPid();
+ int callingUid = getCallingUid();
if (shouldRejectSystemCameraConnection(cameraId)) {
ALOGW("Attempting to connect to system-only camera id %s, connection rejected",
@@ -2156,10 +2137,28 @@
clientPackageNameMaybe);
logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraIdStr, API_1);
+ int clientUid = clientAttribution.uid;
+ int clientPid = clientAttribution.pid;
+
+ // Resolve the client identity. In the near future, we will no longer rely on USE_CALLING_*, and
+ // need a way to guarantee the caller identity early.
+
+ // Check if we can trust clientUid
+ if (!resolveClientUid(clientUid)) {
+ return errorNotTrusted(clientPid, clientUid, cameraIdStr, clientPackageName,
+ /* isPid=*/ false);
+ }
+
+ // Check if we can trust clientUid
+ if (!resolveClientPid(clientPid)) {
+ return errorNotTrusted(clientPid, clientUid, cameraIdStr, clientPackageName,
+ /* isPid= */ true);
+ }
+
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId,
clientPackageName, /*systemNativeClient*/ false, {},
- clientAttribution.uid, clientAttribution.pid, API_1,
+ clientUid, clientPid, API_1,
/*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion,
rotationOverride, forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/client);
@@ -2275,6 +2274,22 @@
clientPackageNameMaybe);
logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraId, API_2);
+ userid_t clientUserId = multiuser_get_user_id(clientAttribution.uid);
+ if (clientAttribution.uid == USE_CALLING_UID) {
+ clientUserId = multiuser_get_user_id(callingUid);
+ }
+
+ // Resolve the client identity. In the near future, we will no longer rely on USE_CALLING_*, and
+ // need a way to guarantee the caller identity early.
+
+ int clientUid = clientAttribution.uid;
+ int clientPid = callingPid;
+ // Check if we can trust clientUid
+ if (!resolveClientUid(clientUid)) {
+ return errorNotTrusted(clientPid, clientUid, cameraId, clientPackageName,
+ /* isPid= */ false);
+ }
+
if (oomScoreOffset < 0) {
std::string msg =
fmt::sprintf("Cannot increase the priority of a client %s pid %d for "
@@ -2284,11 +2299,6 @@
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str());
}
- userid_t clientUserId = multiuser_get_user_id(clientAttribution.uid);
- if (clientAttribution.uid == USE_CALLING_UID) {
- clientUserId = multiuser_get_user_id(callingUid);
- }
-
// Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use cases
// such as rear view and surround view cannot be disabled.
if ((!isAutomotivePrivilegedClient(callingUid) || !isAutomotiveExteriorSystemCamera(cameraId))
@@ -2312,7 +2322,7 @@
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb,
cameraId, /*api1CameraId*/-1, clientPackageName, systemNativeClient,
- clientAttribution.attributionTag, clientAttribution.uid, USE_CALLING_PID, API_2,
+ clientAttribution.attributionTag, clientUid, clientPid, API_2,
/*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, rotationOverride,
/*forceSlowJpegMode*/false, unresolvedCameraId, isNonSystemNdk, /*out*/client);
@@ -4330,14 +4340,9 @@
// Notify app ops that the camera is not available
mOpsCallback = new OpsCallback(this);
- if (flags::watch_foreground_changes()) {
- mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
- toString16(mClientPackageName),
- AppOpsManager::WATCH_FOREGROUND_CHANGES, mOpsCallback);
- } else {
- mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
- toString16(mClientPackageName), mOpsCallback);
- }
+ mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
+ toString16(mClientPackageName),
+ AppOpsManager::WATCH_FOREGROUND_CHANGES, mOpsCallback);
// Just check for camera acccess here on open - delay startOp until
// camera frames start streaming in startCameraStreamingOps
@@ -4520,19 +4525,10 @@
// (WAR for b/175320666)the AppOpsManager could return MODE_IGNORED. Do not treat such
// cases as error.
if (!mUidIsTrusted) {
- if (flags::watch_foreground_changes()) {
- if (isUidVisible && isCameraPrivacyEnabled && supportsCameraMute()) {
- setCameraMute(true);
- } else {
- block();
- }
+ if (isUidVisible && isCameraPrivacyEnabled && supportsCameraMute()) {
+ setCameraMute(true);
} else {
- if (isUidActive && isCameraPrivacyEnabled && supportsCameraMute()) {
- setCameraMute(true);
- } else if (!isUidActive
- || (isCameraPrivacyEnabled && !supportsCameraMute())) {
- block();
- }
+ block();
}
}
} else if (res == AppOpsManager::MODE_ALLOWED) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d5c57cb..0ac391d 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -950,14 +950,16 @@
// If clientPid/clientUid are USE_CALLING_PID/USE_CALLING_UID, they will be overwritten with
// the calling pid/uid.
binder::Status validateConnectLocked(const std::string& cameraId, const std::string& clientName,
- /*inout*/int& clientUid, /*inout*/int& clientPid) const;
+ int clientUid, int clientPid) const;
binder::Status validateClientPermissionsLocked(const std::string& cameraId,
- const std::string& clientName, /*inout*/int& clientUid, /*inout*/int& clientPid) const;
+ const std::string& clientName, int clientUid, int clientPid) const;
// If clientPackageNameMaybe is empty, attempts to resolve the package name.
std::string resolvePackageName(int clientUid, const std::string& clientPackageNameMaybe) const;
void logConnectionAttempt(int clientPid, const std::string& clientPackageName,
const std::string& cameraId, apiLevel effectiveApiLevel) const;
+ binder::Status errorNotTrusted(int clientPid, int clientUid, const std::string& cameraId,
+ const std::string& clientName, bool isPid) const;
bool isCameraPrivacyEnabled(const String16& packageName,const std::string& cameraId,
int clientPid, int ClientUid);
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.cpp b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
index 1c1bd24..ad1a84f 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.cpp
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
@@ -17,11 +17,14 @@
#define LOG_TAG "CameraServiceWatchdog"
#include "CameraServiceWatchdog.h"
+#include "com_android_internal_camera_flags.h"
#include "android/set_abort_message.h"
#include "utils/CameraServiceProxyWrapper.h"
namespace android {
+namespace flags = com::android::internal::camera::flags;
+
bool CameraServiceWatchdog::threadLoop()
{
{
@@ -51,6 +54,12 @@
true /*deviceError*/);
// We use abort here so we can get a tombstone for better
// debugging.
+ if (flags::enable_hal_abort_from_cameraservicewatchdog()) {
+ for (pid_t pid : mProviderPids) {
+ kill(pid, SIGABRT);
+ }
+ }
+
abort();
}
}
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
index 165dece..691a274 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.h
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -30,6 +30,7 @@
*/
#pragma once
#include <chrono>
+#include <set>
#include <thread>
#include <time.h>
#include <utils/Thread.h>
@@ -57,16 +58,17 @@
};
public:
- explicit CameraServiceWatchdog(const std::string &cameraId,
+
+ explicit CameraServiceWatchdog(const std::set<pid_t> &pids, const std::string &cameraId,
std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
- mCameraId(cameraId), mPause(true), mMaxCycles(kMaxCycles),
+ mProviderPids(pids), mCameraId(cameraId), mPause(true), mMaxCycles(kMaxCycles),
mCycleLengthMs(kCycleLengthMs), mEnabled(true),
mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
- explicit CameraServiceWatchdog (const std::string &cameraId, size_t maxCycles,
- uint32_t cycleLengthMs, bool enabled,
+ explicit CameraServiceWatchdog (const std::set<pid_t> &pids, const std::string &cameraId,
+ size_t maxCycles, uint32_t cycleLengthMs, bool enabled,
std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
- mCameraId(cameraId), mPause(true), mMaxCycles(maxCycles),
+ mProviderPids(pids), mCameraId(cameraId), mPause(true), mMaxCycles(maxCycles),
mCycleLengthMs(cycleLengthMs), mEnabled(enabled),
mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
@@ -90,7 +92,8 @@
// Lock for mEnabled
mEnabledLock.lock();
sp<CameraServiceWatchdog> tempWatchdog = new CameraServiceWatchdog(
- mCameraId, cycles, cycleLength, mEnabled, mCameraServiceProxyWrapper);
+ mProviderPids, mCameraId, cycles, cycleLength, mEnabled,
+ mCameraServiceProxyWrapper);
mEnabledLock.unlock();
status_t status = tempWatchdog->run("CameraServiceWatchdog");
@@ -150,6 +153,7 @@
Mutex mWatchdogLock; // Lock for condition variable
Mutex mEnabledLock; // Lock for enabled status
Condition mWatchdogCondition; // Condition variable for stop/start
+ std::set<pid_t> mProviderPids; // Process ID set of camera providers
std::string mCameraId; // Camera Id the watchdog belongs to
bool mPause; // True if tid map is empty
uint32_t mMaxCycles; // Max cycles
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index fcba9bc..8c44e35 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -546,14 +546,14 @@
mRunningSessionStats.mVideoStabilizationMode = entry.data.u8[0];
}
- if (!mRunningSessionStats.mUsedUltraWide && flags::log_ultrawide_usage()) {
+ if (!mRunningSessionStats.mUsedUltraWide) {
entry = physicalSettingsList.begin()->metadata.find(
ANDROID_CONTROL_ZOOM_RATIO);
if (entry.count == 1 && entry.data.f[0] < 1.0f ) {
mRunningSessionStats.mUsedUltraWide = true;
}
}
- if (!mRunningSessionStats.mUsedSettingsOverrideZoom && flags::log_zoom_override_usage()) {
+ if (!mRunningSessionStats.mUsedSettingsOverrideZoom) {
entry = physicalSettingsList.begin()->metadata.find(
ANDROID_CONTROL_SETTINGS_OVERRIDE);
if (entry.count == 1 && entry.data.i32[0] ==
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 2440c37..26864fc 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -34,6 +34,7 @@
#include <inttypes.h>
#include <android_companion_virtualdevice_flags.h>
#include <android_companion_virtualdevice_build_flags.h>
+#include <android/binder_libbinder.h>
#include <android/binder_manager.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/ServiceManagement.h>
@@ -2135,7 +2136,19 @@
}
AidlProviderInfo *aidlProviderInfo = static_cast<AidlProviderInfo *>(providerInfo.get());
- return aidlProviderInfo->initializeAidlProvider(interface, mDeviceState);
+ status_t res = aidlProviderInfo->initializeAidlProvider(interface, mDeviceState);
+
+ if (flags::enable_hal_abort_from_cameraservicewatchdog()) {
+ pid_t pid = 0;
+
+ if (AIBinder_toPlatformBinder(interface->asBinder().get())->getDebugPid(&pid) == OK
+ && res == OK) {
+ std::lock_guard<std::mutex> lock(mProviderPidMapLock);
+ mProviderPidMap[providerInfo->mProviderInstance] = pid;
+ }
+ }
+
+ return res;
}
status_t CameraProviderManager::tryToInitializeHidlProviderLocked(
@@ -2152,7 +2165,23 @@
}
HidlProviderInfo *hidlProviderInfo = static_cast<HidlProviderInfo *>(providerInfo.get());
- return hidlProviderInfo->initializeHidlProvider(interface, mDeviceState);
+ status_t res = hidlProviderInfo->initializeHidlProvider(interface, mDeviceState);
+
+ if (flags::enable_hal_abort_from_cameraservicewatchdog()) {
+ pid_t pid = 0;
+
+ auto ret = interface->getDebugInfo([&pid](
+ const ::android::hidl::base::V1_0::DebugInfo& info) {
+ pid = info.pid;
+ });
+
+ if (ret.isOk() && res == OK) {
+ std::lock_guard<std::mutex> lock(mProviderPidMapLock);
+ mProviderPidMap[providerInfo->mProviderInstance] = pid;
+ }
+ }
+
+ return res;
}
status_t CameraProviderManager::addAidlProviderLocked(const std::string& newProvider) {
@@ -2264,6 +2293,13 @@
ALOGW("%s: Camera provider HAL with name '%s' is not registered", __FUNCTION__,
provider.c_str());
} else {
+ if (flags::enable_hal_abort_from_cameraservicewatchdog()) {
+ {
+ std::lock_guard<std::mutex> pidLock(mProviderPidMapLock);
+ mProviderPidMap.erase(provider);
+ }
+ }
+
// Check if there are any newer camera instances from the same provider and try to
// initialize.
for (const auto& providerInfo : mProviders) {
@@ -2451,6 +2487,20 @@
return kEnableLazyHal && (providerName == kExternalProviderName);
}
+std::set<pid_t> CameraProviderManager::getProviderPids() {
+ std::set<pid_t> pids;
+
+ if (flags::enable_hal_abort_from_cameraservicewatchdog()) {
+ std::lock_guard<std::mutex> lock(mProviderPidMapLock);
+
+ std::transform(mProviderPidMap.begin(), mProviderPidMap.end(),
+ std::inserter(pids, pids.begin()),
+ [](std::pair<const std::string, pid_t>& entry) { return entry.second; });
+ }
+
+ return pids;
+}
+
status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector<String16>&) const {
dprintf(fd, "== Camera Provider HAL %s (v2.%d, %s) static info: %zu devices: ==\n",
mProviderInstance.c_str(),
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 4a64b44..b686a58 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -431,6 +431,11 @@
// LocalRegistrationCallback::onServiceRegistration
virtual void onServiceRegistration(const String16& name, const sp<IBinder> &binder) override;
+ /*
+ * Return list of provider pid
+ */
+ std::set<pid_t> getProviderPids();
+
/**
* Dump out information about available providers and devices
*/
@@ -914,6 +919,9 @@
// Provider names of AIDL providers with retrieved binders.
std::set<std::string> mAidlProviderWithBinders;
+ std::mutex mProviderPidMapLock;
+ std::map<std::string, pid_t> mProviderPidMap;
+
static const char* deviceStatusToString(
const hardware::camera::common::V1_0::CameraDeviceStatus&);
static const char* torchStatusToString(
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index e76b750..5c0e2c6 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -622,12 +622,10 @@
mHasFlashUnit = false;
}
- if (flags::feature_combination_query()) {
- res = addSessionConfigQueryVersionTag();
- if (OK != res) {
- ALOGE("%s: Unable to add sessionConfigurationQueryVersion tag: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- }
+ res = addSessionConfigQueryVersionTag();
+ if (OK != res) {
+ ALOGE("%s: Unable to add sessionConfigurationQueryVersion tag: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
}
camera_metadata_entry entry =
@@ -844,11 +842,7 @@
mVersion.get_minor());
return INVALID_OPERATION;
}
- if (flags::feature_combination_query()) {
- ret = interface->isStreamCombinationWithSettingsSupported(streamConfiguration, status);
- } else {
- return INVALID_OPERATION;
- }
+ ret = interface->isStreamCombinationWithSettingsSupported(streamConfiguration, status);
} else {
ret = interface->isStreamCombinationSupported(streamConfiguration, status);
}
@@ -887,10 +881,6 @@
return res;
}
- if (!flags::feature_combination_query()) {
- return INVALID_OPERATION;
- }
-
auto err = interface->constructDefaultRequestSettings(id, &request);
if (!err.isOk()) {
ALOGE("%s: Transaction error: %s", __FUNCTION__, err.getMessage());
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index 40800d9..c394d43 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -693,12 +693,10 @@
mHasFlashUnit = false;
}
- if (flags::feature_combination_query()) {
- res = addSessionConfigQueryVersionTag();
- if (OK != res) {
- ALOGE("%s: Unable to add sessionConfigurationQueryVersion tag: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- }
+ res = addSessionConfigQueryVersionTag();
+ if (OK != res) {
+ ALOGE("%s: Unable to add sessionConfigurationQueryVersion tag: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
}
camera_metadata_entry entry =
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 11891e9..0cb9b1d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -133,7 +133,7 @@
return mId;
}
-status_t Camera3Device::initializeCommonLocked() {
+status_t Camera3Device::initializeCommonLocked(sp<CameraProviderManager> manager) {
/** Start up status tracker thread */
mStatusTracker = new StatusTracker(this);
@@ -251,7 +251,8 @@
mInjectionMethods = createCamera3DeviceInjectionMethods(this);
/** Start watchdog thread */
- mCameraServiceWatchdog = new CameraServiceWatchdog(mId, mCameraServiceProxyWrapper);
+ mCameraServiceWatchdog = new CameraServiceWatchdog(
+ manager->getProviderPids(), mId, mCameraServiceProxyWrapper);
res = mCameraServiceWatchdog->run("CameraServiceWatchdog");
if (res != OK) {
SET_ERR_L("Unable to start camera service watchdog thread: %s (%d)",
@@ -1835,10 +1836,7 @@
mSessionStatsBuilder.stopCounter();
}
- // Calculate expected duration for flush with additional buffer time in ms for watchdog
- uint64_t maxExpectedDuration = ns2ms(getExpectedInFlightDuration() + kBaseGetBufferWait);
- status_t res = mCameraServiceWatchdog->WATCH_CUSTOM_TIMER(mRequestThread->flush(),
- maxExpectedDuration / kCycleLengthMs, kCycleLengthMs);
+ status_t res = mCameraServiceWatchdog->WATCH(mRequestThread->flush());
return res;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index e5ccbae..3cfe3c9 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -726,7 +726,7 @@
*
* Must be called with mLock and mInterfaceLock held.
*/
- status_t initializeCommonLocked();
+ status_t initializeCommonLocked(sp<CameraProviderManager> manager);
/**
* Update capture request list so that each batch size honors the batch_size_max report from
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 04867b9..83c8a38 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -687,11 +687,7 @@
}
}
- if (flags::surface_ipc()) {
- res = mConsumer->setMaxDequeuedBufferCount(mTotalBufferCount - maxConsumerBuffers);
- } else {
- res = native_window_set_buffer_count(mConsumer.get(), mTotalBufferCount);
- }
+ res = mConsumer->setMaxDequeuedBufferCount(mTotalBufferCount - maxConsumerBuffers);
if (res != OK) {
ALOGE("%s: Unable to set buffer count for stream %d",
__FUNCTION__, mId);
@@ -1035,7 +1031,7 @@
status_t Camera3OutputStream::getEndpointUsageForSurface(uint64_t *usage,
const sp<Surface>& surface) {
bool internalConsumer = (mConsumer.get() != nullptr) && (mConsumer == surface);
- if (mConsumerUsageCachedValue.has_value() && flags::surface_ipc() && internalConsumer) {
+ if (mConsumerUsageCachedValue.has_value() && internalConsumer) {
*usage = mConsumerUsageCachedValue.value();
return OK;
}
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index 57297bc..868b7ef 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -349,7 +349,7 @@
readoutSupported.data.u8[0] == ANDROID_SENSOR_READOUT_TIMESTAMP_HARDWARE;
}
- return initializeCommonLocked();
+ return initializeCommonLocked(manager);
}
::ndk::ScopedAStatus AidlCamera3Device::AidlCameraDeviceCallbacks::processCaptureResult(
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
index 09299e6..f507df9 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -303,7 +303,7 @@
}
mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
- return initializeCommonLocked();
+ return initializeCommonLocked(manager);
}
hardware::Return<void> HidlCamera3Device::requestStreamBuffers(
diff --git a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
index 93b440b..72f8c4b 100644
--- a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
+++ b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
@@ -80,6 +80,33 @@
return;
}
+// TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum.
+bool AttributionAndPermissionUtils::resolveClientUid(/*inout*/ int& clientUid) {
+ int callingUid = getCallingUid();
+
+ if (clientUid == hardware::ICameraService::USE_CALLING_UID) {
+ clientUid = callingUid;
+ } else if (!isTrustedCallingUid(callingUid)) {
+ return false;
+ }
+
+ return true;
+}
+
+// TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum.
+bool AttributionAndPermissionUtils::resolveClientPid(/*inout*/ int& clientPid) {
+ int callingUid = getCallingUid();
+ int callingPid = getCallingPid();
+
+ if (clientPid == hardware::ICameraService::USE_CALLING_PID) {
+ clientPid = callingPid;
+ } else if (!isTrustedCallingUid(callingUid)) {
+ return false;
+ }
+
+ return true;
+}
+
bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient(const std::string &cameraId,
const AttributionSourceState &attributionSource) {
if (isAutomotivePrivilegedClient(attributionSource.uid)) {
diff --git a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
index 4daab0f..a23fba7 100644
--- a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
+++ b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h
@@ -61,6 +61,9 @@
virtual int64_t clearCallingIdentity();
virtual void restoreCallingIdentity(int64_t token);
+ virtual bool resolveClientUid(/*inout*/ int& clientUid);
+ virtual bool resolveClientPid(/*inout*/ int& clientPid);
+
/**
* Pre-grants the permission if the attribution source uid is for an automotive
* privileged client. Otherwise uses system service permission checker to check
@@ -170,6 +173,14 @@
mAttributionAndPermissionUtils->restoreCallingIdentity(token);
}
+ bool resolveClientUid(/*inout*/ int& clientUid) const {
+ return mAttributionAndPermissionUtils->resolveClientUid(clientUid);
+ }
+
+ bool resolveClientPid(/*inout*/ int& clientPid) const {
+ return mAttributionAndPermissionUtils->resolveClientPid(clientPid);
+ }
+
// The word 'System' here does not refer to callers only on the system
// partition. They just need to have an android system uid.
bool callerHasSystemUid() const {
diff --git a/services/camera/virtualcamera/Android.bp b/services/camera/virtualcamera/Android.bp
index 7ece0cb..dd64daa 100644
--- a/services/camera/virtualcamera/Android.bp
+++ b/services/camera/virtualcamera/Android.bp
@@ -25,6 +25,7 @@
"libEGL",
"libGLESv2",
"libGLESv3",
+ "android.companion.virtualdevice.flags-aconfig-cc",
],
static_libs: [
"android.hardware.camera.common@1.0-helper",
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
index 40a96e4..bf4a45d 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
@@ -14,9 +14,12 @@
* limitations under the License.
*/
+// #define LOG_NDEBUG 0
#define LOG_TAG "VirtualCameraRenderThread"
#include "VirtualCameraRenderThread.h"
+#include <android_companion_virtualdevice_flags.h>
+
#include <chrono>
#include <cstdint>
#include <cstring>
@@ -46,13 +49,11 @@
#include "android-base/thread_annotations.h"
#include "android/binder_auto_utils.h"
#include "android/hardware_buffer.h"
-#include "hardware/gralloc.h"
#include "system/camera_metadata.h"
#include "ui/GraphicBuffer.h"
#include "ui/Rect.h"
#include "util/EglFramebuffer.h"
#include "util/JpegUtil.h"
-#include "util/MetadataUtil.h"
#include "util/Util.h"
#include "utils/Errors.h"
@@ -91,6 +92,8 @@
using namespace std::chrono_literals;
+namespace flags = ::android::companion::virtualdevice::flags;
+
static constexpr std::chrono::milliseconds kAcquireFenceTimeout = 500ms;
static constexpr size_t kJpegThumbnailBufferSize = 32 * 1024; // 32 KiB
@@ -117,12 +120,12 @@
NotifyMsg createRequestErrorNotifyMsg(int frameNumber) {
NotifyMsg msg;
- msg.set<NotifyMsg::Tag::error>(ErrorMsg{
- .frameNumber = frameNumber,
- // errorStreamId needs to be set to -1 for ERROR_REQUEST
- // (not tied to specific stream).
- .errorStreamId = -1,
- .errorCode = ErrorCode::ERROR_REQUEST});
+ msg.set<NotifyMsg::Tag::error>(
+ ErrorMsg{.frameNumber = frameNumber,
+ // errorStreamId needs to be set to -1 for ERROR_REQUEST
+ // (not tied to specific stream).
+ .errorStreamId = -1,
+ .errorCode = ErrorCode::ERROR_REQUEST});
return msg;
}
@@ -413,29 +416,8 @@
std::memory_order_relaxed));
if (request.getRequestSettings().fpsRange) {
- const int maxFps =
- std::max(1, request.getRequestSettings().fpsRange->maxFps);
- const std::chrono::nanoseconds minFrameDuration(
- static_cast<uint64_t>(1e9 / maxFps));
- const std::chrono::nanoseconds frameDuration =
- timestamp - lastAcquisitionTimestamp;
- if (frameDuration < minFrameDuration) {
- // We're too fast for the configured maxFps, let's wait a bit.
- const std::chrono::nanoseconds sleepTime =
- minFrameDuration - frameDuration;
- ALOGV("Current frame duration would be %" PRIu64
- " ns corresponding to, "
- "sleeping for %" PRIu64
- " ns before updating texture to match maxFps %d",
- static_cast<uint64_t>(frameDuration.count()),
- static_cast<uint64_t>(sleepTime.count()), maxFps);
-
- std::this_thread::sleep_for(sleepTime);
- timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
- std::chrono::steady_clock::now().time_since_epoch());
- mLastAcquisitionTimestampNanoseconds.store(timestamp.count(),
- std::memory_order_relaxed);
- }
+ int maxFps = std::max(1, request.getRequestSettings().fpsRange->maxFps);
+ timestamp = throttleRendering(maxFps, lastAcquisitionTimestamp, timestamp);
}
// Calculate the maximal amount of time we can afford to wait for next frame.
@@ -463,6 +445,17 @@
}
// Acquire new (most recent) image from the Surface.
mEglSurfaceTexture->updateTexture();
+ std::chrono::nanoseconds captureTimestamp = timestamp;
+
+ if (flags::camera_timestamp_from_surface()) {
+ std::chrono::nanoseconds surfaceTimestamp =
+ getSurfaceTimestamp(elapsedDuration);
+ if (surfaceTimestamp.count() > 0) {
+ captureTimestamp = surfaceTimestamp;
+ }
+ ALOGV("%s captureTimestamp:%lld timestamp:%lld", __func__,
+ captureTimestamp.count(), timestamp.count());
+ }
CaptureResult captureResult;
captureResult.fmqResultSize = 0;
@@ -472,7 +465,7 @@
captureResult.inputBuffer.streamId = -1;
captureResult.physicalCameraMetadata.resize(0);
captureResult.result = createCaptureResultMetadata(
- timestamp, request.getRequestSettings(), mReportedSensorSize);
+ captureTimestamp, request.getRequestSettings(), mReportedSensorSize);
const std::vector<CaptureRequestBuffer>& buffers = request.getBuffers();
captureResult.outputBuffers.resize(buffers.size());
@@ -506,7 +499,7 @@
}
std::vector<NotifyMsg> notifyMsg{
- createShutterNotifyMsg(request.getFrameNumber(), timestamp)};
+ createShutterNotifyMsg(request.getFrameNumber(), captureTimestamp)};
for (const StreamBuffer& resBuffer : captureResult.outputBuffers) {
if (resBuffer.status != BufferStatus::OK) {
notifyMsg.push_back(createBufferErrorNotifyMsg(request.getFrameNumber(),
@@ -535,6 +528,51 @@
ALOGV("%s: Successfully called processCaptureResult", __func__);
}
+std::chrono::nanoseconds VirtualCameraRenderThread::throttleRendering(
+ int maxFps, std::chrono::nanoseconds lastAcquisitionTimestamp,
+ std::chrono::nanoseconds timestamp) {
+ const std::chrono::nanoseconds minFrameDuration(
+ static_cast<uint64_t>(1e9 / maxFps));
+ const std::chrono::nanoseconds frameDuration =
+ timestamp - lastAcquisitionTimestamp;
+ if (frameDuration < minFrameDuration) {
+ // We're too fast for the configured maxFps, let's wait a bit.
+ const std::chrono::nanoseconds sleepTime = minFrameDuration - frameDuration;
+ ALOGV("Current frame duration would be %" PRIu64
+ " ns corresponding to, "
+ "sleeping for %" PRIu64
+ " ns before updating texture to match maxFps %d",
+ static_cast<uint64_t>(frameDuration.count()),
+ static_cast<uint64_t>(sleepTime.count()), maxFps);
+
+ std::this_thread::sleep_for(sleepTime);
+ timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::steady_clock::now().time_since_epoch());
+ mLastAcquisitionTimestampNanoseconds.store(timestamp.count(),
+ std::memory_order_relaxed);
+ }
+ return timestamp;
+}
+
+std::chrono::nanoseconds VirtualCameraRenderThread::getSurfaceTimestamp(
+ std::chrono::nanoseconds timeSinceLastFrame) {
+ std::chrono::nanoseconds surfaceTimestamp = mEglSurfaceTexture->getTimestamp();
+ if (surfaceTimestamp.count() < 0) {
+ uint64_t lastSurfaceTimestamp = mLastSurfaceTimestampNanoseconds.load();
+ if (lastSurfaceTimestamp > 0) {
+ // The timestamps were provided by the producer but we are
+ // repeating the last frame, so we increase the previous timestamp by
+ // the elapsed time sinced its capture, otherwise the camera framework
+ // will discard the frame.
+ surfaceTimestamp = std::chrono::nanoseconds(lastSurfaceTimestamp +
+ timeSinceLastFrame.count());
+ }
+ }
+ mLastSurfaceTimestampNanoseconds.store(surfaceTimestamp.count(),
+ std::memory_order_relaxed);
+ return surfaceTimestamp;
+}
+
void VirtualCameraRenderThread::flushCaptureRequest(
const ProcessCaptureRequestTask& request) {
CaptureResult captureResult;
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.h b/services/camera/virtualcamera/VirtualCameraRenderThread.h
index aafed44..a35eea1 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.h
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.h
@@ -18,6 +18,7 @@
#define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H
#include <atomic>
+#include <chrono>
#include <cstdint>
#include <deque>
#include <future>
@@ -188,6 +189,22 @@
EglFrameBuffer& framebuffer, sp<Fence> fence = nullptr,
std::optional<Rect> viewport = std::nullopt);
+ // Throttle the current thread to ensure that we are not rendering faster than
+ // the provided maxFps.
+ // maxFps: The maximum fps in the capture request
+ // lastAcquisitionTimestamp: timestamp of the previous frame
+ // timestamp: the current capture time
+ // Returns the time at which the capture has happened after throttling.
+ std::chrono::nanoseconds throttleRendering(
+ int maxFps, std::chrono::nanoseconds lastAcquisitionTimestamp,
+ std::chrono::nanoseconds timestamp);
+
+ // Fetch the timestamp of the latest buffer from the EGL Surface
+ // timeSinceLastFrame: The elapsed time since the last captured frame.
+ // Return 0 if no timestamp has been associated to this surface by the producer.
+ std::chrono::nanoseconds getSurfaceTimestamp(
+ std::chrono::nanoseconds timeSinceLastFrame);
+
// Camera callback
const std::shared_ptr<
::aidl::android::hardware::camera::device::ICameraDeviceCallback>
@@ -209,6 +226,7 @@
// Acquisition timestamp of last frame.
std::atomic<uint64_t> mLastAcquisitionTimestampNanoseconds;
+ std::atomic<uint64_t> mLastSurfaceTimestampNanoseconds;
// EGL helpers - constructed and accessed only from rendering thread.
std::unique_ptr<EglDisplayContext> mEglDisplayContext;
diff --git a/services/camera/virtualcamera/util/EglSurfaceTexture.cc b/services/camera/virtualcamera/util/EglSurfaceTexture.cc
index 98bf62a..be36ec4 100644
--- a/services/camera/virtualcamera/util/EglSurfaceTexture.cc
+++ b/services/camera/virtualcamera/util/EglSurfaceTexture.cc
@@ -15,6 +15,8 @@
*/
// #define LOG_NDEBUG 0
+#include <chrono>
+
#include "utils/Timers.h"
#define LOG_TAG "EglSurfaceTexture"
@@ -99,6 +101,10 @@
static_cast<nsecs_t>(timeout.count()));
}
+std::chrono::nanoseconds EglSurfaceTexture::getTimestamp() {
+ return std::chrono::nanoseconds(mGlConsumer->getTimestamp());
+}
+
GLuint EglSurfaceTexture::updateTexture() {
int previousFrameId;
int framesAdvance = 0;
diff --git a/services/camera/virtualcamera/util/EglSurfaceTexture.h b/services/camera/virtualcamera/util/EglSurfaceTexture.h
index a46af8f..c1f1169 100644
--- a/services/camera/virtualcamera/util/EglSurfaceTexture.h
+++ b/services/camera/virtualcamera/util/EglSurfaceTexture.h
@@ -82,6 +82,10 @@
// See SurfaceTexture.getTransformMatrix for more details.
std::array<float, 16> getTransformMatrix();
+ // Retrieves the timestamp associated with the texture image
+ // set by the most recent call to updateTexture.
+ std::chrono::nanoseconds getTimestamp();
+
private:
#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
sp<IGraphicBufferProducer> mBufferProducer;
diff --git a/tools/mainline_hook_partial.sh b/tools/mainline_hook_partial.sh
index 63ae4c0..978dc02 100755
--- a/tools/mainline_hook_partial.sh
+++ b/tools/mainline_hook_partial.sh
Binary files differ
diff --git a/tools/mainline_hook_project.sh b/tools/mainline_hook_project.sh
index d58143e..65f4073 100755
--- a/tools/mainline_hook_project.sh
+++ b/tools/mainline_hook_project.sh
@@ -16,8 +16,9 @@
# tunables
+# as of 2024/5, things are all on the same branch
DEV_BRANCH=main
-MAINLINE_BRANCH=udc-mainline-prod
+MAINLINE_BRANCH=main
###
RED=$(tput setaf 1)