Imported unit tests for ManifestMerger from AOSP.

Summary:
Since ManifestMerger already has unit tests in AOSP for most of its functionality we'll
just import them. We'll extend these unit tests to test new functionality that
we add in a followup diff.

Test Plan: Run unit tests.
diff --git a/lib/BUCK b/lib/BUCK
index 62c3557..d960f9b 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -143,6 +143,7 @@
   visibility = [
     '//src/com/facebook/buck/junit:junit',
     '//test/...',
+    '//third-party/java/aosp/...',
   ],
 )
 
diff --git a/src/com/facebook/buck/android/BUCK b/src/com/facebook/buck/android/BUCK
index e8461d7..2338d5c 100644
--- a/src/com/facebook/buck/android/BUCK
+++ b/src/com/facebook/buck/android/BUCK
@@ -94,7 +94,7 @@
     '//src/com/facebook/buck/util:io',
     '//src/com/facebook/buck/util:util',
     '//src/com/facebook/buck/zip:steps',
-    '//third-party/java/aosp/src/com/android:aosp',
+    '//third-party/java/aosp:aosp',
   ],
   visibility = ['PUBLIC'],
 )
@@ -142,7 +142,7 @@
     '//src/com/facebook/buck/util/environment:environment',
     '//src/com/facebook/buck/zip:steps',
     '//src/com/facebook/buck/zip:stream',
-    '//third-party/java/aosp/src/com/android:aosp',
+    '//third-party/java/aosp:aosp',
   ],
   visibility = ['PUBLIC'],
 )
diff --git a/third-party/java/aosp/BUCK b/third-party/java/aosp/BUCK
new file mode 100644
index 0000000..38d63b2
--- /dev/null
+++ b/third-party/java/aosp/BUCK
@@ -0,0 +1,32 @@
+java_library(
+  name = 'aosp',
+  srcs = glob(['src/**/*.java']),
+  visibility = [
+    'PUBLIC',
+  ],
+)
+
+TEST_SRC = ['tests/src/**/*Test.java'];
+
+java_library(
+  name = 'testutils',
+  srcs = glob(['tests/src/**/*.java'], excludes = TEST_SRC),
+  deps = [
+    ':aosp',
+    '//lib:junit',
+  ],
+)
+
+java_test(
+  name = 'tests',
+  srcs = glob(TEST_SRC),
+  resources = glob(['tests/src/com/android/manifmerger/data/*']),
+  deps = [
+    ':aosp',
+    ':testutils',
+    '//lib:junit',
+  ],
+  source_under_test = [
+    ':aosp',
+  ],
+)
diff --git a/third-party/java/aosp/aosp.iml b/third-party/java/aosp/aosp.iml
index d5c0743..bc160c3 100644
--- a/third-party/java/aosp/aosp.iml
+++ b/third-party/java/aosp/aosp.iml
@@ -4,9 +4,19 @@
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/tests/src" isTestSource="true" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module-library" scope="TEST">
+      <library>
+        <CLASSES>
+          <root url="jar://$APPLICATION_HOME_DIR$/lib/junit.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
   </component>
 </module>
 
