audiopolicy: engineconfigurable: Get rid of criteria text file
Test: make
Change-Id: I8c3a4dbd99f6c1ee8bac60e28b69429f1356ba30
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
index 7506734..7631976 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
@@ -12,10 +12,14 @@
ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
PFW_CORE := external/parameter-framework
-BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
+#@TODO: upstream new domain generator
+#BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
+BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
+
##################################################################
# CONFIGURATION FILES
##################################################################
@@ -82,13 +86,13 @@
LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
LOCAL_REQUIRED_MODULES := \
- PolicyClass.xml \
- PolicySubsystem.xml \
- ParameterFrameworkConfigurationPolicy.xml
+ policy_criteria.xml \
+ policy_criterion_types.xml \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ ParameterFrameworkConfigurationPolicy.xml
ifeq ($(pfw_rebuild_settings),true)
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
PFW_EDD_FILES := \
$(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
$(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -104,6 +108,17 @@
$(LOCAL_PATH)/Settings/device_for_input_source.pfw \
$(LOCAL_PATH)/Settings/volumes.pfw
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+ $(PFW_EDD_FILES)
+
+
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
+
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+
include $(BUILD_PFW_SETTINGS)
else
# Use the existing file
@@ -123,12 +138,15 @@
LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
LOCAL_REQUIRED_MODULES := \
- PolicyClass.xml \
- PolicySubsystem.xml \
- ParameterFrameworkConfigurationPolicy.xml
+ policy_criteria.xml \
+ policy_criterion_types.xml \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ ParameterFrameworkConfigurationPolicy.xml
PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
PFW_EDD_FILES := \
$(LOCAL_PATH)/SettingsNoOutput/device_for_strategies.pfw \
$(LOCAL_PATH)/Settings/strategy_for_stream.pfw \
@@ -148,12 +166,15 @@
LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
LOCAL_REQUIRED_MODULES := \
- PolicyClass.xml \
- PolicySubsystem.xml \
- ParameterFrameworkConfigurationPolicy.xml
+ policy_criteria.xml \
+ policy_criterion_types.xml \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ ParameterFrameworkConfigurationPolicy.xml
PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
PFW_EDD_FILES := \
$(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
$(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -172,3 +193,9 @@
include $(BUILD_PFW_SETTINGS)
endif # ifeq (1, 0)
+
+#######################################################################
+# Recursive call sub-folder Android.mk
+#######################################################################
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
index b43f83b..0710441 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
@@ -8472,7 +8472,7 @@
<Configurations>
<Configuration Name="Sonification">
<CompoundRule Type="All">
- <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="RingTone"/>
+ <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="Ringtone"/>
</CompoundRule>
</Configuration>
<Configuration Name="Phone">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
index b3115e7..fbea9e2 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
@@ -24,7 +24,7 @@
# In case of Ring or Alarm stream type active, switching to sonification
# @todo: handle this dynamic case. As a WA, using Ringtone mode...
#
- TelephonyMode Is RingTone
+ TelephonyMode Is Ringtone
/Policy/policy/usages/assistance_accessibility/applicable_strategy/strategy = sonification
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt b/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
deleted file mode 100644
index 480cbe1..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-ExclusiveCriterion TelephonyMode : Normal RingTone InCall InCommunication
-InclusiveCriterion AvailableInputDevices : Communication Ambient BuiltinMic BluetoothScoHeadset WiredHeadset Hdmi TelephonyRx BackMic RemoteSubmix AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice FmTuner TvTuner Line Spdif BluetoothA2dp Loopback Ip Bus Stub
-InclusiveCriterion AvailableOutputDevices : Earpiece Speaker WiredSpeaker WiredHeadset WiredHeadphone BluetoothSco BluetoothScoHeadset BluetoothScoCarkit BluetoothA2dp BluetoothA2dpHeadphones BluetoothA2dpSpeaker Hdmi AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice RemoteSubmix TelephonyTx Line HdmiArc Spdif Fm AuxLine SpeakerSafe Ip Bus Stub
-ExclusiveCriterion ForceUseForCommunication : ForceNone ForceSpeaker ForceBtSco
-ExclusiveCriterion ForceUseForMedia : ForceNone ForceSpeaker ForceHeadphones ForceBtA2dp ForceWiredAccessory ForceAnalogDock ForceDigitalDock ForceNoBtA2dp ForceSystemEnforced
-ExclusiveCriterion ForceUseForRecord : ForceNone ForceBtSco ForceWiredAccessory
-ExclusiveCriterion ForceUseForDock : ForceNone ForceWiredAccessory ForceBtCarDock ForceBtDeskDock ForceAnalogDock ForceDigitalDock
-ExclusiveCriterion ForceUseForSystem : ForceNone ForceSystemEnforced
-ExclusiveCriterion ForceUseForHdmiSystemAudio : ForceNone ForceHdmiSystemEnforced
-ExclusiveCriterion ForceUseForEncodedSurround : ForceNone ForceEncodedSurroundNever ForceEncodedSurroundAlways
diff --git a/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
new file mode 100644
index 0000000..2b86469
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
@@ -0,0 +1,35 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): MY_TOOL := domainGeneratorPolicy.py
+$(LOCAL_BUILT_MODULE): MY_TOPLEVEL_FILE := $(PFW_TOPLEVEL_FILE)
+$(LOCAL_BUILT_MODULE): MY_CRITERIA_FILE := $(PFW_CRITERIA_FILE)
+$(LOCAL_BUILT_MODULE): MY_TUNING_FILE := $(PFW_TUNING_FILE)
+$(LOCAL_BUILT_MODULE): MY_EDD_FILES := $(PFW_EDD_FILES)
+$(LOCAL_BUILT_MODULE): MY_DOMAIN_FILES := $(PFW_DOMAIN_FILES)
+$(LOCAL_BUILT_MODULE): MY_SCHEMAS_DIR := $(PFW_SCHEMAS_DIR)
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): $(LOCAL_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) domainGeneratorPolicy.py
+
+ "$(MY_TOOL)" --validate \
+ --toplevel-config "$(MY_TOPLEVEL_FILE)" \
+ --criteria "$(MY_CRITERIA_FILE)" \
+ --criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
+ --initial-settings $(MY_TUNING_FILE) \
+ --add-edds $(MY_EDD_FILES) \
+ --add-domains $(MY_DOMAIN_FILES) \
+ --schemas-dir $(MY_SCHEMAS_DIR) > "$@"
+
+
+# Clear variables for further use
+PFW_TOPLEVEL_FILE :=
+PFW_STRUCTURE_FILES :=
+PFW_CRITERIA_FILE :=
+PFW_CRITERION_TYPES_FILE :=
+PFW_TUNING_FILE :=
+PFW_EDD_FILES :=
+PFW_DOMAIN_FILES :=
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
diff --git a/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
new file mode 100755
index 0000000..7929402
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
@@ -0,0 +1,268 @@
+#!/usr/bin/python
+
+#
+# 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 EddParser
+from PFWScriptGenerator import PfwScriptTranslator
+import hostConfig
+
+import argparse
+import re
+import sys
+import tempfile
+import os
+import logging
+import subprocess
+import xml.etree.ElementTree as ET
+
+#
+# In order to build the XML Settings file at build time, an instance of the parameter-framework
+# shall be started and fed with all the criterion types/criteria that will be used by
+# the engineconfigurable.
+# This scripts allows generates the settings from the same audio_criterion_types.xml /
+# audio_criteria.xml files used at run time by the engineconfigurable
+#
+
+def parseArgs():
+ argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+ Settings file generator.\n\
+ Exit with the number of (recoverable or not) error that occured.")
+ argparser.add_argument('--toplevel-config',
+ help="Top-level parameter-framework configuration file. Mandatory.",
+ metavar="TOPLEVEL_CONFIG_FILE",
+ required=True)
+ argparser.add_argument('--criteria',
+ help="Criteria file, in XML format: \
+ in '<criteria> \
+ <criterion name="" type=""/> \
+ </criteria>' \
+ format. Mandatory.",
+ metavar="CRITERIA_FILE",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--criteriontypes',
+ help="Criterion types XML file, in \
+ '<criterion_types> \
+ <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/> \
+ </criterion_types>' \
+ format. Mandatory.",
+ metavar="CRITERION_TYPE_FILE",
+ type=argparse.FileType('r'),
+ required=False)
+ argparser.add_argument('--initial-settings',
+ help="Initial XML settings file (containing a \
+ <ConfigurableDomains> tag",
+ nargs='?',
+ default=None,
+ metavar="XML_SETTINGS_FILE")
+ argparser.add_argument('--add-domains',
+ help="List of single domain files (each containing a single \
+ <ConfigurableDomain> tag",
+ metavar="XML_DOMAIN_FILE",
+ nargs='*',
+ dest='xml_domain_files',
+ default=[])
+ argparser.add_argument('--add-edds',
+ help="List of files in EDD syntax (aka \".pfw\" files)",
+ metavar="EDD_FILE",
+ type=argparse.FileType('r'),
+ nargs='*',
+ default=[],
+ dest='edd_files')
+ argparser.add_argument('--schemas-dir',
+ help="Directory of parameter-framework XML Schemas for generation \
+ validation",
+ default=None)
+ argparser.add_argument('--target-schemas-dir',
+ help="Ignored. Kept for retro-compatibility")
+ argparser.add_argument('--validate',
+ help="Validate the settings against XML schemas",
+ action='store_true')
+ argparser.add_argument('--verbose',
+ action='store_true')
+
+ return argparser.parse_args()
+
+#
+# Parses audio_criterion_types.xml / audio_criteria.xml files used at run time by the
+# engineconfigurable and outputs a dictionnary of criteria.
+# For each criteria, the name, type (aka inclusive (bitfield) or exclusive (enum), the values
+# are provided.
+#
+def parseCriteriaAndCriterionTypes(criteriaFile, criterionTypesFile):
+ # Parse criteria and criterion types XML files
+ #
+ criteria_tree = ET.parse(criteriaFile)
+ logging.info("Importing criteriaFile {}".format(criteriaFile))
+ criterion_types_tree = ET.parse(criterionTypesFile)
+ logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+
+ criteria_root = criteria_tree.getroot()
+ criterion_types_root = criterion_types_tree.getroot()
+
+ all_criteria = []
+ for criterion in criteria_root.findall('criterion'):
+ criterion_name = criterion.get('name')
+ type_name = criterion.get('type')
+ logging.info("Importing criterion_name {}".format(criterion_name))
+ logging.info("Importing type_name {}".format(type_name))
+
+ for criterion_types in criterion_types_tree.findall('criterion_type'):
+ criterion_type_name = criterion_types.get('name')
+ if criterion_type_name == type_name:
+ criterion_inclusiveness = criterion_types.get('type')
+
+ criterion_values = []
+
+ values_node = criterion_types.find('values')
+ if values_node:
+ for value in values_node.findall('value'):
+ criterion_values.append(value.get('literal'))
+
+ if len(criterion_values) == 0:
+ criterion_values.append('')
+
+ logging.info("Importing criterion_type_name {}".format(criterion_type_name))
+ logging.info("Importing criterion_inclusiveness {}".format(criterion_inclusiveness))
+ logging.info("Importing criterion_values {}".format(criterion_values))
+
+ all_criteria.append({
+ "name" : criterion_name,
+ "inclusive" : criterion_inclusiveness,
+ "values" : criterion_values})
+ break
+
+ return all_criteria
+
+#
+# Parses the Edd files (aka .pfw extension file), which is a simplified language to write the
+# parameter framework settings.
+#
+def parseEdd(EDDFiles):
+ parsed_edds = []
+
+ for edd_file in EDDFiles:
+ try:
+ root = EddParser.Parser().parse(edd_file)
+ except EddParser.MySyntaxError as ex:
+ logging.critical(str(ex))
+ logging.info("EXIT ON FAILURE")
+ exit(2)
+
+ try:
+ root.propagate()
+ except EddParser.MyPropagationError, ex :
+ logging.critical(str(ex))
+ logging.info("EXIT ON FAILURE")
+ exit(1)
+
+ parsed_edds.append((edd_file.name, root))
+ return parsed_edds
+
+#
+# Generates all the required commands to be sent to the instance of parameter-framework launched
+# at runtime to generate the XML Settings file.
+# It takes as input the collection of criteria, the domains and the simplified settings read from
+# pfw.
+#
+def generateDomainCommands(logging, all_criteria, initial_settings, xml_domain_files, parsed_edds):
+ # create and inject all the criteria
+ logging.info("Creating all criteria")
+ for criterion in all_criteria:
+ yield ["createSelectionCriterion", criterion['inclusive'],
+ criterion['name']] + criterion['values']
+
+ yield ["start"]
+
+ # Import initial settings file
+ if initial_settings:
+ logging.info("Importing initial settings file {}".format(initial_settings))
+ yield ["importDomainsWithSettingsXML", initial_settings]
+
+ # Import each standalone domain files
+ for domain_file in xml_domain_files:
+ logging.info("Importing single domain file {}".format(domain_file))
+ yield ["importDomainWithSettingsXML", domain_file]
+
+ # Generate the script for each EDD file
+ for filename, parsed_edd in parsed_edds:
+ logging.info("Translating and injecting EDD file {}".format(filename))
+ translator = PfwScriptTranslator()
+ parsed_edd.translate(translator)
+ for command in translator.getScript():
+ yield command
+
+#
+# Entry point of the domain generator.
+# -Parses Criterion types and criteria files
+# -Parses settings written in simplified pfw language.
+# -Launches a parameter-framework
+# -Translates the settings into command that can be interpreted by parameter-framework.
+# -Use the exports command and output them in XML Settings file.
+#
+def main():
+ logging.root.setLevel(logging.INFO)
+ args = parseArgs()
+
+ all_criteria = parseCriteriaAndCriterionTypes(args.criteria, args.criteriontypes)
+
+ #
+ # EDD files (aka ".pfw" files)
+ #
+ parsed_edds = parseEdd(args.edd_files)
+
+ # We need to modify the toplevel configuration file to account for differences
+ # between development setup and target (installation) setup, in particular, the
+ # TuningMwith ode must be enforced, regardless of what will be allowed on the target
+ fake_toplevel_config = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".xml",
+ prefix="TMPdomainGeneratorPFConfig_")
+
+ install_path = os.path.dirname(os.path.realpath(args.toplevel_config))
+ hostConfig.configure(
+ infile=args.toplevel_config,
+ outfile=fake_toplevel_config,
+ structPath=install_path)
+ fake_toplevel_config.close()
+
+ # Create the connector. Pipe its input to us in order to write commands;
+ # connect its output to stdout in order to have it dump the domains
+ # there; connect its error output to stderr.
+ connector = subprocess.Popen(["domainGeneratorConnector",
+ fake_toplevel_config.name,
+ 'verbose' if args.verbose else 'no-verbose',
+ 'validate' if args.validate else 'no-validate',
+ args.schemas_dir],
+ stdout=sys.stdout, stdin=subprocess.PIPE, stderr=sys.stderr)
+
+ initial_settings = None
+ if args.initial_settings:
+ initial_settings = os.path.realpath(args.initial_settings)
+
+ for command in generateDomainCommands(logging, all_criteria, initial_settings,
+ args.xml_domain_files, parsed_edds):
+ connector.stdin.write('\0'.join(command))
+ connector.stdin.write("\n")
+
+ # Closing the connector's input triggers the domain generation
+ connector.stdin.close()
+ connector.wait()
+ os.remove(fake_toplevel_config.name)
+ return connector.returncode
+
+# If this file is directly executed
+if __name__ == "__main__":
+ exit(main())