diff options
author | Raphael Moll <ralf@android.com> | 2012-09-27 16:27:14 -0700 |
---|---|---|
committer | Raphael Moll <ralf@android.com> | 2012-10-01 14:04:51 -0700 |
commit | f3cbbdcb991676dafcf0bdf46298c689314955d7 (patch) | |
tree | b3a9f7662317e59db3fbf53f09771aa9df13e3e4 /manifmerger | |
parent | 19206bf48631dd7997eb5a378300160df842bcf3 (diff) | |
download | sdk-f3cbbdcb991676dafcf0bdf46298c689314955d7.zip sdk-f3cbbdcb991676dafcf0bdf46298c689314955d7.tar.gz sdk-f3cbbdcb991676dafcf0bdf46298c689314955d7.tar.bz2 |
Manifest Merger: override/remove attributes.
Change-Id: Ib9c08ae8eb39caa91c319534f0ab9a786d65b801
Diffstat (limited to 'manifmerger')
13 files changed, 1014 insertions, 84 deletions
diff --git a/manifmerger/src/com/android/manifmerger/ManifestMerger.java b/manifmerger/src/com/android/manifmerger/ManifestMerger.java index bbe6e25..ded4eac 100755 --- a/manifmerger/src/com/android/manifmerger/ManifestMerger.java +++ b/manifmerger/src/com/android/manifmerger/ManifestMerger.java @@ -21,6 +21,7 @@ import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.manifmerger.IMergerLog.FileAndLine; import com.android.manifmerger.IMergerLog.Severity; +import com.android.utils.XmlUtils; import com.android.xml.AndroidXPathFactory; import org.w3c.dom.Attr; @@ -128,9 +129,20 @@ public class ManifestMerger { private XPath mXPath; private Document mMainDoc; - private String NS_URI = SdkConstants.NS_RESOURCES; - private String NS_PREFIX = AndroidXPathFactory.DEFAULT_NS_PREFIX; - private int destMinSdk; + /** Namespace for Android attributes in an AndroidManifest.xml */ + private static final String NS_URI = SdkConstants.NS_RESOURCES; + /** Prefix for the Android namespace to use in XPath expressions. */ + private static final String NS_PREFIX = AndroidXPathFactory.DEFAULT_NS_PREFIX; + /** Namespace used in XML files for Android Tooling attributes */ + private static final String TOOLS_URI = SdkConstants.TOOLS_URI; + /** The name of the tool:merge attribute, to either override or ignore merges. */ + private static final String MERGE_ATTR = "merge"; //$NON-NLS-1$ + /** tool:merge="override" means to ignore what comes from libraries and only keep the + * version from the main manifest. No conflict can be generated. */ + private static final String MERGE_OVERRIDE = "override"; //$NON-NLS-1$ + /** tool:merge="remove" means to remove a node and prevent merging -- not only is the + * node from the libraries not merged, but the element is removed from the main manifest. */ + private static final String MERGE_REMOVE = "remove"; //$NON-NLS-1$ /** * Sets of element/attribute that need to be treated as class names. @@ -141,6 +153,7 @@ public class ManifestMerger { "application/name", "application/backupAgent", "activity/name", + "activity-alias/name", "receiver/name", "service/name", "provider/name", @@ -183,14 +196,14 @@ public class ManifestMerger { File mainFile, File[] libraryFiles, Map<String, String> injectAttributes) { - Document mainDoc = XmlUtils.parseDocument(mainFile, mLog); + Document mainDoc = MergerXmlUtils.parseDocument(mainFile, mLog); if (mainDoc == null) { return false; } boolean success = process(mainDoc, libraryFiles, injectAttributes); - if (!XmlUtils.printXmlFile(mainDoc, outputFile, mLog)) { + if (!MergerXmlUtils.printXmlFile(mainDoc, outputFile, mLog)) { success = false; } return success; @@ -222,20 +235,21 @@ public class ManifestMerger { boolean success = true; mMainDoc = mainDoc; - XmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST); - XmlUtils.injectAttributes(mainDoc, injectAttributes, mLog); + MergerXmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST); + MergerXmlUtils.injectAttributes(mainDoc, injectAttributes, mLog); - String prefix = XmlUtils.lookupNsPrefix(mainDoc, SdkConstants.NS_RESOURCES); + String prefix = XmlUtils.lookupNamespacePrefix(mainDoc, SdkConstants.NS_RESOURCES); mXPath = AndroidXPathFactory.newXPath(prefix); expandFqcns(mainDoc); for (File libFile : libraryFiles) { - Document libDoc = XmlUtils.parseDocument(libFile, mLog); - if (libDoc == null || !mergeLibDoc(libDoc)) { + Document libDoc = MergerXmlUtils.parseDocument(libFile, mLog); + if (libDoc == null || !mergeLibDoc(cleanupToolsAttributes(libDoc))) { success = false; } } + cleanupToolsAttributes(mainDoc); mXPath = null; mMainDoc = null; return success; @@ -258,19 +272,20 @@ public class ManifestMerger { boolean success = true; mMainDoc = mainDoc; - XmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST); + MergerXmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST); - String prefix = XmlUtils.lookupNsPrefix(mainDoc, SdkConstants.NS_RESOURCES); + String prefix = XmlUtils.lookupNamespacePrefix(mainDoc, SdkConstants.NS_RESOURCES); mXPath = AndroidXPathFactory.newXPath(prefix); expandFqcns(mainDoc); for (Document libDoc : libraryDocs) { - XmlUtils.decorateDocument(libDoc, IMergerLog.LIBRARY); - if (!mergeLibDoc(libDoc)) { + MergerXmlUtils.decorateDocument(libDoc, IMergerLog.LIBRARY); + if (!mergeLibDoc(cleanupToolsAttributes(libDoc))) { success = false; } } + cleanupToolsAttributes(mainDoc); mXPath = null; mMainDoc = null; return success; @@ -300,32 +315,37 @@ public class ManifestMerger { err |= !doNotMergeCheckEqual("/manifest/compatible-screens", libDoc); //$NON-NLS-1$ err |= !doNotMergeCheckEqual("/manifest/supports-gl-texture", libDoc); //$NON-NLS-1$ + boolean skipApplication = hasOverrideOrRemoveTag( + findFirstElement(mMainDoc, "/manifest/application")); //$NON-NLS-1$ + // Strategy C - err |= !mergeNewOrEqual( - "/manifest/application/activity", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - err |= !mergeNewOrEqual( - "/manifest/application/activity-alias", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - err |= !mergeNewOrEqual( - "/manifest/application/service", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - err |= !mergeNewOrEqual( - "/manifest/application/receiver", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); - err |= !mergeNewOrEqual( - "/manifest/application/provider", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - libDoc, - true); + if (!skipApplication) { + err |= !mergeNewOrEqual( + "/manifest/application/activity", //$NON-NLS-1$ + "name", //$NON-NLS-1$ + libDoc, + true); + err |= !mergeNewOrEqual( + "/manifest/application/activity-alias", //$NON-NLS-1$ + "name", //$NON-NLS-1$ + libDoc, + true); + err |= !mergeNewOrEqual( + "/manifest/application/service", //$NON-NLS-1$ + "name", //$NON-NLS-1$ + libDoc, + true); + err |= !mergeNewOrEqual( + "/manifest/application/receiver", //$NON-NLS-1$ + "name", //$NON-NLS-1$ + libDoc, + true); + err |= !mergeNewOrEqual( + "/manifest/application/provider", //$NON-NLS-1$ + "name", //$NON-NLS-1$ + libDoc, + true); + } err |= !mergeNewOrEqual( "/manifest/permission", //$NON-NLS-1$ "name", //$NON-NLS-1$ @@ -348,12 +368,14 @@ public class ManifestMerger { false); // Strategy D - err |= !mergeAdjustRequired( - "/manifest/application/uses-library", //$NON-NLS-1$ - "name", //$NON-NLS-1$ - "required", //$NON-NLS-1$ - libDoc, - null /*alternateKeyAttr*/); + if (!skipApplication) { + err |= !mergeAdjustRequired( + "/manifest/application/uses-library", //$NON-NLS-1$ + "name", //$NON-NLS-1$ + "required", //$NON-NLS-1$ + libDoc, + null /*alternateKeyAttr*/); + } err |= !mergeAdjustRequired( "/manifest/uses-feature", //$NON-NLS-1$ "name", //$NON-NLS-1$ @@ -455,6 +477,10 @@ public class ManifestMerger { if (libApp == null) { return true; } + if (hasOverrideOrRemoveTag(mainApp)) { + // Don't check the <application> element since it is tagged with override or remove. + return true; + } for (String attrName : new String[] { "name", "backupAgent" }) { String libValue = getAttributeValue(libApp, attrName); @@ -506,6 +532,9 @@ public class ManifestMerger { boolean found = false; for (Element dest : findElements(mMainDoc, path)) { + if (hasOverrideOrRemoveTag(dest)) { + continue; + } if (compareElements(dest, src, false, null /*diff*/, null /*keyAttr*/)) { found = true; break; @@ -518,7 +547,7 @@ public class ManifestMerger { xmlFileAndLine(src), "%1$s defined in library, missing from main manifest:\n%2$s", path, - XmlUtils.dump(src, false /*nextSiblings*/)); + MergerXmlUtils.dump(src, false /*nextSiblings*/)); } } @@ -583,7 +612,13 @@ public class ManifestMerger { "Manifest has more than one %1$s[@%2$s=%3$s] element.", path, keyAttr, name); } + boolean doMerge = true; for (Element dest : dests) { + // Don't try to merge this element since it has tools:merge=override|remove. + if (hasOverrideOrRemoveTag(dest)) { + doMerge = false; + continue; + } // If there's already a similar node in the destination, check it's identical. StringBuilder diff = new StringBuilder(); if (compareElements(dest, src, false, diff, keyAttr)) { @@ -608,10 +643,12 @@ public class ManifestMerger { } } - // Ready to merge element src. Select which previous siblings to merge. - Node start = selectPreviousSiblings(src); + if (doMerge) { + // Ready to merge element src. Select which previous siblings to merge. + Node start = selectPreviousSiblings(src); - insertAtEndOf(parent, start, src); + insertAtEndOf(parent, start, src); + } } return success; @@ -634,7 +671,7 @@ public class ManifestMerger { /** * Merge elements as identified by their key name attribute. * The element must have an option boolean "required" attribute which can be either "true" or - * "false". Default is true if the attribute is misisng. When merging, a "false" is superseded + * "false". Default is true if the attribute is missisng. When merging, a "false" is superseded * by a "true" (explicit or implicit). * <p/> * When merging, this does NOT merge any other attributes than {@code keyAttr} and @@ -705,6 +742,7 @@ public class ManifestMerger { path, keyAttr, name); } if (dests.size() > 0) { + attr = src.getAttributeNodeNS(NS_URI, requiredAttr); String value = attr == null ? "true" : attr.getNodeValue(); //$NON-NLS-1$ if (value == null || !(value.equals("true") || value.equals("false"))) { @@ -717,8 +755,12 @@ public class ManifestMerger { boolean boolE = Boolean.parseBoolean(value); for (Element dest : dests) { - // Destination node exists. Compare the required attributes. + // Don't try to merge this element since it has tools:merge=override|remove. + if (hasOverrideOrRemoveTag(dest)) { + continue; + } + // Compare the required attributes. attr = dest.getAttributeNodeNS(NS_URI, requiredAttr); value = attr == null ? "true" : attr.getNodeValue(); //$NON-NLS-1$ if (value == null || !(value.equals("true") || value.equals("false"))) { @@ -927,6 +969,12 @@ public class ManifestMerger { boolean result = true; Element destUsesSdk = findFirstElement(mMainDoc, "/manifest/uses-sdk"); //$NON-NLS-1$ + + if (hasOverrideOrRemoveTag(destUsesSdk)) { + // Don't try to check this element since it has tools:merge=override|remove. + return true; + } + Element srcUsesSdk = findFirstElement(libDoc, "/manifest/uses-sdk"); //$NON-NLS-1$ AtomicInteger destValue = new AtomicInteger(1); @@ -935,7 +983,7 @@ public class ManifestMerger { AtomicBoolean srcImplied = new AtomicBoolean(true); // Check minSdkVersion - destMinSdk = 1; + int destMinSdk = 1; result = extractSdkVersionAttribute( libDoc, destUsesSdk, srcUsesSdk, @@ -1144,8 +1192,8 @@ public class ManifestMerger { */ private Node insertAtEndOf(Element dest, Node start, Node end) { // Check whether we'll need to adjust URI prefixes - String destPrefix = XmlUtils.lookupNsPrefix(mMainDoc, NS_URI); - String srcPrefix = XmlUtils.lookupNsPrefix(start.getOwnerDocument(), NS_URI); + String destPrefix = XmlUtils.lookupNamespacePrefix(mMainDoc, NS_URI); + String srcPrefix = XmlUtils.lookupNamespacePrefix(start.getOwnerDocument(), NS_URI); boolean needPrefixChange = destPrefix != null && !destPrefix.equals(srcPrefix); // First let's figure out the insertion point. @@ -1233,13 +1281,13 @@ public class ManifestMerger { @Nullable String keyAttr) { Map<String, String> nsPrefixE = new HashMap<String, String>(); Map<String, String> nsPrefixA = new HashMap<String, String>(); - String sE = XmlUtils.printElement(expected, nsPrefixE, ""); //$NON-NLS-1$ - String sA = XmlUtils.printElement(actual, nsPrefixA, ""); //$NON-NLS-1$ + String sE = MergerXmlUtils.printElement(expected, nsPrefixE, ""); //$NON-NLS-1$ + String sA = MergerXmlUtils.printElement(actual, nsPrefixA, ""); //$NON-NLS-1$ if (sE.equals(sA)) { return true; } else { if (diff != null) { - XmlUtils.printXmlDiff(diff, sE, sA, nsPrefixE, nsPrefixA, NS_URI + ':' + keyAttr); + MergerXmlUtils.printXmlDiff(diff, sE, sA, nsPrefixE, nsPrefixA, NS_URI + ':' + keyAttr); } return false; } @@ -1363,8 +1411,86 @@ public class ManifestMerger { * @return A new non-null {@link FileAndLine} combining the file name and line number. */ private @NonNull FileAndLine xmlFileAndLine(@NonNull Node node) { - return XmlUtils.xmlFileAndLine(node); + return MergerXmlUtils.xmlFileAndLine(node); + } + + /** + * Checks whether the given element has a tools:merge=override or tools:merge=remove attribute. + * @param node The node to check. + * @return True if the element has a tools:merge=override or tools:merge=remove attribute. + */ + private boolean hasOverrideOrRemoveTag(@Nullable Node node) { + if (node == null || node.getNodeType() != Node.ELEMENT_NODE) { + return false; + } + NamedNodeMap attrs = node.getAttributes(); + Node merge = attrs.getNamedItemNS(TOOLS_URI, MERGE_ATTR); + String value = merge == null ? null : merge.getNodeValue(); + return MERGE_OVERRIDE.equals(value) || MERGE_REMOVE.equals(value); } + /** + * Cleans up all tools attributes from the given node hierarchy. + * <p/> + * If an element is marked with tools:merge=override, this attribute is removed. + * If an element is marked with tools:merge=remove, the <em>whole</em> element is removed. + * + * @param root The root node to parse and edit, recursively. + */ + private void cleanupToolsAttributes(@Nullable Node root) { + if (root == null) { + return; + } + NamedNodeMap attrs = root.getAttributes(); + if (attrs != null) { + for (int i = attrs.getLength() - 1; i >= 0; i--) { + Node attr = attrs.item(i); + if (SdkConstants.XMLNS_URI.equals(attr.getNamespaceURI()) && + TOOLS_URI.equals(attr.getNodeValue())) { + attrs.removeNamedItem(attr.getNodeName()); + } else if (TOOLS_URI.equals(attr.getNamespaceURI()) && + MERGE_ATTR.equals(attr.getLocalName())) { + attrs.removeNamedItem(attr.getNodeName()); + } + } + assert attrs.getNamedItemNS(TOOLS_URI, MERGE_ATTR) == null; + } + + for (Node child = root.getFirstChild(); child != null; ) { + if (child.getNodeType() != Node.ELEMENT_NODE) { + child = child.getNextSibling(); + continue; + } + attrs = child.getAttributes(); + Node merge = attrs == null ? null : attrs.getNamedItemNS(TOOLS_URI, MERGE_ATTR); + String value = merge == null ? null : merge.getNodeValue(); + Node sibling = child.getNextSibling(); + if (MERGE_REMOVE.equals(value)) { + // Note: save the previous sibling since removing the child will clear its siblings. + Node prev = child.getPreviousSibling(); + root.removeChild(child); + // If there's some whitespace just before that element, clean it up too. + while (prev != null && prev.getNodeType() == Node.TEXT_NODE) { + if (prev.getNodeValue().trim().length() == 0) { + Node prevPrev = prev.getPreviousSibling(); + root.removeChild(prev); + prev = prevPrev; + } else { + break; + } + } + } else { + cleanupToolsAttributes(child); + } + child = sibling; + } + } + /** + * @see #cleanupToolsAttributes(Node) + */ + private Document cleanupToolsAttributes(@NonNull Document doc) { + cleanupToolsAttributes(doc.getFirstChild()); + return doc; + } } diff --git a/manifmerger/src/com/android/manifmerger/XmlUtils.java b/manifmerger/src/com/android/manifmerger/MergerXmlUtils.java index b17c7d4..4381479 100755 --- a/manifmerger/src/com/android/manifmerger/XmlUtils.java +++ b/manifmerger/src/com/android/manifmerger/MergerXmlUtils.java @@ -21,6 +21,7 @@ import com.android.annotations.Nullable; import com.android.manifmerger.IMergerLog.FileAndLine; import com.android.manifmerger.IMergerLog.Severity; import com.android.utils.ILogger; +import com.android.utils.XmlUtils; import org.w3c.dom.Attr; import org.w3c.dom.Document; @@ -57,7 +58,7 @@ import javax.xml.transform.stream.StreamResult; /** * A few XML handling utilities. */ -class XmlUtils { +class MergerXmlUtils { private static final String DATA_ORIGIN_FILE = "manif.merger.file"; //$NON-NLS-1$ private static final String DATA_FILE_NAME = "manif.merger.filename"; //$NON-NLS-1$ @@ -270,17 +271,6 @@ class XmlUtils { } /** - * Find the prefix for the given NS_URI in the document. - * - * @param doc The document root. - * @param nsUri The Namespace URI to look for. - * @return The namespace prefix if found or null. - */ - static String lookupNsPrefix(Document doc, String nsUri) { - return com.android.utils.XmlUtils.lookupNamespacePrefix(doc, nsUri); - } - - /** * Outputs the given XML {@link Document} to the file {@code outFile}. * * TODO right now reformats the document. Needs to output as-is, respecting white-space. @@ -617,8 +607,9 @@ class XmlUtils { // We want to add or replace the attribute. if (attr == null) { attr = doc.createAttributeNS(attrNsUri, attrName); - attr.setPrefix( - com.android.utils.XmlUtils.lookupNamespacePrefix(element, attrNsUri)); + if (attrNsUri != null) { + attr.setPrefix(XmlUtils.lookupNamespacePrefix(element, attrNsUri)); + } attrs.setNamedItemNS(attr); } attr.setNodeValue(value); @@ -703,7 +694,7 @@ class XmlUtils { hasText = true; } } else if (t == Node.ELEMENT_NODE) { - children.add(printElement(child, nsPrefix, prefix)); //$NON-NLS-1$ + children.add(printElement(child, nsPrefix, prefix)); if (!nextSiblings) { break; } diff --git a/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTest.java b/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTest.java index 63b76b8..717533a 100755 --- a/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTest.java +++ b/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTest.java @@ -157,4 +157,24 @@ public class ManifestMergerTest extends ManifestMergerTestCase { public void test60_merge_order() throws Exception { processTestFiles(); } + + public void test65_override_app() throws Exception { + processTestFiles(); + } + + public void test66_remove_app() throws Exception { + processTestFiles(); + } + + public void test67_override_activities() throws Exception { + processTestFiles(); + } + + public void test68_override_uses() throws Exception { + processTestFiles(); + } + + public void test69_remove_uses() throws Exception { + processTestFiles(); + } } diff --git a/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTestCase.java b/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTestCase.java index b2cdfab..b044c3a 100755 --- a/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTestCase.java +++ b/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTestCase.java @@ -435,19 +435,19 @@ abstract class ManifestMergerTestCase extends TestCase { // Test result XML. There should always be one created // since the process action does not stop on errors. log.clear(); - Document document = XmlUtils.parseDocument(testFiles.getActualResult(), mergerLog); + Document document = MergerXmlUtils.parseDocument(testFiles.getActualResult(), mergerLog); assertNotNull(document); assert document != null; // for Eclipse null analysis - String actual = XmlUtils.printXmlString(document, mergerLog); + String actual = MergerXmlUtils.printXmlString(document, mergerLog); assertEquals("Error parsing actual result XML", "[]", log.toString()); log.clear(); - document = XmlUtils.parseDocument( + document = MergerXmlUtils.parseDocument( testFiles.getExpectedResult(), mergerLog, new FileAndLine("<expected-result>", 0)); - assertNotNull(document); + assertNotNull("Failed to parse result document: " + testFiles.getExpectedResult(),document); assert document != null; - String expected = XmlUtils.printXmlString(document, mergerLog); + String expected = MergerXmlUtils.printXmlString(document, mergerLog); assertEquals("Error parsing expected result XML", "[]", log.toString()); assertEquals("Error comparing expected to actual result", expected, actual); diff --git a/manifmerger/tests/src/com/android/manifmerger/data/17_fqcn_conflict.xml b/manifmerger/tests/src/com/android/manifmerger/data/17_fqcn_conflict.xml index 7b95027..b4f5ea0 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/17_fqcn_conflict.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/17_fqcn_conflict.xml @@ -70,7 +70,9 @@ @lib4_not_package <manifest xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- It's an error for the manifest to lack a 'package' attribute. --> + <!-- It's an error for the manifest to lack a 'package' attribute. + We just emit a warning in this case. + --> <application> <!-- These class name can't be expanded due to the lack of 'package' attribute. --> diff --git a/manifmerger/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml b/manifmerger/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml index 65f0fb6..9e8f5a0 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml @@ -75,7 +75,7 @@ android:name="com.example.SomeLibrary2_RequiredTrue" android:required="true" /> - <!-- Same as 3 from main. Warning because destination as a duplicate. --> + <!-- Same as 3 from main. Warning because destination has a duplicate. --> <uses-library android:name="com.example.SomeLibrary3_RequiredFalse" android:required="false" /> diff --git a/manifmerger/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml b/manifmerger/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml index 494fd2e..114e9f4 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml @@ -1,7 +1,6 @@ # # Test supports-gl-texture: -# - it's OK if a library defines one or multiple times an element already in the application. -# - it's a warning if the library defines an element not in the application. +# - it's a warning if the library defines a supports-gl-texture not in the application. # - this does not actually merge anything. The XML is not changed at all. # diff --git a/manifmerger/tests/src/com/android/manifmerger/data/60_merge_order.xml b/manifmerger/tests/src/com/android/manifmerger/data/60_merge_order.xml index e820ecb..d6767f7 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/60_merge_order.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/60_merge_order.xml @@ -1,8 +1,9 @@ # -# Test: +# Test merge order: # - When activity / activity-alias / service / receiver / provider are merged, # we do a comparison to check whether the elements are already present in the -# main manifest. +# main manifest. The order of the elements must NOT matter in the comparison, +# nor does the whitespace between them. # - What this checks is that the order of the elements or attributes within # the elements should not matter. # diff --git a/manifmerger/tests/src/com/android/manifmerger/data/65_override_app.xml b/manifmerger/tests/src/com/android/manifmerger/data/65_override_app.xml new file mode 100755 index 0000000..464b52f --- /dev/null +++ b/manifmerger/tests/src/com/android/manifmerger/data/65_override_app.xml @@ -0,0 +1,197 @@ +# +# Test the tools:merge="override" tag on an application. +# It essentially ignores _any_ application tag from libraries. +# All other non-application elements are merged as usual. +# + +@main + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="com.example.app1" + android:versionCode="100" + android:versionName="1.0.0"> + + <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> + + <supports-screens + android:largeScreens="true" + android:smallScreens="true" + android:normalScreens="true" + android:resizeable="true" + android:xlargeScreens="true" + /> + + <uses-permission android:name="android.permission.INTERNET" /> + + <application + tools:merge="override" + android:name="TheApp" + android:backupAgent=".MyBackupAgent" > + <activity android:name=".MainActivity" /> + <receiver android:name="AppReceiver" /> + <activity android:name="com.example.lib2.LibActivity" /> + </application> + +</manifest> + + +@lib1_widget + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.lib1"> + + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> + + <permission + android:name="com.example.WhatWereYouThinking" + android:permissionGroup="com.example.MasterControlPermission" + android:protectionLevel="signatureOrSystem" /> + + <!-- This is overridden by main manifest and never merged, INCLUDING all activities. --> + <application android:name="TheApp" > + <activity android:name=".WidgetLibrary1" /> + </application> + +</manifest> + + +@lib2_widget + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.lib2"> + + <uses-feature + android:name="android.hardware.touchscreen" + android:required="false" /> + + <permission + android:description="Insert boring description here" + android:icon="@drawable/robot" + android:label="Danger, Will Robinson!" + android:name="com.example.DangerWillRobinson" + android:permissionGroup="com.example.MasterControlPermission" + android:protectionLevel="dangerous" /> + + <!-- This is overridden by main manifest and never merged, INCLUDING all activities. --> + <application + android:name="com.example.app1.TheApp" + android:backupAgent=".MyBackupAgent" > + <activity android:name=".WidgetLibrary2" /> + <activity android:name=".LibActivity" /> + </application> + +</manifest> + + +@lib3_widget + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.lib3"> + + <permission-group + android:description="Nobody expects..." + android:icon="@drawable/ignored_icon" + android:label="the Spanish Inquisition" + android:name="com.example.MasterControlPermission" /> + + <!-- This is overridden by main manifest and never merged, INCLUDING all activities. --> + <application android:name="com.example.app1.TheApp"> + <activity android:name=".WidgetLibrary3" /> + </application> + +</manifest> + + +@lib4_not_package + +<!-- It's an error for the manifest to lack a 'package' attribute. + We just emit a warning in this case. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + + <!-- Permission tree for lib4 --> + <permission-tree + android:label="This is not a label" + android:name="com.example.PermTree" /> + + <!-- This is overridden by main manifest and never merged, INCLUDING all activities. --> + <application> + <!-- These class name can't be expanded due to the lack of 'package' attribute. --> + <activity android:name=".LibActivity4" /> + <service android:name=".LibService4" /> + <receiver android:name=".LibReceiver4" /> + <provider android:name=".LibProvider4" /> + + </application> + +</manifest> + + +@result + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.app1" + android:versionCode="100" + android:versionName="1.0.0"> + + <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="11"/> + + <supports-screens + android:largeScreens="true" + android:smallScreens="true" + android:normalScreens="true" + android:resizeable="true" + android:xlargeScreens="true" + /> + + <uses-permission android:name="android.permission.INTERNET" /> + + <application + android:name="com.example.app1.TheApp" + android:backupAgent="com.example.app1.MyBackupAgent" > + <activity android:name="com.example.app1.MainActivity" /> + <receiver android:name="com.example.app1.AppReceiver" /> + <activity android:name="com.example.lib2.LibActivity" /> + </application> + + <permission + android:name="com.example.WhatWereYouThinking" + android:permissionGroup="com.example.MasterControlPermission" + android:protectionLevel="signatureOrSystem" /> + + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> + + <permission + android:description="Insert boring description here" + android:icon="@drawable/robot" + android:label="Danger, Will Robinson!" + android:name="com.example.DangerWillRobinson" + android:permissionGroup="com.example.MasterControlPermission" + android:protectionLevel="dangerous" /> + + <uses-feature + android:name="android.hardware.touchscreen" + android:required="false" /> + + <permission-group + android:description="Nobody expects..." + android:icon="@drawable/ignored_icon" + android:label="the Spanish Inquisition" + android:name="com.example.MasterControlPermission" /> + + <!-- Permission tree for lib4 --> + <permission-tree + android:label="This is not a label" + android:name="com.example.PermTree" /> + +</manifest> + +@errors + +W [ManifestMergerTest4_lib4_not_package.xml:1] Missing 'package' attribute in manifest. diff --git a/manifmerger/tests/src/com/android/manifmerger/data/66_remove_app.xml b/manifmerger/tests/src/com/android/manifmerger/data/66_remove_app.xml new file mode 100755 index 0000000..a1b04b5 --- /dev/null +++ b/manifmerger/tests/src/com/android/manifmerger/data/66_remove_app.xml @@ -0,0 +1,53 @@ +# +# Test how elements are removed by tools:merge="remove". +# + +@main + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="com.example.app1" + android:versionCode="100" + android:versionName="1.0.0"> + + <!-- The "remove" tag will eradicate this element from the output. --> + <application + tools:merge="remove" + android:name="TheApp" + android:backupAgent=".MyBackupAgent" > + <activity android:name=".MainActivity" /> + <receiver android:name="AppReceiver" /> + <activity android:name="com.example.lib2.LibActivity" /> + </application> +</manifest> + + +@lib1_widget + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.lib1"> + + <!-- This application and all its activities or content is ignored because the + main manifest requested to remove the application element. --> + <application android:name="TheApp" > + <activity android:name=".WidgetLibrary1" /> + </application> +</manifest> + + + +@result + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.app1" + android:versionCode="100" + android:versionName="1.0.0"> + + <!-- The "remove" tag will eradicate this element from the output. --> +</manifest> + +@errors + diff --git a/manifmerger/tests/src/com/android/manifmerger/data/67_override_activities.xml b/manifmerger/tests/src/com/android/manifmerger/data/67_override_activities.xml new file mode 100755 index 0000000..8bcdb63 --- /dev/null +++ b/manifmerger/tests/src/com/android/manifmerger/data/67_override_activities.xml @@ -0,0 +1,159 @@ +# +# Test how elements are overriden by tools:merge="override". +# The override only blocks elements that would be merged. +# + +@main + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="com.example" + android:versionCode="100" + android:versionName="1.0.0"> + + <application + android:name="TheApp" + android:backupAgent=".MyBackupAgent" > + <activity android:name=".MainActivity" tools:merge="override" /> + <receiver android:name="AppReceiver" tools:merge="override"/> + <activity android:name="com.example.lib2.LibActivity" /> + <service android:name="com.example.AppService1" tools:merge="override" /> + <provider android:name="com.example.Provider1" tools:merge="override" /> + <activity-alias android:name="AliasActivity1" tools:merge="override" /> + + </application> +</manifest> + + +@lib1 + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example"> + + <application> + <!-- Activity merged --> + <activity android:name=".WidgetLibrary1" /> + + <!-- Conflicting activity ignored by override --> + <activity + android:name="com.example.MainActivity" + android:label="@string/activity_name" + android:icon="@drawable/activity_icon" + android:theme="@style/Some.Theme"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <!-- Conflicting receiver ignored by override --> + <receiver + android:name="com.example.AppReceiver" + android:icon="@drawable/app_icon"> + <intent-filter> + <action android:name="com.example.action.ACTION_CUSTOM" /> + </intent-filter> + </receiver> + + <!-- Receiver merged --> + <receiver android:name="LibReceiver" /> + + <!-- Conflicting alias activity ignored by override --> + <activity-alias + android:name="com.example.AliasActivity1" + android:targetActivity="com.example.MainActivity1" + android:label="@string/alias_name1" + android:icon="@drawable/alias_icon1"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity-alias> + + <!-- Alias activity merged --> + <activity-alias + android:name="com.example.alias.MyActivity2" + android:targetActivity="com.example.MainActivity2" + android:label="@string/alias_name2" + android:icon="@drawable/alias_icon2"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity-alias> + + <!-- Conflicting service ignored by override --> + <service + android:icon="@drawable/app_icon" + android:name="com.example.AppService1" /> + + <!-- Service merged --> + <service + android:icon="@drawable/app_icon" + android:name="com.example.AppService2" /> + + <!-- Conflicting provider ignored by override --> + <provider + android:name="com.example.Provider1" + android:authorities="com.example.android.apis.app.thingy1" + android:enabled="@bool/someConditionalValue" /> + + <!-- Provider merged --> + <provider + android:name="com.example.Provider2" /> + + </application> +</manifest> + + +@result + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example" + android:versionCode="100" + android:versionName="1.0.0"> + + <application + android:name="com.example.TheApp" + android:backupAgent="com.example.MyBackupAgent" > + <activity android:name="com.example.MainActivity" /> + <receiver android:name="com.example.AppReceiver" /> + <activity android:name="com.example.lib2.LibActivity" /> + <service android:name="com.example.AppService1" /> + <provider android:name="com.example.Provider1" /> + <activity-alias android:name="com.example.AliasActivity1" /> + <!-- Activity merged --> + <activity android:name="com.example.WidgetLibrary1" /> + + <!-- Alias activity merged --> + <activity-alias + android:name="com.example.alias.MyActivity2" + android:targetActivity="com.example.MainActivity2" + android:label="@string/alias_name2" + android:icon="@drawable/alias_icon2"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity-alias> + + <!-- Service merged --> + <service + android:icon="@drawable/app_icon" + android:name="com.example.AppService2" /> + + <!-- Receiver merged --> + <receiver android:name="com.example.LibReceiver" /> + + <!-- Provider merged --> + <provider + android:name="com.example.Provider2" /> + + </application> +</manifest> + +@errors + diff --git a/manifmerger/tests/src/com/android/manifmerger/data/68_override_uses.xml b/manifmerger/tests/src/com/android/manifmerger/data/68_override_uses.xml new file mode 100755 index 0000000..a43d13e --- /dev/null +++ b/manifmerger/tests/src/com/android/manifmerger/data/68_override_uses.xml @@ -0,0 +1,205 @@ +# +# Test how elements are overriden by tools:merge="override". +# The override only blocks elements that would be merged. +# That means items which are just checked (not merged) still produce warnings. +# + +@main + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="com.example" + android:versionCode="100" + android:versionName="1.0.0"> + + <!-- This is the same as writing android:minSdkVersion="1" --> + <uses-sdk android:targetSdkVersion="14" tools:merge="override" /> + + <!-- Ignore permissions elements from lib that would conflict because + their definition is different. --> + <permission + tools:merge="override" + android:name="com.example.WhatWereYouThinking" + android:permissionGroup="com.example.MasterControlPermission" + android:protectionLevel="signatureOrSystem" /> + + <permission-group + tools:merge="override" + android:description="Nobody expects..." + android:icon="@drawable/ignored_icon" + android:label="the Spanish Inquisition" + android:name="com.example.MasterControlPermission" /> + + <permission-tree + tools:merge="override" + android:label="This is not a label" + android:name="com.example.PermTree" /> + + <!-- uses-feature is never merged, only checked, so tools:merge=override does nothing. --> + <uses-feature + android:name="com.example.SomeFeature0" + android:glEsVersion="0x00020001" /> + <!-- Ignore uses-feature from library, which would change required to + true if it were merged. --> + <uses-feature + tools:merge="override" + android:name="com.example.SomeFeature1" + android:required="false" /> + + <!-- supports-screens is never merged, only checked, so tools:merge=override does nothing. --> + <supports-screens + tools:merge="override" + android:smallScreens="true" + android:resizeable="false" + /> + + <!-- supports-gl-texture-screens-feature is never merged, only checked, so tools:merge=override does nothing. --> + <supports-gl-texture android:name="some.gl.texture1" tools:merge="override" /> + + <application android:name="com.example.TheApp" > + <!-- Ignore uses-library from library, which would change required to + true if it were merged. --> + <uses-library + android:name="com.example.SomeLibrary4_RequiredFalse" + android:required="false" + tools:merge="override" /> + + </application> + +</manifest> + + +@lib1 + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example"> + + <!-- The app can cope with API 1 but this library can only cope with API 4. --> + <uses-sdk android:minSdkVersion="4" /> + + <!-- Ignored permissions --> + <permission + android:name="com.example.WhatWereYouThinking" + android:permissionGroup="com.example.AnotherGroup" + android:protectionLevel="system" /> + + <permission-group + android:label="Nobody expects the Spanish Inquisition" + android:name="com.example.MasterControlPermission" /> + + <permission-tree + android:description="This is not the same label" + android:name="com.example.PermTree" /> + + <!-- GL 0.0 is a warning which is not prevented by tools:merge=override. --> + <uses-feature + android:name="com.example.SomeFeature0" + android:glEsVersion="0x00000000" /> + <uses-feature + android:name="com.example.SomeFeature1" + android:required="true" /> + + <!-- supports-screens isn't really merged, just checked, so tools:merge=override does nothing. --> + <!-- this is the not same supports-screens than in the main, will till make a warning. --> + <supports-screens + android:smallScreens="false" + android:resizeable="false" + /> + + <!-- supports-gl-texture isn't really merged, just checked, so tools:merge=override does nothing. --> + <!-- this is the not same supports-gl-texture than in the main. --> + <supports-gl-texture android:name="some.gl.texture3" /> + + <application android:name="com.example.TheApp" > + <!-- Ignored uses-library --> + <uses-library + android:name="com.example.SomeLibrary4_RequiredFalse" + android:required="true" /> + + </application> + +</manifest> + + +@lib2 + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example"> + + <!-- The app targets API 14 but this library targets 42. --> + <uses-sdk android:targetSdkVersion="42" /> + +</manifest> + + +@result + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example" + android:versionCode="100" + android:versionName="1.0.0"> + + <!-- This is the same as writing android:minSdkVersion="1" --> + <uses-sdk android:targetSdkVersion="14" /> + + <!-- Ignore permissions elements from lib that would conflict because + their definition is different. --> + <permission + android:name="com.example.WhatWereYouThinking" + android:permissionGroup="com.example.MasterControlPermission" + android:protectionLevel="signatureOrSystem" /> + + <permission-group + android:description="Nobody expects..." + android:icon="@drawable/ignored_icon" + android:label="the Spanish Inquisition" + android:name="com.example.MasterControlPermission" /> + + <permission-tree + android:label="This is not a label" + android:name="com.example.PermTree" /> + + <!-- uses-feature is never merged, only checked, so tools:merge=override does nothing. --> + <uses-feature + android:name="com.example.SomeFeature0" + android:glEsVersion="0x00020001" /> + <!-- Ignore uses-feature from library, which would change required to + true if it were merged. --> + <uses-feature + android:name="com.example.SomeFeature1" + android:required="false" /> + + <!-- supports-screens is never merged, only checked, so tools:merge=override does nothing. --> + <supports-screens + android:smallScreens="true" + android:resizeable="false" + /> + + <!-- supports-gl-texture-screens-feature is never merged, only checked, so tools:merge=override does nothing. --> + <supports-gl-texture android:name="some.gl.texture1" /> + + <application android:name="com.example.TheApp" > + <!-- Ignore uses-library from library, which would change required to + true if it were merged. --> + <uses-library + android:name="com.example.SomeLibrary4_RequiredFalse" + android:required="false" /> + + </application> + +</manifest> + +@errors + +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:19] /manifest/supports-screens defined in library, missing from main manifest: +<supports-screens> + @android:resizeable = false + @android:smallScreens = false +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:23] /manifest/supports-gl-texture defined in library, missing from main manifest: +<supports-gl-texture> + @android:name = some.gl.texture3 +W [ManifestMergerTest1_lib1.xml:14] Ignoring <uses-feature android:glEsVersion='0x00000000'> because it's smaller than 1.0. diff --git a/manifmerger/tests/src/com/android/manifmerger/data/69_remove_uses.xml b/manifmerger/tests/src/com/android/manifmerger/data/69_remove_uses.xml new file mode 100755 index 0000000..c3e46c9 --- /dev/null +++ b/manifmerger/tests/src/com/android/manifmerger/data/69_remove_uses.xml @@ -0,0 +1,177 @@ +# +# Test how elements are removed by tools:merge="remove". +# The removal happens is done at the end and block merges. +# That means items which are just checked (not merged) still produce warnings. +# + +@main + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="com.example" + android:versionCode="100" + android:versionName="1.0.0"> + + <!-- This is the same as writing android:minSdkVersion="1" --> + <uses-sdk android:targetSdkVersion="14" tools:merge="remove" /> + + <!-- Ignore permissions elements from lib that would conflict because + their definition is different. --> + <permission + tools:merge="remove" + android:name="com.example.WhatWereYouThinking" + android:permissionGroup="com.example.MasterControlPermission" + android:protectionLevel="signatureOrSystem" /> + + <permission-group + tools:merge="remove" + android:description="Nobody expects..." + android:icon="@drawable/ignored_icon" + android:label="the Spanish Inquisition" + android:name="com.example.MasterControlPermission" /> + + <permission-tree + tools:merge="remove" + android:label="This is not a label" + android:name="com.example.PermTree" /> + + <!-- uses-feature is never merged, only checked, so tools:merge=remove does nothing. --> + <uses-feature + tools:merge="remove" + android:name="com.example.SomeFeature0" + android:glEsVersion="0x00020001" /> + <!-- Ignore uses-feature from library, which would change required to + true if it were merged. --> + <uses-feature + tools:merge="remove" + android:name="com.example.SomeFeature1" + android:required="false" /> + + <!-- supports-screens is never merged, only checked, so tools:merge=remove does nothing. --> + <supports-screens + tools:merge="remove" + android:smallScreens="true" + android:resizeable="false" + /> + + <!-- supports-gl-texture-screens-feature is never merged, only checked, so tools:merge=remove does nothing. --> + <supports-gl-texture android:name="some.gl.texture1" tools:merge="remove" /> + + <application android:name="com.example.TheApp" > + <!-- Ignore uses-library from library, which would change required to + true if it were merged. --> + <uses-library + tools:merge="remove" + android:name="com.example.SomeLibrary4_RequiredFalse" + android:required="false" /> + + </application> + +</manifest> + + +@lib1 + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example"> + + <!-- The app can cope with API 1 but this library can only cope with API 4. --> + <uses-sdk android:minSdkVersion="4" /> + + <!-- Ignored permissions --> + <permission + android:name="com.example.WhatWereYouThinking" + android:permissionGroup="com.example.AnotherGroup" + android:protectionLevel="system" /> + + <permission-group + android:label="Nobody expects the Spanish Inquisition" + android:name="com.example.MasterControlPermission" /> + + <permission-tree + android:description="This is not the same label" + android:name="com.example.PermTree" /> + + <!-- GL 0.0 is a warning which is not prevented by tools:merge=remove. --> + <uses-feature + android:name="com.example.SomeFeature0" + android:glEsVersion="0x00000000" /> + <uses-feature + android:name="com.example.SomeFeature1" + android:required="true" /> + + <!-- supports-screens isn't really merged, just checked, so tools:merge=remove does nothing. --> + <!-- this is the not same supports-screens than in the main, will till make a warning. --> + <supports-screens + android:smallScreens="false" + android:resizeable="false" + /> + + <!-- supports-gl-texture isn't really merged, just checked, so tools:merge=remove does nothing. --> + <!-- this is the not same supports-gl-texture than in the main. --> + <supports-gl-texture android:name="some.gl.texture3" /> + + <application android:name="com.example.TheApp" > + <!-- Ignored uses-library --> + <uses-library + android:name="com.example.SomeLibrary4_RequiredFalse" + android:required="true" /> + + </application> + +</manifest> + + +@lib2 + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example"> + + <!-- The app targets API 14 but this library targets 42. --> + <uses-sdk android:targetSdkVersion="42" /> + +</manifest> + + +@result + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example" + android:versionCode="100" + android:versionName="1.0.0"> + + <!-- This is the same as writing android:minSdkVersion="1" --> + + <!-- Ignore permissions elements from lib that would conflict because + their definition is different. --> + + <!-- uses-feature is never merged, only checked, so tools:merge=remove does nothing. --> + <!-- Ignore uses-feature from library, which would change required to + true if it were merged. --> + + <!-- supports-screens is never merged, only checked, so tools:merge=remove does nothing. --> + + <!-- supports-gl-texture-screens-feature is never merged, only checked, so tools:merge=remove does nothing. --> + + <application android:name="com.example.TheApp" > + <!-- Ignore uses-library from library, which would change required to + true if it were merged. --> + + </application> + +</manifest> + +@errors + +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:19] /manifest/supports-screens defined in library, missing from main manifest: +<supports-screens> + @android:resizeable = false + @android:smallScreens = false +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:23] /manifest/supports-gl-texture defined in library, missing from main manifest: +<supports-gl-texture> + @android:name = some.gl.texture3 +W [ManifestMergerTest1_lib1.xml:14] Ignoring <uses-feature android:glEsVersion='0x00000000'> because it's smaller than 1.0. |