blob: 4c75f8bf2d00133a9c7c9e6ed9506f1b0d7cec46 [file] [log] [blame]
Colin Cross72119102019-05-20 13:14:18 -07001#!/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."""
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 as_int(s):
69 try:
70 i = int(s)
71 except ValueError:
72 return s, False
73 return i, True
74
75
76def compare_version_gt(a, b):
77 """Compare two SDK versions.
78
79 Compares a and b, treating codenames like 'Q' as higher
80 than numerical versions like '28'.
81
82 Returns True if a > b
83
84 Args:
85 a: value to compare
86 b: value to compare
87 Returns:
88 True if a is a higher version than b
89 """
90
91 a, a_is_int = as_int(a.upper())
92 b, b_is_int = as_int(b.upper())
93
94 if a_is_int == b_is_int:
95 # Both are codenames or both are versions, compare directly
96 return a > b
97 else:
98 # One is a codename, the other is not. Return true if
99 # b is an integer version
100 return b_is_int
101
102
103def get_indent(element, default_level):
104 indent = ''
105 if element is not None and element.nodeType == minidom.Node.TEXT_NODE:
106 text = element.nodeValue
107 indent = text[:len(text)-len(text.lstrip())]
108 if not indent or indent == '\n':
109 # 1 indent = 4 space
110 indent = '\n' + (' ' * default_level * 4)
111 return indent
112
113
114def write_xml(f, doc):
115 f.write('<?xml version="1.0" encoding="utf-8"?>\n')
116 for node in doc.childNodes:
117 f.write(node.toxml(encoding='utf-8') + '\n')