1#!/usr/bin/python3 2 3# 4# Copyright 2019, The Android Open Source Project 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19import argparse 20import sys 21import os 22import logging 23import xml.etree.ElementTree as ET 24import xml.etree.ElementInclude as EI 25import xml.dom.minidom as MINIDOM 26 27# 28# Helper script that helps to feed at build time the XML Product Strategies Structure file file used 29# by the engineconfigurable to start the parameter-framework. 30# It prevents to fill them manually and avoid divergences with android. 31# 32# The Product Strategies Structure file is fed from the audio policy engine configuration file 33# in order to discover all the strategies available for the current platform. 34# --audiopolicyengineconfigurationfile <path/to/audio_policy_engine_configuration.xml> 35# 36# The reference file of ProductStrategies structure must also be set as an input of the script: 37# --productstrategiesstructurefile <path/to/structure/file/ProductStrategies.xml.in> 38# 39# At last, the output of the script shall be set also: 40# --outputfile <path/to/out/<system|vendor|odm>/etc/ProductStrategies.xml> 41# 42 43def parseArgs(): 44 argparser = argparse.ArgumentParser(description="Parameter-Framework XML \ 45 product strategies structure file generator.\n\ 46 Exit with the number of (recoverable or not) \ 47 error that occured.") 48 argparser.add_argument('--audiopolicyengineconfigurationfile', 49 help="Android Audio Policy Engine Configuration file, Mandatory.", 50 metavar="(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)", 51 type=argparse.FileType('r'), 52 required=True) 53 argparser.add_argument('--productstrategiesstructurefile', 54 help="Product Strategies Structure XML base file, Mandatory.", 55 metavar="STRATEGIES_STRUCTURE_FILE", 56 type=argparse.FileType('r'), 57 required=True) 58 argparser.add_argument('--outputfile', 59 help="Product Strategies Structure output file, Mandatory.", 60 metavar="STRATEGIES_STRUCTURE_OUTPUT_FILE", 61 type=argparse.FileType('w'), 62 required=True) 63 argparser.add_argument('--verbose', 64 action='store_true') 65 66 return argparser.parse_args() 67 68 69def generateXmlStructureFile(strategies, strategy_structure_in_file, output_file): 70 71 logging.info("Importing strategy_structure_in_file {}".format(strategy_structure_in_file)) 72 strategies_in_tree = ET.parse(strategy_structure_in_file) 73 74 strategies_root = strategies_in_tree.getroot() 75 strategy_components = strategies_root.find('ComponentType') 76 77 for strategy_name in strategies: 78 context_mapping = "".join(map(str, ["Name:", strategy_name])) 79 strategy_pfw_name = strategy_name.replace('STRATEGY_', '').lower() 80 ET.SubElement(strategy_components, "Component", 81 Name=strategy_pfw_name, Type="ProductStrategy", 82 Mapping=context_mapping) 83 84 xmlstr = ET.tostring(strategies_root, encoding='utf8', method='xml') 85 reparsed = MINIDOM.parseString(xmlstr) 86 prettyXmlStr = reparsed.toprettyxml(newl='\r\n') 87 prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()]) 88 output_file.write(prettyXmlStr) 89 90def capitalizeLine(line): 91 return ' '.join((w.capitalize() for w in line.split(' '))) 92 93 94# 95# Parse the audio policy configuration file and output a dictionary of device criteria addresses 96# 97def parseAndroidAudioPolicyEngineConfigurationFile(audiopolicyengineconfigurationfile): 98 99 logging.info("Checking Audio Policy Engine Configuration file {}".format( 100 audiopolicyengineconfigurationfile)) 101 # 102 # extract all product strategies name from audio policy engine configuration file 103 # 104 strategy_names = [] 105 106 old_working_dir = os.getcwd() 107 print("Current working directory %s" % old_working_dir) 108 109 new_dir = os.path.join(old_working_dir, audiopolicyengineconfigurationfile.name) 110 111 policy_engine_in_tree = ET.parse(audiopolicyengineconfigurationfile) 112 os.chdir(os.path.dirname(os.path.normpath(new_dir))) 113 114 print("new working directory %s" % os.getcwd()) 115 116 policy_engine_root = policy_engine_in_tree.getroot() 117 EI.include(policy_engine_root) 118 119 os.chdir(old_working_dir) 120 121 for strategy in policy_engine_root.iter('ProductStrategy'): 122 strategy_names.append(strategy.get('name')) 123 124 return strategy_names 125 126 127def main(): 128 logging.root.setLevel(logging.INFO) 129 args = parseArgs() 130 131 strategies = parseAndroidAudioPolicyEngineConfigurationFile( 132 args.audiopolicyengineconfigurationfile) 133 134 product_strategies_structure = args.productstrategiesstructurefile 135 136 generateXmlStructureFile(strategies, product_strategies_structure, args.outputfile) 137 138# If this file is directly executed 139if __name__ == "__main__": 140 sys.exit(main()) 141