Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 1 | #!/usr/bin/python3 |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 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 |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 20 | import sys |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 21 | import os |
| 22 | import logging |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 23 | import xml.etree.ElementTree as ET |
| 24 | import xml.etree.ElementInclude as EI |
| 25 | import xml.dom.minidom as MINIDOM |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 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 | |
| 43 | def parseArgs(): |
| 44 | argparser = argparse.ArgumentParser(description="Parameter-Framework XML \ |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 45 | product strategies structure file generator.\n\ |
| 46 | Exit with the number of (recoverable or not) \ |
| 47 | error that occured.") |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 48 | argparser.add_argument('--audiopolicyengineconfigurationfile', |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 49 | help="Android Audio Policy Engine Configuration file, Mandatory.", |
| 50 | metavar="(AUDIO_POLICY_ENGINE_CONFIGURATION_FILE)", |
| 51 | type=argparse.FileType('r'), |
| 52 | required=True) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 53 | argparser.add_argument('--productstrategiesstructurefile', |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 54 | help="Product Strategies Structure XML base file, Mandatory.", |
| 55 | metavar="STRATEGIES_STRUCTURE_FILE", |
| 56 | type=argparse.FileType('r'), |
| 57 | required=True) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 58 | argparser.add_argument('--outputfile', |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 59 | help="Product Strategies Structure output file, Mandatory.", |
| 60 | metavar="STRATEGIES_STRUCTURE_OUTPUT_FILE", |
| 61 | type=argparse.FileType('w'), |
| 62 | required=True) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 63 | argparser.add_argument('--verbose', |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 64 | action='store_true') |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 65 | |
| 66 | return argparser.parse_args() |
| 67 | |
| 68 | |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 69 | def generateXmlStructureFile(strategies, strategy_structure_in_file, output_file): |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 70 | |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 71 | logging.info("Importing strategy_structure_in_file {}".format(strategy_structure_in_file)) |
| 72 | strategies_in_tree = ET.parse(strategy_structure_in_file) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 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() |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 80 | ET.SubElement(strategy_components, "Component", |
| 81 | Name=strategy_pfw_name, Type="ProductStrategy", |
| 82 | Mapping=context_mapping) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 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()]) |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 88 | output_file.write(prettyXmlStr) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 89 | |
| 90 | def 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 | # |
| 97 | def parseAndroidAudioPolicyEngineConfigurationFile(audiopolicyengineconfigurationfile): |
| 98 | |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 99 | logging.info("Checking Audio Policy Engine Configuration file {}".format( |
| 100 | audiopolicyengineconfigurationfile)) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 101 | # |
| 102 | # extract all product strategies name from audio policy engine configuration file |
| 103 | # |
| 104 | strategy_names = [] |
| 105 | |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 106 | old_working_dir = os.getcwd() |
| 107 | print("Current working directory %s" % old_working_dir) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 108 | |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 109 | new_dir = os.path.join(old_working_dir, audiopolicyengineconfigurationfile.name) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 110 | |
| 111 | policy_engine_in_tree = ET.parse(audiopolicyengineconfigurationfile) |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 112 | os.chdir(os.path.dirname(os.path.normpath(new_dir))) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 113 | |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 114 | print("new working directory %s" % os.getcwd()) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 115 | |
| 116 | policy_engine_root = policy_engine_in_tree.getroot() |
| 117 | EI.include(policy_engine_root) |
| 118 | |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 119 | os.chdir(old_working_dir) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 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 | |
Francois Gaffie | 31987fb | 2019-09-03 11:57:33 +0200 | [diff] [blame] | 131 | strategies = parseAndroidAudioPolicyEngineConfigurationFile( |
| 132 | args.audiopolicyengineconfigurationfile) |
Francois Gaffie | 7d602f0 | 2019-02-13 10:37:49 +0100 | [diff] [blame] | 133 | |
| 134 | product_strategies_structure = args.productstrategiesstructurefile |
| 135 | |
| 136 | generateXmlStructureFile(strategies, product_strategies_structure, args.outputfile) |
| 137 | |
| 138 | # If this file is directly executed |
| 139 | if __name__ == "__main__": |
François Gaffie | df7f0a2 | 2019-04-02 17:42:15 +0200 | [diff] [blame] | 140 | sys.exit(main()) |