diff --git a/third-party/java/aosp/src/com/android/BUCK b/third-party/java/aosp/src/com/android/BUCK
deleted file mode 100644
index 6304e69..0000000
--- a/third-party/java/aosp/src/com/android/BUCK
+++ /dev/null
@@ -1,7 +0,0 @@
-java_library(
-  name = 'aosp',
-  srcs = glob(['**/*.java']),
-  visibility = [
-    'PUBLIC',
-  ],
-)
diff --git a/third-party/java/aosp/src/com/android/manifmerger/XmlUtils.java b/third-party/java/aosp/src/com/android/manifmerger/XmlUtils.java
index 0a3b08e..42fb074 100755
--- a/third-party/java/aosp/src/com/android/manifmerger/XmlUtils.java
+++ b/third-party/java/aosp/src/com/android/manifmerger/XmlUtils.java
@@ -487,7 +487,7 @@
             @Override
             public int compare(Attr a1, Attr a2) {
                 String s1 = a1 == null ? "" : a1.getNodeName();           //$NON-NLS-1$
-                String s2 = a2 == null ? "" : a2.getNodeValue();          //$NON-NLS-1$
+                String s2 = a2 == null ? "" : a2.getNodeName();           //$NON-NLS-1$
 
                 int prio1 = s1.equals("name") ? 0 : 1;                    //$NON-NLS-1$
                 int prio2 = s2.equals("name") ? 0 : 1;                    //$NON-NLS-1$
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/ManifestMergerTest.java b/third-party/java/aosp/tests/src/com/android/manifmerger/ManifestMergerTest.java
new file mode 100755
index 0000000..47f46c4
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/ManifestMergerTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.manifmerger;
+
+
+/**
+ * Unit tests for {@link ManifestMerger}.
+ */
+public class ManifestMergerTest extends ManifestMergerTestCase {
+
+    /*
+     * Wait, I hear you, where are the tests?
+     *
+     * processTestFiles() uses loadTestData(), which infers the data filename
+     * from the caller method name.
+     * E.g. the method "test00_noop" will use the data file named "data/00_noop.xml".
+     *
+     * We could simplify this even further by simply iterating on the data
+     * files and getting rid of the test methods; however there's some value in
+     * having tests break on a method name that easily points to the data file.
+     */
+
+  public void test00_noop() throws Exception {
+    processTestFiles();
+  }
+
+  public void test01_ignore_app_attr() throws Exception {
+    processTestFiles();
+  }
+
+  public void test02_ignore_instrumentation() throws Exception {
+    processTestFiles();
+  }
+
+  public void test10_activity_merge() throws Exception {
+    processTestFiles();
+  }
+
+  public void test11_activity_dup() throws Exception {
+    processTestFiles();
+  }
+
+  public void test12_alias_dup() throws Exception {
+    processTestFiles();
+  }
+
+  public void test13_service_dup() throws Exception {
+    processTestFiles();
+  }
+
+  public void test14_receiver_dup() throws Exception {
+    processTestFiles();
+  }
+
+  public void test15_provider_dup() throws Exception {
+    processTestFiles();
+  }
+
+  public void test16_fqcn_merge() throws Exception {
+    processTestFiles();
+  }
+
+  public void test17_fqcn_conflict() throws Exception {
+    processTestFiles();
+  }
+
+  public void test20_uses_lib_merge() throws Exception {
+    processTestFiles();
+  }
+
+  public void test21_uses_lib_errors() throws Exception {
+    processTestFiles();
+  }
+
+  public void test25_permission_merge() throws Exception {
+    processTestFiles();
+  }
+
+  public void test26_permission_dup() throws Exception {
+    processTestFiles();
+  }
+
+  public void test28_uses_perm_merge() throws Exception {
+    processTestFiles();
+  }
+
+  public void test30_uses_sdk_ok() throws Exception {
+    processTestFiles();
+  }
+
+  public void test32_uses_sdk_minsdk_ok() throws Exception {
+    processTestFiles();
+  }
+
+  public void test33_uses_sdk_minsdk_conflict() throws Exception {
+    processTestFiles();
+  }
+
+  public void test36_uses_sdk_targetsdk_warning() throws Exception {
+    processTestFiles();
+  }
+
+  public void test40_uses_feat_merge() throws Exception {
+    processTestFiles();
+  }
+
+  public void test41_uses_feat_errors() throws Exception {
+    processTestFiles();
+  }
+
+  public void test45_uses_feat_gles_once() throws Exception {
+    processTestFiles();
+  }
+
+  public void test47_uses_feat_gles_conflict() throws Exception {
+    processTestFiles();
+  }
+
+  public void test50_uses_conf_warning() throws Exception {
+    processTestFiles();
+  }
+
+  public void test52_support_screens_warning() throws Exception {
+    processTestFiles();
+  }
+
+  public void test54_compat_screens_warning() throws Exception {
+    processTestFiles();
+  }
+
+  public void test56_support_gltext_warning() throws Exception {
+    processTestFiles();
+  }
+}
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/ManifestMergerTestCase.java b/third-party/java/aosp/tests/src/com/android/manifmerger/ManifestMergerTestCase.java
new file mode 100755
index 0000000..e152c06
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/ManifestMergerTestCase.java
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.manifmerger;
+
+import com.android.common.annotations.NonNull;
+import com.android.manifmerger.IMergerLog.FileAndLine;
+
+import org.w3c.dom.Document;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * Some utilities to reduce repetitions in the {@link ManifestMergerTest}s.
+ * <p/>
+ * See {@link #loadTestData(String)} for an explanation of the data file format.
+ */
+abstract class ManifestMergerTestCase extends TestCase {
+
+  /**
+   * Delimiter that indicates the test must fail.
+   * An XML output and errors are still generated and checked.
+   */
+  private static final String DELIM_FAILS = "fails";
+  /**
+   * Delimiter that starts a library XML content.
+   * The delimiter name must be in the form {@code @libSomeName} and it will be
+   * used as the base for the test file name. Using separate lib names is encouraged
+   * since it makes the error output easier to read.
+   */
+  private static final String DELIM_LIB = "lib";
+  /**
+   * Delimiter that starts the main manifest XML content.
+   */
+  private static final String DELIM_MAIN = "main";
+  /**
+   * Delimiter that starts the resulting XML content, whatever is generated by the merge.
+   */
+  private static final String DELIM_RESULT = "result";
+  /**
+   * Delimiter that starts the SdkLog output.
+   * The logger prints each entry on its lines, prefixed with E for errors,
+   * W for warnings and P for regular printfs.
+   */
+  private static final String DELIM_ERRORS = "errors";
+
+  static class TestFiles {
+    private final File mMain;
+    private final File[] mLibs;
+    private final File mActualResult;
+    private final String mExpectedResult;
+    private final String mExpectedErrors;
+    private final boolean mShouldFail;
+
+    /**
+     * Files used by a given test case.
+     */
+    public TestFiles(
+        boolean shouldFail,
+        @NonNull File main,
+        @NonNull File[] libs,
+        @NonNull File actualResult,
+        @NonNull String expectedResult,
+        @NonNull String expectedErrors) {
+      mShouldFail = shouldFail;
+      mMain = main;
+      mLibs = libs;
+      mActualResult = actualResult;
+      mExpectedResult = expectedResult;
+      mExpectedErrors = expectedErrors;
+    }
+
+    public boolean getShouldFail() {
+      return mShouldFail;
+    }
+
+    @NonNull
+    public File getMain() {
+      return mMain;
+    }
+
+    @NonNull
+    public File[] getLibs() {
+      return mLibs;
+    }
+
+    @NonNull
+    public File getActualResult() {
+      return mActualResult;
+    }
+
+    @NonNull
+    public String getExpectedResult() {
+      return mExpectedResult;
+    }
+
+    public String getExpectedErrors() {
+      return mExpectedErrors;
+    }
+
+    // Try to delete any temp file potentially created.
+    public void cleanup() {
+      if (mMain != null && mMain.isFile()) {
+        mMain.delete();
+      }
+
+      if (mActualResult != null && mActualResult.isFile()) {
+        mActualResult.delete();
+      }
+
+      for (File f : mLibs) {
+        if (f != null && f.isFile()) {
+          f.delete();
+        }
+      }
+    }
+  }
+
+  /**
+   * Calls {@link #loadTestData(String)} by
+   * inferring the data filename from the caller's method name.
+   * <p/>
+   * The caller method name must be composed of "test" + the leaf filename.
+   * Extensions ".xml" or ".txt" are implied.
+   * <p/>
+   * E.g. to use the data file "12_foo.xml", simply call this from a method
+   * named "test12_foo".
+   *
+   * @return A new {@link TestFiles} instance. Never null.
+   * @throws Exception when things go wrong.
+   * @see #loadTestData(String)
+   */
+  @NonNull
+  TestFiles loadTestData() throws Exception {
+    StackTraceElement[] stack = Thread.currentThread().getStackTrace();
+    for (int i = 0, n = stack.length; i < n; i++) {
+      StackTraceElement caller = stack[i];
+      String name = caller.getMethodName();
+      if (name.startsWith("test")) {
+        return loadTestData(name.substring(4));
+      }
+    }
+
+    throw new IllegalArgumentException("No caller method found which name started with 'test'");
+  }
+
+  /**
+   * Loads test data for a given test case.
+   * The input (main + libs) are stored in temp files.
+   * A new destination temp file is created to store the actual result output.
+   * The expected result is actually kept in a string.
+   * <p/>
+   * Data File Syntax:
+   * <ul>
+   * <li> Lines starting with # are ignored (anywhere, as long as # is the first char).
+   * <li> Lines before the first {@code @delimiter} are ignored.
+   * <li> Empty lines just after the {@code @delimiter}
+   * and before the first &lt; XML line are ignored.
+   * <li> Valid delimiters are {@code @main} for the XML of the main app manifest.
+   * <li> Following delimiters are {@code @libXYZ}, read in the order of definition.
+   * The name can be anything as long as it starts with "{@code @lib}".
+   * </ul>
+   *
+   * @param filename The test data filename. If no extension is provided, this will
+   *                 try with .xml or .txt. Must not be null.
+   * @return A new {@link TestFiles} instance. Must not be null.
+   * @throws Exception when things fail to load properly.
+   */
+  @NonNull
+  TestFiles loadTestData(@NonNull String filename) throws Exception {
+
+    String resName = "data" + File.separator + filename;
+    InputStream is = null;
+    BufferedReader reader = null;
+    BufferedWriter writer = null;
+
+    try {
+      is = this.getClass().getResourceAsStream(resName);
+      if (is == null && !filename.endsWith(".xml")) {
+        String resName2 = resName + ".xml";
+        is = this.getClass().getResourceAsStream(resName2);
+        if (is != null) {
+          filename = resName2;
+        }
+      }
+      if (is == null && !filename.endsWith(".txt")) {
+        String resName3 = resName + ".txt";
+        is = this.getClass().getResourceAsStream(resName3);
+        if (is != null) {
+          filename = resName3;
+        }
+      }
+      assertNotNull("Test data file not found for " + filename, is);
+
+      reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+
+      // Get the temporary directory to use. Just create a temp file, extracts its
+      // directory and remove the file.
+      File tempFile = File.createTempFile(this.getClass().getSimpleName(), ".tmp");
+      File tempDir = tempFile.getParentFile();
+      if (!tempFile.delete()) {
+        tempFile.deleteOnExit();
+      }
+
+      String line = null;
+      String delimiter = null;
+      boolean skipEmpty = true;
+
+      boolean shouldFail = false;
+      StringBuilder expectedResult = new StringBuilder();
+      StringBuilder expectedErrors = new StringBuilder();
+      File mainFile = null;
+      File actualResultFile = null;
+      List<File> libFiles = new ArrayList<File>();
+      int tempIndex = 0;
+
+      while ((line = reader.readLine()) != null) {
+        if (skipEmpty && line.trim().length() == 0) {
+          continue;
+        }
+        if (line.length() > 0 && line.charAt(0) == '#') {
+          continue;
+        }
+        if (line.length() > 0 && line.charAt(0) == '@') {
+          delimiter = line.substring(1);
+          assertTrue(
+              "Unknown delimiter @" + delimiter + " in " + filename,
+              delimiter.startsWith(DELIM_LIB) ||
+                  delimiter.equals(DELIM_MAIN) ||
+                  delimiter.equals(DELIM_RESULT) ||
+                  delimiter.equals(DELIM_ERRORS) ||
+                  delimiter.equals(DELIM_FAILS));
+
+          skipEmpty = true;
+
+          if (writer != null) {
+            try {
+              writer.close();
+            } catch (IOException ignore) {
+            }
+            writer = null;
+          }
+
+          if (delimiter.equals(DELIM_FAILS)) {
+            shouldFail = true;
+
+          } else if (!delimiter.equals(DELIM_ERRORS)) {
+            tempFile = new File(tempDir, String.format("%1$s%2$d_%3$s.xml",
+                this.getClass().getSimpleName(),
+                tempIndex++,
+                delimiter.replaceAll("[^a-zA-Z0-9_-]", "")
+            ));
+            tempFile.deleteOnExit();
+
+            if (delimiter.startsWith(DELIM_LIB)) {
+              libFiles.add(tempFile);
+
+            } else if (delimiter.equals(DELIM_MAIN)) {
+              mainFile = tempFile;
+
+            } else if (delimiter.equals(DELIM_RESULT)) {
+              actualResultFile = tempFile;
+
+            } else {
+              fail("Unexpected data file delimiter @" + delimiter +
+                  " in " + filename);
+            }
+
+            if (!delimiter.equals(DELIM_RESULT)) {
+              writer = new BufferedWriter(new FileWriter(tempFile));
+            }
+          }
+
+          continue;
+        }
+        if (delimiter != null &&
+            skipEmpty &&
+            line.length() > 0 &&
+            line.charAt(0) != '#' &&
+            line.charAt(0) != '@') {
+          skipEmpty = false;
+        }
+        if (writer != null) {
+          writer.write(line);
+          writer.write('\n');
+        } else if (DELIM_RESULT.equals(delimiter)) {
+          expectedResult.append(line).append('\n');
+        } else if (DELIM_ERRORS.equals(delimiter)) {
+          expectedErrors.append(line).append('\n');
+        }
+      }
+
+      assertNotNull("Missing @" + DELIM_MAIN + " in " + filename, mainFile);
+      assertNotNull("Missing @" + DELIM_RESULT + " in " + filename, actualResultFile);
+
+      assert mainFile != null;
+      assert actualResultFile != null;
+
+      return new TestFiles(
+          shouldFail,
+          mainFile,
+          libFiles.toArray(new File[libFiles.size()]),
+          actualResultFile,
+          expectedResult.toString(),
+          expectedErrors.toString());
+
+    } catch (UnsupportedEncodingException e) {
+      // BufferedReader failed to decode UTF-8, O'RLY?
+      throw e;
+
+    } finally {
+      if (writer != null) {
+        try {
+          writer.close();
+        } catch (IOException ignore) {
+        }
+      }
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (IOException ignore) {
+        }
+      }
+      if (is != null) {
+        try {
+          is.close();
+        } catch (IOException ignore) {
+        }
+      }
+    }
+  }
+
+  /**
+   * Loads the data test files using {@link #loadTestData()} and then
+   * invokes {@link #processTestFiles(TestFiles)} to test them.
+   *
+   * @see #loadTestData()
+   * @see #processTestFiles(TestFiles)
+   */
+  void processTestFiles() throws Exception {
+    processTestFiles(loadTestData());
+  }
+
+  /**
+   * Processes the data from the given {@link TestFiles} by
+   * invoking {@link ManifestMerger#process(File, File, File[])}:
+   * the given library files are applied consecutively to the main XML
+   * document and the output is generated.
+   * <p/>
+   * Then the expected and actual outputs are loaded into a DOM,
+   * dumped again to a String using an XML transform and compared.
+   * This makes sure only the structure is checked and that any
+   * formatting is ignored in the comparison.
+   *
+   * @param testFiles The test files to process. Must not be null.
+   * @throws Exception when this go wrong.
+   */
+  void processTestFiles(TestFiles testFiles) throws Exception {
+    MockLog log = new MockLog();
+    IMergerLog mergerLog = MergerLog.wrapSdkLog(log);
+    ManifestMerger merger = new ManifestMerger(mergerLog, new ICallback() {
+      @Override
+      public int queryCodenameApiLevel(@NonNull String codename) {
+        if ("ApiCodename1".equals(codename)) {
+          return 1;
+        } else if ("ApiCodename10".equals(codename)) {
+          return 10;
+        }
+        return ICallback.UNKNOWN_CODENAME;
+      }
+    });
+    boolean processOK = merger.process(testFiles.getActualResult(),
+        testFiles.getMain(),
+        testFiles.getLibs());
+
+    String expectedErrors = testFiles.getExpectedErrors().trim();
+    StringBuilder actualErrors = new StringBuilder();
+    for (String s : log.getMessages()) {
+      actualErrors.append(s);
+      if (!s.endsWith("\n")) {
+        actualErrors.append('\n');
+      }
+    }
+    assertEquals("Error generated during merging",
+        expectedErrors, actualErrors.toString().trim());
+
+    if (testFiles.getShouldFail()) {
+      assertFalse("Merge process() returned true, expected false", processOK);
+    } else {
+      assertTrue("Merge process() returned false, expected true", processOK);
+    }
+
+    // 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);
+    assertNotNull(document);
+    assert document != null; // for Eclipse null analysis
+    String actual = XmlUtils.printXmlString(document, mergerLog);
+    assertEquals("Error parsing actual result XML", "[]", log.toString());
+    log.clear();
+    document = XmlUtils.parseDocument(
+        testFiles.getExpectedResult(),
+        mergerLog,
+        new FileAndLine("<expected-result>", 0));
+    assertNotNull(document);
+    assert document != null;
+    String expected = XmlUtils.printXmlString(document, mergerLog);
+    assertEquals("Error parsing expected result XML", "[]", log.toString());
+    assertEquals("Error comparing expected to actual result", expected, actual);
+
+    testFiles.cleanup();
+  }
+
+}
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/MockLog.java b/third-party/java/aosp/tests/src/com/android/manifmerger/MockLog.java
new file mode 100644
index 0000000..cfb5de6
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/MockLog.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.manifmerger;
+
+import com.android.common.annotations.NonNull;
+import com.android.common.utils.ILogger;
+
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.List;
+
+/**
+ * An instance of {@link ILogger} that captures all messages to an internal list.
+ * Messages can be retrieved later using {@link #toString()}.
+ * Useful for unit-tests.
+ */
+public class MockLog implements ILogger {
+  private ArrayList<String> mMessages = new ArrayList<String>();
+
+  private void add(String code, String format, Object... args) {
+    Formatter formatter = new Formatter();
+    mMessages.add(formatter.format(code + format, args).toString());
+    formatter.close();
+  }
+
+  @Override
+  public void warning(@NonNull String format, Object... args) {
+    add("W ", format, args);
+  }
+
+  @Override
+  public void info(@NonNull String format, Object... args) {
+    add("P ", format, args);
+  }
+
+  @Override
+  public void verbose(@NonNull String format, Object... args) {
+    add("V ", format, args);
+  }
+
+  @Override
+  public void error(Throwable t, String format, Object... args) {
+    if (t != null) {
+      add("T", "%s", t.toString());
+    }
+    add("E ", format, args);
+  }
+
+  @Override
+  public String toString() {
+    return mMessages.toString();
+  }
+
+  @NonNull
+  public List<String> getMessages() {
+    return mMessages;
+  }
+
+  public void clear() {
+    mMessages.clear();
+  }
+}
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/00_noop.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/00_noop.xml
new file mode 100755
index 0000000..2160f69
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/00_noop.xml
@@ -0,0 +1,229 @@
+#
+# Syntax:
+# - Lines starting with # are ignored (anywhere, as long as # is the first char).
+# - Lines before the first @delimiter are ignored.
+# - Empty lines just after the @delimiter and before the first < XML line are ignored.
+# - Valid delimiters are @main for the XML of the main app manifest.
+# - Following delimiters are @libXYZ, read in the order of definition. The name can be
+#   anything as long as it starts with "@lib".
+# - Last delimiter should be @result.
+#
+
+@main
+
+<!--
+  This is a canonical manifest that has some uses-permissions,
+  the usual uses-sdk and supports-screens, an app with an activity,
+  customer receiver & service and a widget.
+-->
+
+<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"
+        />
+
+    <!-- Typical analytics permissions. -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. -->
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+        <!-- Receiver -->
+        <receiver
+            android:name="com.example.AppReceiver"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Broadcast Receiver for a widget. -->
+        <receiver
+            android:label="@string/widget_name"
+            android:icon="@drawable/widget_icon"
+            android:name="com.example.WidgetReceiver" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/widget_provider"
+                />
+        </receiver>
+
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService" />
+
+        <!-- Activity to configure widget -->
+        <activity
+            android:icon="@drawable/widget_icon"
+            android:label="Configure Widget"
+            android:name="com.example.WidgetConfigurationUI"
+            android:theme="@style/Theme.WidgetConfigurationUI" >
+            <intent-filter >
+                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
+            </intent-filter>
+        </activity>
+
+        <!-- Provider extracted from ApiDemos -->
+        <provider android:name=".app.LoaderThrottle$SimpleProvider"
+            android:authorities="com.example.android.apis.app.LoaderThrottle"
+            android:enabled="@bool/atLeastHoneycomb" />
+
+    </application>
+
+</manifest>
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+</manifest>
+
+
+@lib2
+
+# An empty library is not supported. It must be a valid XML file.
+<manifest/>
+
+@result
+
+<!--
+  This is a canonical manifest that has some uses-permissions,
+  the usual uses-sdk and supports-screens, an app with an activity,
+  customer receiver & service and a widget.
+-->
+
+<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"
+        />
+
+    <!-- Typical analytics permissions. -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. -->
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+        <!-- Receiver -->
+        <receiver
+            android:name="com.example.AppReceiver"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Broadcast Receiver for a widget. -->
+        <receiver
+            android:label="@string/widget_name"
+            android:icon="@drawable/widget_icon"
+            android:name="com.example.WidgetReceiver" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/widget_provider"
+                />
+        </receiver>
+
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService" />
+
+        <!-- Activity to configure widget -->
+        <activity
+            android:icon="@drawable/widget_icon"
+            android:label="Configure Widget"
+            android:name="com.example.WidgetConfigurationUI"
+            android:theme="@style/Theme.WidgetConfigurationUI" >
+            <intent-filter >
+                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
+            </intent-filter>
+        </activity>
+
+        <!-- Provider extracted from ApiDemos -->
+        <provider
+            android:name="com.example.app1.app.LoaderThrottle$SimpleProvider"
+            android:authorities="com.example.android.apis.app.LoaderThrottle"
+            android:enabled="@bool/atLeastHoneycomb" />
+
+    </application>
+
+</manifest>
+
+
+@errors
+
+W [ManifestMergerTest2_lib2.xml:1] Missing 'package' attribute in manifest.
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/01_ignore_app_attr.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/01_ignore_app_attr.xml
new file mode 100755
index 0000000..b939dd7
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/01_ignore_app_attr.xml
@@ -0,0 +1,69 @@
+#
+# Test:
+# - Attributes from the application element in a library are ignored (except name)
+# - Comments from nodes ignored in libraries are not merged either.
+#
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <!-- Source comments are preserved as-is. -->
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+    </application>
+
+</manifest>
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <!-- The attributes from <application> in a library are not merged nor checked
+         except for 'name' and 'backupAgent' which must match.
+         This comment is ignored. -->
+    <application
+        android:label="@string/lib_name"
+        android:icon="@drawable/lib_icon"
+        android:name="com.example.TheApp" >
+    </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">
+
+    <!-- Source comments are preserved as-is. -->
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+    </application>
+
+</manifest>
+
+@errors
+
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/02_ignore_instrumentation.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/02_ignore_instrumentation.xml
new file mode 100755
index 0000000..ed0dbbc
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/02_ignore_instrumentation.xml
@@ -0,0 +1,62 @@
+#
+# Test:
+# - Instrumentation element from libraries are not merged in main manifest.
+#
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+    </application>
+
+</manifest>
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <!-- Instrumentation is not merged from libraries. -->
+    <instrumentation
+        android:targetPackage="com.example.app1"
+        android:name="android.test.InstrumentationTestRunner" />
+
+</manifest>
+
+@result
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+    </application>
+
+</manifest>
+
+@errors
+
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/10_activity_merge.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/10_activity_merge.xml
new file mode 100755
index 0000000..59c5c42
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/10_activity_merge.xml
@@ -0,0 +1,378 @@
+#
+# Test:
+# - Activities from libraries are merged in the main manifest.
+# - Acts on activity / activity-alias / service / receiver / provider.
+# - Elements are merged as-is with the first comment element preceding them.
+# - Whitespace preceding the merged elements is transfered over too.
+#
+# Note:
+# - New elements are always merged at the end of the application element.
+# - It's an error if an element with the same @name attribute is defined
+#   or merged more than once unless the definition is *exactly* the same,
+#   the "same" being defined by the exact XML elements, whitespace excluded.
+#
+# This tests that a normal merge is done as expected.
+# There's a warning because one of the activities from lib2 is already defined
+# in the main but it's purely identical so it's not an error.
+#
+
+@main
+
+<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"
+        />
+
+    <!-- Typical analytics permissions. -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. -->
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+        <!-- Receiver -->
+        <receiver
+            android:name="com.example.AppReceiver"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+        <!-- This is exactly the same as in lib2_activity -->
+        <activity
+            android:name="com.example.LibActivity"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon"
+            android:theme="@style/Lib.Theme">
+
+            <!-- When comparing duplicate elements, whitespace and comments are ignored. -->
+
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+
+        </activity>
+
+        <!-- end of the main manifest's application element. Note that the
+             merger will insert at the end of this comment, in the specific
+             order activity, activity-alias, service, receiver and provider. -->
+
+    </application>
+
+</manifest>
+
+
+@lib1_widget
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <application android:label="@string/lib_name" >
+
+        <!-- Broadcast Receiver for a widget. -->
+        <receiver
+            android:label="@string/widget_name"
+            android:icon="@drawable/widget_icon"
+            android:name="com.example.WidgetReceiver" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/widget_provider"
+                />
+        </receiver>
+
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService" />
+
+        <!-- Activity to configure widget -->
+        <activity
+            android:icon="@drawable/widget_icon"
+            android:label="Configure Widget"
+            android:name="com.example.WidgetConfigurationUI"
+            android:theme="@style/Theme.WidgetConfigurationUI" >
+            <intent-filter >
+                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
+
+
+@lib2_activity
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <application android:label="@string/lib_name" >
+
+        <!-- This won't be merged because there's already an identical definition in the main. -->
+        <activity
+            android:name="com.example.LibActivity"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon"
+            android:theme="@style/Lib.Theme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <!-- Provider extracted from ApiDemos -->
+        <provider android:name=".app.LoaderThrottle$SimpleProvider"
+            android:authorities="com.example.android.apis.app.LoaderThrottle"
+            android:enabled="@bool/atLeastHoneycomb" />
+
+        <!-- This one does not conflict with the main -->
+        <activity
+            android:name="com.example.LibActivity2"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon"
+            android:theme="@style/Lib.Theme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+
+</manifest>
+
+
+@lib3_alias
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib3">
+
+    <!-- This comment is ignored. -->
+
+    <application android:label="@string/lib_name" >
+
+        <!-- The first comment just before the element
+             is carried over as-is.
+        -->
+        <!-- Formatting is preserved. -->
+        <!-- All consecutive comments are taken together. -->
+
+        <activity-alias
+            android:name="com.example.alias.MyActivity"
+            android:targetActivity="com.example.MainActivity"
+            android:label="@string/alias_name"
+            android:icon="@drawable/alias_icon"
+            >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity-alias>
+
+        <!-- This is a dup of the 2nd activity in lib2 -->
+        <activity
+            android:name="com.example.LibActivity2"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon"
+            android:theme="@style/Lib.Theme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </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"
+        />
+
+    <!-- Typical analytics permissions. -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. -->
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+        <!-- Receiver -->
+        <receiver
+            android:name="com.example.AppReceiver"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+        <!-- This is exactly the same as in lib2_activity -->
+        <activity
+            android:name="com.example.LibActivity"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon"
+            android:theme="@style/Lib.Theme">
+
+            <!-- When comparing duplicate elements, whitespace and comments are ignored. -->
+
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+
+        </activity>
+
+        <!-- end of the main manifest's application element. Note that the
+             merger will insert at the end of this comment, in the specific
+             order activity, activity-alias, service, receiver and provider. -->
+
+# from @lib1_widget
+        <!-- Activity to configure widget -->
+        <activity
+            android:icon="@drawable/widget_icon"
+            android:label="Configure Widget"
+            android:name="com.example.WidgetConfigurationUI"
+            android:theme="@style/Theme.WidgetConfigurationUI" >
+            <intent-filter >
+                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
+            </intent-filter>
+        </activity>
+
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService" />
+
+        <!-- Broadcast Receiver for a widget. -->
+        <receiver
+            android:label="@string/widget_name"
+            android:icon="@drawable/widget_icon"
+            android:name="com.example.WidgetReceiver" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/widget_provider"
+                />
+        </receiver>
+
+# from @lib2_activity
+        <!-- This one does not conflict with the main -->
+        <activity
+            android:name="com.example.LibActivity2"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon"
+            android:theme="@style/Lib.Theme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <!-- Provider extracted from ApiDemos -->
+        <provider android:name="com.example.lib2.app.LoaderThrottle$SimpleProvider"
+            android:authorities="com.example.android.apis.app.LoaderThrottle"
+            android:enabled="@bool/atLeastHoneycomb" />
+
+# from @lib3_alias
+        <!-- The first comment just before the element
+             is carried over as-is.
+        -->
+        <!-- Formatting is preserved. -->
+        <!-- All consecutive comments are taken together. -->
+
+        <activity-alias
+            android:name="com.example.alias.MyActivity"
+            android:targetActivity="com.example.MainActivity"
+            android:label="@string/alias_name"
+            android:icon="@drawable/alias_icon"
+            >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity-alias>
+
+    </application>
+
+</manifest>
+
+@errors
+
+P [ManifestMergerTest0_main.xml:31, ManifestMergerTest2_lib2_activity.xml:6] Skipping identical /manifest/application/activity[@name=com.example.LibActivity] element.
+P [ManifestMergerTest0_main.xml, ManifestMergerTest3_lib3_alias.xml:19] Skipping identical /manifest/application/activity[@name=com.example.LibActivity2] element.
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/11_activity_dup.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/11_activity_dup.xml
new file mode 100755
index 0000000..5ba6688
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/11_activity_dup.xml
@@ -0,0 +1,387 @@
+#
+# Test:
+# - Activities from libraries are merged in the main manifest.
+# - Acts on activity / activity-alias / service / receiver / provider.
+# - Elements are merged as-is with the first comment element preceding them.
+# - Whitespace preceding the merged elements is transfered over too.
+#
+# Note:
+# - New elements are always merged at the end of the application element.
+# - It's an error if an element with the same @name attribute is defined
+#   or merged more than once unless the definition is *exactly* the same,
+#   the "same" being defined by the exact XML elements, whitespace excluded.
+#
+# This tests that an error is generated because the libraries define
+# activities which are already in the main, with slightly different XML content:
+# number and *order* of elements must match, attributes must match.
+#
+
+@fails
+
+@main
+
+<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"
+        />
+
+    <!-- Typical analytics permissions. -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. -->
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+        <!-- Receiver -->
+        <receiver
+            android:name="com.example.AppReceiver"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+
+        <!-- Conflict with lib1 -->
+        <activity
+            android:icon="@drawable/widget_icon"
+            android:label="Configure Widget"
+            android:name="com.example.WidgetConfigurationUI"
+            android:theme="@style/Theme.WidgetConfigurationUI" >
+            <!-- missing the intent-filter -->
+        </activity>
+
+
+        <!-- Conflict with lib2 -->
+        <activity
+            android:name="com.example.LibActivity"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon">
+            <!-- missing attribute android:theme="@style/Lib.Theme" -->
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+
+</manifest>
+
+
+@lib1_widget
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <application android:label="@string/lib_name" >
+
+        <!-- Broadcast Receiver for a widget. -->
+        <receiver
+            android:label="@string/widget_name"
+            android:icon="@drawable/widget_icon"
+            android:name="com.example.WidgetReceiver" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/widget_provider"
+                />
+        </receiver>
+
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService" />
+
+        <!-- Activity to configure widget -->
+        <activity
+            android:icon="@drawable/widget_icon"
+            android:label="Configure Widget"
+            android:name="com.example.WidgetConfigurationUI"
+            android:theme="@style/Theme.WidgetConfigurationUI" >
+            <intent-filter >
+                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
+
+
+@lib2_activity
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <application android:label="@string/lib_name" >
+
+        <!-- This won't be merged because there's already an identical definition in the main. -->
+        <activity
+            android:name="com.example.LibActivity"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon"
+            android:theme="@style/Lib.Theme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <!-- Provider extracted from ApiDemos -->
+        <provider android:name=".app.LoaderThrottle$SimpleProvider"
+            android:authorities="com.example.android.apis.app.LoaderThrottle"
+            android:enabled="@bool/atLeastHoneycomb" />
+
+        <!-- This one does not conflict with the main -->
+        <activity
+            android:name="com.example.LibActivity2"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon"
+            android:theme="@style/Lib.Theme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+
+</manifest>
+
+
+@lib3_alias
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib3">
+
+    <!-- This comment is ignored. -->
+
+    <application android:label="@string/lib_name" >
+
+        <!-- The first comment just before the element
+             is carried over as-is.
+        -->
+        <!-- Formatting is preserved. -->
+        <!-- All consecutive comments are taken together. -->
+
+        <activity-alias
+            android:name="com.example.alias.MyActivity"
+            android:targetActivity="com.example.MainActivity"
+            android:label="@string/alias_name"
+            android:icon="@drawable/alias_icon"
+            >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity-alias>
+
+        <!-- This will conflict with the 2nd one from lib2 -->
+        <activity
+            android:name="com.example.LibActivity2"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon"
+            android:theme="@style/Lib.Theme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.MOARCATZPLZ" />
+            </intent-filter>
+        </activity>
+
+    </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"
+        />
+
+    <!-- Typical analytics permissions. -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <!-- Touchscreen feature, optional to make sure we can run on devices with no touch screen. -->
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+        <!-- Receiver -->
+        <receiver
+            android:name="com.example.AppReceiver"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+
+        <!-- Conflict with lib1 -->
+        <activity
+            android:icon="@drawable/widget_icon"
+            android:label="Configure Widget"
+            android:name="com.example.WidgetConfigurationUI"
+            android:theme="@style/Theme.WidgetConfigurationUI" >
+            <!-- missing the intent-filter -->
+        </activity>
+
+
+        <!-- Conflict with lib2 -->
+        <activity
+            android:name="com.example.LibActivity"
+            android:label="@string/lib_activity_name"
+            android:icon="@drawable/lib_activity_icon">
+            <!-- missing attribute android:theme="@style/Lib.Theme" -->
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+# from @lib1_widget
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService" />
+
+        <!-- Broadcast Receiver for a widget. -->
+        <receiver
+            android:label="@string/widget_name"
+            android:icon="@drawable/widget_icon"
+            android:name="com.example.WidgetReceiver" >
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/widget_provider"
+                />
+        </receiver>
+
+# from @lib2_activity
+        <!-- This one does not conflict with the main -->
+        <activity android:icon="@drawable/lib_activity_icon" android:label="@string/lib_activity_name" android:name="com.example.LibActivity2" android:theme="@style/Lib.Theme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+
+        <!-- Provider extracted from ApiDemos -->
+        <provider android:name="com.example.lib2.app.LoaderThrottle$SimpleProvider"
+            android:authorities="com.example.android.apis.app.LoaderThrottle"
+            android:enabled="@bool/atLeastHoneycomb" />
+
+# from @lib3_alias
+        <!-- The first comment just before the element
+             is carried over as-is.
+        -->
+        <!-- Formatting is preserved. -->
+        <!-- All consecutive comments are taken together. -->
+
+        <activity-alias
+            android:name="com.example.alias.MyActivity"
+            android:targetActivity="com.example.MainActivity"
+            android:label="@string/alias_name"
+            android:icon="@drawable/alias_icon"
+            >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity-alias>
+
+    </application>
+
+</manifest>
+
+@errors
+
+E [ManifestMergerTest0_main.xml:32, ManifestMergerTest1_lib1_widget.xml:16] Trying to merge incompatible /manifest/application/activity[@name=com.example.WidgetConfigurationUI] element:
+  <activity android:name=com.example.WidgetConfigurationUI>
+--  <intent-filter>
+++  (end reached)
+E [ManifestMergerTest0_main.xml:38, ManifestMergerTest2_lib2_activity.xml:6] Trying to merge incompatible /manifest/application/activity[@name=com.example.LibActivity] element:
+  <activity android:name=com.example.LibActivity>
+      @android:icon = @drawable/lib_activity_icon
+      @android:label = @string/lib_activity_name
+      @android:name = com.example.LibActivity
+--    @android:theme = @style/Lib.Theme
+E [ManifestMergerTest0_main.xml, ManifestMergerTest3_lib3_alias.xml:19] Trying to merge incompatible /manifest/application/activity[@name=com.example.LibActivity2] element:
+  <activity android:name=com.example.LibActivity2>
+    <intent-filter>
+      <action android:name=android.intent.action.MAIN>
+      <category android:name=android.intent.category.LAUNCHER>
+--    <category android:name=android.intent.category.MOARCATZPLZ>
+++    (end reached)
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/12_alias_dup.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/12_alias_dup.xml
new file mode 100755
index 0000000..696965f
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/12_alias_dup.xml
@@ -0,0 +1,205 @@
+#
+# Test:
+# - Activities from libraries are merged in the main manifest.
+# - Acts on activity / activity-alias / service / receiver / provider.
+# - Elements are merged as-is with the first comment element preceding them.
+# - Whitespace preceding the merged elements is transfered over too.
+#
+# Note:
+# - New elements are always merged at the end of the application element.
+# - It's an error if an element with the same @name attribute is defined
+#   or merged more than once unless the definition is *exactly* the same,
+#   the "same" being defined by the exact XML elements, whitespace excluded.
+#
+# This tests that an error is generated because the libraries define
+# aliases which are already defined differently.
+#
+
+@fails
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <activity-alias
+            android:name="com.example.alias.MyActivity1"
+            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>
+
+        <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>
+
+    </application>
+
+</manifest>
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <application android:label="@string/lib_name1" >
+
+        <!-- Same as 1 in main -->
+        <activity-alias
+            android:name="com.example.alias.MyActivity1"
+            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>
+
+        <!-- Differs from 2 in main -->
+        <activity-alias
+            android:name="com.example.alias.MyActivity2"
+            android:targetActivity="com.example.MainActivity2">
+        </activity-alias>
+
+        <!-- A new one defined by lib1 -->
+        <activity-alias
+            android:name="com.example.alias.MyActivity3"
+            android:targetActivity="com.example.MainActivity3"
+            android:label="@string/alias_name3"
+            android:icon="@drawable/alias_icon3"
+            >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity-alias>
+
+    </application>
+
+</manifest>
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <application android:label="@string/lib_name2" >
+
+        <!-- Conflicts with 3 from lib1 -->
+        <activity-alias
+            android:name="com.example.alias.MyActivity3"
+            android:label="@string/alias_name3"
+            android:icon="@drawable/alias_icon3">
+            <intent-filter>
+                <category android:name="android.intent.category.LAUNCHER2" />
+            </intent-filter>
+        </activity-alias>
+    </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">
+
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <activity-alias
+            android:name="com.example.alias.MyActivity1"
+            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>
+
+        <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>
+
+        <!-- A new one defined by lib1 -->
+        <activity-alias
+            android:name="com.example.alias.MyActivity3"
+            android:targetActivity="com.example.MainActivity3"
+            android:label="@string/alias_name3"
+            android:icon="@drawable/alias_icon3"
+            >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity-alias>
+
+    </application>
+
+</manifest>
+
+@errors
+
+P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/activity-alias[@name=com.example.alias.MyActivity1] element.
+E [ManifestMergerTest0_main.xml:13, ManifestMergerTest1_lib1.xml:14] Trying to merge incompatible /manifest/application/activity-alias[@name=com.example.alias.MyActivity2] element:
+  <activity-alias android:name=com.example.alias.MyActivity2>
+++    @android:icon = @drawable/alias_icon2
+++    @android:label = @string/alias_name2
+      @android:name = com.example.alias.MyActivity2
+      @android:targetActivity = com.example.MainActivity2
+E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/activity-alias[@name=com.example.alias.MyActivity3] element:
+  <activity-alias android:name=com.example.alias.MyActivity3>
+      @android:icon = @drawable/alias_icon3
+      @android:label = @string/alias_name3
+      @android:name = com.example.alias.MyActivity3
+++    @android:targetActivity = com.example.MainActivity3
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/13_service_dup.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/13_service_dup.xml
new file mode 100755
index 0000000..36d7e24
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/13_service_dup.xml
@@ -0,0 +1,155 @@
+#
+# Test:
+# - Activities from libraries are merged in the main manifest.
+# - Acts on activity / activity-alias / service / receiver / provider.
+# - Elements are merged as-is with the first comment element preceding them.
+# - Whitespace preceding the merged elements is transfered over too.
+#
+# Note:
+# - New elements are always merged at the end of the application element.
+# - It's an error if an element with the same @name attribute is defined
+#   or merged more than once unless the definition is *exactly* the same,
+#   the "same" being defined by the exact XML elements, whitespace excluded.
+#
+# This tests that an error is generated because the libraries define
+# services which are already defined differently.
+#
+
+@fails
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService1" />
+
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService2" />
+
+    </application>
+
+</manifest>
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <application android:label="@string/lib_name1" >
+
+        <!-- Same as 1 in main -->
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService1" />
+
+        <!-- Differs from 2 in main -->
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService2" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </service>
+
+        <!-- A new one defined by lib1 -->
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService3" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </service>
+
+    </application>
+
+</manifest>
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <application android:label="@string/lib_name2" >
+
+        <!-- Conflicts with 3 from lib1 -->
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService3" />
+
+    </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">
+
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService1" />
+
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService2" />
+
+        <!-- A new one defined by lib1 -->
+        <service
+            android:icon="@drawable/app_icon"
+            android:name="com.example.AppService3" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </service>
+
+    </application>
+
+</manifest>
+
+@errors
+
+P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/service[@name=com.example.AppService1] element.
+E [ManifestMergerTest0_main.xml:8, ManifestMergerTest1_lib1.xml:9] Trying to merge incompatible /manifest/application/service[@name=com.example.AppService2] element:
+  <service android:name=com.example.AppService2>
+--  <intent-filter>
+++  (end reached)
+E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/service[@name=com.example.AppService3] element:
+  <service android:name=com.example.AppService3>
+--  (end reached)
+++  <intent-filter>
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/14_receiver_dup.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/14_receiver_dup.xml
new file mode 100755
index 0000000..a2547af
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/14_receiver_dup.xml
@@ -0,0 +1,176 @@
+#
+# Test:
+# - Activities from libraries are merged in the main manifest.
+# - Acts on activity / activity-alias / service / receiver / provider.
+# - Elements are merged as-is with the first comment element preceding them.
+# - Whitespace preceding the merged elements is transfered over too.
+#
+# Note:
+# - New elements are always merged at the end of the application element.
+# - It's an error if an element with the same @name attribute is defined
+#   or merged more than once unless the definition is *exactly* the same,
+#   the "same" being defined by the exact XML elements, whitespace excluded.
+#
+# This tests that an error is generated because the libraries define
+# receivers which are already defined differently.
+#
+
+@fails
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <receiver
+            android:name="com.example.AppReceiver1"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+        <receiver
+            android:name="com.example.AppReceiver2"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+    </application>
+
+</manifest>
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <application android:label="@string/lib_name1" >
+
+        <!-- Same as 1 in main -->
+        <receiver
+            android:name="com.example.AppReceiver1"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Differs from 2 in main -->
+        <receiver
+            android:name="com.example.AppReceiver2" />
+
+        <!-- A new one defined by lib1 -->
+        <receiver
+            android:name="com.example.AppReceiver3"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM1" />
+                <action android:name="com.example.action.ACTION_CUSTOM2" />
+                <action android:name="com.example.action.ACTION_CUSTOM3" />
+            </intent-filter>
+        </receiver>
+
+    </application>
+
+</manifest>
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <application android:label="@string/lib_name2" >
+
+        <!-- Conflicts with 3 from lib1 -->
+        <receiver
+            android:name="com.example.AppReceiver3"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+    </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">
+
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <receiver
+            android:name="com.example.AppReceiver1"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+        <receiver
+            android:name="com.example.AppReceiver2"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM" />
+            </intent-filter>
+        </receiver>
+
+        <!-- A new one defined by lib1 -->
+        <receiver
+            android:name="com.example.AppReceiver3"
+            android:icon="@drawable/app_icon">
+            <intent-filter>
+                <action android:name="com.example.action.ACTION_CUSTOM1" />
+                <action android:name="com.example.action.ACTION_CUSTOM2" />
+                <action android:name="com.example.action.ACTION_CUSTOM3" />
+            </intent-filter>
+        </receiver>
+
+    </application>
+
+</manifest>
+
+@errors
+
+P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/receiver[@name=com.example.AppReceiver1] element.
+E [ManifestMergerTest0_main.xml:12, ManifestMergerTest1_lib1.xml:13] Trying to merge incompatible /manifest/application/receiver[@name=com.example.AppReceiver2] element:
+  <receiver android:name=com.example.AppReceiver2>
+++    @android:icon = @drawable/app_icon
+      @android:name = com.example.AppReceiver2
+E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/receiver[@name=com.example.AppReceiver3] element:
+  <receiver android:name=com.example.AppReceiver3>
+    <intent-filter>
+      <action android:name=com.example.action.ACTION_CUSTOM>
+--        @android:name = com.example.action.ACTION_CUSTOM
+++        @android:name = com.example.action.ACTION_CUSTOM1
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/15_provider_dup.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/15_provider_dup.xml
new file mode 100755
index 0000000..7938c1e
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/15_provider_dup.xml
@@ -0,0 +1,145 @@
+#
+# Test:
+# - Activities from libraries are merged in the main manifest.
+# - Acts on activity / activity-alias / service / receiver / provider.
+# - Elements are merged as-is with the first comment element preceding them.
+# - Whitespace preceding the merged elements is transfered over too.
+#
+# Note:
+# - New elements are always merged at the end of the application element.
+# - It's an error if an element with the same @name attribute is defined
+#   or merged more than once unless the definition is *exactly* the same,
+#   the "same" being defined by the exact XML elements, whitespace excluded.
+#
+# This tests that an error is generated because the libraries define
+# providers which are already defined differently.
+#
+
+@fails
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <provider
+            android:name="com.example.Provider1"
+            android:authorities="com.example.android.apis.app.thingy1"
+            android:enabled="@bool/someConditionalValue" />
+
+        <provider
+            android:name="com.example.Provider2" />
+
+    </application>
+
+</manifest>
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <application android:label="@string/lib_name1" >
+
+        <!-- Same as MyActivity1 in main -->
+        <provider
+            android:name="com.example.Provider1"
+            android:authorities="com.example.android.apis.app.thingy1"
+            android:enabled="@bool/someConditionalValue" />
+
+        <!-- Differs from MyActivity2 in main -->
+        <provider
+            android:name="com.example.Provider2"
+            android:authorities="com.example.android.apis.app.thingy2"
+            android:enabled="@bool/someConditionalValue2" />
+
+        <!-- A new one defined by lib1 -->
+        <provider
+            android:name="com.example.Provider3"
+            android:authorities="com.example.android.apis.app.thingy3"
+            android:enabled="@bool/someConditionalValue" />
+
+    </application>
+
+</manifest>
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <application android:label="@string/lib_name2" >
+
+        <!-- Conflicts with 3 from lib1 -->
+        <provider
+            android:name="com.example.Provider3"
+            android:authorities="com.example.android.apis.app.thingy3" />
+    </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">
+
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <provider
+            android:name="com.example.Provider1"
+            android:authorities="com.example.android.apis.app.thingy1"
+            android:enabled="@bool/someConditionalValue" />
+
+        <provider
+            android:name="com.example.Provider2" />
+
+        <!-- A new one defined by lib1 -->
+        <provider
+            android:name="com.example.Provider3"
+            android:authorities="com.example.android.apis.app.thingy3"
+            android:enabled="@bool/someConditionalValue" />
+
+    </application>
+
+</manifest>
+
+@errors
+
+P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/provider[@name=com.example.Provider1] element.
+E [ManifestMergerTest0_main.xml:8, ManifestMergerTest1_lib1.xml:9] Trying to merge incompatible /manifest/application/provider[@name=com.example.Provider2] element:
+  <provider android:name=com.example.Provider2>
+--    @android:authorities = com.example.android.apis.app.thingy2
+--    @android:enabled = @bool/someConditionalValue2
+      @android:name = com.example.Provider2
+E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/provider[@name=com.example.Provider3] element:
+  <provider android:name=com.example.Provider3>
+      @android:authorities = com.example.android.apis.app.thingy3
+++    @android:enabled = @bool/someConditionalValue
+      @android:name = com.example.Provider3
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/16_fqcn_merge.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/16_fqcn_merge.xml
new file mode 100755
index 0000000..8414a3c
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/16_fqcn_merge.xml
@@ -0,0 +1,129 @@
+#
+# Test how FQCN class names are expanded and handled:
+# - A library application can be merged doesn't have an app class name.
+# - A library application can be merged if it has the same class name as the app.
+# - A partial class name is expanded using the package name in a library or app.
+#
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <application
+            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">
+
+    <application android:name="com.example.app1.TheApp" >
+        <activity android:name=".WidgetLibrary" />
+        <receiver android:name=".WidgetReceiver" />
+        <service  android:name="AppService" />
+        <activity android:name="com.example.lib1.WidgetConfigurationUI" />
+    </application>
+</manifest>
+
+
+@lib2_activity
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <application>
+        <!-- This won't be merged because there's already an identical definition in the main. -->
+        <activity android:name="LibActivity" />
+
+        <!-- Provider extracted from ApiDemos -->
+        <provider android:name=".app.LoaderThrottle$SimpleProvider" />
+
+        <!-- This one does not conflict with the main -->
+        <activity android:name="com.example.lib2.LibActivity2" />
+
+    </application>
+</manifest>
+
+
+@lib3_alias
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib3" >
+    <!-- This manifest has a 'package' attribute and FQCNs get resolved. -->
+
+    <application
+            android:name="com.example.app1.TheApp"
+            android:backupAgent="com.example.app1.MyBackupAgent">
+        <activity-alias android:name="com.example.lib3.MyActivity"
+            android:targetActivity="com.example.app1.MainActivity" />
+
+        <!-- This is a dup of the 2nd activity in lib2 -->
+        <activity android:name="com.example.lib2.LibActivity2" />
+
+        <!-- These class name should be expanded. -->
+        <activity android:name=".LibActivity3" />
+        <service  android:name=".LibService3" />
+        <receiver android:name=".LibReceiver3" />
+        <provider android:name=".LibProvider3" />
+
+    </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">
+
+    <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" />
+# from @lib1_widget
+        <activity android:name="com.example.lib1.WidgetLibrary" />
+        <activity android:name="com.example.lib1.WidgetConfigurationUI" />
+        <service  android:name="com.example.lib1.AppService" />
+        <receiver android:name="com.example.lib1.WidgetReceiver" />
+
+# from @lib2_activity
+        <!-- This one does not conflict with the main -->
+        <activity android:name="com.example.lib2.LibActivity2" />
+
+        <!-- Provider extracted from ApiDemos -->
+        <provider android:name="com.example.lib2.app.LoaderThrottle$SimpleProvider" />
+
+# from @lib3_alias
+        <!-- These class name should be expanded. -->
+        <activity android:name="com.example.lib3.LibActivity3" />
+        <activity-alias android:name="com.example.lib3.MyActivity"
+            android:targetActivity="com.example.app1.MainActivity" />
+        <service  android:name="com.example.lib3.LibService3" />
+        <receiver android:name="com.example.lib3.LibReceiver3" />
+        <provider android:name="com.example.lib3.LibProvider3" />
+    </application>
+</manifest>
+
+@errors
+
+P [ManifestMergerTest0_main.xml:6, ManifestMergerTest2_lib2_activity.xml:5] Skipping identical /manifest/application/activity[@name=com.example.lib2.LibActivity] element.
+P [ManifestMergerTest0_main.xml, ManifestMergerTest3_lib3_alias.xml:8] Skipping identical /manifest/application/activity[@name=com.example.lib2.LibActivity2] element.
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/17_fqcn_conflict.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/17_fqcn_conflict.xml
new file mode 100755
index 0000000..7b95027
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/17_fqcn_conflict.xml
@@ -0,0 +1,118 @@
+#
+# Test how FQCN class names are expanded and handled:
+# - A library application can be merged doesn't have an app class name.
+# - A library application can be merged if it has the same class name as the app.
+# - A partial class name is expanded using the package name in a library or app.
+#
+# All tests fail with just warnings, no solid errors.
+#
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <application
+            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">
+
+    <!-- App name is different, will not merge. -->
+    <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">
+
+    <!-- App name is good, but backupAgent is mentioned and is different, will not merge. -->
+    <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">
+
+    <application android:name="com.example.app1.TheApp">
+        <activity android:name=".WidgetLibrary3" />
+    </application>
+
+</manifest>
+
+
+@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. -->
+
+    <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">
+
+    <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" />
+        <activity android:name="com.example.lib1.WidgetLibrary1" />
+        <activity android:name="com.example.lib2.WidgetLibrary2" />
+        <activity android:name="com.example.lib3.WidgetLibrary3" />
+# from @lib4_alias
+        <!-- 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>
+
+@errors
+
+W [ManifestMergerTest0_main.xml:3, ManifestMergerTest1_lib1_widget.xml:4] Main manifest has <application android:name='com.example.app1.TheApp'> but library uses name='com.example.lib1.TheApp'.
+W [ManifestMergerTest0_main.xml:3, ManifestMergerTest2_lib2_widget.xml:4] Main manifest has <application android:backupAgent='com.example.app1.MyBackupAgent'> but library uses backupAgent='com.example.lib2.MyBackupAgent'.
+P [ManifestMergerTest0_main.xml:6, ManifestMergerTest2_lib2_widget.xml:6] Skipping identical /manifest/application/activity[@name=com.example.lib2.LibActivity] element.
+W [ManifestMergerTest4_lib4_not_package.xml:1] Missing 'package' attribute in manifest.
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/20_uses_lib_merge.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/20_uses_lib_merge.xml
new file mode 100755
index 0000000..a5eecce
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/20_uses_lib_merge.xml
@@ -0,0 +1,176 @@
+#
+# Test merge of uses-library:
+# - Merge is OK if destination already has one with the same @name.
+# - required defaults to "true"
+# - when merging, a required=true (explicit or implicit) overwrites a required=false.
+#
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <!-- A library that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary0_DefaultTrue" />
+
+        <!-- A library that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary1_DefaultTrue" />
+
+        <!-- A library that is explicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary2_RequiredTrue"
+            android:required="true" />
+
+        <!-- A library that is explicitly marked as required=false -->
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="false" />
+
+        <!-- A library that is explicitly marked as required=false -->
+        <uses-library
+            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.lib1">
+
+    <application android:label="@string/lib_name1" >
+
+        <!-- Same as 1 from main, marking it as required=false -->
+        <uses-library
+            android:name="com.example.SomeLibrary1_DefaultTrue"
+            android:required="false" />
+
+        <!-- Same as 3 from main -->
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="false" />
+
+        <!-- Same as 4 from main -->
+        <uses-library
+            android:name="com.example.SomeLibrary4_RequiredFalse"
+            android:required="false" />
+
+        <!-- Add a new lib that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary5_RequiredTrue"
+            android:required="true" />
+
+        <!-- Add a new lib that is implicitly marked as required=false -->
+        <uses-library
+            android:name="com.example.SomeLibrary6_RequiredFalse"
+            android:required="false" />
+
+    </application>
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <application android:label="@string/lib_name1" >
+
+        <!-- Overrides 3, changing it from required=false to true -->
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="true" />
+
+        <!-- Same as 4 from main -->
+        <uses-library
+            android:name="com.example.SomeLibrary4_RequiredFalse"
+            android:required="false" />
+
+        <!-- Overrides 6, but implicitly declaring required=True -->
+        <uses-library
+            android:name="com.example.SomeLibrary6_RequiredFalse"  />
+
+    </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">
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <!-- A library that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary0_DefaultTrue" />
+
+        <!-- A library that is implicitly marked as required=true -->
+# required=false from lib1 is ignored, it stays at the default
+        <uses-library
+            android:name="com.example.SomeLibrary1_DefaultTrue" />
+
+        <!-- A library that is explicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary2_RequiredTrue"
+            android:required="true" />
+
+        <!-- A library that is explicitly marked as required=false -->
+# lib1 keeps it required=false but lib2 makes it switch to required=true
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="true" />
+
+        <!-- A library that is explicitly marked as required=false -->
+        <uses-library
+            android:name="com.example.SomeLibrary4_RequiredFalse"
+            android:required="false" />
+
+# new from lib1
+        <!-- Add a new lib that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary5_RequiredTrue"
+            android:required="true" />
+
+# new from lib1, but lib2 makes it switch to required=true
+        <!-- Add a new lib that is implicitly marked as required=false -->
+        <uses-library
+            android:name="com.example.SomeLibrary6_RequiredFalse"
+            android:required="true" />
+
+    </application>
+
+</manifest>
+
+
+@errors
+
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml
new file mode 100755
index 0000000..65f0fb6
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml
@@ -0,0 +1,202 @@
+#
+# Test merge of uses-library:
+# - Merge is OK if destination already has one with the same @name.
+# - required defaults to "true"
+# - when merging, a required=true (explicit or implicit) overwrites a required=false.
+#
+
+@fails
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <!-- A library that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary0_DefaultTrue" />
+
+        <!-- A library that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary1_DefaultTrue" />
+
+        <!-- A library that is explicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary2_RequiredTrue"
+            android:required="booh!" />
+
+        <!-- A library that is explicitly marked as required=false -->
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="false" />
+
+        <!-- A library that is explicitly marked as required=false. Duplicated. -->
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="false" />
+
+        <!-- A library that is explicitly marked as required=false -->
+        <uses-library
+            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.lib1">
+
+    <application android:label="@string/lib_name1" >
+
+        <!-- Error: android:name attribute is missing. -->
+        <uses-library />
+        <uses-library android:required="false" />
+        <uses-library android:required="true" />
+
+        <!-- Same as 2 from main. Warning/ignore because dest required isn't true/false. -->
+        <uses-library
+            android:name="com.example.SomeLibrary2_RequiredTrue"
+            android:required="true" />
+
+        <!-- Same as 3 from main. Warning because destination as a duplicate. -->
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="false" />
+
+        <!-- Same as 4 from main. Warning because required isn't true or false. -->
+        <uses-library
+            android:name="com.example.SomeLibrary4_RequiredFalse"
+            android:required="foo" />
+
+        <!-- Add a new lib that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary5_RequiredTrue"
+            android:required="true" />
+
+        <!-- Add a new lib that is implicitly marked as required=false -->
+        <uses-library
+            android:name="com.example.SomeLibrary6_RequiredFalse"
+            android:required="false" />
+
+    </application>
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <application android:label="@string/lib_name1" >
+
+        <!-- Overrides 3, changing it from required=false to true -->
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="true" />
+
+        <!-- Same as 4 from main -->
+        <uses-library
+            android:name="com.example.SomeLibrary4_RequiredFalse"
+            android:required="false" />
+
+        <!-- Overrides 6, but implicitly declaring required=True -->
+        <uses-library
+            android:name="com.example.SomeLibrary6_RequiredFalse"  />
+
+    </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">
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <!-- A library that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary0_DefaultTrue" />
+
+        <!-- A library that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary1_DefaultTrue" />
+
+        <!-- A library that is explicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary2_RequiredTrue"
+            android:required="booh!" />
+
+        <!-- A library that is explicitly marked as required=false -->
+# lib1 keeps it required=false but lib2 makes it switch to required=true
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="true" />
+
+        <!-- A library that is explicitly marked as required=false. Duplicated. -->
+        <uses-library
+            android:name="com.example.SomeLibrary3_RequiredFalse"
+            android:required="true" />
+
+        <!-- A library that is explicitly marked as required=false -->
+        <uses-library
+            android:name="com.example.SomeLibrary4_RequiredFalse"
+            android:required="false" />
+
+# new from lib1
+        <!-- Add a new lib that is implicitly marked as required=true -->
+        <uses-library
+            android:name="com.example.SomeLibrary5_RequiredTrue"
+            android:required="true" />
+
+# new from lib1, but lib2 makes it switch to required=true
+        <!-- Add a new lib that is implicitly marked as required=false -->
+        <uses-library
+            android:name="com.example.SomeLibrary6_RequiredFalse"
+            android:required="true" />
+
+    </application>
+
+</manifest>
+
+
+@errors
+
+E [ManifestMergerTest1_lib1.xml:6] Undefined 'name' attribute in /manifest/application/uses-library.
+E [ManifestMergerTest1_lib1.xml:7] Undefined 'name' attribute in /manifest/application/uses-library.
+E [ManifestMergerTest1_lib1.xml:8] Undefined 'name' attribute in /manifest/application/uses-library.
+W [ManifestMergerTest0_main.xml:12] Invalid attribute 'required' in /manifest/application/uses-library[@name=com.example.SomeLibrary2_RequiredTrue] element:
+Expected 'true' or 'false' but found 'booh!'.
+W [ManifestMergerTest0_main.xml:15] Manifest has more than one /manifest/application/uses-library[@name=com.example.SomeLibrary3_RequiredFalse] element.
+W [ManifestMergerTest1_lib1.xml:17] Invalid attribute 'required' in /manifest/application/uses-library[@name=com.example.SomeLibrary4_RequiredFalse] element:
+Expected 'true' or 'false' but found 'foo'.
+W [ManifestMergerTest0_main.xml:15] Manifest has more than one /manifest/application/uses-library[@name=com.example.SomeLibrary3_RequiredFalse] element.
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/25_permission_merge.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/25_permission_merge.xml
new file mode 100755
index 0000000..07208ad
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/25_permission_merge.xml
@@ -0,0 +1,259 @@
+#
+# Text permission, permission-group and permission-tree:
+# - Libraries can add any of these elements as long as they don't conflict
+#   with the destination: either the element must not be at all in the destination
+#   (as identified by the name) or it must match exactly.
+#
+
+@main
+
+<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" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <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" />
+
+    <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" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- Same permissions as main manifest -->
+    <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" />
+    <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" />
+
+    <!-- Added by lib1. -->
+    <permission
+        android:name="com.example.Permission1"
+        android:permissionGroup="com.example.Permission1"
+        android:protectionLevel="normal" />
+
+    <permission-group
+        android:description="This is getting"
+        android:label="too silly"
+        android:name="com.example.EnoughWithTheQuotes" />
+
+    <permission-tree
+        android:name="com.example.PermTree1" />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- Redefine one permission from main manifest -->
+    <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" />
+    <!-- And one from lib1. -->
+    <permission
+        android:name="com.example.Permission1"
+        android:permissionGroup="com.example.Permission1"
+        android:protectionLevel="normal" />
+    <permission-tree
+        android:name="com.example.PermTree1" />
+
+    <!-- Added by lib2. -->
+    <permission
+        android:name="com.example.SensiblePermission2"
+        android:permissionGroup="com.example.SensibleGroup2"
+        android:protectionLevel="normal" />
+
+    <permission-group
+        android:name="com.example.SensibleGroup2" />
+
+    <permission-tree
+        android:name="com.example.PermTree2" />
+
+</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" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <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" />
+
+    <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" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+# Added by lib1
+    <!-- Added by lib1. -->
+    <permission
+        android:name="com.example.Permission1"
+        android:permissionGroup="com.example.Permission1"
+        android:protectionLevel="normal" />
+
+    <permission-group
+        android:description="This is getting"
+        android:label="too silly"
+        android:name="com.example.EnoughWithTheQuotes" />
+
+    <permission-tree
+        android:name="com.example.PermTree1" />
+
+# Added by lib2
+    <!-- Added by lib2. -->
+    <permission
+        android:name="com.example.SensiblePermission2"
+        android:permissionGroup="com.example.SensibleGroup2"
+        android:protectionLevel="normal" />
+
+    <permission-group
+        android:name="com.example.SensibleGroup2" />
+
+    <permission-tree
+        android:name="com.example.PermTree2" />
+
+</manifest>
+
+
+@errors
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/26_permission_dup.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/26_permission_dup.xml
new file mode 100755
index 0000000..3862249
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/26_permission_dup.xml
@@ -0,0 +1,307 @@
+#
+# Text permission, permission-group and permission-tree:
+# - Libraries can add any of these elements as long as they don't conflict
+#   with the destination: either the element must not be at all in the destination
+#   (as identified by the name) or it must match exactly.
+#
+# This one tests that duplicate definitions that are strictly equal generate errors
+# with some (hopefully useful) diff.
+#
+
+@fails
+
+@main
+
+<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" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <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" />
+
+    <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" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- Similar permissions as main manifest, but with slight conflicts -->
+    <permission
+        android:description="Different description here"
+        android:icon="@drawable/not_the_same_icon"
+        android:label="Danger, Will Robinson!"
+        android:name="com.example.DangerWillRobinson"
+        android:permissionGroup="com.example.MasterControlPermission"
+        android:protectionLevel="dangerous" />
+    <!-- missing icon: --><permission-group
+        android:description="Nobody expects..."
+        android:label="the Spanish Inquisition"
+        android:name="com.example.MasterControlPermission" />
+    <permission-tree
+        android:label="This is not the same label"
+        android:name="com.example.PermTree" />
+
+    <!-- different protectionLevel --><permission
+        android:name="com.example.WhatWereYouThinking"
+        android:permissionGroup="com.example.MasterControlPermission"
+        android:protectionLevel="normal" />
+
+    <!-- Added by lib1. -->
+    <permission
+        android:name="com.example.Permission1"
+        android:permissionGroup="com.example.Permission1"
+        android:protectionLevel="normal" />
+
+    <permission-group
+        android:description="This is getting"
+        android:label="too silly"
+        android:name="com.example.EnoughWithTheQuotes" />
+
+    <permission-tree
+        android:name="com.example.PermTree1" />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- Redefine one permission from main manifest -->
+    <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" />
+    <!-- And one from lib1, with a slight variation. -->
+    <permission
+        android:name="com.example.Permission1"
+        android:permissionGroup="com.example.Permission1"
+        android:protectionLevel="system" />
+    <permission-tree
+        android:description="Extra description"
+        android:name="com.example.PermTree1" />
+
+    <!-- Added by lib2. -->
+    <permission
+        android:name="com.example.SensiblePermission2"
+        android:permissionGroup="com.example.SensibleGroup2"
+        android:protectionLevel="normal" />
+
+    <permission-group
+        android:name="com.example.SensibleGroup2" />
+
+    <permission-tree
+        android:name="com.example.PermTree2" />
+
+</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" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <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" />
+
+    <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" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+# Added by lib1
+    <!-- Added by lib1. -->
+    <permission
+        android:name="com.example.Permission1"
+        android:permissionGroup="com.example.Permission1"
+        android:protectionLevel="normal" />
+
+    <permission-group
+        android:description="This is getting"
+        android:label="too silly"
+        android:name="com.example.EnoughWithTheQuotes" />
+
+    <permission-tree
+        android:name="com.example.PermTree1" />
+
+# Added by lib2
+    <!-- Added by lib2. -->
+    <permission
+        android:name="com.example.SensiblePermission2"
+        android:permissionGroup="com.example.SensibleGroup2"
+        android:protectionLevel="normal" />
+
+    <permission-group
+        android:name="com.example.SensibleGroup2" />
+
+    <permission-tree
+        android:name="com.example.PermTree2" />
+
+</manifest>
+
+
+@errors
+
+E [ManifestMergerTest0_main.xml:12, ManifestMergerTest1_lib1.xml:4] Trying to merge incompatible /manifest/permission[@name=com.example.DangerWillRobinson] element:
+  <permission android:name=com.example.DangerWillRobinson>
+--    @android:description = Different description here
+++    @android:description = Insert boring description here
+--    @android:icon = @drawable/not_the_same_icon
+++    @android:icon = @drawable/robot
+      @android:label = Danger, Will Robinson!
+      @android:name = com.example.DangerWillRobinson
+      @android:permissionGroup = com.example.MasterControlPermission
+      @android:protectionLevel = dangerous
+E [ManifestMergerTest0_main.xml:14, ManifestMergerTest1_lib1.xml:8] Trying to merge incompatible /manifest/permission[@name=com.example.WhatWereYouThinking] element:
+  <permission android:name=com.example.WhatWereYouThinking>
+      @android:name = com.example.WhatWereYouThinking
+      @android:permissionGroup = com.example.MasterControlPermission
+--    @android:protectionLevel = normal
+++    @android:protectionLevel = signatureOrSystem
+E [ManifestMergerTest0_main.xml:16, ManifestMergerTest1_lib1.xml:5] Trying to merge incompatible /manifest/permission-group[@name=com.example.MasterControlPermission] element:
+  <permission-group android:name=com.example.MasterControlPermission>
+      @android:description = Nobody expects...
+++    @android:icon = @drawable/ignored_icon
+      @android:label = the Spanish Inquisition
+      @android:name = com.example.MasterControlPermission
+E [ManifestMergerTest0_main.xml:18, ManifestMergerTest1_lib1.xml:6] Trying to merge incompatible /manifest/permission-tree[@name=com.example.PermTree] element:
+  <permission-tree android:name=com.example.PermTree>
+++    @android:label = This is not a label
+--    @android:label = This is not the same label
+      @android:name = com.example.PermTree
+E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/permission[@name=com.example.Permission1] element:
+  <permission android:name=com.example.Permission1>
+      @android:name = com.example.Permission1
+      @android:permissionGroup = com.example.Permission1
+++    @android:protectionLevel = normal
+--    @android:protectionLevel = system
+E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:7] Trying to merge incompatible /manifest/permission-tree[@name=com.example.PermTree1] element:
+  <permission-tree android:name=com.example.PermTree1>
+--    @android:description = Extra description
+      @android:name = com.example.PermTree1
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/28_uses_perm_merge.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/28_uses_perm_merge.xml
new file mode 100755
index 0000000..ecc644a
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/28_uses_perm_merge.xml
@@ -0,0 +1,156 @@
+#
+# Text uses-permission:
+# - Libraries can add any of these elements as long as they don't conflict
+#   with the destination: either the element must not be at all in the destination
+#   (as identified by the name) or it must match exactly.
+#
+
+@main
+
+<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" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- Same permissions as main manifest -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <!-- Library 1 wants to know what you're running. -->
+    <uses-permission android:name="android.permission.GET_TASKS" />
+
+    <!-- Are you calling me? -->
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- Redefine one permission from main manifest -->
+    <uses-permission android:name="android.permission.INTERNET" />
+    <!-- And one from lib1. -->
+    <uses-permission android:name="android.permission.GET_TASKS" />
+
+    <!-- Lib2 wants to know it all. -->
+    <uses-permission android:name="android.permission.READ_LOGS"/>
+
+</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" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+# Added by lib1
+    <!-- Library 1 wants to know what you're running. -->
+    <uses-permission android:name="android.permission.GET_TASKS" />
+
+    <!-- Are you calling me? -->
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
+# Added by lib2
+    <!-- Lib2 wants to know it all. -->
+    <uses-permission android:name="android.permission.READ_LOGS"/>
+
+</manifest>
+
+
+@errors
+
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/30_uses_sdk_ok.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/30_uses_sdk_ok.xml
new file mode 100755
index 0000000..bcee4ce
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/30_uses_sdk_ok.xml
@@ -0,0 +1,86 @@
+#
+# Test uses-sdk: add a uses-sdk from an app that doesn't define one.
+#
+
+@main
+
+<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="11"
+        android:targetSdkVersion="14"
+        />
+
+    <application />
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- This app requires cupcake. -->
+    <uses-sdk android:minSdkVersion="3" />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- This only defines a max-sdk, and we purposely ignore this attribute.
+         It doesn't get merged and doesn't generate a conflict either.
+    -->
+    <uses-sdk
+        android:maxSdkVersion="5"
+        />
+
+</manifest>
+
+
+@lib3
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib3">
+
+    <!-- Lib3 redefines the same requirements as lib1.
+    -->
+    <uses-sdk
+        android:minSdkVersion="3"
+        android:targetSdkVersion="11"
+        />
+
+</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="11"
+        android:targetSdkVersion="14"
+        />
+
+    <application />
+
+</manifest>
+
+
+@errors
+
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/32_uses_sdk_minsdk_ok.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/32_uses_sdk_minsdk_ok.xml
new file mode 100755
index 0000000..b94efe8
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/32_uses_sdk_minsdk_ok.xml
@@ -0,0 +1,70 @@
+#
+# Test uses-sdk: it's ok for a library to have a smaller minSdkVersion than the main manifest.
+#
+
+@main
+
+<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="14" />
+
+    <application />
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- it's ok for a library to have a smaller minSdkVersion than the main manifest. -->
+    <uses-sdk android:minSdkVersion="4" />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <uses-sdk android:minSdkVersion="10" />
+
+</manifest>
+
+
+@lib3
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib3">
+
+    <uses-sdk android:minSdkVersion="11" />
+
+</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="14" />
+
+    <application />
+
+</manifest>
+
+
+@errors
+
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml
new file mode 100755
index 0000000..8edbedb
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml
@@ -0,0 +1,148 @@
+#
+# Test uses-sdk: it's an error for a library to require a minSdkVersion higher than the
+# one defined in the main manifest.
+#
+# Also a uses-sdk with a lack of minSdkVersion is equivalent to using version=1.
+#
+
+@fails
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <!-- This is the same as writing android:minSdkVersion="1" -->
+    <uses-sdk android:targetSdkVersion="14" />
+
+    <application />
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- The app can cope with API 1 but this library can only cope with API 4. -->
+    <uses-sdk android:minSdkVersion="4" />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <uses-sdk android:minSdkVersion="10" />
+
+</manifest>
+
+
+@lib3
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib3">
+
+    <uses-sdk android:minSdkVersion="11" />
+
+</manifest>
+
+
+@lib4_parsingError
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib4">
+
+    <!-- Parsing errors -->
+    <uses-sdk android:minSdkVersion="abcd" />
+
+</manifest>
+
+
+@lib5_parsingError
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib5">
+
+    <!-- Parsing errors -->
+    <uses-sdk android:minSdkVersion="123456789123456789" />
+
+</manifest>
+
+
+@lib6_parsingError
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib6">
+
+    <!-- Parsing errors -->
+    <uses-sdk android:minSdkVersion="0xFFFFFFFFFFFFFFFF" />
+
+</manifest>
+
+
+@lib7_parsingError
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib7">
+
+    <!-- Parsing errors -->
+    <uses-sdk android:minSdkVersion="InvalidMinSdk" android:targetSdkVersion="InvalidTargetSdk" />
+
+</manifest>
+
+
+@lib8_parsingCodename
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib8">
+
+    <!-- Test code names -->
+    <uses-sdk android:minSdkVersion="ApiCodename1" android:targetSdkVersion="ApiCodename10" />
+
+</manifest>
+
+
+@result
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <!-- This is the same as writing android:minSdkVersion="1" -->
+    <uses-sdk android:targetSdkVersion="14" />
+
+    <application />
+
+</manifest>
+
+
+@errors
+
+E [ManifestMergerTest0_main.xml:4, ManifestMergerTest1_lib1.xml:4] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='4'
+Note: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1.
+E [ManifestMergerTest0_main.xml:4, ManifestMergerTest2_lib2.xml:3] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='10'
+Note: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1.
+E [ManifestMergerTest0_main.xml:4, ManifestMergerTest3_lib3.xml:3] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='11'
+Note: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1.
+E [ManifestMergerTest4_lib4_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='abcd'>: must be an integer number or codename.
+E [ManifestMergerTest5_lib5_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='123456789123456789'>: must be an integer number or codename.
+E [ManifestMergerTest6_lib6_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='0xFFFFFFFFFFFFFFFF'>: must be an integer number or codename.
+E [ManifestMergerTest7_lib7_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='InvalidMinSdk'>: must be an integer number or codename.
+E [ManifestMergerTest7_lib7_parsingError.xml:4] Failed to parse <uses-sdk targetSdkVersion='InvalidTargetSdk'>: must be an integer number or codename.
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml
new file mode 100755
index 0000000..df8b717
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml
@@ -0,0 +1,77 @@
+#
+# Test uses-sdk: there's a warning if the main manifest defines a targetSdkVersion that
+# is smaller than what the libraries target.
+#
+
+@fails
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <!-- This app requires cupcake and targets at least 10. -->
+    <uses-sdk
+        android:minSdkVersion="3"
+        android:targetSdkVersion="ApiCodename10"
+        />
+
+    <application />
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- This lib requires cupcake and targets 11 which is > 10 so it's a warning. -->
+    <uses-sdk
+        android:minSdkVersion="3"
+        android:targetSdkVersion="11"
+        />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- This is not an error nor a warning. -->
+    <uses-sdk
+        android:minSdkVersion="3"
+        android:targetSdkVersion="4"
+        />
+</manifest>
+
+
+@result
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <!-- This app requires cupcake and targets at least 10. -->
+    <uses-sdk
+        android:minSdkVersion="3"
+        android:targetSdkVersion="ApiCodename10"
+        />
+
+    <application />
+
+</manifest>
+
+
+@errors
+
+W [ManifestMergerTest0_main.xml:4, ManifestMergerTest1_lib1.xml:4] Main manifest has <uses-sdk android:targetSdkVersion='10'> but library uses targetSdkVersion='11'
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/40_uses_feat_merge.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/40_uses_feat_merge.xml
new file mode 100755
index 0000000..d14dcaa
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/40_uses_feat_merge.xml
@@ -0,0 +1,178 @@
+#
+# Test merge of uses-feature:
+# - Merge is OK if destination already has one with the same @name.
+# - required defaults to "true"
+# - when merging, a required=true (explicit or implicit) overwrites a required=false.
+#
+# Note: uses-feature with android:glEsVersion is dealt with in another test case.
+#
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <!-- A feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature0_DefaultTrue" />
+
+    <!-- A feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature1_DefaultTrue" />
+
+    <!-- A feature that is explicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature2_RequiredTrue"
+        android:required="true" />
+
+    <!-- A feature that is explicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="false" />
+
+    <!-- A feature that is explicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature4_RequiredFalse"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- Same as 1 from main, marking it as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature1_DefaultTrue"
+        android:required="false" />
+
+    <!-- Same as 3 from main -->
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="false" />
+
+    <!-- Same as 4 from main -->
+    <uses-feature
+        android:name="com.example.SomeFeature4_RequiredFalse"
+        android:required="false" />
+
+    <!-- Add a new feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature5_RequiredTrue"
+        android:required="true" />
+
+    <!-- Add a new feature that is implicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature6_RequiredFalse"
+        android:required="false" />
+
+    <application android:label="@string/lib_name1" >
+
+    </application>
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- Overrides 3, changing it from required=false to true -->
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="true" />
+
+    <!-- Same as 4 from main -->
+    <uses-feature
+        android:name="com.example.SomeFeature4_RequiredFalse"
+        android:required="false" />
+
+    <!-- Overrides 6, but implicitly declaring required=True -->
+    <uses-feature
+        android:name="com.example.SomeFeature6_RequiredFalse"  />
+
+    <application android:label="@string/lib_name2" >
+
+    </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">
+
+    <!-- A feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature0_DefaultTrue" />
+
+    <!-- A feature that is implicitly marked as required=true -->
+# required=false from lib1 is ignored, it stays at the default
+    <uses-feature
+        android:name="com.example.SomeFeature1_DefaultTrue" />
+
+    <!-- A feature that is explicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature2_RequiredTrue"
+        android:required="true" />
+
+    <!-- A feature that is explicitly marked as required=false -->
+# lib1 keeps it required=false but lib2 makes it switch to required=true
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="true" />
+
+    <!-- A feature that is explicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature4_RequiredFalse"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+    </application>
+
+# new from lib1
+    <!-- Add a new feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature5_RequiredTrue"
+        android:required="true" />
+
+# new from lib1, but lib2 makes it switch to required=true
+    <!-- Add a new feature that is implicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature6_RequiredFalse"
+        android:required="true" />
+
+</manifest>
+
+
+@errors
+
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/41_uses_feat_errors.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/41_uses_feat_errors.xml
new file mode 100755
index 0000000..b86f74a
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/41_uses_feat_errors.xml
@@ -0,0 +1,205 @@
+#
+# Test merge of uses-feature:
+# - Merge is OK if destination already has one with the same @name.
+# - required defaults to "true"
+# - when merging, a required=true (explicit or implicit) overwrites a required=false.
+#
+# Note: uses-feature with android:glEsVersion is dealt with in another test case.
+#
+
+@fails
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <!-- A feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature0_DefaultTrue" />
+
+    <!-- A feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature1_DefaultTrue" />
+
+    <!-- A feature that is explicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature2_RequiredTrue"
+        android:required="booh!" />
+
+    <!-- A feature that is explicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="false" />
+
+    <!-- A feature that is explicitly marked as required=false. Duplicated. -->
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="false" />
+
+    <!-- A feature that is explicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature4_RequiredFalse"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- Error: android:name attribute is missing. -->
+    <uses-feature />
+    <uses-feature android:required="false" />
+    <uses-feature android:required="true" />
+
+    <!-- Same as 2 from main. Warning/ignore because dest required isn't true/false. -->
+    <uses-feature
+        android:name="com.example.SomeFeature2_RequiredTrue"
+        android:required="true" />
+
+    <!-- Same as 3 from main. Warning because destination as a duplicate. -->
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="false" />
+
+    <!-- Same as 4 from main. Warning because required isn't true or false. -->
+    <uses-feature
+        android:name="com.example.SomeFeature4_RequiredFalse"
+        android:required="foo" />
+
+    <!-- Add a new feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature5_RequiredTrue"
+        android:required="true" />
+
+    <!-- Add a new feature that is implicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature6_RequiredFalse"
+        android:required="false" />
+
+    <application android:label="@string/lib_name1" >
+
+    </application>
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- Overrides 3, changing it from required=false to true -->
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="true" />
+
+    <!-- Same as 4 from main -->
+    <uses-feature
+        android:name="com.example.SomeFeature4_RequiredFalse"
+        android:required="false" />
+
+    <!-- Overrides 6, but implicitly declaring required=True -->
+    <uses-feature
+        android:name="com.example.SomeFeature6_RequiredFalse"  />
+
+    <application android:label="@string/lib_name2" >
+
+    </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">
+
+    <!-- A feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature0_DefaultTrue" />
+
+    <!-- A feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature1_DefaultTrue" />
+
+    <!-- A feature that is explicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature2_RequiredTrue"
+        android:required="booh!" />
+
+    <!-- A feature that is explicitly marked as required=false -->
+# lib1 keeps it required=false but lib2 makes it switch to required=true
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="true" />
+
+    <!-- A feature that is explicitly marked as required=false. Duplicated. -->
+# in case of duplicated name, they are all modified.
+    <uses-feature
+        android:name="com.example.SomeFeature3_RequiredFalse"
+        android:required="true" />
+
+    <!-- A feature that is explicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature4_RequiredFalse"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+    </application>
+
+# new from lib1
+    <!-- Add a new feature that is implicitly marked as required=true -->
+    <uses-feature
+        android:name="com.example.SomeFeature5_RequiredTrue"
+        android:required="true" />
+
+# new from lib1, but lib2 makes it switch to required=true
+    <!-- Add a new feature that is implicitly marked as required=false -->
+    <uses-feature
+        android:name="com.example.SomeFeature6_RequiredFalse"
+        android:required="true" />
+
+</manifest>
+
+
+@errors
+
+E [ManifestMergerTest1_lib1.xml:4] Undefined 'name' attribute in /manifest/uses-feature.
+E [ManifestMergerTest1_lib1.xml:5] Undefined 'name' attribute in /manifest/uses-feature.
+E [ManifestMergerTest1_lib1.xml:6] Undefined 'name' attribute in /manifest/uses-feature.
+W [ManifestMergerTest0_main.xml:10] Invalid attribute 'required' in /manifest/uses-feature[@name=com.example.SomeFeature2_RequiredTrue] element:
+Expected 'true' or 'false' but found 'booh!'.
+W [ManifestMergerTest0_main.xml:13] Manifest has more than one /manifest/uses-feature[@name=com.example.SomeFeature3_RequiredFalse] element.
+W [ManifestMergerTest1_lib1.xml:15] Invalid attribute 'required' in /manifest/uses-feature[@name=com.example.SomeFeature4_RequiredFalse] element:
+Expected 'true' or 'false' but found 'foo'.
+W [ManifestMergerTest0_main.xml:13] Manifest has more than one /manifest/uses-feature[@name=com.example.SomeFeature3_RequiredFalse] element.
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/45_uses_feat_gles_once.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/45_uses_feat_gles_once.xml
new file mode 100755
index 0000000..57937a6
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/45_uses_feat_gles_once.xml
@@ -0,0 +1,126 @@
+#
+# Test merge of uses-feature with android:glEsVersion:
+# - Error if defined in lib+dest with dest < lib.
+# - Never automatically change dest.
+# - Default implied value is 1.0 (0x00010000).
+#
+# This tests a case that works. Also checks that glEsVersion attributes are stripped
+# when merging uses-feature with the name attribute.
+#
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <uses-feature
+        android:name="com.example.SomeFeature0" />
+    <uses-feature
+        android:name="com.example.SomeFeature1"
+        android:required="false" />
+    <uses-feature android:glEsVersion="0x00020001" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- Add a new feature with a glEsVersion of 2.1 -->
+    <uses-feature
+        android:name="com.example.SomeFeature5"
+        android:required="false"
+        android:glEsVersion="0x00020001"
+        />
+
+    <!-- Add a glEsVersion of 2.0, which will be ignored -->
+    <uses-feature
+        android:glEsVersion="0x00020000"
+        />
+
+    <application android:label="@string/lib_name1" />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- Add a new feature with a glEsVersion of 1.1 which will be ignored -->
+    <uses-feature
+        android:name="com.example.SomeFeature6"
+        android:required="false"
+        android:glEsVersion="0x00020001"
+        />
+
+    <!-- Add a glEsVersion of 1.0, which will be ignored -->
+    <uses-feature android:glEsVersion="0x00010000" />
+
+</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-feature
+        android:name="com.example.SomeFeature0" />
+    <uses-feature
+        android:name="com.example.SomeFeature1"
+        android:required="false" />
+    <uses-feature android:glEsVersion="0x00020001" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+    </application>
+
+    <!-- Add a new feature with a glEsVersion of 2.1 -->
+# lib1 adds this new node. Note how the glEsVersion=2.1 is stripped out.
+    <uses-feature
+        android:name="com.example.SomeFeature5"
+        android:required="false"
+        />
+
+    <!-- Add a new feature with a glEsVersion of 1.1 which will be ignored -->
+# lib2 adds this new node. Note how the glEsVersion=2.0 is stripped out.
+    <uses-feature
+        android:name="com.example.SomeFeature6"
+        android:required="false"
+        />
+
+</manifest>
+
+
+@errors
+
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml
new file mode 100755
index 0000000..936d009
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml
@@ -0,0 +1,162 @@
+#
+# Test merge of uses-feature with android:glEsVersion:
+# - Error if defined in lib+dest with dest < lib.
+# - Never automatically change dest.
+# - Default implied value is 1.0 (0x00010000).
+#
+# This tests a case that doesn't works because the main manifest doesn't declare
+# the value and thus defaults to 1.0, so libraries with higher requirements will
+# conflict.
+#
+
+@fails
+
+@main
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.app1"
+    android:versionCode="100"
+    android:versionName="1.0.0">
+
+    <uses-feature
+        android:name="com.example.SomeFeature0" />
+    <uses-feature
+        android:name="com.example.SomeFeature1"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- Add a new feature with a glEsVersion of 2.1 -->
+    <uses-feature
+        android:name="com.example.SomeFeature5"
+        android:required="false"
+        android:glEsVersion="0x00020001"
+        />
+
+    <!-- Add a glEsVersion of 2.0, which will be ignored -->
+    <uses-feature
+        android:glEsVersion="0x00020000"
+        />
+
+    <application android:label="@string/lib_name1" />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- Add a new feature with a glEsVersion of 1.1 which will be ignored -->
+    <uses-feature
+        android:name="com.example.SomeFeature6"
+        android:required="false"
+        android:glEsVersion="0x00020001"
+        />
+
+    <!-- Add a glEsVersion of 1.0, which will be ignored -->
+    <uses-feature
+        android:glEsVersion="0x00010000"
+        />
+
+    <!-- Test some invalid values. -->
+
+    <!-- 0 isn't a valid value and generates a warning stating it's ignored. -->
+    <uses-feature
+        android:glEsVersion="0"
+        />
+
+    <!-- 0.0xFFFF is 0.99... and generates a warning stating it's ignored.
+         The real minimal value is 1.0, not 0.99... -->
+    <uses-feature
+        android:glEsVersion="0x0000FFFF"
+        />
+
+    <!-- 0xFFFF.xFFFF is not invalid. It does correspond to  65535.9999847412109375
+         which is unlikely to be valid anyway. It's not ignored and should parse just fine.
+    -->
+    <uses-feature
+        android:glEsVersion="0xFFFFFFFF"
+        />
+
+    <!-- This value shouldn't parse correctly with a Long and will generate a parsing error.
+    -->
+    <uses-feature
+        android:glEsVersion="0xFFFFFFFFFFFFFFFF"
+        />
+
+</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-feature
+        android:name="com.example.SomeFeature0" />
+    <uses-feature
+        android:name="com.example.SomeFeature1"
+        android:required="false" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+    </application>
+
+    <!-- Add a new feature with a glEsVersion of 2.1 -->
+# lib1 adds this new node. Note how the glEsVersion=2.1 is stripped out.
+    <uses-feature
+        android:name="com.example.SomeFeature5"
+        android:required="false"
+        />
+
+    <!-- Add a new feature with a glEsVersion of 1.1 which will be ignored -->
+# lib2 adds this new node. Note how the glEsVersion=2.0 is stripped out.
+    <uses-feature
+        android:name="com.example.SomeFeature6"
+        android:required="false"
+        />
+
+</manifest>
+
+
+@errors
+
+W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:4] Main manifest has <uses-feature android:glEsVersion='0x00010000'> but library uses glEsVersion='0x00020001'
+Note: main manifest lacks a <uses-feature android:glEsVersion> declaration, and thus defaults to glEsVersion=0x00010000.
+W [ManifestMergerTest2_lib2.xml:12] Ignoring <uses-feature android:glEsVersion='0'> because it's smaller than 1.0.
+W [ManifestMergerTest2_lib2.xml:15] Ignoring <uses-feature android:glEsVersion='0x0000FFFF'> because it's smaller than 1.0.
+E [ManifestMergerTest2_lib2.xml:21] Failed to parse <uses-feature android:glEsVersion='0xFFFFFFFFFFFFFFFF'>: must be an integer in the form 0x00020001.
+W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:18] Main manifest has <uses-feature android:glEsVersion='0x00010000'> but library uses glEsVersion='0xffffffff'
+Note: main manifest lacks a <uses-feature android:glEsVersion> declaration, and thus defaults to glEsVersion=0x00010000.
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/50_uses_conf_warning.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/50_uses_conf_warning.xml
new file mode 100755
index 0000000..b1cb3f9
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/50_uses_conf_warning.xml
@@ -0,0 +1,162 @@
+#
+# Test uses-configuration:
+# - 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.
+# - this does not actually merge anything. The XML is not changed at all.
+#
+
+@main
+
+<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-configuration
+        android:reqFiveWayNav="true"
+        android:reqHardKeyboard="false"
+        android:reqKeyboardType="undefined"
+        android:reqNavigation="nonav"
+        android:reqTouchScreen="stylus"
+        />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <supports-gl-texture android:name="some.gl.texture1" />
+    <supports-gl-texture android:name="some.gl.texture2" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- this is the same uses-conf than in the main. -->
+    <uses-configuration
+        android:reqFiveWayNav="true"
+        android:reqHardKeyboard="false"
+        android:reqKeyboardType="undefined"
+        android:reqNavigation="nonav"
+        android:reqTouchScreen="stylus"
+        />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- this is the not same uses-conf than in the main. -->
+    <uses-configuration
+        android:reqFiveWayNav="false"
+        android:reqNavigation="trackball"
+        android:reqTouchScreen="finger" />
+
+</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-configuration
+        android:reqFiveWayNav="true"
+        android:reqHardKeyboard="false"
+        android:reqKeyboardType="undefined"
+        android:reqNavigation="nonav"
+        android:reqTouchScreen="stylus"
+        />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <supports-gl-texture android:name="some.gl.texture1" />
+    <supports-gl-texture android:name="some.gl.texture2" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@errors
+
+W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/uses-configuration defined in library, missing from main manifest:
+<uses-configuration>
+    @android:reqFiveWayNav = false
+    @android:reqNavigation = trackball
+    @android:reqTouchScreen = finger
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/52_support_screens_warning.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/52_support_screens_warning.xml
new file mode 100755
index 0000000..363fb2b
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/52_support_screens_warning.xml
@@ -0,0 +1,162 @@
+#
+# Test supports-screens:
+# - 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.
+# - this does not actually merge anything. The XML is not changed at all.
+#
+
+@main
+
+<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-configuration
+        android:reqFiveWayNav="true"
+        android:reqHardKeyboard="false"
+        android:reqKeyboardType="undefined"
+        android:reqNavigation="nonav"
+        android:reqTouchScreen="stylus"
+        />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <supports-gl-texture android:name="some.gl.texture1" />
+    <supports-gl-texture android:name="some.gl.texture2" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- this is the same supports-screens than in the main. -->
+    <supports-screens
+        android:largeScreens="true"
+        android:smallScreens="true"
+        android:normalScreens="true"
+        android:resizeable="true"
+        android:xlargeScreens="true"
+        />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- this is the not same supports-screens than in the main. -->
+    <supports-screens
+        android:smallScreens="false"
+        android:resizeable="false"
+        />
+
+</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-configuration
+        android:reqFiveWayNav="true"
+        android:reqHardKeyboard="false"
+        android:reqKeyboardType="undefined"
+        android:reqNavigation="nonav"
+        android:reqTouchScreen="stylus"
+        />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <supports-gl-texture android:name="some.gl.texture1" />
+    <supports-gl-texture android:name="some.gl.texture2" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@errors
+
+W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/supports-screens defined in library, missing from main manifest:
+<supports-screens>
+    @android:resizeable = false
+    @android:smallScreens = false
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/54_compat_screens_warning.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/54_compat_screens_warning.xml
new file mode 100755
index 0000000..1e1c2d2
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/54_compat_screens_warning.xml
@@ -0,0 +1,204 @@
+#
+# Test compatible-screens:
+# - 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.
+# - this does not actually merge anything. The XML is not changed at all.
+#
+
+@main
+
+<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-configuration
+        android:reqFiveWayNav="true"
+        android:reqHardKeyboard="false"
+        android:reqKeyboardType="undefined"
+        android:reqNavigation="nonav"
+        android:reqTouchScreen="stylus"
+        />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <supports-gl-texture android:name="some.gl.texture1" />
+    <supports-gl-texture android:name="some.gl.texture2" />
+
+    <compatible-screens>
+        <screen android:screenSize="small"  android:screenDensity="ldpi" />
+        <screen android:screenSize="normal" android:screenDensity="xhdpi" />
+    </compatible-screens>
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- this is the same compatible-screens than in the main. -->
+    <compatible-screens>
+        <screen android:screenSize="small"  android:screenDensity="ldpi" />
+        <screen android:screenSize="normal" android:screenDensity="xhdpi" />
+    </compatible-screens>
+
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- this is the not same compatible-screens than in the main. -->
+    <compatible-screens>
+        <screen android:screenSize="small"  android:screenDensity="ldpi" />
+        <screen android:screenSize="normal" android:screenDensity="mdpi" />
+    </compatible-screens>
+
+    <compatible-screens>
+        <screen android:screenSize="small"  android:screenDensity="ldpi" />
+    </compatible-screens>
+
+    <compatible-screens>
+        <screen android:screenSize="normal" android:screenDensity="ldpi" />
+        <screen android:screenSize="normal" android:screenDensity="mdpi" />
+        <screen android:screenSize="normal" android:screenDensity="hdpi" />
+        <screen android:screenSize="normal" android:screenDensity="xhdpi" />
+    </compatible-screens>
+
+</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-configuration
+        android:reqFiveWayNav="true"
+        android:reqHardKeyboard="false"
+        android:reqKeyboardType="undefined"
+        android:reqNavigation="nonav"
+        android:reqTouchScreen="stylus"
+        />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <supports-gl-texture android:name="some.gl.texture1" />
+    <supports-gl-texture android:name="some.gl.texture2" />
+
+    <compatible-screens>
+        <screen android:screenSize="small"  android:screenDensity="ldpi" />
+        <screen android:screenSize="normal" android:screenDensity="xhdpi" />
+    </compatible-screens>
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@errors
+
+W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/compatible-screens defined in library, missing from main manifest:
+<compatible-screens>
+  <screen>
+      @android:screenDensity = ldpi
+      @android:screenSize = small
+  <screen>
+      @android:screenDensity = mdpi
+      @android:screenSize = normal
+W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:9] /manifest/compatible-screens defined in library, missing from main manifest:
+<compatible-screens>
+  <screen>
+      @android:screenDensity = ldpi
+      @android:screenSize = small
+W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:13] /manifest/compatible-screens defined in library, missing from main manifest:
+<compatible-screens>
+  <screen>
+      @android:screenDensity = ldpi
+      @android:screenSize = normal
+  <screen>
+      @android:screenDensity = mdpi
+      @android:screenSize = normal
+  <screen>
+      @android:screenDensity = hdpi
+      @android:screenSize = normal
+  <screen>
+      @android:screenDensity = xhdpi
+      @android:screenSize = normal
diff --git a/third-party/java/aosp/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml b/third-party/java/aosp/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml
new file mode 100755
index 0000000..494fd2e
--- /dev/null
+++ b/third-party/java/aosp/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml
@@ -0,0 +1,152 @@
+#
+# 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.
+# - this does not actually merge anything. The XML is not changed at all.
+#
+
+@main
+
+<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-configuration
+        android:reqFiveWayNav="true"
+        android:reqHardKeyboard="false"
+        android:reqKeyboardType="undefined"
+        android:reqNavigation="nonav"
+        android:reqTouchScreen="stylus"
+        />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <supports-gl-texture android:name="some.gl.texture1" />
+    <supports-gl-texture android:name="some.gl.texture2" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@lib1
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib1">
+
+    <!-- this is the same supports-gl-texture than in the main. -->
+    <supports-gl-texture android:name="some.gl.texture1" />
+
+</manifest>
+
+
+@lib2
+
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.lib2">
+
+    <!-- this is the not same supports-gl-texture than in the main. -->
+    <supports-gl-texture android:name="some.gl.texture3" />
+
+</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-configuration
+        android:reqFiveWayNav="true"
+        android:reqHardKeyboard="false"
+        android:reqKeyboardType="undefined"
+        android:reqNavigation="nonav"
+        android:reqTouchScreen="stylus"
+        />
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+
+    <supports-gl-texture android:name="some.gl.texture1" />
+    <supports-gl-texture android:name="some.gl.texture2" />
+
+    <application
+        android:label="@string/app_name"
+        android:icon="@drawable/app_icon"
+        android:backupAgent="com.example.app.BackupAgentClass"
+        android:restoreAnyVersion="true"
+        android:allowBackup="true"
+        android:killAfterRestore="true"
+        android:name="com.example.TheApp" >
+
+        <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>
+
+    </application>
+
+</manifest>
+
+
+@errors
+
+W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/supports-gl-texture defined in library, missing from main manifest:
+<supports-gl-texture>
+    @android:name = some.gl.texture3