Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 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 | |
| 19 | import argparse |
| 20 | import re |
| 21 | import sys |
| 22 | import tempfile |
| 23 | import os |
| 24 | import logging |
| 25 | import subprocess |
| 26 | import xml.etree.ElementTree as ET |
| 27 | import xml.etree.ElementInclude as EI |
| 28 | import xml.dom.minidom as MINIDOM |
| 29 | from 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 | |
| 47 | def 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 | |
| 72 | def 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 | |
| 91 | def 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 | # |
| 98 | def 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 | |
| 127 | def 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 |
| 138 | if __name__ == "__main__": |
François Gaffie | df7f0a2 | 2019-04-02 17:42:15 +0200 | [diff] [blame] | 139 | sys.exit(main()) |