def add_uses_non_sdk_api(doc): """Add android:usesNonSdkApi=true attribute to <application>. Args: doc: The XML document. May be modified by this function. Raises: RuntimeError: Invalid manifest """ manifest = parse_manifest(doc) elems = get_children_with_tag(manifest, 'application') application = elems[0] if len(elems) == 1 else None if len(elems) > 1: raise RuntimeError('found multiple <application> tags') elif not elems: application = doc.createElement('application') indent = get_indent(manifest.firstChild, 1) first = manifest.firstChild manifest.insertBefore(doc.createTextNode(indent), first) manifest.insertBefore(application, first) attr = application.getAttributeNodeNS(android_ns, 'usesNonSdkApi') if attr is None: attr = doc.createAttributeNS(android_ns, 'android:usesNonSdkApi') attr.value = 'true' application.setAttributeNode(attr)
def extract_uses_libs_xml(xml): """Extract <uses-library> tags from the manifest.""" manifest = parse_manifest(xml) elems = get_children_with_tag(manifest, 'application') application = elems[0] if len(elems) == 1 else None if len(elems) > 1: raise RuntimeError('found multiple <application> tags') elif not elems: if uses_libraries or optional_uses_libraries: raise ManifestMismatchError('no <application> tag found') return libs = get_children_with_tag(application, 'uses-library') required = [uses_library_name(x) for x in libs if uses_library_required(x)] optional = [ uses_library_name(x) for x in libs if not uses_library_required(x) ] # render <uses-library> tags as XML for a pretty error message tags = [] for lib in libs: tags.append(lib.toprettyxml()) required = first_unique_elements(required) optional = first_unique_elements(optional) tags = first_unique_elements(tags) return required, optional, tags
def extract_target_sdk_version(doc): """Returns the targetSdkVersion from the manifest. Args: doc: The XML document. Raises: RuntimeError: invalid manifest """ manifest = parse_manifest(doc) # Get or insert the uses-sdk element uses_sdk = get_children_with_tag(manifest, 'uses-sdk') if len(uses_sdk) > 1: raise RuntimeError('found multiple uses-sdk elements') elif len(uses_sdk) == 0: raise RuntimeError('missing uses-sdk element') uses_sdk = uses_sdk[0] min_attr = uses_sdk.getAttributeNodeNS(android_ns, 'minSdkVersion') if min_attr is None: raise RuntimeError('minSdkVersion is not specified') target_attr = uses_sdk.getAttributeNodeNS(android_ns, 'targetSdkVersion') if target_attr is None: target_attr = min_attr return target_attr.value
def raise_min_sdk_version(doc, min_sdk_version, target_sdk_version, library): """Ensure the manifest contains a <uses-sdk> tag with a minSdkVersion. Args: doc: The XML document. May be modified by this function. min_sdk_version: The requested minSdkVersion attribute. target_sdk_version: The requested targetSdkVersion attribute. library: True if the manifest is for a library. Raises: RuntimeError: invalid manifest """ manifest = parse_manifest(doc) # Get or insert the uses-sdk element uses_sdk = get_children_with_tag(manifest, 'uses-sdk') if len(uses_sdk) > 1: raise RuntimeError('found multiple uses-sdk elements') elif len(uses_sdk) == 1: element = uses_sdk[0] else: element = doc.createElement('uses-sdk') indent = get_indent(manifest.firstChild, 1) manifest.insertBefore(element, manifest.firstChild) # Insert an indent before uses-sdk to line it up with the indentation of the # other children of the <manifest> tag. manifest.insertBefore(doc.createTextNode(indent), manifest.firstChild) # Get or insert the minSdkVersion attribute. If it is already present, make # sure it as least the requested value. min_attr = element.getAttributeNodeNS(android_ns, 'minSdkVersion') if min_attr is None: min_attr = doc.createAttributeNS(android_ns, 'android:minSdkVersion') min_attr.value = min_sdk_version element.setAttributeNode(min_attr) else: if compare_version_gt(min_sdk_version, min_attr.value): min_attr.value = min_sdk_version # Insert the targetSdkVersion attribute if it is missing. If it is already # present leave it as is. target_attr = element.getAttributeNodeNS(android_ns, 'targetSdkVersion') if target_attr is None: target_attr = doc.createAttributeNS(android_ns, 'android:targetSdkVersion') if library: # TODO(b/117122200): libraries shouldn't set targetSdkVersion at all, but # ManifestMerger treats minSdkVersion="Q" as targetSdkVersion="Q" if it # is empty. Set it to something low so that it will be overriden by the # main manifest, but high enough that it doesn't cause implicit # permissions grants. target_attr.value = '15' else: target_attr.value = target_sdk_version element.setAttributeNode(target_attr)
def main(argv): if argv.__len__() < 2: if str(argv[0]).endswith(".manifest"): path = argv[0] else: path = os.path.abspath( '../') + "/resources/flowers-xy-V201902220937263726.manifest" data_set = manifest.parse_manifest(path) validate(data_set) elif argv.__len__() < 3: data_set = manifest.parse_manifest(argv[1]) validate(data_set) else: path = argv[1] ak = argv[2] sk = argv[3] endpoint = argv[4] data_set = manifest.parse_manifest(path, ak, sk, endpoint) validate(data_set)
def add_uses_libraries(doc, new_uses_libraries, required): """Add additional <uses-library> tags Args: doc: The XML document. May be modified by this function. new_uses_libraries: The names of libraries to be added by this function. required: The value of android:required attribute. Can be true or false. Raises: RuntimeError: Invalid manifest """ manifest = parse_manifest(doc) elems = get_children_with_tag(manifest, 'application') application = elems[0] if len(elems) == 1 else None if len(elems) > 1: raise RuntimeError('found multiple <application> tags') elif not elems: application = doc.createElement('application') indent = get_indent(manifest.firstChild, 1) first = manifest.firstChild manifest.insertBefore(doc.createTextNode(indent), first) manifest.insertBefore(application, first) indent = get_indent(application.firstChild, 2) last = application.lastChild if last is not None and last.nodeType != minidom.Node.TEXT_NODE: last = None for name in new_uses_libraries: if find_child_with_attribute(application, 'uses-library', android_ns, 'name', name) is not None: # If the uses-library tag of the same 'name' attribute value exists, # respect it. continue ul = doc.createElement('uses-library') ul.setAttributeNS(android_ns, 'android:name', name) ul.setAttributeNS(android_ns, 'android:required', str(required).lower()) application.insertBefore(doc.createTextNode(indent), last) application.insertBefore(ul, last) # align the closing tag with the opening tag if it's not # indented if application.lastChild.nodeType != minidom.Node.TEXT_NODE: indent = get_indent(application.previousSibling, 1) application.appendChild(doc.createTextNode(indent))
def overwrite_package_name(test_config_doc, manifest_doc, package_name): manifest = parse_manifest(manifest_doc) original_package = manifest.getAttribute('package') test_config = parse_test_config(test_config_doc) tests = get_children_with_tag(test_config, 'test') for test in tests: options = get_children_with_tag(test, 'option') for option in options: if option.getAttribute( 'name') == "package" and option.getAttribute( 'value') == original_package: option.setAttribute('value', package_name)
def AddLoggingParent(android_manifest, logging_parent_value): """Add logging parent as an additional <meta-data> tag. Args: android_manifest: A string representing AndroidManifest.xml logging_parent_value: A string representing the logging parent value. Raises: RuntimeError: Invalid manifest Returns: A path to modified AndroidManifest.xml """ doc = minidom.parse(android_manifest) manifest = parse_manifest(doc) logging_parent_key = 'android.content.pm.LOGGING_PARENT' elems = get_children_with_tag(manifest, 'application') application = elems[0] if len(elems) == 1 else None if len(elems) > 1: raise RuntimeError('found multiple <application> tags') elif not elems: application = doc.createElement('application') indent = get_indent(manifest.firstChild, 1) first = manifest.firstChild manifest.insertBefore(doc.createTextNode(indent), first) manifest.insertBefore(application, first) indent = get_indent(application.firstChild, 2) last = application.lastChild if last is not None and last.nodeType != minidom.Node.TEXT_NODE: last = None if not find_child_with_attribute(application, 'meta-data', android_ns, 'name', logging_parent_key): ul = doc.createElement('meta-data') ul.setAttributeNS(android_ns, 'android:name', logging_parent_key) ul.setAttributeNS(android_ns, 'android:value', logging_parent_value) application.insertBefore(doc.createTextNode(indent), last) application.insertBefore(ul, last) last = application.lastChild if last and last.nodeType != minidom.Node.TEXT_NODE: indent = get_indent(application.previousSibling, 1) application.appendChild(doc.createTextNode(indent)) with tempfile.NamedTemporaryFile(delete=False) as temp: write_xml(temp, doc) return temp.name
def add_logging_parent(doc, logging_parent_value): """Add logging parent as an additional <meta-data> tag. Args: doc: The XML document. May be modified by this function. logging_parent_value: A string representing the logging parent value. Raises: RuntimeError: Invalid manifest """ manifest = parse_manifest(doc) logging_parent_key = 'android.content.pm.LOGGING_PARENT' elems = get_children_with_tag(manifest, 'application') application = elems[0] if len(elems) == 1 else None if len(elems) > 1: raise RuntimeError('found multiple <application> tags') elif not elems: application = doc.createElement('application') indent = get_indent(manifest.firstChild, 1) first = manifest.firstChild manifest.insertBefore(doc.createTextNode(indent), first) manifest.insertBefore(application, first) indent = get_indent(application.firstChild, 2) last = application.lastChild if last is not None and last.nodeType != minidom.Node.TEXT_NODE: last = None if not find_child_with_attribute(application, 'meta-data', android_ns, 'name', logging_parent_key): ul = doc.createElement('meta-data') ul.setAttributeNS(android_ns, 'android:name', logging_parent_key) ul.setAttributeNS(android_ns, 'android:value', logging_parent_value) application.insertBefore(doc.createTextNode(indent), last) application.insertBefore(ul, last) last = application.lastChild # align the closing tag with the opening tag if it's not # indented if last and last.nodeType != minidom.Node.TEXT_NODE: indent = get_indent(application.previousSibling, 1) application.appendChild(doc.createTextNode(indent))
def set_has_code_to_false(doc): manifest = parse_manifest(doc) elems = get_children_with_tag(manifest, 'application') application = elems[0] if len(elems) == 1 else None if len(elems) > 1: raise RuntimeError('found multiple <application> tags') elif not elems: application = doc.createElement('application') indent = get_indent(manifest.firstChild, 1) first = manifest.firstChild manifest.insertBefore(doc.createTextNode(indent), first) manifest.insertBefore(application, first) attr = application.getAttributeNodeNS(android_ns, 'hasCode') if attr is not None: # Do nothing if the application already has a hasCode attribute. return attr = doc.createAttributeNS(android_ns, 'android:hasCode') attr.value = 'false' application.setAttributeNode(attr)
def add_use_embedded_dex(doc): manifest = parse_manifest(doc) elems = get_children_with_tag(manifest, 'application') application = elems[0] if len(elems) == 1 else None if len(elems) > 1: raise RuntimeError('found multiple <application> tags') elif not elems: application = doc.createElement('application') indent = get_indent(manifest.firstChild, 1) first = manifest.firstChild manifest.insertBefore(doc.createTextNode(indent), first) manifest.insertBefore(application, first) attr = application.getAttributeNodeNS(android_ns, 'useEmbeddedDex') if attr is None: attr = doc.createAttributeNS(android_ns, 'android:useEmbeddedDex') attr.value = 'true' application.setAttributeNode(attr) elif attr.value != 'true': raise RuntimeError( 'existing attribute mismatches the option of --use-embedded-dex')
def extract_target_sdk_version_xml(xml): """Extract targetSdkVersion tags from the manifest.""" manifest = parse_manifest(xml) # Get or insert the uses-sdk element uses_sdk = get_children_with_tag(manifest, 'uses-sdk') if len(uses_sdk) > 1: raise RuntimeError('found multiple uses-sdk elements') elif len(uses_sdk) == 0: raise RuntimeError('missing uses-sdk element') uses_sdk = uses_sdk[0] min_attr = uses_sdk.getAttributeNodeNS(android_ns, 'minSdkVersion') if min_attr is None: raise RuntimeError('minSdkVersion is not specified') target_attr = uses_sdk.getAttributeNodeNS(android_ns, 'targetSdkVersion') if target_attr is None: target_attr = min_attr return target_attr.value
def add_extract_native_libs(doc, extract_native_libs): manifest = parse_manifest(doc) elems = get_children_with_tag(manifest, 'application') application = elems[0] if len(elems) == 1 else None if len(elems) > 1: raise RuntimeError('found multiple <application> tags') elif not elems: application = doc.createElement('application') indent = get_indent(manifest.firstChild, 1) first = manifest.firstChild manifest.insertBefore(doc.createTextNode(indent), first) manifest.insertBefore(application, first) value = str(extract_native_libs).lower() attr = application.getAttributeNodeNS(android_ns, 'extractNativeLibs') if attr is None: attr = doc.createAttributeNS(android_ns, 'android:extractNativeLibs') attr.value = value application.setAttributeNode(attr) elif attr.value != value: raise RuntimeError( 'existing attribute extractNativeLibs="%s" conflicts with --extract-native-libs="%s"' % (attr.value, value))
def enforce_uses_libraries(doc, uses_libraries, optional_uses_libraries): """Verify that the <uses-library> tags in the manifest match those provided by the build system. Args: doc: The XML document. uses_libraries: The names of <uses-library> tags known to the build system optional_uses_libraries: The names of <uses-library> tags with required:fals known to the build system Raises: RuntimeError: Invalid manifest ManifestMismatchError: Manifest does not match """ manifest = parse_manifest(doc) elems = get_children_with_tag(manifest, 'application') application = elems[0] if len(elems) == 1 else None if len(elems) > 1: raise RuntimeError('found multiple <application> tags') elif not elems: if uses_libraries or optional_uses_libraries: raise ManifestMismatchError('no <application> tag found') return verify_uses_library(application, uses_libraries, optional_uses_libraries)