1#!/usr/bin/env python 2# 3# Copyright (C) 2018 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17"""A tool for inserting values from the build system into a manifest or a test config.""" 18 19from __future__ import print_function 20from xml.dom import minidom 21 22 23android_ns = 'http://schemas.android.com/apk/res/android' 24 25 26def get_children_with_tag(parent, tag_name): 27 children = [] 28 for child in parent.childNodes: 29 if child.nodeType == minidom.Node.ELEMENT_NODE and \ 30 child.tagName == tag_name: 31 children.append(child) 32 return children 33 34 35def find_child_with_attribute(element, tag_name, namespace_uri, 36 attr_name, value): 37 for child in get_children_with_tag(element, tag_name): 38 attr = child.getAttributeNodeNS(namespace_uri, attr_name) 39 if attr is not None and attr.value == value: 40 return child 41 return None 42 43 44def parse_manifest(doc): 45 """Get the manifest element.""" 46 47 manifest = doc.documentElement 48 if manifest.tagName != 'manifest': 49 raise RuntimeError('expected manifest tag at root') 50 return manifest 51 52 53def ensure_manifest_android_ns(doc): 54 """Make sure the manifest tag defines the android namespace.""" 55 56 manifest = parse_manifest(doc) 57 58 ns = manifest.getAttributeNodeNS(minidom.XMLNS_NAMESPACE, 'android') 59 if ns is None: 60 attr = doc.createAttributeNS(minidom.XMLNS_NAMESPACE, 'xmlns:android') 61 attr.value = android_ns 62 manifest.setAttributeNode(attr) 63 elif ns.value != android_ns: 64 raise RuntimeError('manifest tag has incorrect android namespace ' + 65 ns.value) 66 67 68def parse_test_config(doc): 69 """ Get the configuration element. """ 70 71 test_config = doc.documentElement 72 if test_config.tagName != 'configuration': 73 raise RuntimeError('expected configuration tag at root') 74 return test_config 75 76 77def as_int(s): 78 try: 79 i = int(s) 80 except ValueError: 81 return s, False 82 return i, True 83 84 85def compare_version_gt(a, b): 86 """Compare two SDK versions. 87 88 Compares a and b, treating codenames like 'Q' as higher 89 than numerical versions like '28'. 90 91 Returns True if a > b 92 93 Args: 94 a: value to compare 95 b: value to compare 96 Returns: 97 True if a is a higher version than b 98 """ 99 100 a, a_is_int = as_int(a.upper()) 101 b, b_is_int = as_int(b.upper()) 102 103 if a_is_int == b_is_int: 104 # Both are codenames or both are versions, compare directly 105 return a > b 106 else: 107 # One is a codename, the other is not. Return true if 108 # b is an integer version 109 return b_is_int 110 111 112def get_indent(element, default_level): 113 indent = '' 114 if element is not None and element.nodeType == minidom.Node.TEXT_NODE: 115 text = element.nodeValue 116 indent = text[:len(text)-len(text.lstrip())] 117 if not indent or indent == '\n': 118 # 1 indent = 4 space 119 indent = '\n' + (' ' * default_level * 4) 120 return indent 121 122 123def write_xml(f, doc): 124 f.write('<?xml version="1.0" encoding="utf-8"?>\n') 125 for node in doc.childNodes: 126 f.write(node.toxml(encoding='utf-8') + '\n') 127