1#!/usr/bin/python 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 re 21import sys 22import tempfile 23import os 24import logging 25import subprocess 26import xml.etree.ElementTree as ET 27import xml.etree.ElementInclude as EI 28import xml.dom.minidom as MINIDOM 29from collections import OrderedDict 30 31# 32# Helper script that helps to feed at build time the XML Product Strategies Structure file file used 33# by the engineconfigurable to start the parameter-framework. 34# It prevents to fill them manually and avoid divergences with android. 35# 36# The Product Strategies Structure file is fed from the audio policy engine configuration file 37# in order to discover all the strategies available for the current platform. 38# --audiopolicyengineconfigurationfile <path/to/audio_policy_engine_configuration.xml> 39# 40# The reference file of ProductStrategies structure must also be set as an input of the script: 41# --productstrategiesstructurefile <path/to/structure/file/ProductStrategies.xml.in> 42# 43# At last, the output of the script shall be set also: 44# --outputfile <path/to/out/<system|vendor|odm>/etc/ProductStrategies.xml> 45# 46 47def parseArgs(): 48 argparser = argparse.ArgumentParser(description="Parameter-Framework XML \ 49 product strategies structure file generator.\n\ 50 Exit with the number of (recoverable or not) error that occured.") 51 argparser.add_argument('--audiopolicyengineconfigurationfile', 52 help="Android Audio Policy Engine Configuration file, Mandatory.", 53 metavar="(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)", 54 type=argparse.FileType('r'), 55 required=True) 56 argparser.add_argument('--productstrategiesstructurefile', 57 help="Product Strategies Structure XML base file, Mandatory.", 58 metavar="STRATEGIES_STRUCTURE_FILE", 59 type=argparse.FileType('r'), 60 required=True) 61 argparser.add_argument('--outputfile', 62 help="Product Strategies Structure output file, Mandatory.", 63 metavar="STRATEGIES_STRUCTURE_OUTPUT_FILE", 64 type=argparse.FileType('w'), 65 required=True) 66 argparser.add_argument('--verbose', 67 action='store_true') 68 69 return argparser.parse_args() 70 71 72def generateXmlStructureFile(strategies, strategyStructureInFile, outputFile): 73 74 logging.info("Importing strategyStructureInFile {}".format(strategyStructureInFile)) 75 strategies_in_tree = ET.parse(strategyStructureInFile) 76 77 strategies_root = strategies_in_tree.getroot() 78 strategy_components = strategies_root.find('ComponentType') 79 80 for strategy_name in strategies: 81 context_mapping = "".join(map(str, ["Name:", strategy_name])) 82 strategy_pfw_name = strategy_name.replace('STRATEGY_', '').lower() 83 strategy_component_node = ET.SubElement(strategy_components, "Component", Name=strategy_pfw_name, Type="ProductStrategy", Mapping=context_mapping) 84 85 xmlstr = ET.tostring(strategies_root, encoding='utf8', method='xml') 86 reparsed = MINIDOM.parseString(xmlstr) 87 prettyXmlStr = reparsed.toprettyxml(newl='\r\n') 88 prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()]) 89 outputFile.write(prettyXmlStr.encode('utf-8')) 90 91def capitalizeLine(line): 92 return ' '.join((w.capitalize() for w in line.split(' '))) 93 94 95# 96# Parse the audio policy configuration file and output a dictionary of device criteria addresses 97# 98def parseAndroidAudioPolicyEngineConfigurationFile(audiopolicyengineconfigurationfile): 99 100 logging.info("Checking Audio Policy Engine Configuration file {}".format(audiopolicyengineconfigurationfile)) 101 # 102 # extract all product strategies name from audio policy engine configuration file 103 # 104 strategy_names = [] 105 106 oldWorkingDir = os.getcwd() 107 print "Current working directory %s" % oldWorkingDir 108 109 newDir = os.path.join(oldWorkingDir , audiopolicyengineconfigurationfile.name) 110 111 policy_engine_in_tree = ET.parse(audiopolicyengineconfigurationfile) 112 os.chdir(os.path.dirname(os.path.normpath(newDir))) 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(oldWorkingDir) 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(args.audiopolicyengineconfigurationfile) 132 133 product_strategies_structure = args.productstrategiesstructurefile 134 135 generateXmlStructureFile(strategies, product_strategies_structure, args.outputfile) 136 137# If this file is directly executed 138if __name__ == "__main__": 139 sys.exit(main()) 140