Merge "Add full test coverage for android.app.Person" into pi-dev
am: 2cedf371ed

Change-Id: Id2fae6bd6a2bd0753243ba1688ac2ead1ca79b59
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleEncryptedClientService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleEncryptedClientService.java
index 68797f5..090ad01 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleEncryptedClientService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleEncryptedClientService.java
@@ -309,7 +309,7 @@
                             mBluetoothGatt.discoverServices();

                         }

                     }, 1000);

-                } else if (status == BluetoothProfile.STATE_DISCONNECTED) {

+                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {

                     showMessage("Bluetooth LE disconnected");

                     mTaskQueue.addTask(new Runnable() {

                         @Override

diff --git a/common/device-side/util/src/com/android/compatibility/common/util/ApiLevelUtil.java b/common/device-side/util/src/com/android/compatibility/common/util/ApiLevelUtil.java
index a49e949..943ebc7 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/ApiLevelUtil.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/ApiLevelUtil.java
@@ -46,7 +46,7 @@
     }
 
     public static boolean isAtLeast(String version) {
-        return Build.VERSION.SDK_INT > resolveVersionString(version);
+        return Build.VERSION.SDK_INT >= resolveVersionString(version);
     }
 
     public static boolean isAtMost(int version) {
diff --git a/hostsidetests/api/Android.mk b/hostsidetests/api/Android.mk
index 11f1e9d..63cb700 100644
--- a/hostsidetests/api/Android.mk
+++ b/hostsidetests/api/Android.mk
@@ -35,7 +35,7 @@
 test-mock/api/android-test-mock-current.txt)
 
 # API 27 is added since some support libraries are using old APIs
-LOCAL_JAVA_RESOURCE_FILES += prebuilts/sdk/api/27.txt
+LOCAL_JAVA_RESOURCE_FILES += prebuilts/sdk/27/public/api/android.txt
 
 include $(BUILD_HOST_JAVA_LIBRARY)
 
diff --git a/hostsidetests/api/src/com/android/cts/api/UnofficialApisUsageTest.java b/hostsidetests/api/src/com/android/cts/api/UnofficialApisUsageTest.java
index 6ecefb0..443d02b 100644
--- a/hostsidetests/api/src/com/android/cts/api/UnofficialApisUsageTest.java
+++ b/hostsidetests/api/src/com/android/cts/api/UnofficialApisUsageTest.java
@@ -179,7 +179,7 @@
             "/android-test-base-current.txt",
             "/android-test-runner-current.txt",
             "/android-test-mock-current.txt",
-            "/27.txt"
+            "/android.txt"
         }).map(name -> new File(name));
 
         approvedApis = new ApprovedApis(apiFiles);
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk
index 08fa1bd..746e45d 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk
@@ -36,4 +36,9 @@
 LOCAL_APK_LIBRARIES := $(featureOf)
 LOCAL_AAPT_FLAGS += --feature-of $(featureOfApk)
 
+# Disable AAPT2 to fix:
+# unknown option '--feature-of'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
index a0a8080..696ef62 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
@@ -40,6 +40,11 @@
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
 
 
@@ -69,6 +74,11 @@
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
 
 
@@ -97,6 +107,11 @@
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
 
 
@@ -125,6 +140,11 @@
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
 
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk b/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk
index b61c5d6..a3dd573 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk
@@ -25,4 +25,9 @@
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
index 06901d8..42f6423 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
@@ -39,4 +39,10 @@
 
 LOCAL_AAPT_FLAGS += --feature-of $(featureOfApk)
 
+# Disable AAPT2 to fix:
+# unknown option '--feature-of'.
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
index 5337057..c82bb6f 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
@@ -29,4 +29,9 @@
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
index 7fceede..6b4579e 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
@@ -29,4 +29,9 @@
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
index 9149930..1f81e90 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
@@ -29,4 +29,9 @@
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
index 95d02d0..56a3f14 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
@@ -29,4 +29,9 @@
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
index ad10be0..ab958a0 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
@@ -29,4 +29,9 @@
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
index f008564..e4b74df 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
@@ -29,4 +29,9 @@
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
index ded5b29..665a600 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
@@ -29,4 +29,9 @@
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
 
+# Disable AAPT2 to fix:
+# unknown option '--replace-version'.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java b/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java
index 591dcb4..0f0e13b 100644
--- a/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java
+++ b/hostsidetests/compilation/src/android/cts/compilation/AdbRootDependentCompilationTest.java
@@ -31,6 +31,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.EnumSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
@@ -77,6 +78,8 @@
     private File apkFile;
     private boolean mCanEnableDeviceRootAccess;
 
+    private Matcher mAdbLineFilter;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -104,6 +107,9 @@
         assertTrue("empty profile", profileBytes.length > 0); // sanity check
         textProfileFile = File.createTempFile("compilationtest", "prof.txt");
         Files.write(profileBytes, textProfileFile);
+
+        // Ignore issues in cmd.
+        mAdbLineFilter = Pattern.compile("FORTIFY: pthread_mutex_lock.*").matcher("");
     }
 
     @Override
@@ -351,9 +357,25 @@
         return propUseJitProfiles;
     }
 
