manifest.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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. from __future__ import print_function
  19. from xml.dom import minidom
  20. android_ns = 'http://schemas.android.com/apk/res/android'
  21. def get_children_with_tag(parent, tag_name):
  22. children = []
  23. for child in parent.childNodes:
  24. if child.nodeType == minidom.Node.ELEMENT_NODE and \
  25. child.tagName == tag_name:
  26. children.append(child)
  27. return children
  28. def find_child_with_attribute(element, tag_name, namespace_uri,
  29. attr_name, value):
  30. for child in get_children_with_tag(element, tag_name):
  31. attr = child.getAttributeNodeNS(namespace_uri, attr_name)
  32. if attr is not None and attr.value == value:
  33. return child
  34. return None
  35. def parse_manifest(doc):
  36. """Get the manifest element."""
  37. manifest = doc.documentElement
  38. if manifest.tagName != 'manifest':
  39. raise RuntimeError('expected manifest tag at root')
  40. return manifest
  41. def ensure_manifest_android_ns(doc):
  42. """Make sure the manifest tag defines the android namespace."""
  43. manifest = parse_manifest(doc)
  44. ns = manifest.getAttributeNodeNS(minidom.XMLNS_NAMESPACE, 'android')
  45. if ns is None:
  46. attr = doc.createAttributeNS(minidom.XMLNS_NAMESPACE, 'xmlns:android')
  47. attr.value = android_ns
  48. manifest.setAttributeNode(attr)
  49. elif ns.value != android_ns:
  50. raise RuntimeError('manifest tag has incorrect android namespace ' +
  51. ns.value)
  52. def parse_test_config(doc):
  53. """ Get the configuration element. """
  54. test_config = doc.documentElement
  55. if test_config.tagName != 'configuration':
  56. raise RuntimeError('expected configuration tag at root')
  57. return test_config
  58. def as_int(s):
  59. try:
  60. i = int(s)
  61. except ValueError:
  62. return s, False
  63. return i, True
  64. def compare_version_gt(a, b):
  65. """Compare two SDK versions.
  66. Compares a and b, treating codenames like 'Q' as higher
  67. than numerical versions like '28'.
  68. Returns True if a > b
  69. Args:
  70. a: value to compare
  71. b: value to compare
  72. Returns:
  73. True if a is a higher version than b
  74. """
  75. a, a_is_int = as_int(a.upper())
  76. b, b_is_int = as_int(b.upper())
  77. if a_is_int == b_is_int:
  78. # Both are codenames or both are versions, compare directly
  79. return a > b
  80. else:
  81. # One is a codename, the other is not. Return true if
  82. # b is an integer version
  83. return b_is_int
  84. def get_indent(element, default_level):
  85. indent = ''
  86. if element is not None and element.nodeType == minidom.Node.TEXT_NODE:
  87. text = element.nodeValue
  88. indent = text[:len(text)-len(text.lstrip())]
  89. if not indent or indent == '\n':
  90. # 1 indent = 4 space
  91. indent = '\n' + (' ' * default_level * 4)
  92. return indent
  93. def write_xml(f, doc):
  94. f.write('<?xml version="1.0" encoding="utf-8"?>\n')
  95. for node in doc.childNodes:
  96. f.write(node.toxml() + '\n')