Configurable Audio Policy: migrate settings to AudioAIDL
Add the missing support of Cap Settings through Audio AIDL.
Bug: 307310023
Test: manual
Change-Id: I06920b3318bffd210829f45f28175df12dc0267f
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index cf594c6..01c9660 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -25,6 +25,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;
} // namespace android
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 2c2f90d..deab0d7 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -50,7 +50,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 878bca9..3d20c6f 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/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 5e8bf34..e6e7c33 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -191,9 +191,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),