+    private String[] filterAdbLines(String[] lines) {
+        List<String> linesList = new ArrayList<String>(Arrays.asList(lines));
+        Iterator<String> it = linesList.iterator();
+        while (it.hasNext()) {
+            String line = it.next();
+            mAdbLineFilter.reset(line);
+            if (mAdbLineFilter.matches()) {
+                it.remove();
+            }
+        }
+        if (linesList.size() != lines.length) {
+            return linesList.toArray(new String[linesList.size()]);
+        }
+        return lines;
+    }
+
     private String[] executeSuShellAdbCommand(int numLinesOutputExpected, String... command)
             throws DeviceNotAvailableException {
-        String[] lines = executeSuShellAdbCommand(command);
+        String[] lines = filterAdbLines(executeSuShellAdbCommand(command));
         assertEquals(
                 String.format(Locale.US, "Expected %d lines output, got %d running %s: %s",
                         numLinesOutputExpected, lines.length, Arrays.toString(command),
@@ -369,7 +391,7 @@
         String output = mDevice.executeShellCommand("su root " + cmdString);
         // "".split() returns { "" }, but we want an empty array
         String[] lines = output.equals("") ? new String[0] : output.split("\n");
-        return lines;
+        return filterAdbLines(lines);
     }
 
     private String getSelinuxLabel(String path) throws DeviceNotAvailableException {
diff --git a/hostsidetests/jvmti/allocation-tracking/app/src/android/jvmti/cts/JvmtiTrackingTest.java b/hostsidetests/jvmti/allocation-tracking/app/src/android/jvmti/cts/JvmtiTrackingTest.java
index 7a13e79..dbd6ecd 100644
--- a/hostsidetests/jvmti/allocation-tracking/app/src/android/jvmti/cts/JvmtiTrackingTest.java
+++ b/hostsidetests/jvmti/allocation-tracking/app/src/android/jvmti/cts/JvmtiTrackingTest.java
@@ -14,6 +14,7 @@
 package android.jvmti.cts;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import java.util.ArrayList;
 import org.junit.Before;
@@ -65,10 +66,11 @@
 
         enableAllocationTracking(null, false);
 
-        assertEquals(
-                "ObjectAllocated type java.lang.Object/java.lang.Object size 8#"
-                        + "ObjectAllocated type java.lang.Integer/java.lang.Integer size 16#",
-                        getAndResetAllocationTrackingString());
+        String trackingString = getAndResetAllocationTrackingString();
+        String object_line = "ObjectAllocated type java.lang.Object/java.lang.Object size 8#";
+        String integer_line = "ObjectAllocated type java.lang.Integer/java.lang.Integer size 16#";
+        assertTrue("does not contain " + object_line, trackingString.contains(object_line));
+        assertTrue("does not contain " + integer_line, trackingString.contains(integer_line));
 
         l.add(new Float(1.0f));
 
diff --git a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
index f80492c..89f1132 100644
--- a/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
+++ b/hostsidetests/jvmti/base/host/src/android/jvmti/cts/JvmtiHostTest.java
@@ -95,7 +95,9 @@
         // set a max deadline limit to avoid hanging forever
         runner.setMaxTimeToOutputResponse(2, TimeUnit.MINUTES);
 
-        TestResults tr = new TestResults(new AttachAgent(device, mTestPackageName, mTestApk));
+        AttachAgent aa = new AttachAgent(device, mTestPackageName, mTestApk);
+        aa.prepare();
+        TestResults tr = new TestResults(aa);
 
         device.runInstrumentationTests(runner, tr);
 
@@ -114,14 +116,15 @@
         private String mPkg;
         private String mApk;
 
+        private String mAgentInDataData;
+
         public AttachAgent(ITestDevice device, String pkg, String apk) {
             this.mDevice = device;
             this.mPkg = pkg;
             this.mApk = apk;
         }
 
-        @Override
-        public void run() {
+        public void prepare() {
             try {
                 String pwd = mDevice.executeShellCommand("run-as " + mPkg + " pwd");
                 if (pwd == null) {
@@ -132,9 +135,19 @@
                     throw new RuntimeException("pwd failed");
                 }
 
-                String agentInDataData = installLibToDataData(pwd, "libctsjvmtiagent.so");
+                mAgentInDataData = installLibToDataData(pwd, "libctsjvmtiagent.so");
+            } catch (Exception e) {
+                throw new RuntimeException("Failed installing", e);
+            }
+        }
 
-                String attachCmd = "cmd activity attach-agent " + mPkg + " " + agentInDataData;
+        @Override
+        public void run() {
+            try {
+                if (mAgentInDataData == null) {
+                    throw new IllegalStateException("prepare() has not been called");
+                }
+                String attachCmd = "cmd activity attach-agent " + mPkg + " " + mAgentInDataData;
                 String attachReply = mDevice.executeShellCommand(attachCmd);
                 // Don't try to parse the output. The test will time out anyways if this didn't
                 // work.
@@ -146,7 +159,7 @@
             }
         }
 
-        String installLibToDataData(String dataData, String library) throws Exception {
+        private String installLibToDataData(String dataData, String library) throws Exception {
             ZipFile zf = null;
             File tmpFile = null;
             String libInTmp = null;
diff --git a/hostsidetests/jvmti/base/jni/tracking.cpp b/hostsidetests/jvmti/base/jni/tracking.cpp
index a07d653..23acde9 100644
--- a/hostsidetests/jvmti/base/jni/tracking.cpp
+++ b/hostsidetests/jvmti/base/jni/tracking.cpp
@@ -85,6 +85,17 @@
     std::unique_lock<std::mutex> mu(gLock);
     result.swap(gCollection);
   }
+  // Make sure we give any other threads that might have been waiting to get a last crack time to
+  // run. We will ignore their additions however.
+  bool is_empty = false;
+  do {
+    {
+      std::unique_lock<std::mutex> mu(gLock);
+      is_empty = gCollection.empty();
+      gCollection.clear();
+    }
+    sched_yield();
+  } while (!is_empty);
 
   if (result.empty()) {
     return nullptr;
diff --git a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/Android.mk b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/Android.mk
index 8d3a6d2..212a4ec 100644
--- a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/Android.mk
+++ b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/Android.mk
@@ -30,4 +30,9 @@
 
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
 
+# Disable AAPT2 to fix:
+# cts/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/AndroidManifest.xml:28: error: unexpected element <additional-certificate> found in <manifest><application><uses-static-library>.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-8427/poc.c b/hostsidetests/security/securityPatch/CVE-2016-8427/poc.c
index 0c54420..1e3d9c8 100644
--- a/hostsidetests/security/securityPatch/CVE-2016-8427/poc.c
+++ b/hostsidetests/security/securityPatch/CVE-2016-8427/poc.c
@@ -18,11 +18,11 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <sys/ioctl.h>
 #include <sys/syscall.h>
 #include <string.h>
 #include <stdint.h>
 #include <pthread.h>
-#include <linux/ion.h>
 
 #define NVHOST_DBG_GPU_IOCTL_BIND_CHANNEL 0xc0084401ul
 
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index d3f4001..bf77652 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -51,6 +51,7 @@
 import java.util.regex.Pattern;
 import java.util.Scanner;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -918,6 +919,28 @@
                    + errorString, errorString.length() == 0);
     }
 
+   /**
+     * Tests that taking a bugreport does not produce any dumpstate-related
+     * SELinux denials.
+     *
+     * @throws Exception
+     */
+    public void testNoBugreportDenials() throws Exception {
+        // Take a bugreport and get its logcat output.
+        mDevice.executeAdbCommand("logcat", "-c");
+        mDevice.executeAdbCommand("bugreport");
+        String log = mDevice.executeAdbCommand("logcat", "-d");
+        // Find all the dumpstate-related types and make a regex that will match them.
+        Set<String> types = sepolicyAnalyzeGetTypesAssociatedWithAttribute("hal_dumpstate_server");
+        types.add("dumpstate");
+        String typeRegex = types.stream().collect(Collectors.joining("|"));
+        Pattern p = Pattern.compile("avc: *denied.*scontext=u:(?:r|object_r):(?:" + typeRegex + "):s0.*");
+        // Fail if logcat contains such a denial.
+        Matcher m = p.matcher(log);
+        if (m.find())
+            fail("Found illegal SELinux denial: " + m.group());
+    }
+
     /**
      * Tests that important domain labels are being appropriately applied.
      */
diff --git a/hostsidetests/theme/assets/Q/260dpi.zip b/hostsidetests/theme/assets/Q/260dpi.zip
new file mode 100644
index 0000000..68423a4
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/260dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/280dpi.zip b/hostsidetests/theme/assets/Q/280dpi.zip
new file mode 100644
index 0000000..9a09eb4
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/280dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/300dpi.zip b/hostsidetests/theme/assets/Q/300dpi.zip
new file mode 100644
index 0000000..35390b9
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/300dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/340dpi.zip b/hostsidetests/theme/assets/Q/340dpi.zip
new file mode 100644
index 0000000..a65cc9f
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/340dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/360dpi.zip b/hostsidetests/theme/assets/Q/360dpi.zip
new file mode 100644
index 0000000..a7be2b6
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/360dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/400dpi.zip b/hostsidetests/theme/assets/Q/400dpi.zip
new file mode 100644
index 0000000..f8e62bb
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/400dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/420dpi.zip b/hostsidetests/theme/assets/Q/420dpi.zip
new file mode 100644
index 0000000..3d70848
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/420dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/560dpi.zip b/hostsidetests/theme/assets/Q/560dpi.zip
new file mode 100644
index 0000000..e1527ed
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/560dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/hdpi.zip b/hostsidetests/theme/assets/Q/hdpi.zip
new file mode 100644
index 0000000..59c6efc
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/hdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/ldpi.zip b/hostsidetests/theme/assets/Q/ldpi.zip
new file mode 100644
index 0000000..8e408af
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/ldpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/mdpi.zip b/hostsidetests/theme/assets/Q/mdpi.zip
new file mode 100644
index 0000000..9aebe9d
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/mdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/tvdpi.zip b/hostsidetests/theme/assets/Q/tvdpi.zip
new file mode 100644
index 0000000..55525fb
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/tvdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/xhdpi.zip b/hostsidetests/theme/assets/Q/xhdpi.zip
new file mode 100644
index 0000000..3fecabe
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/xhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/xxhdpi.zip b/hostsidetests/theme/assets/Q/xxhdpi.zip
new file mode 100644
index 0000000..14d7680
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/xxhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/Q/xxxhdpi.zip b/hostsidetests/theme/assets/Q/xxxhdpi.zip
new file mode 100644
index 0000000..aa8d087
--- /dev/null
+++ b/hostsidetests/theme/assets/Q/xxxhdpi.zip
Binary files differ
diff --git a/tests/accessibility/res/xml/vibrating_accessibilityservice.xml b/tests/accessibility/res/xml/vibrating_accessibilityservice.xml
index 2219ee7..e1b9706 100644
--- a/tests/accessibility/res/xml/vibrating_accessibilityservice.xml
+++ b/tests/accessibility/res/xml/vibrating_accessibilityservice.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accessibilityEventTypes="typeAllMask|"
+    android:accessibilityEventTypes="typeAllMask"
     android:accessibilityFeedbackType="feedbackHaptic"
     android:accessibilityFlags="flagDefault|flagRequestTouchExplorationMode"
     android:canRetrieveWindowContent="true"
diff --git a/tests/app/app/Android.mk b/tests/app/app/Android.mk
index 706be8f..89034bb 100644
--- a/tests/app/app/Android.mk
+++ b/tests/app/app/Android.mk
@@ -47,4 +47,9 @@
 LOCAL_PACKAGE_NAME := CtsAppTestStubs
 LOCAL_PRIVATE_PLATFORM_APIS := true
 
+# Disable AAPT2 to fix:
+# cts/tests/app/app/AndroidManifest.xml:25: error: unexpected element <meta-data> found in <manifest><permission>.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/app/src/android/app/cts/DialogTest.java b/tests/app/src/android/app/cts/DialogTest.java
index b2749c7..c9a9a38 100755
--- a/tests/app/src/android/app/cts/DialogTest.java
+++ b/tests/app/src/android/app/cts/DialogTest.java
@@ -245,7 +245,7 @@
         mInstrumentation.waitForIdleSync();
 
         assertEquals(View.GONE, decor.getVisibility());
-        assertTrue(d.isShowing());
+        assertFalse(d.isShowing());
 
         mActivityRule.runOnUiThread(new Runnable() {
             public void run() {
diff --git a/tests/libcore/javautilcollections/Android.mk b/tests/libcore/javautilcollections/Android.mk
deleted file mode 100644
index 5a0bbb9..0000000
--- a/tests/libcore/javautilcollections/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2016 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := guava-20.0-prebuilt
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_SRC_FILES := libs/guava-20.0.jar
-LOCAL_UNINSTALLABLE_MODULE := true
-LOCAL_SDK_VERSION := current
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := guava-testlib-20.0-prebuilt
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_SRC_FILES := libs/guava-testlib-20.0.jar
-LOCAL_UNINSTALLABLE_MODULE := true
-LOCAL_SDK_VERSION := current
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    ctstestrunner \
-    guava-20.0-prebuilt \
-    guava-testlib-20.0-prebuilt
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_PACKAGE_NAME := CtsLibcoreJavaUtilCollectionsTestCases
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/libcore/javautilcollections/AndroidManifest.xml b/tests/libcore/javautilcollections/AndroidManifest.xml
deleted file mode 100644
index a7e8cee..0000000
--- a/tests/libcore/javautilcollections/AndroidManifest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2016 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
-  -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="libcore.java.util.collectiontests">
-
-    <!-- AndroidJUnitRunner needs a largeHeap to collect the ~ 240k test methods to run. -->
-    <application android:largeHeap="true">
-        <uses-library android:name="android.test.runner"/>
-    </application>
-
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="libcore.java.util.collectiontests"
-                     android:label="Tests for Collection implementations in java.util">
-    </instrumentation>
-
-</manifest>
-
diff --git a/tests/libcore/javautilcollections/AndroidTest.xml b/tests/libcore/javautilcollections/AndroidTest.xml
deleted file mode 100644
index 7ea7634..0000000
--- a/tests/libcore/javautilcollections/AndroidTest.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-<configuration description="Config for CTS Libcore java.util Collection test cases">
-    <option name="test-suite-tag" value="cts" />
-    <option name="not-shardable" value="true" />
-    <option name="config-descriptor:metadata" key="component" value="libcore" />
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsLibcoreJavaUtilCollectionsTestCases.apk" />
-    </target_preparer>
-    <!--
-    Notes as of November 2016:
-
-    1.) When the runner collects the set of tests to run, it
-    (a) attempts to directly run TestCase subclasses from guava-testlib, which they don't support,
-    (b) doesn't find classes with suite() methods.
-    (c) runs out of memory if attempting to run all of the > 220k tests in a single go
-    Breaking the tests down into chunks of ~ 40-50k tests each, and explicitly specifying the
-    suites to run, solves these problems.
-
-    2.) Due to http://b/33068110 the classes with the suite() methods (in the "suite" sub-package)
-    need to extend TestSuite, which means that they need to delegate to separate classes (in the
-     "tests" sub-package) that extend classes from guava-testlib.
-    -->
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="libcore.java.util.collectiontests" />
-        <option name="class" value="libcore.java.util.suite.ConcurrentSkipListMapNaturalSuite" />
-        <option name="runtime-hint" value="10m" />
-        <option name="test-timeout" value="1200000" />
-        <option name="shell-timeout" value="1400000" />
-    </test>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="libcore.java.util.collectiontests" />
-        <option name="class" value="libcore.java.util.suite.ConcurrentSkipListMapWithComparatorSuite" />
-        <option name="runtime-hint" value="10m" />
-        <option name="test-timeout" value="1200000" />
-        <option name="shell-timeout" value="1400000" />
-    </test>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="libcore.java.util.collectiontests" />
-        <option name="class" value="libcore.java.util.suite.TreeMapNaturalSuite" />
-        <option name="runtime-hint" value="10m" />
-        <option name="test-timeout" value="1200000" />
-        <option name="shell-timeout" value="1400000" />
-    </test>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="libcore.java.util.collectiontests" />
-        <option name="class" value="libcore.java.util.suite.TreeMapWithComparatorSuite" />
-        <option name="runtime-hint" value="10m" />
-        <option name="test-timeout" value="1200000" />
-        <option name="shell-timeout" value="1400000" />
-    </test>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="libcore.java.util.collectiontests" />
-        <option name="class" value="libcore.java.util.suite.OtherCollectionsSuite" />
-        <option name="runtime-hint" value="8m" />
-        <option name="test-timeout" value="1200000" />
-        <option name="shell-timeout" value="1400000" />
-    </test>
-</configuration>
diff --git a/tests/libcore/javautilcollections/libs/guava-20.0.jar b/tests/libcore/javautilcollections/libs/guava-20.0.jar
deleted file mode 100644
index 632772f..0000000
--- a/tests/libcore/javautilcollections/libs/guava-20.0.jar
+++ /dev/null
Binary files differ
diff --git a/tests/libcore/javautilcollections/libs/guava-testlib-20.0.jar b/tests/libcore/javautilcollections/libs/guava-testlib-20.0.jar
deleted file mode 100644
index 6dd8d90..0000000
--- a/tests/libcore/javautilcollections/libs/guava-testlib-20.0.jar
+++ /dev/null
Binary files differ
diff --git a/tests/libcore/javautilcollections/src/libcore/java/util/suite/ConcurrentSkipListMapNaturalSuite.java b/tests/libcore/javautilcollections/src/libcore/java/util/suite/ConcurrentSkipListMapNaturalSuite.java
deleted file mode 100644
index 332190b..0000000
--- a/tests/libcore/javautilcollections/src/libcore/java/util/suite/ConcurrentSkipListMapNaturalSuite.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2016 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 libcore.java.util.suite;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil;
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil.MapsToTest;
-
-public class ConcurrentSkipListMapNaturalSuite extends TestSuite {
-    public static Test suite() {
-        return new AndroidTestsForMapsInJavaUtil(MapsToTest.CONCURRENT_SKIP_LIST_MAP_NATURAL)
-                .allTests();
-    }
-}
diff --git a/tests/libcore/javautilcollections/src/libcore/java/util/suite/ConcurrentSkipListMapWithComparatorSuite.java b/tests/libcore/javautilcollections/src/libcore/java/util/suite/ConcurrentSkipListMapWithComparatorSuite.java
deleted file mode 100644
index 878e721..0000000
--- a/tests/libcore/javautilcollections/src/libcore/java/util/suite/ConcurrentSkipListMapWithComparatorSuite.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2016 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 libcore.java.util.suite;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil;
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil.MapsToTest;
-
-public class ConcurrentSkipListMapWithComparatorSuite extends TestSuite {
-    public static Test suite() {
-        return new AndroidTestsForMapsInJavaUtil(
-                MapsToTest.CONCURRENT_SKIP_LIST_MAP_WITH_COMPARATOR).allTests();
-    }
-
-}
diff --git a/tests/libcore/javautilcollections/src/libcore/java/util/suite/OtherCollectionsSuite.java b/tests/libcore/javautilcollections/src/libcore/java/util/suite/OtherCollectionsSuite.java
deleted file mode 100644
index 6af45f4..0000000
--- a/tests/libcore/javautilcollections/src/libcore/java/util/suite/OtherCollectionsSuite.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2016 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 libcore.java.util.suite;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import libcore.java.util.tests.AndroidTestsForListsInJavaUtil;
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil;
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil.MapsToTest;
-import libcore.java.util.tests.AndroidTestsForQueuesInJavaUtil;
-import libcore.java.util.tests.AndroidTestsForSetsInJavaUtil;
-
-/**
- * A suite of all guava-testlib Collection tests not covered by the other suites in this
- * package.
- */
-public class OtherCollectionsSuite extends TestSuite {
-    public static Test suite() {
-        TestSuite result = new TestSuite();
-        result.addTest(new AndroidTestsForListsInJavaUtil().allTests());
-        result.addTest(new AndroidTestsForMapsInJavaUtil(MapsToTest.OTHER).allTests());
-        result.addTest(new AndroidTestsForQueuesInJavaUtil().allTests());
-        result.addTest(new AndroidTestsForSetsInJavaUtil().allTests());
-        return result;
-    }
-}
diff --git a/tests/libcore/javautilcollections/src/libcore/java/util/suite/TreeMapNaturalSuite.java b/tests/libcore/javautilcollections/src/libcore/java/util/suite/TreeMapNaturalSuite.java
deleted file mode 100644
index 68a7624..0000000
--- a/tests/libcore/javautilcollections/src/libcore/java/util/suite/TreeMapNaturalSuite.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2016 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 libcore.java.util.suite;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil;
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil.MapsToTest;
-
-public class TreeMapNaturalSuite extends TestSuite {
-    public static Test suite() {
-        return new AndroidTestsForMapsInJavaUtil(MapsToTest.TREE_MAP_NATURAL).allTests();
-    }
-}
diff --git a/tests/libcore/javautilcollections/src/libcore/java/util/suite/TreeMapWithComparatorSuite.java b/tests/libcore/javautilcollections/src/libcore/java/util/suite/TreeMapWithComparatorSuite.java
deleted file mode 100644
index 6e6fd6f..0000000
--- a/tests/libcore/javautilcollections/src/libcore/java/util/suite/TreeMapWithComparatorSuite.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2016 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 libcore.java.util.suite;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil;
-import libcore.java.util.tests.AndroidTestsForMapsInJavaUtil.MapsToTest;
-
-public class TreeMapWithComparatorSuite extends TestSuite {
-    public static Test suite() {
-        return new AndroidTestsForMapsInJavaUtil(MapsToTest.TREE_MAP_WITH_COMPARATOR).allTests();
-    }
-}
diff --git a/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForListsInJavaUtil.java b/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForListsInJavaUtil.java
deleted file mode 100644
index 8d9177c..0000000
--- a/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForListsInJavaUtil.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 libcore.java.util.tests;
-
-import com.google.common.collect.testing.TestsForListsInJavaUtil;
-import com.google.common.collect.testing.testers.CollectionToArrayTester;
-
-import junit.framework.Test;
-
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * Guava-testlib tests for {@code List} implementations from {@code java.util}.
- */
-public class AndroidTestsForListsInJavaUtil extends TestsForListsInJavaUtil {
-    @Override
-    protected Collection<Method> suppressForArraysAsList() {
-        return Collections.singleton(
-                // http://b/30829421
-                CollectionToArrayTester.getToArrayIsPlainObjectArrayMethod());
-    }
-}
diff --git a/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForMapsInJavaUtil.java b/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForMapsInJavaUtil.java
deleted file mode 100644
index 11f0afe..0000000
--- a/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForMapsInJavaUtil.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2016 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 libcore.java.util.tests;
-
-import com.google.common.collect.testing.TestsForMapsInJavaUtil;
-import com.google.common.collect.testing.testers.CollectionAddAllTester;
-import com.google.common.collect.testing.testers.CollectionAddTester;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Objects;
-
-/**
- * Guava-testlib tests for {@link MapsToTest} that were specified as a
- * constructor argument.
- */
-public class AndroidTestsForMapsInJavaUtil extends TestsForMapsInJavaUtil {
-    public enum MapsToTest {
-        /** All Maps other than those below. */
-        OTHER,
-        /** TreeMao with natural ordering. */
-        TREE_MAP_NATURAL,
-        /** TreeMap with a Comparator. */
-        TREE_MAP_WITH_COMPARATOR,
-        /** ConcurrentSKipListMap with natural ordering. */
-        CONCURRENT_SKIP_LIST_MAP_NATURAL,
-        /** ConcurrentSKipListMap with a Comparator. */
-        CONCURRENT_SKIP_LIST_MAP_WITH_COMPARATOR
-    }
-
-    private final MapsToTest mapsToTest;
-
-    public AndroidTestsForMapsInJavaUtil(MapsToTest mapsToTest) {
-        this.mapsToTest = Objects.requireNonNull(mapsToTest);
-    }
-
-    /**
-     * Returns the tests for the {@link MapsToTest} from {@code java.util}.
-     */
-    @Override
-    public final Test allTests() {
-        TestSuite suite = new TestSuite("java.util Maps: " + mapsToTest);
-        switch (mapsToTest) {
-            case OTHER:
-                suite.addTest(testsForCheckedMap());
-                suite.addTest(testsForCheckedSortedMap());
-                suite.addTest(testsForEmptyMap());
-                suite.addTest(testsForSingletonMap());
-                suite.addTest(testsForHashMap());
-                suite.addTest(testsForLinkedHashMap());
-                suite.addTest(testsForEnumMap());
-                suite.addTest(testsForConcurrentHashMap());
-                break;
-            case TREE_MAP_NATURAL:
-                suite.addTest(testsForTreeMapNatural());
-                break;
-            case TREE_MAP_WITH_COMPARATOR:
-                suite.addTest(testsForTreeMapWithComparator());
-                break;
-            case CONCURRENT_SKIP_LIST_MAP_NATURAL:
-                suite.addTest(testsForConcurrentSkipListMapNatural());
-                break;
-            case CONCURRENT_SKIP_LIST_MAP_WITH_COMPARATOR:
-                suite.addTest(testsForConcurrentSkipListMapWithComparator());
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown part: " + mapsToTest);
-        }
-        return suite;
-    }
-
-    @Override
-    protected final Collection<Method> suppressForConcurrentHashMap() {
-        // http://b/30853241
-        return Arrays.asList(
-                CollectionAddAllTester.getAddAllUnsupportedNonePresentMethod(),
-                CollectionAddAllTester.getAddAllUnsupportedSomePresentMethod(),
-                CollectionAddTester.getAddUnsupportedNotPresentMethod());
-    }
-}
diff --git a/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForQueuesInJavaUtil.java b/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForQueuesInJavaUtil.java
deleted file mode 100644
index 52f0eb3..0000000
--- a/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForQueuesInJavaUtil.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2016 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 libcore.java.util.tests;
-
-import com.google.common.collect.testing.MinimalCollection;
-import com.google.common.collect.testing.QueueTestSuiteBuilder;
-import com.google.common.collect.testing.TestStringQueueGenerator;
-import com.google.common.collect.testing.TestsForListsInJavaUtil;
-import com.google.common.collect.testing.TestsForQueuesInJavaUtil;
-import com.google.common.collect.testing.features.CollectionFeature;
-import com.google.common.collect.testing.features.CollectionSize;
-
-import java.util.LinkedList;
-import java.util.Queue;
-import junit.framework.Test;
-
-/**
- * Guava-testlib tests for {@code Queue} implementations from {@code java.util}.
- */
-public class AndroidTestsForQueuesInJavaUtil extends TestsForQueuesInJavaUtil {
-
-    /**
-     * Override and copy the super class's implementation in order to change the name to ensure
-     * that created tests are unique and do not clash with those created by
-     * {@link TestsForListsInJavaUtil#testsForLinkedList()}, see bug 62438629.
-     */
-    @Override
-    public Test testsForLinkedList() {
-        return QueueTestSuiteBuilder.using(
-                new TestStringQueueGenerator() {
-                    @Override
-                    public Queue<String> create(String[] elements) {
-                        return new LinkedList<String>(MinimalCollection.of(elements));
-                    }
-                })
-                .named("LinkedList as Queue")
-                .withFeatures(
-                        CollectionFeature.GENERAL_PURPOSE,
-                        CollectionFeature.ALLOWS_NULL_VALUES,
-                        CollectionFeature.KNOWN_ORDER,
-                        CollectionSize.ANY)
-                .skipCollectionTests() // already covered in TestsForListsInJavaUtil
-                .suppressing(suppressForLinkedList())
-                .createTestSuite();
-    }
-}
diff --git a/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForSetsInJavaUtil.java b/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForSetsInJavaUtil.java
deleted file mode 100644
index c4e41f4..0000000
--- a/tests/libcore/javautilcollections/src/libcore/java/util/tests/AndroidTestsForSetsInJavaUtil.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2016 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 libcore.java.util.tests;
-
-import com.google.common.collect.testing.TestsForSetsInJavaUtil;
-
-import junit.framework.Test;
-
-/**
- * Guava-testlib tests for {@code Set} implementations from {@code java.util}.
- */
-public class AndroidTestsForSetsInJavaUtil extends TestsForSetsInJavaUtil {
-}
diff --git a/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml b/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml
index a18f87a..672deb0 100644
--- a/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml
+++ b/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml
@@ -17,12 +17,12 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.netsecpolicy.usescleartext.false.cts">
+          package="android.netsecpolicy.usescleartext_false.cts">
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-    <uses-library android:name="org.apache.http.legacy"/>
 
     <application android:usesCleartextTraffic="false">
+        <uses-library android:name="org.apache.http.legacy"/>
     </application>
 </manifest>
diff --git a/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml b/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml
index d4b7d5b..29a550b 100644
--- a/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml
+++ b/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml
@@ -17,12 +17,12 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.netsecpolicy.usescleartext.true.cts">
+          package="android.netsecpolicy.usescleartext_true.cts">
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-    <uses-library android:name="org.apache.http.legacy"/>
 
     <application android:usesCleartextTraffic="true">
+        <uses-library android:name="org.apache.http.legacy"/>
     </application>
 </manifest>
diff --git a/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml b/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml
index 07731b9..d574488 100644
--- a/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml
+++ b/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml
@@ -17,12 +17,12 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.netsecpolicy.usescleartext.unspecified.cts">
+          package="android.netsecpolicy.usescleartext_unspecified.cts">
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-    <uses-library android:name="org.apache.http.legacy"/>
 
     <application>
+        <uses-library android:name="org.apache.http.legacy"/>
     </application>
 </manifest>
diff --git a/tests/signature/api/Android.mk b/tests/signature/api/Android.mk
index b257c5e..3924744 100644
--- a/tests/signature/api/Android.mk
+++ b/tests/signature/api/Android.mk
@@ -44,7 +44,7 @@
 $(eval $(call build_xml_api_file,android-test-runner-current.api,frameworks/base/test-runner/api/android-test-runner-current.txt))
 $(foreach ver,$(PLATFORM_SYSTEMSDK_VERSIONS),\
   $(if $(call math_is_number,$(ver)),\
-    $(eval $(call build_xml_api_file,system-$(ver).api,prebuilts/sdk/system-api/$(ver).txt))\
+    $(eval $(call build_xml_api_file,system-$(ver).api,prebuilts/sdk/$(ver)/system/api/android.txt))\
   )\
 )
 
diff --git a/tests/tests/carrierapi/Android.mk b/tests/tests/carrierapi/Android.mk
index 3386907..2215b88 100644
--- a/tests/tests/carrierapi/Android.mk
+++ b/tests/tests/carrierapi/Android.mk
@@ -44,4 +44,10 @@
 # environment.
 LOCAL_CERTIFICATE := build/make/target/product/security/testkey
 
+# This APK must be signed to match the test SIM's cert whitelist.
+# While "testkey" is the default, there are different per-device testkeys, so
+# hard-code the AOSP default key to ensure it is used regardless of build
+# environment.
+LOCAL_CERTIFICATE := build/make/target/product/security/testkey
+
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml b/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml
index d4ce39a..89ce66a 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidManifest.xml
@@ -17,7 +17,7 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.netsecpolicy.usescleartext.false">
+        package="com.android.cts.netsecpolicy.usescleartext_false">
 
   <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
   <application>
@@ -26,7 +26,7 @@
   </application>
 
   <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                   android:targetPackage="android.netsecpolicy.usescleartext.false.cts"
+                   android:targetPackage="android.netsecpolicy.usescleartext_false.cts"
                    android:label="Tests for NetworkSecurityPolicy cleartext traffic policy when it is set to denied.">
         <meta-data android:name="listener"
             android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidTest.xml b/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidTest.xml
index 2b91cea..3979b65 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidTest.xml
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidTest.xml
@@ -22,7 +22,7 @@
         <option name="test-file-name" value="CtsNetSecPolicyUsesCleartextTrafficFalseTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.cts.netsecpolicy.usescleartext.false" />
+        <option name="package" value="com.android.cts.netsecpolicy.usescleartext_false" />
         <option name="runtime-hint" value="12m" />
     </test>
 </configuration>
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml b/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml
index fe31e80..e2e9a5d 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidManifest.xml
@@ -17,7 +17,7 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.netsecpolicy.usescleartext.true">
+        package="com.android.cts.netsecpolicy.usescleartext_true">
 
   <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
   <application>
@@ -26,7 +26,7 @@
   </application>
 
   <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                   android:targetPackage="android.netsecpolicy.usescleartext.true.cts"
+                   android:targetPackage="android.netsecpolicy.usescleartext_true.cts"
                    android:label="Tests for NetworkSecurityPolicy cleartext traffic policy when it is set to permitted.">
         <meta-data android:name="listener"
             android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidTest.xml b/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidTest.xml
index c025dad..43c31d7 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidTest.xml
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidTest.xml
@@ -22,7 +22,7 @@
         <option name="test-file-name" value="CtsNetSecPolicyUsesCleartextTrafficTrueTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.cts.netsecpolicy.usescleartext.true" />
+        <option name="package" value="com.android.cts.netsecpolicy.usescleartext_true" />
         <option name="runtime-hint" value="8m" />
     </test>
 </configuration>
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml
index c6b65c0..6ec5bac 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidManifest.xml
@@ -17,7 +17,7 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.netsecpolicy.usescleartext.unspecified">
+        package="com.android.cts.netsecpolicy.usescleartext_unspecified">
 
   <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
   <application>
@@ -26,7 +26,7 @@
   </application>
 
   <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                   android:targetPackage="android.netsecpolicy.usescleartext.unspecified.cts"
+                   android:targetPackage="android.netsecpolicy.usescleartext_unspecified.cts"
                    android:label="Tests for NetworkSecurityPolicy cleartext traffic policy when it is not specified.">
         <meta-data android:name="listener"
             android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidTest.xml b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidTest.xml
index ae25db7..0eb3788 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidTest.xml
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidTest.xml
@@ -22,7 +22,7 @@
         <option name="test-file-name" value="CtsNetSecPolicyUsesCleartextTrafficUnspecifiedTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.cts.netsecpolicy.usescleartext.unspecified" />
+        <option name="package" value="com.android.cts.netsecpolicy.usescleartext_unspecified" />
         <option name="runtime-hint" value="8m" />
     </test>
 </configuration>
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index 9cd0b87..7cc67ae 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -56,6 +56,11 @@
 # Do not compress minijail policy files.
 LOCAL_AAPT_FLAGS := -0 .policy
 
+# Disable AAPT2 to fix:
+# cts/tests/tests/os/AndroidManifest.xml:25: error: unexpected element <meta-data> found in <manifest><permission>.
+# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
+LOCAL_USE_AAPT2 := false
+
 include $(BUILD_CTS_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/os/assets/platform_versions.txt b/tests/tests/os/assets/platform_versions.txt
index f11c82a..73c52c3 100644
--- a/tests/tests/os/assets/platform_versions.txt
+++ b/tests/tests/os/assets/platform_versions.txt
@@ -1 +1 @@
-9
\ No newline at end of file
+Q
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index dc868fc..a316e24 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -421,6 +421,16 @@
     }
 
     @Test
+    public void testExplicitGc() throws Exception {
+        StrictMode.setThreadPolicy(
+                new StrictMode.ThreadPolicy.Builder().detectExplicitGc().penaltyLog().build());
+
+        inspectViolation(
+                () -> { Runtime.getRuntime().gc(); },
+                violation -> assertPolicy(violation, StrictMode.DETECT_EXPLICIT_GC));
+    }
+
+    @Test
     public void testViolationAcrossBinder() throws Exception {
         runWithRemoteServiceBound(
                 getContext(),
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index a5faa42..72aff71 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -83,9 +83,9 @@
 
     private static final Set<String> WHITELISTED_PACKAGES = new HashSet<String>(Arrays.asList(
             // APKS are installed before beigning test
-            "android.netsecpolicy.usescleartext.false.cts",
-            "android.netsecpolicy.usescleartext.unspecified.cts",
-            "android.netsecpolicy.usescleartext.true.cts",
+            "android.netsecpolicy.usescleartext_false.cts",
+            "android.netsecpolicy.usescleartext_unspecified.cts",
+            "android.netsecpolicy.usescleartext_true.cts",
 
             // The accessibility APK required to be installed while running CTS
             "android.accessibilityservice.delegate",
diff --git a/tests/tests/view/res/values/styles.xml b/tests/tests/view/res/values/styles.xml
index 17bc2a3..5e47363 100644
--- a/tests/tests/view/res/values/styles.xml
+++ b/tests/tests/view/res/values/styles.xml
@@ -125,8 +125,8 @@
 
     <style name="TestProgressBar">
         <item name="android:indeterminateOnly">false</item>
-        <item name="android:progressDrawable">?android:drawable/progress_horizontal</item>
-        <item name="android:indeterminateDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:progressDrawable">@android:drawable/progress_horizontal</item>
+        <item name="android:indeterminateDrawable">@android:drawable/progress_horizontal</item>
         <item name="android:minHeight">20dip</item>
         <item name="android:maxHeight">20dip</item>
         <item name="android:focusable">true</item>
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
index 08e96fe..8e324c9 100644
--- a/tests/tests/widget/res/values/styles.xml
+++ b/tests/tests/widget/res/values/styles.xml
@@ -297,8 +297,8 @@
 
     <style name="TestProgressBar">
         <item name="android:indeterminateOnly">false</item>
-        <item name="android:progressDrawable">?android:drawable/progress_horizontal</item>
-        <item name="android:indeterminateDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:progressDrawable">@android:drawable/progress_horizontal</item>
+        <item name="android:indeterminateDrawable">@android:drawable/progress_horizontal</item>
         <item name="android:minHeight">20dip</item>
         <item name="android:maxHeight">20dip</item>
         <item name="android:focusable">true</item>
diff --git a/tools/cfassembler/Android.bp b/tools/cfassembler/Android.bp
new file mode 100644
index 0000000..a5431d1
--- /dev/null
+++ b/tools/cfassembler/Android.bp
@@ -0,0 +1,23 @@
+// 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.
+
+java_binary_host {
+  name: "cfassembler",
+  srcs: [
+    "src/dxconvext/ClassFileAssembler.java",
+    "src/dxconvext/util/FileUtils.java",
+  ],
+  manifest: "etc/cfassembler_manifest.txt",
+  wrapper: "etc/cfassembler",
+}
diff --git a/tools/cfassembler/Android.mk b/tools/cfassembler/Android.mk
deleted file mode 100644
index df736ed..0000000
--- a/tools/cfassembler/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# cfassembler host module
-#============================================================
-
-include $(CLEAR_VARS)
-
-LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE := cfassembler
-LOCAL_SRC_FILES := etc/cfassembler
-LOCAL_ADDITIONAL_DEPENDENCIES := $(HOST_OUT_JAVA_LIBRARIES)/cfassembler$(COMMON_JAVA_PACKAGE_SUFFIX)
-include $(BUILD_PREBUILT)
-
-INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)
-
-# cfassembler java library
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := src/dxconvext/ClassFileAssembler.java src/dxconvext/util/FileUtils.java
-LOCAL_JAR_MANIFEST := etc/cfassembler_manifest.txt
-
-LOCAL_MODULE:= cfassembler
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)
diff --git a/tools/dasm/Android.bp b/tools/dasm/Android.bp
new file mode 100644
index 0000000..c9bddd1
--- /dev/null
+++ b/tools/dasm/Android.bp
@@ -0,0 +1,25 @@
+//
+// 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.
+//
+
+java_binary_host {
+  name: "dasm",
+  srcs: [ "src/**/*.java" ],
+  static_libs: [
+    "dx",
+  ],
+  manifest: "etc/manifest.txt",
+  wrapper: "etc/dasm",
+}
diff --git a/tools/dasm/Android.mk b/tools/dasm/Android.mk
deleted file mode 100644
index 1b1f328..0000000
--- a/tools/dasm/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# 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.
-#
-LOCAL_PATH := $(call my-dir)
-
-# dasm (dalvik assembler) java library
-# ============================================================
-
-include $(CLEAR_VARS)
-LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE := dasm
-LOCAL_SRC_FILES := etc/dasm
-LOCAL_ADDITIONAL_DEPENDENCIES := $(HOST_OUT_JAVA_LIBRARIES)/dasm$(COMMON_JAVA_PACKAGE_SUFFIX)
-include $(BUILD_PREBUILT)
-
-INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)
-
-include $(LOCAL_PATH)/src/Android.mk
diff --git a/tools/dasm/src/Android.mk b/tools/dasm/src/Android.mk
deleted file mode 100644
index df6108a..0000000
--- a/tools/dasm/src/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# 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.
-#
-LOCAL_PATH := $(call my-dir)
-
-
-# dasm (dalvik assembler) java library
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_JAR_MANIFEST := ../etc/manifest.txt
-LOCAL_JAVA_LIBRARIES := dx
-
-LOCAL_MODULE:= dasm
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)
-
diff --git a/tools/vm-tests-tf/Android.bp b/tools/vm-tests-tf/Android.bp
new file mode 100644
index 0000000..be10c05
--- /dev/null
+++ b/tools/vm-tests-tf/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2018 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.
+
+java_library_host {
+    name: "host-cts-vmtests-dot",
+    libs: [ "junit" ],
+    srcs: [ "src/dot/**/*.java" ],
+    include_srcs: true,
+}
+
+java_binary_host {
+    name: "vmtests-buildutil",
+    static_libs: [ "host-cts-vmtests-dot", "junit" ],
+    srcs: [
+        "src/util/build/BuildCTSHostSources.java",
+        "src/util/build/BuildUtilBase.java",
+        "src/util/build/FileUtil.java",
+        "src/util/build/JUnitTestCollector.java",
+    ],
+    wrapper: "etc/vmtests-buildutil.sh",
+}
+
+genrule {
+    name: "vmtests_generated_host_test_sources",
+    tools: [
+        "vmtests-buildutil",
+        "soong_zip",
+    ],
+    cmd: "$(location vmtests-buildutil) util.build.BuildCTSHostSources $(genDir) " +
+         " && $(location soong_zip) -jar -o $(out) -C $(genDir) -D $(genDir)/dot",
+    out: ["vmtests.host.generated.srcjar"],
+}
diff --git a/tools/vm-tests-tf/Android.mk b/tools/vm-tests-tf/Android.mk
index ea4f09b..cc8d76b 100644
--- a/tools/vm-tests-tf/Android.mk
+++ b/tools/vm-tests-tf/Android.mk
@@ -72,7 +72,8 @@
 vmteststf_dep_jars := \
     $(HOST_JDK_TOOLS_JAR) \
     $(cts-tf-dalvik-lib.jar) \
-    $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/, cts-tf-dalvik-buildutil.jar dasm.jar dx.jar cfassembler.jar junit-host.jar d8.jar)
+    $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/, cts-tf-dalvik-buildutil.jar dasm.jar dx.jar cfassembler.jar junit-host.jar d8.jar) \
+    $(call intermediates-dir-for,JAVA_LIBRARIES,host-cts-vmtests-dot,HOST)/javalib.jar
 
 $(LOCAL_BUILT_MODULE): PRIVATE_SRC_FOLDER := $(LOCAL_PATH)/src
 $(LOCAL_BUILT_MODULE): PRIVATE_INTERMEDIATES_CLASSES := $(call intermediates-dir-for,JAVA_LIBRARIES,cts-tf-dalvik-buildutil,HOST)/classes
diff --git a/tools/vm-tests-tf/etc/vmtests-buildutil.sh b/tools/vm-tests-tf/etc/vmtests-buildutil.sh
new file mode 100755
index 0000000..759c5c2
--- /dev/null
+++ b/tools/vm-tests-tf/etc/vmtests-buildutil.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+#
+# Copyright (C) 2018 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.
+#
+# Execute the vmtests-buildutil program
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+jarfile=vmtests-buildutil.jar
+libdir="$progdir"
+
+if [ ! -r "$libdir/$jarfile" ]; then
+    # set vmtests-buildutil.jar location for the Android tree case
+    libdir=`dirname "$progdir"`/framework
+fi
+
+if [ ! -r "$libdir/$jarfile" ]; then
+    echo `basename "$prog"`": can't find $jarfile"
+    exit 1
+fi
+
+# By default, give vmtests-buildutil a max heap size of 1 gig. This can be overridden
+# by using a "-J" option (see below).
+defaultMx="-Xmx1024M"
+
+# The following will extract any initial parameters of the form "-J<stuff>" from
+# the command line and pass them to the Java invocation (instead of to vmtests-buildutil).
+# This makes it possible for you to add a command-line parameter such as
+# "-JXmx256M" in your scripts, for example. "java" (with no args) and "java -X"
+# give a summary of available options.
+
+javaOpts=""
+
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "x$1" : 'x-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    if expr "x${opt}" : "xXmx[0-9]" >/dev/null; then
+        defaultMx="no"
+    fi
+    shift
+done
+
+if [ "${defaultMx}" != "no" ]; then
+    javaOpts="${javaOpts} ${defaultMx}"
+fi
+
+if [ "$OSTYPE" = "cygwin" ]; then
+    # For Cygwin, convert the jarfile path into native Windows style.
+    jarpath=`cygpath -w "$libdir/$jarfile"`
+else
+    jarpath="$libdir/$jarfile"
+fi
+
+exec java $javaOpts -cp "$jarpath" "$@"
diff --git a/tools/vm-tests-tf/src/util/build/BuildCTSHostSources.java b/tools/vm-tests-tf/src/util/build/BuildCTSHostSources.java
new file mode 100644
index 0000000..3038394
--- /dev/null
+++ b/tools/vm-tests-tf/src/util/build/BuildCTSHostSources.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2011 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 util.build;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Main class to generate data from the test suite to later run from a shell
+ * script. the project's home folder.<br>
+ * <project-home>/src must contain the java sources<br>
+ * <project-home>/src/<for-each-package>/Main_testN1.java will be generated<br>
+ * (one Main class for each test method in the Test_... class
+ */
+public class BuildCTSHostSources extends BuildUtilBase {
+
+    public static final String TARGET_MAIN_FILE = "mains.jar";
+
+    // the folder for the generated junit-files for the cts host (which in turn
+    // execute the real vm tests using adb push/shell etc)
+    private static String HOSTJUNIT_SRC_OUTPUT_FOLDER = "";
+
+    private static final String TARGET_JAR_ROOT_PATH = "/data/local/tmp/vm-tests";
+
+    /**
+     * @param args
+     *            args 0 must be the project root folder (where src, lib etc.
+     *            resides)
+     * @throws IOException
+     */
+    public static void main(String[] args) throws IOException {
+        BuildCTSHostSources cat = new BuildCTSHostSources();
+
+        if (!cat.parseArgs(args)) {
+          printUsage();
+          System.exit(-1);
+        }
+
+        long start = System.currentTimeMillis();
+        cat.run(cat::handleTest);
+        long end = System.currentTimeMillis();
+
+        System.out.println("elapsed seconds: " + (end - start) / 1000);
+    }
+
+    private boolean parseArgs(String[] args) {
+      if (args.length == 1) {
+          HOSTJUNIT_SRC_OUTPUT_FOLDER = args[0];
+          return true;
+      } else {
+          return false;
+      }
+    }
+
+    private static void printUsage() {
+        System.out.println("usage: java-src-folder output-folder classpath " +
+                           "generated-main-files compiled_output generated-main-files " +
+                           "[restrict-to-opcode]");
+    }
+
+    private static class HostState {
+        private String fileName;
+        private StringBuilder fileData;
+
+        public HostState(String fileName) {
+            this.fileName = fileName;
+            fileData = new StringBuilder();
+        }
+
+        public void append(String s) {
+            fileData.append(s);
+        }
+
+        private void addCTSHostMethod(String pName, String method,
+                Collection<String> dependentTestClassNames) {
+            fileData.append("public void " + method + "() throws Exception {\n");
+            final String targetCoreJarPath = String.format("%s/dot/junit/dexcore.jar",
+                    TARGET_JAR_ROOT_PATH);
+
+            String mainsJar = String.format("%s/%s", TARGET_JAR_ROOT_PATH, TARGET_MAIN_FILE);
+
+            String cp = String.format("%s:%s", targetCoreJarPath, mainsJar);
+            for (String depFqcn : dependentTestClassNames) {
+                String sourceName = depFqcn.replaceAll("\\.", "/") + ".jar";
+                String targetName= String.format("%s/%s", TARGET_JAR_ROOT_PATH,
+                        sourceName);
+                cp += ":" + targetName;
+                // dot.junit.opcodes.invoke_interface_range.ITest
+                // -> dot/junit/opcodes/invoke_interface_range/ITest.jar
+            }
+
+            //"dot.junit.opcodes.add_double_2addr.Main_testN2";
+            String mainclass = pName + ".Main_" + method;
+            fileData.append(getShellExecJavaLine(cp, mainclass));
+            fileData.append("\n}\n\n");
+        }
+
+        public void end() {
+            fileData.append("\n}\n");
+        }
+
+        public File getFileToWrite() {
+            return new File(fileName);
+        }
+        public String getData() {
+            return fileData.toString();
+        }
+    }
+
+    private void flushHostState(HostState state) {
+        state.end();
+
+        File toWrite = state.getFileToWrite();
+        writeToFileMkdir(toWrite, state.getData());
+    }
+
+    private HostState openCTSHostFileFor(String pName, String classOnlyName) {
+        String sourceName = classOnlyName;
+
+        String modPackage = pName;
+        {
+            // Given a class name of "Test_zzz" and a package of "xxx.yyy.zzz," strip
+            // "zzz" from the package to reduce duplication (and dashboard clutter).
+            int lastDot = modPackage.lastIndexOf('.');
+            if (lastDot > 0) {
+                String lastPackageComponent = modPackage.substring(lastDot + 1);
+                if (classOnlyName.equals("Test_" + lastPackageComponent)) {
+                    // Drop the duplication.
+                    modPackage = modPackage.substring(0, lastDot);
+                }
+            }
+        }
+
+        String fileName = HOSTJUNIT_SRC_OUTPUT_FOLDER + "/" + modPackage.replaceAll("\\.", "/")
+                + "/" + sourceName + ".java";
+
+        HostState newState = new HostState(fileName);
+
+        newState.append(getWarningMessage());
+        newState.append("package " + modPackage + ";\n");
+        newState.append("import java.io.IOException;\n" +
+                "import java.util.concurrent.TimeUnit;\n\n" +
+                "import com.android.tradefed.device.CollectingOutputReceiver;\n" +
+                "import com.android.tradefed.testtype.IAbi;\n" +
+                "import com.android.tradefed.testtype.IAbiReceiver;\n" +
+                "import com.android.tradefed.testtype.DeviceTestCase;\n" +
+                "import com.android.tradefed.util.AbiFormatter;\n" +
+                "\n");
+        newState.append("public class " + sourceName + " extends DeviceTestCase implements " +
+                "IAbiReceiver {\n");
+
+        newState.append("\n" +
+                "protected IAbi mAbi;\n" +
+                "@Override\n" +
+                "public void setAbi(IAbi abi) {\n" +
+                "    mAbi = abi;\n" +
+                "}\n\n");
+
+        return newState;
+    }
+
+    private static String getShellExecJavaLine(String classpath, String mainclass) {
+      String cmd = String.format("ANDROID_DATA=%s dalvikvm|#ABI#| -Xmx512M -Xss32K -Xnodex2oat " +
+              "-Djava.io.tmpdir=%s -classpath %s %s", TARGET_JAR_ROOT_PATH, TARGET_JAR_ROOT_PATH,
+              classpath, mainclass);
+      StringBuilder code = new StringBuilder();
+      code.append("    String cmd = AbiFormatter.formatCmdForAbi(\"")
+          .append(cmd)
+          .append("\", mAbi.getBitness());\n")
+          .append("    CollectingOutputReceiver receiver = new CollectingOutputReceiver();\n")
+          .append("    getDevice().executeShellCommand(cmd, receiver, 6, TimeUnit.MINUTES, 1);\n")
+          .append("    // A sucessful adb shell command returns an empty string.\n")
+          .append("    assertEquals(cmd, \"\", receiver.getOutput());");
+      return code.toString();
+    }
+
+    private String getWarningMessage() {
+        return "//Autogenerated code by " + this.getClass().getName() + "; do not edit.\n";
+    }
+
+    private void handleTest(String fqcn, List<String> methods) {
+        int lastDotPos = fqcn.lastIndexOf('.');
+        String pName = fqcn.substring(0, lastDotPos);
+        String classOnlyName = fqcn.substring(lastDotPos + 1);
+
+        HostState hostState = openCTSHostFileFor(pName, classOnlyName);
+
+        Collections.sort(methods, new Comparator<String>() {
+            @Override
+            public int compare(String s1, String s2) {
+                // TODO sort according: test ... N, B, E, VFE
+                return s1.compareTo(s2);
+            }
+        });
+        for (String method : methods) {
+            // e.g. testN1
+            if (!method.startsWith("test")) {
+                throw new RuntimeException("no test method: " + method);
+            }
+
+            // generate the Main_xx java class
+
+            // a Main_testXXX.java contains:
+            // package <packagenamehere>;
+            // public class Main_testxxx {
+            // public static void main(String[] args) {
+            // new dxc.junit.opcodes.aaload.Test_aaload().testN1();
+            // }
+            // }
+            MethodData md = parseTestMethod(pName, classOnlyName, method);
+            String methodContent = md.methodBody;
+
+            List<String> dependentTestClassNames = parseTestClassName(pName,
+                    classOnlyName, methodContent);
+
+            hostState.addCTSHostMethod(pName, method, dependentTestClassNames);
+        }
+
+        flushHostState(hostState);
+    }
+}
diff --git a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
index e223289..7b510ce 100644
--- a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
+++ b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
@@ -16,38 +16,14 @@
 
 package util.build;
 
-import com.android.dex.util.FileUtils;
-
-import dot.junit.AllTests;
-import util.build.BuildStep.BuildFile;
-
-import junit.framework.TestCase;
-import junit.framework.TestResult;
-import junit.framework.TestSuite;
-import junit.textui.TestRunner;
-
-import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
 import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Scanner;
 import java.util.Set;
 import java.util.TreeSet;
-import java.util.Map.Entry;
-import java.util.regex.MatchResult;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * Main class to generate data from the test suite to later run from a shell
@@ -56,13 +32,10 @@
  * <project-home>/src/<for-each-package>/Main_testN1.java will be generated<br>
  * (one Main class for each test method in the Test_... class
  */
-public class BuildDalvikSuite {
+public class BuildDalvikSuite extends BuildUtilBase {
 
     public static final String TARGET_MAIN_FILE = "mains.jar";
 
-    public static boolean DEBUG = true;
-
-    private static String JAVASRC_FOLDER = "";
     private static String MAIN_SRC_OUTPUT_FOLDER = "";
 
     // the folder for the generated junit-files for the cts host (which in turn
@@ -76,26 +49,9 @@
 
     private static String CLASS_PATH = "";
 
-    private static String restrictTo = null; // e.g. restrict to "opcodes.add_double"
-
     private static final String TARGET_JAR_ROOT_PATH = "/data/local/tmp/vm-tests";
 
-    private int testClassCnt = 0;
-    private int testMethodsCnt = 0;
-
-    /*
-     * using a linked hashmap to keep the insertion order for iterators.
-     * the junit suite/tests adding order is used to generate the order of the
-     * report.
-     * a map. key: fully qualified class name, value: a list of test methods for
-     * the given class
-     */
-    private LinkedHashMap<String, List<String>> map = new LinkedHashMap<String,
-    List<String>>();
-
-    private class MethodData {
-        String methodBody, constraint, title;
-    }
+    private String JAVASRC_FOLDER;
 
     /**
      * @param args
@@ -104,22 +60,21 @@
      * @throws IOException
      */
     public static void main(String[] args) throws IOException {
-
-        if (!parseArgs(args)) {
+        BuildDalvikSuite cat = new BuildDalvikSuite();
+        if (!cat.parseArgs(args)) {
           printUsage();
           System.exit(-1);
         }
 
         long start = System.currentTimeMillis();
-        BuildDalvikSuite cat = new BuildDalvikSuite();
-        cat.compose();
+        cat.run(null);
         long end = System.currentTimeMillis();
 
         System.out.println("elapsed seconds: " + (end - start) / 1000);
     }
 
-    public static boolean parseArgs(String[] args) {
-      if (args.length > 5) {
+    private boolean parseArgs(String[] args) {
+      if (args.length == 6) {
           JAVASRC_FOLDER = args[0];
           OUTPUT_FOLDER = args[1];
           CLASS_PATH = args[2];
@@ -130,12 +85,6 @@
 
           HOSTJUNIT_SRC_OUTPUT_FOLDER = args[5];
           HOSTJUNIT_CLASSES_OUTPUT_FOLDER = HOSTJUNIT_SRC_OUTPUT_FOLDER + "/classes";
-
-          if (args.length > 6) {
-              // optional: restrict to e.g. "opcodes.add_double"
-              restrictTo = args[6];
-              System.out.println("restricting build to: " + restrictTo);
-          }
           return true;
       } else {
           return false;
@@ -148,96 +97,115 @@
                            "[restrict-to-opcode]");
     }
 
-    public void compose() throws IOException {
-        System.out.println("Collecting all junit tests...");
-        new TestRunner() {
-            @Override
-            protected TestResult createTestResult() {
-                return new TestResult() {
-                    @Override
-                    protected void run(TestCase test) {
-                        addToTests(test);
-                    }
-
-                };
-            }
-        }.doRun(AllTests.suite());
-
-        // for each combination of TestClass and method, generate a Main_testN1
-        // class in the respective package.
-        // for the report make sure all N... tests are called first, then B,
-        // then E, then VFE test methods.
-        // e.g. dxc.junit.opcodes.aaload.Test_aaload - testN1() ->
-        // File Main_testN1.java in package dxc.junit.opcodes.aaload.
-        //
-        handleTests();
-    }
-
-    private void addToTests(TestCase test) {
-
-        String packageName = test.getClass().getPackage().getName();
-        packageName = packageName.substring(packageName.lastIndexOf('.'));
-
-
-        String method = test.getName(); // e.g. testVFE2
-        String fqcn = test.getClass().getName(); // e.g.
-        // dxc.junit.opcodes.iload_3.Test_iload_3
-
-        // ignore all tests not belonging to the given restriction
-        if (restrictTo != null && !fqcn.contains(restrictTo)) return;
-
-        testMethodsCnt++;
-        List<String> li = map.get(fqcn);
-        if (li == null) {
-            testClassCnt++;
-            li = new ArrayList<String>();
-            map.put(fqcn, li);
-        }
-        li.add(method);
-    }
-    private String curJunitFileName = null;
-    private String curJunitName = null;
-    private String curJunitFileData = "";
-
     private SourceBuildStep hostJunitBuildStep;
 
-    private void flushHostJunitFile() {
-        if (curJunitFileName != null) {
-            File toWrite = new File(curJunitFileName);
-            String absPath = toWrite.getAbsolutePath();
-            // add to java source files for later compilation
-            hostJunitBuildStep.addSourceFile(absPath);
-            // write file
-            curJunitFileData += "\n}\n";
-            writeToFileMkdir(toWrite, curJunitFileData);
+    private static class HostState {
+        private String fileName;
+        private StringBuilder fileData;
 
-            curJunitFileName = null;
-            curJunitFileData = "";
+        public HostState(String fileName) {
+            this.fileName = fileName;
+            fileData = new StringBuilder();
+        }
+
+        public void append(String s) {
+            fileData.append(s);
+        }
+
+        private void addCTSHostMethod(String pName, String method,
+                Collection<String> dependentTestClassNames) {
+            fileData.append("public void " + method + "() throws Exception {\n");
+            final String targetCoreJarPath = String.format("%s/dot/junit/dexcore.jar",
+                    TARGET_JAR_ROOT_PATH);
+
+            String mainsJar = String.format("%s/%s", TARGET_JAR_ROOT_PATH, TARGET_MAIN_FILE);
+
+            String cp = String.format("%s:%s", targetCoreJarPath, mainsJar);
+            for (String depFqcn : dependentTestClassNames) {
+                String sourceName = depFqcn.replaceAll("\\.", "/") + ".jar";
+                String targetName= String.format("%s/%s", TARGET_JAR_ROOT_PATH,
+                        sourceName);
+                cp += ":" + targetName;
+                // dot.junit.opcodes.invoke_interface_range.ITest
+                // -> dot/junit/opcodes/invoke_interface_range/ITest.jar
+            }
+
+            //"dot.junit.opcodes.add_double_2addr.Main_testN2";
+            String mainclass = pName + ".Main_" + method;
+            fileData.append(getShellExecJavaLine(cp, mainclass));
+            fileData.append("\n}\n\n");
+        }
+
+        public void end() {
+            fileData.append("\n}\n");
+        }
+
+        public File getFileToWrite() {
+            return new File(fileName);
+        }
+        public String getBuildStep() {
+            return new File(fileName).getAbsolutePath();
+        }
+        public String getData() {
+            return fileData.toString();
         }
     }
 
-    private void openCTSHostFileFor(String pName, String classOnlyName) {
-        // flush previous JunitFile
-        flushHostJunitFile();
-        String sourceName = "JUnit_" + classOnlyName;
+    private void flushHostState(HostState state) {
+        state.end();
 
-        // prepare current testcase-file
-        curJunitFileName = HOSTJUNIT_SRC_OUTPUT_FOLDER + "/" + pName.replaceAll("\\.","/") + "/" +
-        sourceName + ".java";
-        curJunitFileData = getWarningMessage() +
-        "package " + pName + ";\n" +
-        "import java.io.IOException;\n" +
-        "import java.util.concurrent.TimeUnit;\n\n" +
-        "import com.android.tradefed.device.CollectingOutputReceiver;\n" +
-        "import com.android.tradefed.testtype.IAbi;\n" +
-        "import com.android.tradefed.testtype.IAbiReceiver;\n" +
-        "import com.android.tradefed.testtype.DeviceTestCase;\n" +
-        "import com.android.tradefed.util.AbiFormatter;\n" +
-        "\n" +
-        "public class " + sourceName + " extends DeviceTestCase implements IAbiReceiver {\n";
+        File toWrite = state.getFileToWrite();
+        writeToFileMkdir(toWrite, state.getData());
+
+        hostJunitBuildStep.addSourceFile(state.getBuildStep());
     }
 
-    private String getShellExecJavaLine(String classpath, String mainclass) {
+    private HostState openCTSHostFileFor(String pName, String classOnlyName) {
+        String sourceName = classOnlyName;
+
+        String modPackage = pName;
+        {
+            // Given a class name of "Test_zzz" and a package of "xxx.yyy.zzz," strip
+            // "zzz" from the package to reduce duplication (and dashboard clutter).
+            int lastDot = modPackage.lastIndexOf('.');
+            if (lastDot > 0) {
+                String lastPackageComponent = modPackage.substring(lastDot + 1);
+                if (classOnlyName.equals("Test_" + lastPackageComponent)) {
+                    // Drop the duplication.
+                    modPackage = modPackage.substring(0, lastDot);
+                }
+            }
+        }
+
+        String fileName = HOSTJUNIT_SRC_OUTPUT_FOLDER + "/" + modPackage.replaceAll("\\.", "/")
+                + "/" + sourceName + ".java";
+
+        HostState newState = new HostState(fileName);
+
+        newState.append(getWarningMessage());
+        newState.append("package " + modPackage + ";\n");
+        newState.append("import java.io.IOException;\n" +
+                "import java.util.concurrent.TimeUnit;\n\n" +
+                "import com.android.tradefed.device.CollectingOutputReceiver;\n" +
+                "import com.android.tradefed.testtype.IAbi;\n" +
+                "import com.android.tradefed.testtype.IAbiReceiver;\n" +
+                "import com.android.tradefed.testtype.DeviceTestCase;\n" +
+                "import com.android.tradefed.util.AbiFormatter;\n" +
+                "\n");
+        newState.append("public class " + sourceName + " extends DeviceTestCase implements " +
+                "IAbiReceiver {\n");
+
+        newState.append("\n" +
+                "protected IAbi mAbi;\n" +
+                "@Override\n" +
+                "public void setAbi(IAbi abi) {\n" +
+                "    mAbi = abi;\n" +
+                "}\n\n");
+
+        return newState;
+    }
+
+    private static String getShellExecJavaLine(String classpath, String mainclass) {
       String cmd = String.format("ANDROID_DATA=%s dalvikvm|#ABI#| -Xmx512M -Xss32K -Xnodex2oat " +
               "-Djava.io.tmpdir=%s -classpath %s %s", TARGET_JAR_ROOT_PATH, TARGET_JAR_ROOT_PATH,
               classpath, mainclass);
@@ -256,62 +224,21 @@
         return "//Autogenerated code by " + this.getClass().getName() + "; do not edit.\n";
     }
 
-    private void addCTSHostMethod(String pName, String method, MethodData md,
-            Collection<String> dependentTestClassNames) {
-        curJunitFileData += "public void " + method + "() throws Exception {\n";
-        final String targetCoreJarPath = String.format("%s/dot/junit/dexcore.jar",
-                TARGET_JAR_ROOT_PATH);
-
-        String mainsJar = String.format("%s/%s", TARGET_JAR_ROOT_PATH, TARGET_MAIN_FILE);
-
-        String cp = String.format("%s:%s", targetCoreJarPath, mainsJar);
-        for (String depFqcn : dependentTestClassNames) {
-            String sourceName = depFqcn.replaceAll("\\.", "/") + ".jar";
-            String targetName= String.format("%s/%s", TARGET_JAR_ROOT_PATH,
-                    sourceName);
-            cp += ":" + targetName;
-            // dot.junit.opcodes.invoke_interface_range.ITest
-            // -> dot/junit/opcodes/invoke_interface_range/ITest.jar
-        }
-
-        //"dot.junit.opcodes.add_double_2addr.Main_testN2";
-        String mainclass = pName + ".Main_" + method;
-        curJunitFileData += getShellExecJavaLine(cp, mainclass);
-        curJunitFileData += "\n}\n\n";
-    }
-
-    private void handleTests() throws IOException {
-        System.out.println("collected " + testMethodsCnt + " test methods in " +
-                testClassCnt + " junit test classes");
-        String datafileContent = "";
+    class MyTestHandler implements TestHandler {
+        public String datafileContent = "";
         Set<BuildStep> targets = new TreeSet<BuildStep>();
+        public SourceBuildStep srcBuildStep = new JavacBuildStep(CLASSES_OUTPUT_FOLDER, CLASS_PATH);
 
-        SourceBuildStep srcBuildStep;
-        hostJunitBuildStep = new JavacBuildStep(
-            HOSTJUNIT_CLASSES_OUTPUT_FOLDER, CLASS_PATH);
-
-        String mainsJar = OUTPUT_FOLDER + File.separator + TARGET_MAIN_FILE;
-        srcBuildStep = new JavacBuildStep(CLASSES_OUTPUT_FOLDER, CLASS_PATH);
-
-        for (Entry<String, List<String>> entry : map.entrySet()) {
-
-            String fqcn = entry.getKey();
+        @Override
+        public void handleTest(String fqcn, List<String> methods) {
             int lastDotPos = fqcn.lastIndexOf('.');
             String pName = fqcn.substring(0, lastDotPos);
             String classOnlyName = fqcn.substring(lastDotPos + 1);
-            String instPrefix = "new " + classOnlyName + "()";
 
-            openCTSHostFileFor(pName, classOnlyName);
+            HostState hostState = openCTSHostFileFor(pName, classOnlyName);
 
-            curJunitFileData += "\n" +
-                    "protected IAbi mAbi;\n" +
-                    "@Override\n" +
-                    "public void setAbi(IAbi abi) {\n" +
-                    "    mAbi = abi;\n" +
-                    "}\n\n";
-
-            List<String> methods = entry.getValue();
             Collections.sort(methods, new Comparator<String>() {
+                @Override
                 public int compare(String s1, String s2) {
                     // TODO sort according: test ... N, B, E, VFE
                     return s1.compareTo(s2);
@@ -338,23 +265,26 @@
                 List<String> dependentTestClassNames = parseTestClassName(pName,
                         classOnlyName, methodContent);
 
-                addCTSHostMethod(pName, method, md, dependentTestClassNames);
-
+                hostState.addCTSHostMethod(pName, method, dependentTestClassNames);
 
                 if (dependentTestClassNames.isEmpty()) {
                     continue;
                 }
 
-
                 String content = getWarningMessage() +
-                "package " + pName + ";\n" +
-                "import " + pName + ".d.*;\n" +
-                "import dot.junit.*;\n" +
-                "public class Main_" + method + " extends DxAbstractMain {\n" +
-                "    public static void main(String[] args) throws Exception {" +
-                methodContent + "\n}\n";
+                        "package " + pName + ";\n" +
+                        "import " + pName + ".d.*;\n" +
+                        "import dot.junit.*;\n" +
+                        "public class Main_" + method + " extends DxAbstractMain {\n" +
+                        "    public static void main(String[] args) throws Exception {" +
+                        methodContent + "\n}\n";
 
-                File sourceFile = getFileFromPackage(pName, method);
+                File sourceFile;
+                try {
+                    sourceFile = getFileFromPackage(pName, method);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
 
                 writeToFile(sourceFile, content);
                 srcBuildStep.addSourceFile(sourceFile.getAbsolutePath());
@@ -438,38 +368,43 @@
                 line += ";" + description + ";" + comment + ";" + details;
 
                 datafileContent += line + "\n";
-                generateBuildStepFor(pName, method, dependentTestClassNames,
-                        targets);
+                generateBuildStepFor(dependentTestClassNames, targets);
             }
 
-
+            flushHostState(hostState);
         }
+    }
+
+    @Override
+    protected void handleTests(JUnitTestCollector tests, TestHandler ignored) {
+        hostJunitBuildStep = new JavacBuildStep(
+                HOSTJUNIT_CLASSES_OUTPUT_FOLDER, CLASS_PATH);
+
+        MyTestHandler handler = new MyTestHandler();
+        super.handleTests(tests, handler);
 
         D8BuildStep dexBuildStep = new D8BuildStep(
             new BuildStep.BuildFile(new File(CLASSES_OUTPUT_FOLDER)),
-            new BuildStep.BuildFile(new File(mainsJar)),
+            new BuildStep.BuildFile(new File(OUTPUT_FOLDER + File.separator + TARGET_MAIN_FILE)),
             false);
 
-        targets.add(dexBuildStep);
-
-        // write latest HOSTJUNIT generated file.
-        flushHostJunitFile();
+        handler.targets.add(dexBuildStep);
 
         File scriptDataDir = new File(OUTPUT_FOLDER + "/data/");
         scriptDataDir.mkdirs();
-        writeToFile(new File(scriptDataDir, "scriptdata"), datafileContent);
+        writeToFile(new File(scriptDataDir, "scriptdata"), handler.datafileContent);
 
         if (!hostJunitBuildStep.build()) {
             System.out.println("main javac cts-host-hostjunit-classes build step failed");
             System.exit(1);
         }
 
-        if (!srcBuildStep.build()) {
+        if (!handler.srcBuildStep.build()) {
             System.out.println("main src dalvik-cts-buildutil build step failed");
             System.exit(1);
         }
 
-        for (BuildStep buildStep : targets) {
+        for (BuildStep buildStep : handler.targets) {
             if (!buildStep.build()) {
                 System.out.println("building failed. buildStep: " +
                         buildStep.getClass().getName() + ", " + buildStep);
@@ -478,10 +413,8 @@
         }
     }
 
-    private void generateBuildStepFor(String pName, String method,
-            Collection<String> dependentTestClassNames, Set<BuildStep> targets) {
-
-
+    private void generateBuildStepFor(Collection<String> dependentTestClassNames,
+            Set<BuildStep> targets) {
         for (String dependentTestClassName : dependentTestClassNames) {
             generateBuildStepForDependant(dependentTestClassName, targets);
         }
@@ -579,219 +512,6 @@
         return dexBuildStep;
     }
 
-    /**
-     * @param pName
-     * @param classOnlyName
-     * @param methodSource
-     * @return testclass names
-     */
-    private List<String> parseTestClassName(String pName, String classOnlyName,
-            String methodSource) {
-        List<String> entries = new ArrayList<String>(2);
-        String opcodeName = classOnlyName.substring(5);
-
-        Scanner scanner = new Scanner(methodSource);
-
-        String[] patterns = new String[] {"new\\s(T_" + opcodeName + "\\w*)",
-                "(T_" + opcodeName + "\\w*)", "new\\s(T\\w*)"};
-
-        String token = null;
-        for (String pattern : patterns) {
-            token = scanner.findWithinHorizon(pattern, methodSource.length());
-            if (token != null) {
-                break;
-            }
-        }
-
-        if (token == null) {
-            System.err.println("warning: failed to find dependent test class name: " + pName +
-                    ", " + classOnlyName + " in methodSource:\n" + methodSource);
-            return entries;
-        }
-
-        MatchResult result = scanner.match();
-
-        entries.add((pName + ".d." + result.group(1)).trim());
-
-        // search additional @uses directives
-        Pattern p = Pattern.compile("@uses\\s+(.*)\\s+", Pattern.MULTILINE);
-        Matcher m = p.matcher(methodSource);
-        while (m.find()) {
-            String res = m.group(1);
-            entries.add(0, res.trim());
-        }
-
-        // search for " load(\"...\" " and add as dependency
-        Pattern loadPattern = Pattern.compile("load\\(\"([^\"]*)\"", Pattern.MULTILINE);
-        Matcher loadMatcher = loadPattern.matcher(methodSource);
-        while (loadMatcher.find()) {
-            String res = loadMatcher.group(1);
-            entries.add(res.trim());
-        }
-
-        // search for " loadAndRun(\"...\" " and add as dependency
-        Pattern loadAndRunPattern = Pattern.compile("loadAndRun\\(\"([^\"]*)\"", Pattern.MULTILINE);
-        Matcher loadAndRunMatcher = loadAndRunPattern.matcher(methodSource);
-        while (loadAndRunMatcher.find()) {
-            String res = loadAndRunMatcher.group(1);
-            entries.add(res.trim());
-        }
-
-        // lines with the form @uses
-        // dot.junit.opcodes.add_double.jm.T_add_double_2
-        // one dependency per one @uses
-        // TODO
-
-        return entries;
-    }
-
-    private MethodData parseTestMethod(String pname, String classOnlyName,
-            String method) {
-
-        String path = pname.replaceAll("\\.", "/");
-        String absPath = JAVASRC_FOLDER + "/" + path + "/" + classOnlyName + ".java";
-        File f = new File(absPath);
-
-        Scanner scanner;
-        try {
-            scanner = new Scanner(f);
-        } catch (FileNotFoundException e) {
-            throw new RuntimeException("error while reading to file: " + e.getClass().getName() +
-                    ", msg:" + e.getMessage());
-        }
-
-        String methodPattern = "public\\s+void\\s+" + method + "[^\\{]+\\{";
-
-        String token = scanner.findWithinHorizon(methodPattern, (int) f.length());
-        if (token == null) {
-            throw new RuntimeException("cannot find method source of 'public void " + method +
-                    "' in file '" + absPath + "'");
-        }
-
-        MatchResult result = scanner.match();
-        result.start();
-        result.end();
-
-        StringBuilder builder = new StringBuilder();
-        //builder.append(token);
-
-        try {
-            FileReader reader = new FileReader(f);
-            reader.skip(result.end());
-
-            int readResult;
-            int blocks = 1;
-            while ((readResult = reader.read()) != -1 && blocks > 0) {
-                char currentChar = (char) readResult;
-                switch (currentChar) {
-                    case '}': {
-                        blocks--;
-                        builder.append(currentChar);
-                        break;
-                    }
-                    case '{': {
-                        blocks++;
-                        builder.append(currentChar);
-                        break;
-                    }
-                    default: {
-                        builder.append(currentChar);
-                        break;
-                    }
-                }
-            }
-            if (reader != null) {
-                reader.close();
-            }
-        } catch (Exception e) {
-            throw new RuntimeException("failed to parse", e);
-        }
-
-        // find the @title/@constraint in javadoc comment for this method
-        // using platform's default charset
-        String all = new String(FileUtils.readFile(f));
-        // System.out.println("grepping javadoc found for method " + method +
-        // " in " + pname + "," + classOnlyName);
-        String commentPattern = "/\\*\\*([^{]*)\\*/\\s*" + methodPattern;
-        Pattern p = Pattern.compile(commentPattern, Pattern.DOTALL);
-        Matcher m = p.matcher(all);
-        String title = null, constraint = null;
-        if (m.find()) {
-            String res = m.group(1);
-            // System.out.println("res: " + res);
-            // now grep @title and @constraint
-            Matcher titleM = Pattern.compile("@title (.*)", Pattern.DOTALL)
-            .matcher(res);
-            if (titleM.find()) {
-                title = titleM.group(1).replaceAll("\\n     \\*", "");
-                title = title.replaceAll("\\n", " ");
-                title = title.trim();
-                // System.out.println("title: " + title);
-            } else {
-                System.err.println("warning: no @title found for method " + method + " in " + pname +
-                        "," + classOnlyName);
-            }
-            // constraint can be one line only
-            Matcher constraintM = Pattern.compile("@constraint (.*)").matcher(
-                    res);
-            if (constraintM.find()) {
-                constraint = constraintM.group(1);
-                constraint = constraint.trim();
-                // System.out.println("constraint: " + constraint);
-            } else if (method.contains("VFE")) {
-                System.err
-                .println("warning: no @constraint for for a VFE method:" + method + " in " +
-                        pname + "," + classOnlyName);
-            }
-        } else {
-            System.err.println("warning: no javadoc found for method " + method + " in " + pname +
-                    "," + classOnlyName);
-        }
-        MethodData md = new MethodData();
-        md.methodBody = builder.toString();
-        md.constraint = constraint;
-        md.title = title;
-        if (scanner != null) {
-            scanner.close();
-        }
-        return md;
-    }
-
-    private void writeToFileMkdir(File file, String content) {
-        File parent = file.getParentFile();
-        if (!parent.exists() && !parent.mkdirs()) {
-            throw new RuntimeException("failed to create directory: " + parent.getAbsolutePath());
-        }
-        writeToFile(file, content);
-    }
-
-    private void writeToFile(File file, String content) {
-        try {
-            if (file.exists() && file.length() == content.length()) {
-                FileReader reader = new FileReader(file);
-                char[] charContents = new char[(int) file.length()];
-                reader.read(charContents);
-                reader.close();
-                String contents = new String(charContents);
-                if (contents.equals(content)) {
-                    // System.out.println("skipping identical: "
-                    // + file.getAbsolutePath());
-                    return;
-                }
-            }
-
-            //System.out.println("writing file " + file.getAbsolutePath());
-
-            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
-                    new FileOutputStream(file), "utf-8"));
-            bw.write(content);
-            bw.close();
-        } catch (Exception e) {
-            throw new RuntimeException("error while writing to file: " + e.getClass().getName() +
-                    ", msg:" + e.getMessage());
-        }
-    }
-
     private File getFileFromPackage(String pname, String methodName)
     throws IOException {
         // e.g. dxc.junit.argsreturns.pargsreturn
diff --git a/tools/vm-tests-tf/src/util/build/BuildUtilBase.java b/tools/vm-tests-tf/src/util/build/BuildUtilBase.java
new file mode 100644
index 0000000..8a6eab4
--- /dev/null
+++ b/tools/vm-tests-tf/src/util/build/BuildUtilBase.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2011 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 util.build;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Scanner;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Helper base class for code generators.
+ */
+public abstract class BuildUtilBase {
+
+    public static boolean DEBUG = true;
+
+    public static class MethodData {
+        String methodBody, constraint, title;
+    }
+
+    public interface TestHandler {
+        public void handleTest(String fqcn, List<String> methods);
+    }
+
+    public void run(TestHandler handler) {
+        System.out.println("Collecting all junit tests...");
+        JUnitTestCollector tests = new JUnitTestCollector(getClass().getClassLoader());
+
+        handleTests(tests, handler);
+    }
+
+    protected void handleTests(JUnitTestCollector tests, TestHandler handler) {
+        System.out.println("collected " + tests.testMethodsCnt + " test methods in " +
+                tests.testClassCnt + " junit test classes");
+
+        for (Entry<String, List<String>> entry : tests.map.entrySet()) {
+            handler.handleTest(entry.getKey(), entry.getValue());
+        }
+    }
+
+    private static String readURL(URL in) {
+        // Use common scanner idiom to read a complete InputStream into a string.
+        try (Scanner scanner = new Scanner(in.openStream(), StandardCharsets.UTF_8.toString())) {
+            scanner.useDelimiter("\\A");  // This delimits by "start of content," of which there is
+                                          // only one.
+            return scanner.hasNext() ? scanner.next() : null;
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected MethodData parseTestMethod(String pname, String classOnlyName,
+            String method) {
+        String searchPath = "src/" + pname.replaceAll("\\.", "/") + "/" + classOnlyName + ".java";
+        String content;
+        {
+            URL resource = getClass().getClassLoader().getResource(searchPath);
+            if (resource == null) {
+                throw new RuntimeException("Could not find " + searchPath);
+            }
+            content = readURL(resource);
+            if (content == null) {
+                throw new RuntimeException("Could not retrieve content for " + searchPath);
+            }
+        }
+
+        final String methodPattern = "public\\s+void\\s+" + method + "[^\\{]+\\{";
+
+        int methodSkip;
+        try (Scanner scanner = new Scanner(content)) {
+            String token = scanner.findWithinHorizon(methodPattern, content.length());
+            if (token == null) {
+                throw new RuntimeException("cannot find method source of 'public void " + method +
+                        "' in file '" + searchPath + "'");
+            }
+
+            MatchResult result = scanner.match();
+            result.start();
+            methodSkip = result.end();
+        }
+
+        StringBuilder builder = new StringBuilder();
+
+        try {
+            StringReader reader = new StringReader(content);
+            reader.skip(methodSkip);
+
+            int readResult;
+            int blocks = 1;
+            while ((readResult = reader.read()) != -1 && blocks > 0) {
+                char currentChar = (char) readResult;
+                switch (currentChar) {
+                    case '}': {
+                        blocks--;
+                        builder.append(currentChar);
+                        break;
+                    }
+                    case '{': {
+                        blocks++;
+                        builder.append(currentChar);
+                        break;
+                    }
+                    default: {
+                        builder.append(currentChar);
+                        break;
+                    }
+                }
+            }
+            if (reader != null) {
+                reader.close();
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("failed to parse", e);
+        }
+
+        // find the @title/@constraint in javadoc comment for this method
+        // using platform's default charset
+
+        // System.out.println("grepping javadoc found for method " + method +
+        // " in " + pname + "," + classOnlyName);
+        String commentPattern = "/\\*\\*([^{]*)\\*/\\s*" + methodPattern;
+        Pattern p = Pattern.compile(commentPattern, Pattern.DOTALL);
+        Matcher m = p.matcher(content);
+        String title = null, constraint = null;
+        if (m.find()) {
+            String res = m.group(1);
+            // System.out.println("res: " + res);
+            // now grep @title and @constraint
+            Matcher titleM = Pattern.compile("@title (.*)", Pattern.DOTALL)
+            .matcher(res);
+            if (titleM.find()) {
+                title = titleM.group(1).replaceAll("\\n     \\*", "");
+                title = title.replaceAll("\\n", " ");
+                title = title.trim();
+                // System.out.println("title: " + title);
+            } else {
+                System.err.println("warning: no @title found for method " + method + " in " + pname +
+                        "," + classOnlyName);
+            }
+            // constraint can be one line only
+            Matcher constraintM = Pattern.compile("@constraint (.*)").matcher(
+                    res);
+            if (constraintM.find()) {
+                constraint = constraintM.group(1);
+                constraint = constraint.trim();
+                // System.out.println("constraint: " + constraint);
+            } else if (method.contains("VFE")) {
+                System.err
+                .println("warning: no @constraint for for a VFE method:" + method + " in " +
+                        pname + "," + classOnlyName);
+            }
+        } else {
+            System.err.println("warning: no javadoc found for method " + method + " in " + pname +
+                    "," + classOnlyName);
+        }
+        MethodData md = new MethodData();
+        md.methodBody = builder.toString();
+        md.constraint = constraint;
+        md.title = title;
+        return md;
+    }
+
+    /**
+     * @param pName
+     * @param classOnlyName
+     * @param methodSource
+     * @return testclass names
+     */
+    protected static List<String> parseTestClassName(String pName, String classOnlyName,
+            String methodSource) {
+        List<String> entries = new ArrayList<String>(2);
+        String opcodeName = classOnlyName.substring(5);
+
+        try (Scanner scanner = new Scanner(methodSource)) {
+            String[] patterns = new String[] { "new\\s(T_" + opcodeName + "\\w*)",
+                    "(T_" + opcodeName + "\\w*)", "new\\s(T\\w*)" };
+
+            String token = null;
+            for (String pattern : patterns) {
+                token = scanner.findWithinHorizon(pattern, methodSource.length());
+                if (token != null) {
+                    break;
+                }
+            }
+
+            if (token == null) {
+                System.err.println("warning: failed to find dependent test class name: " + pName
+                        + ", " + classOnlyName + " in methodSource:\n" + methodSource);
+                return entries;
+            }
+
+            MatchResult result = scanner.match();
+
+            entries.add((pName + ".d." + result.group(1)).trim());
+
+            // search additional @uses directives
+            Pattern p = Pattern.compile("@uses\\s+(.*)\\s+", Pattern.MULTILINE);
+            Matcher m = p.matcher(methodSource);
+            while (m.find()) {
+                String res = m.group(1);
+                entries.add(0, res.trim());
+            }
+
+            // search for " load(\"...\" " and add as dependency
+            Pattern loadPattern = Pattern.compile("load\\(\"([^\"]*)\"", Pattern.MULTILINE);
+            Matcher loadMatcher = loadPattern.matcher(methodSource);
+            while (loadMatcher.find()) {
+                String res = loadMatcher.group(1);
+                entries.add(res.trim());
+            }
+
+            // search for " loadAndRun(\"...\" " and add as dependency
+            Pattern loadAndRunPattern = Pattern.compile("loadAndRun\\(\"([^\"]*)\"",
+                    Pattern.MULTILINE);
+            Matcher loadAndRunMatcher = loadAndRunPattern.matcher(methodSource);
+            while (loadAndRunMatcher.find()) {
+                String res = loadAndRunMatcher.group(1);
+                entries.add(res.trim());
+            }
+
+            // lines with the form @uses
+            // dot.junit.opcodes.add_double.jm.T_add_double_2
+            // one dependency per one @uses
+            // TODO
+
+            return entries;
+        }
+    }
+
+    public static void writeToFileMkdir(File file, String content) {
+        File parent = file.getParentFile();
+        if (!parent.exists() && !parent.mkdirs()) {
+            throw new RuntimeException("failed to create directory: " + parent.getAbsolutePath());
+        }
+        writeToFile(file, content);
+    }
+
+    public static void writeToFile(File file, String content) {
+        try {
+            if (file.exists() && file.length() == content.length()) {
+                FileReader reader = new FileReader(file);
+                char[] charContents = new char[(int) file.length()];
+                reader.read(charContents);
+                reader.close();
+                String contents = new String(charContents);
+                if (contents.equals(content)) {
+                    // System.out.println("skipping identical: "
+                    // + file.getAbsolutePath());
+                    return;
+                }
+            }
+
+            //System.out.println("writing file " + file.getAbsolutePath());
+
+            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
+                    new FileOutputStream(file), "utf-8"));
+            bw.write(content);
+            bw.close();
+        } catch (Exception e) {
+            throw new RuntimeException("error while writing to file: " + e.getClass().getName() +
+                    ", msg:" + e.getMessage());
+        }
+    }
+
+}
diff --git a/tools/vm-tests-tf/src/util/build/FileUtil.java b/tools/vm-tests-tf/src/util/build/FileUtil.java
new file mode 100644
index 0000000..efb3571
--- /dev/null
+++ b/tools/vm-tests-tf/src/util/build/FileUtil.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 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 util.build;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class FileUtil {
+
+    public static String readFile(File f) {
+        if (f.length() > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException(f.toString());
+        }
+        byte tmp[] = new byte[(int)f.length()];
+        try (FileInputStream fis = new FileInputStream(f)) {
+            int pos = 0;
+            while (pos != tmp.length) {
+                int read = fis.read(tmp, pos, tmp.length - pos);
+                if (read == -1) {
+                    throw new IOException("Unexpected EOF");
+                }
+                pos += read;
+            }
+            return new String(tmp);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/tools/vm-tests-tf/src/util/build/JUnitTestCollector.java b/tools/vm-tests-tf/src/util/build/JUnitTestCollector.java
new file mode 100644
index 0000000..7332806
--- /dev/null
+++ b/tools/vm-tests-tf/src/util/build/JUnitTestCollector.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 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 util.build;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.textui.TestRunner;
+
+public class JUnitTestCollector {
+
+    public final int testClassCnt;
+    public final int testMethodsCnt;
+
+    /**
+     * Map collection all found tests.
+     *
+     * using a linked hashmap to keep the insertion order for iterators.
+     * the junit suite/tests adding order is used to generate the order of the
+     * report.
+     * a map. key: fully qualified class name, value: a list of test methods for
+     * the given class
+     */
+    public final LinkedHashMap<String, List<String>> map =
+            new LinkedHashMap<String, List<String>>();
+
+    public JUnitTestCollector(ClassLoader loader) {
+        Test test;
+        try {
+            Class<?> allTestsClass = loader.loadClass("dot.junit.AllTests");
+            Method suiteMethod = allTestsClass.getDeclaredMethod("suite");
+            test = (Test)suiteMethod.invoke(null);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        final Counters counters = new Counters();
+        new TestRunner() {
+            @Override
+            protected TestResult createTestResult() {
+                return new TestResult() {
+                    @Override
+                    protected void run(TestCase test) {
+                        String packageName = test.getClass().getPackage().getName();
+                        packageName = packageName.substring(packageName.lastIndexOf('.'));
+
+
+                        String method = test.getName(); // e.g. testVFE2
+                        String fqcn = test.getClass().getName(); // e.g.
+                        // dxc.junit.opcodes.iload_3.Test_iload_3
+
+                        counters.a++;
+                        List<String> li = map.get(fqcn);
+                        if (li == null) {
+                            counters.b++;
+                            li = new ArrayList<String>();
+                            map.put(fqcn, li);
+                        }
+                        li.add(method);
+                    }
+
+                };
+            }
+        }.doRun(test);
+        testMethodsCnt = counters.a;
+        testClassCnt = counters.b;
+    }
+
+    private static class Counters {
+        int a = 0;
+        int b = 0;
+    }
+}