Merge "EDI: Add feature version to FeatureDeviceInfo" into nyc-dev
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index 7733c5d..a5fc819 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -68,7 +68,7 @@
         # Todo: test for radial distortion enabled devices has not yet been
         # implemented
         its.caps.skip_unless(not its.caps.radial_distortion_correction(props))
-        full_device = its.caps.full(props)
+        full_device = its.caps.full_or_better(props)
         limited_device = its.caps.limited(props)
         its.caps.skip_unless(full_device or limited_device)
         level3_device = its.caps.level3(props)
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hcef/HceFEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hcef/HceFEmulatorActivity.java
index 89f040b..7118ae3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hcef/HceFEmulatorActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hcef/HceFEmulatorActivity.java
@@ -61,7 +61,7 @@
         registerReceiver(mReceiver, filter);
         ComponentName hceFService = new ComponentName("com.android.cts.verifier",
                 MyHostFelicaService.class.getName());
-        mNfcFCardEmulation.enableNfcFForegroundService(this, hceFService);
+        mNfcFCardEmulation.enableService(this, hceFService);
     }
 
     @Override
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk b/hostsidetests/compilation/Android.mk
similarity index 65%
copy from tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk
copy to hostsidetests/compilation/Android.mk
index 4aebb74..40077f0 100644
--- a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk
+++ b/hostsidetests/compilation/Android.mk
@@ -12,23 +12,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
 
-LOCAL_PACKAGE_NAME := CtsShortcutManagerLauncher4
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
-
-LOCAL_SDK_VERSION := current
+LOCAL_MODULE_TAGS := tests
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.launcher4
+LOCAL_MODULE := CtsCompilationTestCases
 
-include $(BUILD_CTS_PACKAGE)
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt compatibility-host-util
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/compilation/AndroidTest.xml b/hostsidetests/compilation/AndroidTest.xml
new file mode 100644
index 0000000..4e5b0bd
--- /dev/null
+++ b/hostsidetests/compilation/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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 Compilation Test">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsCompilationApp.apk" />
+    </target_preparer>
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsCompilationTestCases.jar" />
+    </test>
+</configuration>
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk b/hostsidetests/compilation/app/Android.mk
similarity index 70%
rename from tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk
rename to hostsidetests/compilation/app/Android.mk
index 4aebb74..5bcf108 100644
--- a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk
+++ b/hostsidetests/compilation/app/Android.mk
@@ -16,19 +16,16 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_PACKAGE_NAME := CtsShortcutManagerLauncher4
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := tests
 
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
 
+LOCAL_PACKAGE_NAME := CtsCompilationApp
+
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.launcher4
-
-include $(BUILD_CTS_PACKAGE)
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/AndroidManifest.xml b/hostsidetests/compilation/app/AndroidManifest.xml
similarity index 79%
rename from tests/tests/shortcutmanager/packages/launchermanifest_nonshared/AndroidManifest.xml
rename to hostsidetests/compilation/app/AndroidManifest.xml
index 9808da4..99b13b2 100755
--- a/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/AndroidManifest.xml
+++ b/hostsidetests/compilation/app/AndroidManifest.xml
@@ -16,17 +16,16 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.content.pm.cts.shortcutmanager.packages">
+    package="android.cts.compilation">
 
     <application>
-        <activity android:name="Launcher">
+        <activity android:name=".CompilationTargetActivity" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.LAUNCHER" />
-                <category android:name="android.intent.category.HOME" />
             </intent-filter>
         </activity>
     </application>
+
 </manifest>
 
diff --git a/tests/tests/shortcutmanager/packages/src/android/content/pm/cts/shortcutmanager/packages/Launcher.java b/hostsidetests/compilation/app/src/android/cts/compilation/CompilationTargetActivity.java
similarity index 66%
rename from tests/tests/shortcutmanager/packages/src/android/content/pm/cts/shortcutmanager/packages/Launcher.java
rename to hostsidetests/compilation/app/src/android/cts/compilation/CompilationTargetActivity.java
index 88db59a..37bbdab 100644
--- a/tests/tests/shortcutmanager/packages/src/android/content/pm/cts/shortcutmanager/packages/Launcher.java
+++ b/hostsidetests/compilation/app/src/android/cts/compilation/CompilationTargetActivity.java
@@ -13,9 +13,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.pm.cts.shortcutmanager.packages;
+
+package android.cts.compilation;
 
 import android.app.Activity;
+import android.os.Bundle;
 
-public class Launcher extends Activity {
+import java.lang.Override;
+
+/**
+ * A simple activity which can be subjected to (dex to native) compilation.
+ */
+public class CompilationTargetActivity extends Activity {
+
+    @Override
+    public void onCreate(Bundle bundle) {
+        super.onCreate(bundle);
+    }
+
 }
diff --git a/hostsidetests/compilation/src/android/cts/compilation/CompilationTest.java b/hostsidetests/compilation/src/android/cts/compilation/CompilationTest.java
new file mode 100644
index 0000000..3e673ea
--- /dev/null
+++ b/hostsidetests/compilation/src/android/cts/compilation/CompilationTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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 android.cts.compilation;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CompilationTest extends DeviceTestCase {
+    private static final String APPLICATION_PACKAGE = "android.cts.compilation";
+
+    private ITestDevice mDevice;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDevice = getDevice();
+        mDevice.executeAdbCommand("root");
+    }
+
+    /**
+     * Tests the case where no profile is available because the app has never run.
+     */
+    public void testForceCompile_noProfileAvailable() throws Exception {
+        String stdoutContents = mDevice.executeAdbCommand("shell", "cmd", "package", "compile",
+                "-m", "speed-profile", "-f", APPLICATION_PACKAGE);
+        assertEquals("Success\n", stdoutContents);
+
+        // Find location of the base.odex file
+        String odexFilePath = getOdexFilePath();
+
+        // Confirm the compiler-filter used in creating the odex file
+        String compilerFilter = getCompilerFilter(odexFilePath);
+
+        assertEquals("compiler-filter", "speed-profile", compilerFilter);
+    }
+
+    /**
+     * Parses the value for the key "compiler-filter" out of the output from
+     * {@code oatdump --header-only}.
+     */
+    private String getCompilerFilter(String odexFilePath) throws DeviceNotAvailableException {
+        String[] response = executeAdbCommand(
+                "shell", "oatdump", "--header-only", "--oat-file=" + odexFilePath);
+        String prefix = "compiler-filter =";
+        for (String line : response) {
+            line = line.trim();
+            if (line.startsWith(prefix)) {
+                return line.substring(prefix.length()).trim();
+            }
+        }
+        fail("No occurence of \"" + prefix + "\" in: " + Arrays.toString(response));
+        return null;
+    }
+
+    /**
+     * Returns the path to the application's base.odex file that should have
+     * been created by the compiler.
+     */
+    private String getOdexFilePath() throws DeviceNotAvailableException {
+        // Something like "package:/data/app/android.cts.compilation-1/base.apk"
+        String pathSpec = executeAdbCommand(1, "shell", "pm", "path", APPLICATION_PACKAGE)[0];
+        Matcher matcher = Pattern.compile("^package:(.+/)base\\.apk$").matcher(pathSpec);
+        boolean found = matcher.find();
+        assertTrue("Malformed spec: " + pathSpec, found);
+        String apkDir = matcher.group(1);
+        // E.g. /data/app/android.cts.compilation-1/oat/arm64/base.odex
+        String result = executeAdbCommand(1, "shell", "find", apkDir, "-name", "base.odex")[0];
+        assertTrue("odex file not found: " + result, mDevice.doesFileExist(result));
+        return result;
+    }
+
+    private String[] executeAdbCommand(int numLinesOutputExpected, String... command)
+            throws DeviceNotAvailableException {
+        String[] lines = executeAdbCommand(command);
+        assertEquals(
+                String.format(Locale.US, "Expected %d lines output, got %d running %s: %s",
+                        numLinesOutputExpected, lines.length, Arrays.toString(command),
+                        Arrays.toString(lines)),
+                numLinesOutputExpected, lines.length);
+        return lines;
+    }
+
+    private String[] executeAdbCommand(String... command) throws DeviceNotAvailableException {
+        String output = mDevice.executeAdbCommand(command);
+        // "".split() returns { "" }, but we want an empty array
+        String[] lines = output.equals("") ? new String[0] : output.split("\n");
+        return lines;
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/WidgetProvider/src/com/android/cts/widgetprovider/SimpleAppWidgetHostService.java b/hostsidetests/devicepolicy/app/WidgetProvider/src/com/android/cts/widgetprovider/SimpleAppWidgetHostService.java
index b5b6003..6b9a2af 100644
--- a/hostsidetests/devicepolicy/app/WidgetProvider/src/com/android/cts/widgetprovider/SimpleAppWidgetHostService.java
+++ b/hostsidetests/devicepolicy/app/WidgetProvider/src/com/android/cts/widgetprovider/SimpleAppWidgetHostService.java
@@ -31,6 +31,7 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
@@ -58,6 +59,8 @@
     private static final int RESULT_INTERRUPTED = 3;
     private static final int RESULT_TIMEOUT = 4;
 
+    private static final long GET_PROVIDER_TIMEOUT_MILLIS = 30 * 1000; // 30 seconds
+
     public static final String USER_EXTRA = "user-extra";
     public static final String PACKAGE_EXTRA = "package-extra";
     public static final String REPLY_EXTRA = "reply-extra";
@@ -213,8 +216,10 @@
         }
 
         public AppWidgetProviderInfo getProvider(Bundle params) throws InterruptedException {
+            final long startTime = SystemClock.elapsedRealtime();
+            long nextTimeout = GET_PROVIDER_TIMEOUT_MILLIS;
             String packageName = params.getString(PACKAGE_EXTRA);
-            while (mSemaphore.tryAcquire(30, TimeUnit.SECONDS)) {
+            while ((nextTimeout > 0) && mSemaphore.tryAcquire(nextTimeout, TimeUnit.MILLISECONDS)) {
                 mSemaphore.drainPermits();
                 Log.d(TAG, "checking for " + packageName + " " + mUserHandle);
                 synchronized (this) {
@@ -225,6 +230,8 @@
                             return providerInfo;
                         }
                     }
+                    nextTimeout = startTime + GET_PROVIDER_TIMEOUT_MILLIS
+                            - SystemClock.elapsedRealtime();
                 }
             }
             return null;
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 3ee2f68..f2a69f2 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -176,34 +176,90 @@
         assertNetworkAccess(true);
     }
 
+    protected void assertForegroundServiceNetworkAccess() throws Exception {
+        assertForegroundServiceState(); // Sanity check.
+        assertNetworkAccess(true);
+    }
+
+    /**
+     * Asserts that an app always have access while on foreground or running a foreground service.
+     *
+     * <p>This method will launch an activity and a foreground service to make the assertion, but
+     * will finish the activity / stop the service afterwards.
+     */
+    protected void assertsForegroundAlwaysHasNetworkAccess() throws Exception{
+        // Checks foreground first.
+        launchActivity();
+        assertForegroundNetworkAccess();
+        finishActivity();
+
+        // Then foreground service
+        startForegroundService();
+        assertForegroundServiceNetworkAccess();
+        stopForegroundService();
+    }
+
     protected final void assertBackgroundState() throws Exception {
-        final ProcessState state = getProcessStateByUid(mUid);
-        Log.v(TAG, "assertBackgroundState(): status for app2 (" + mUid + "): " + state);
-        final boolean isBackground = isBackground(state.state);
-        assertTrue("App2 is not on background state: " + state, isBackground);
+        final int maxTries = 30;
+        ProcessState state = null;
+        for (int i = 1; i <= maxTries; i++) {
+            state = getProcessStateByUid(mUid);
+            Log.v(TAG, "assertBackgroundState(): status for app2 (" + mUid + ") on attempt #" + i
+                    + ": " + state);
+            if (isBackground(state.state)) {
+                return;
+            }
+            Log.d(TAG, "App not on background state on attempt #" + i
+                    + "; sleeping 1s before trying again");
+            Thread.sleep(SECOND_IN_MS);
+        }
+        fail("App2 is not on background state after " + maxTries + " attempts: " + state );
     }
 
     protected final void assertForegroundState() throws Exception {
-        final ProcessState state = getProcessStateByUid(mUid);
-        Log.v(TAG, "assertForegroundState(): status for app2 (" + mUid + "): " + state);
-        final boolean isForeground = !isBackground(state.state);
-        assertTrue("App2 is not on foreground state: " + state, isForeground);
+        final int maxTries = 30;
+        ProcessState state = null;
+        for (int i = 1; i <= maxTries; i++) {
+            state = getProcessStateByUid(mUid);
+            Log.v(TAG, "assertForegroundState(): status for app2 (" + mUid + ") on attempt #" + i
+                    + ": " + state);
+            if (!isBackground(state.state)) {
+                return;
+            }
+            Log.d(TAG, "App not on foreground state on attempt #" + i
+                    + "; sleeping 1s before trying again");
+            Thread.sleep(SECOND_IN_MS);
+        }
+        fail("App2 is not on foreground state after " + maxTries + " attempts: " + state );
     }
 
     protected final void assertForegroundServiceState() throws Exception {
-        final ProcessState state = getProcessStateByUid(mUid);
-        Log.v(TAG, "assertForegroundServiceState(): status for app2 (" + mUid + "): " + state);
-        assertEquals("App2 is not on foreground service state: " + state,
-                PROCESS_STATE_FOREGROUND_SERVICE, state.state);
+        final int maxTries = 30;
+        ProcessState state = null;
+        for (int i = 1; i <= maxTries; i++) {
+            state = getProcessStateByUid(mUid);
+            Log.v(TAG, "assertForegroundServiceState(): status for app2 (" + mUid + ") on attempt #"
+                    + i + ": " + state);
+            if (state.state == PROCESS_STATE_FOREGROUND_SERVICE) {
+                return;
+            }
+            Log.d(TAG, "App not on foreground service state on attempt #" + i
+                    + "; sleeping 1s before trying again");
+            Thread.sleep(SECOND_IN_MS);
+        }
+        fail("App2 is not on foreground service state after " + maxTries + " attempts: " + state );
     }
 
     /**
      * Returns whether an app state should be considered "background" for restriction purposes.
      */
     protected boolean isBackground(int state) {
-        return state >= PROCESS_STATE_FOREGROUND_SERVICE;
+        return state > PROCESS_STATE_FOREGROUND_SERVICE;
     }
 
+    /**
+     * Asserts whether the active network is available or not.
+     */
     private void assertNetworkAccess(boolean expectAvailable) throws Exception {
         final Intent intent = new Intent(ACTION_CHECK_NETWORK);
 
@@ -495,13 +551,27 @@
                 "am startservice com.android.cts.net.hostside.app2/.MyForegroundService");
     }
 
+    protected void stopForegroundService() throws Exception {
+        executeShellCommand(
+                "am stopservice com.android.cts.net.hostside.app2/.MyForegroundService");
+    }
+
     /**
      * Launches an activity on app2 so its process is elevated to foreground status.
      */
-    protected void launchApp2Activity() throws Exception {
+    protected void launchActivity() throws Exception {
         executeShellCommand("am start com.android.cts.net.hostside.app2/.MyActivity");
     }
 
+    /**
+     * Finishes an activity on app2 so its process is demoted fromforeground status.
+     */
+    protected void finishActivity() throws Exception {
+        executeShellCommand("am broadcast -a "
+                + " com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY "
+                + "--receiver-foreground --receiver-registered-only");
+    }
+
     private String toString(int status) {
         switch (status) {
             case RESTRICT_BACKGROUND_STATUS_DISABLED:
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java
index 5f5f80b..d1db01c 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java
@@ -23,8 +23,10 @@
     public void setUp() throws Exception {
         super.setUp();
 
+        // Set initial state.
+        removePowerSaveModeWhitelist(TEST_APP2_PKG);
         setPowerSaveMode(false);
-        assertPowerSaveModeWhitelist(TEST_APP2_PKG, false); // Sanity check
+
         registerBroadcastReceiver();
     }
 
@@ -39,35 +41,46 @@
         setPowerSaveMode(true);
         assertBackgroundNetworkAccess(false);
 
-        // Make sure app is allowed if running a foreground service.
-        startForegroundService();
-        assertForegroundServiceState();
-        assertBackgroundNetworkAccess(true);
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(false);
 
-        // Should always have access when running on foreground
-        launchApp2Activity();
+        // Make sure foreground app doesn't lose access upon enabling it.
+        setPowerSaveMode(false);
+        launchActivity();
         assertForegroundNetworkAccess();
+        setPowerSaveMode(true);
+        assertForegroundNetworkAccess();
+        finishActivity();
+        assertBackgroundNetworkAccess(false);
+
+        // Same for foreground service.
+        setPowerSaveMode(false);
+        startForegroundService();
+        assertForegroundNetworkAccess();
+        setPowerSaveMode(true);
+        assertForegroundNetworkAccess();
+        stopForegroundService();
+        assertBackgroundNetworkAccess(false);
     }
 
     public void testBackgroundNetworkAccess_whitelisted() throws Exception {
         setPowerSaveMode(true);
         assertBackgroundNetworkAccess(false);
+
         addPowerSaveModeWhitelist(TEST_APP2_PKG);
         assertBackgroundNetworkAccess(true);
+
         removePowerSaveModeWhitelist(TEST_APP2_PKG);
         assertBackgroundNetworkAccess(false);
 
-        // Should always have access when running on foreground
-        launchApp2Activity();
-        assertForegroundNetworkAccess();
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(false);
     }
 
     public void testBackgroundNetworkAccess_disabled() throws Exception {
-        setPowerSaveMode(false);
         assertBackgroundNetworkAccess(true);
 
-        // Should always have access when running on foreground
-        launchApp2Activity();
-        assertForegroundNetworkAccess();
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(true);
     }
 }
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeTest.java
index 539c598..22b876a 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeTest.java
@@ -23,9 +23,11 @@
     public void setUp() throws Exception {
         super.setUp();
 
+        // Set initial state.
         setMeteredNetwork();
+        removePowerSaveModeWhitelist(TEST_APP2_PKG);
         setPowerSaveMode(false);
-        assertPowerSaveModeWhitelist(TEST_APP2_PKG, false); // Sanity check
+
         registerBroadcastReceiver();
     }
 
@@ -42,38 +44,48 @@
 
     public void testBackgroundNetworkAccess_enabled() throws Exception {
         setPowerSaveMode(true);
-
         assertBackgroundNetworkAccess(false);
 
-        // Make sure app is allowed if running a foreground service.
-        startForegroundService();
-        assertForegroundServiceState();
-        assertBackgroundNetworkAccess(true);
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(false);
 
-        // Should always have access when running on foreground
-        launchApp2Activity();
+        // Make sure foreground app doesn't lose access upon enabling it.
+        setPowerSaveMode(false);
+        launchActivity();
         assertForegroundNetworkAccess();
+        setPowerSaveMode(true);
+        assertForegroundNetworkAccess();
+        finishActivity();
+        assertBackgroundNetworkAccess(false);
+
+        // Same for foreground service.
+        setPowerSaveMode(false);
+        startForegroundService();
+        assertForegroundNetworkAccess();
+        setPowerSaveMode(true);
+        assertForegroundNetworkAccess();
+        stopForegroundService();
+        assertBackgroundNetworkAccess(false);
     }
 
     public void testBackgroundNetworkAccess_whitelisted() throws Exception {
         setPowerSaveMode(true);
         assertBackgroundNetworkAccess(false);
+
         addPowerSaveModeWhitelist(TEST_APP2_PKG);
         assertBackgroundNetworkAccess(true);
+
         removePowerSaveModeWhitelist(TEST_APP2_PKG);
         assertBackgroundNetworkAccess(false);
 
-        // Should always have access when running on foreground
-        launchApp2Activity();
-        assertForegroundNetworkAccess();
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(false);
     }
 
     public void testBackgroundNetworkAccess_disabled() throws Exception {
-        setPowerSaveMode(false);
         assertBackgroundNetworkAccess(true);
 
-        // Should always have access when running on foreground
-        launchApp2Activity();
-        assertForegroundNetworkAccess();
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(true);
     }
 }
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index 0971770..1895156 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -20,15 +20,6 @@
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
 
-/*
- * TODO: need to add more scenarios:
- * - test access on foreground app
- * - test access on foreground service app
- * - make sure it works when app is on foreground and state is transitioned:
- *   - data saver is enabled
- *   - app is added/removed to blacklist
- *
- */
 public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
 
     private static final String[] REQUIRED_WHITELISTED_PACKAGES = {
@@ -39,9 +30,14 @@
     public void setUp() throws Exception {
         super.setUp();
 
+        // Set initial state.
         setMeteredNetwork();
         setRestrictBackground(false);
+        removeRestrictBackgroundWhitelist(mUid);
+        removeRestrictBackgroundBlacklist(mUid);
+
         registerBroadcastReceiver();
+        assertRestrictBackgroundChangedReceived(0);
    }
 
     @Override
@@ -56,8 +52,6 @@
     }
 
     public void testGetRestrictBackgroundStatus_disabled() throws Exception {
-        removeRestrictBackgroundWhitelist(mUid);
-        assertRestrictBackgroundChangedReceived(0);
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
 
         // Sanity check: make sure status is always disabled, never whitelisted
@@ -65,14 +59,14 @@
         assertRestrictBackgroundChangedReceived(0);
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
 
-        // Should always have access when running on foreground
-        launchApp2Activity();
-        assertForegroundNetworkAccess();
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
     }
 
     public void testGetRestrictBackgroundStatus_whitelisted() throws Exception {
         setRestrictBackground(true);
         assertRestrictBackgroundChangedReceived(1);
+        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
         addRestrictBackgroundWhitelist(mUid);
         assertRestrictBackgroundChangedReceived(2);
@@ -80,11 +74,10 @@
 
         removeRestrictBackgroundWhitelist(mUid);
         assertRestrictBackgroundChangedReceived(3);
-        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_ENABLED);
+        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
-        // Should always have access when running on foreground
-        launchApp2Activity();
-        assertForegroundNetworkAccess();
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
     }
 
     public void testGetRestrictBackgroundStatus_enabled() throws Exception {
@@ -92,19 +85,26 @@
         assertRestrictBackgroundChangedReceived(1);
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
-        removeRestrictBackgroundWhitelist(mUid);
-        assertRestrictBackgroundChangedReceived(1);
+        assertsForegroundAlwaysHasNetworkAccess();
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
-        // Make sure app is allowed if running a foreground service.
-        assertBackgroundNetworkAccess(false);
-        startForegroundService();
-        assertForegroundServiceState();
-        assertBackgroundNetworkAccess(true);
-
-        // Should always have access when running on foreground
-        launchApp2Activity();
+        // Make sure foreground app doesn't lose access upon enabling it.
+        setRestrictBackground(false);
+        launchActivity();
         assertForegroundNetworkAccess();
+        setRestrictBackground(true);
+        assertForegroundNetworkAccess();
+        finishActivity();
+        assertBackgroundNetworkAccess(false);
+
+        // Same for foreground service.
+        setRestrictBackground(false);
+        startForegroundService();
+        assertForegroundNetworkAccess();
+        setRestrictBackground(true);
+        assertForegroundNetworkAccess();
+        stopForegroundService();
+        assertBackgroundNetworkAccess(false);
     }
 
     public void testGetRestrictBackgroundStatus_blacklisted() throws Exception {
@@ -112,6 +112,9 @@
         assertRestrictBackgroundChangedReceived(1);
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
+
         // Make sure blacklist prevails over whitelist.
         setRestrictBackground(true);
         assertRestrictBackgroundChangedReceived(2);
@@ -128,12 +131,8 @@
         assertRestrictBackgroundChangedReceived(5);
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
 
-        // Should always have access when running on foreground
-        addRestrictBackgroundBlacklist(mUid);
-        assertRestrictBackgroundChangedReceived(6);
-        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
-        launchApp2Activity();
-        assertForegroundNetworkAccess();
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
     }
 
     public void testGetRestrictBackgroundStatus_requiredWhitelistedPackages() throws Exception {
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java
new file mode 100644
index 0000000..140d135
--- /dev/null
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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 com.android.cts.net.hostside;
+
+import android.util.Log;
+
+/**
+ * Test cases for the more complex scenarios where multiple restrictions (like Battery Saver Mode
+ * and Data Saver Mode) are applied simultaneously.
+ * <p>
+ * <strong>NOTE: </strong>it might sound like the test methods on this class are testing too much,
+ * which would make it harder to diagnose individual failures, but the assumption is that such
+ * failure most likely will happen when the restriction is tested individually as well.
+ */
+public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase {
+    private static final String TAG = "MixedModesTest";
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // Set initial state.
+        removeRestrictBackgroundWhitelist(mUid);
+        removeRestrictBackgroundBlacklist(mUid);
+        removePowerSaveModeWhitelist(TEST_APP2_PKG);
+
+        registerBroadcastReceiver();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        try {
+            setRestrictBackground(false);
+        } finally {
+            setPowerSaveMode(false);
+        }
+    }
+
+    /**
+     * Tests all DS ON and BS ON scenarios from network-policy-restrictions.md on metered networks.
+     */
+    public void testDataAndBatterySaverModes_meteredNetwork() throws Exception {
+        Log.i(TAG, "testDataAndBatterySaverModes_meteredNetwork() tests");
+        setMeteredNetwork();
+
+        try {
+            setRestrictBackground(true);
+            setPowerSaveMode(true);
+
+            Log.v(TAG, "Not whitelisted for any.");
+            assertBackgroundNetworkAccess(false);
+            assertsForegroundAlwaysHasNetworkAccess();
+            assertBackgroundNetworkAccess(false);
+
+            Log.v(TAG, "Whitelisted for Data Saver but not for Battery Saver.");
+            addRestrictBackgroundWhitelist(mUid);
+            removePowerSaveModeWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+            assertsForegroundAlwaysHasNetworkAccess();
+            assertBackgroundNetworkAccess(false);
+            removeRestrictBackgroundWhitelist(mUid);
+
+            Log.v(TAG, "Whitelisted for Battery Saver but not for Data Saver.");
+            addPowerSaveModeWhitelist(TEST_APP2_PKG);
+            removeRestrictBackgroundWhitelist(mUid);
+            assertBackgroundNetworkAccess(false);
+            assertsForegroundAlwaysHasNetworkAccess();
+            assertBackgroundNetworkAccess(false);
+            removePowerSaveModeWhitelist(TEST_APP2_PKG);
+
+            Log.v(TAG, "Whitelisted for both.");
+            addRestrictBackgroundWhitelist(mUid);
+            addPowerSaveModeWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(true);
+            assertsForegroundAlwaysHasNetworkAccess();
+            assertBackgroundNetworkAccess(true);
+            removePowerSaveModeWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+            removeRestrictBackgroundWhitelist(mUid);
+
+            Log.v(TAG, "Blacklisted for Data Saver, not whitelisted for Battery Saver.");
+            addRestrictBackgroundBlacklist(mUid);
+            removePowerSaveModeWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+            assertsForegroundAlwaysHasNetworkAccess();
+            assertBackgroundNetworkAccess(false);
+            removeRestrictBackgroundBlacklist(mUid);
+
+            Log.v(TAG, "Blacklisted for Data Saver, whitelisted for Battery Saver.");
+            addRestrictBackgroundBlacklist(mUid);
+            addPowerSaveModeWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+            assertsForegroundAlwaysHasNetworkAccess();
+            assertBackgroundNetworkAccess(false);
+            removeRestrictBackgroundBlacklist(mUid);
+            removePowerSaveModeWhitelist(TEST_APP2_PKG);
+        } finally {
+            resetMeteredNetwork();
+        }
+    }
+
+    /**
+     * Tests all DS ON and BS ON scenarios from network-policy-restrictions.md on non-metered
+     * networks.
+     */
+    public void testDataAndBatterySaverModes_nonMeteredNetwork() throws Exception {
+        if (mCm.isActiveNetworkMetered()) {
+            Log.w(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() skipped because network"
+                    + " is metered");
+            return;
+        }
+        Log.i(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() tests");
+        setRestrictBackground(true);
+        setPowerSaveMode(true);
+
+        Log.v(TAG, "Not whitelisted for any.");
+        assertBackgroundNetworkAccess(false);
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(false);
+
+        Log.v(TAG, "Whitelisted for Data Saver but not for Battery Saver.");
+        addRestrictBackgroundWhitelist(mUid);
+        removePowerSaveModeWhitelist(TEST_APP2_PKG);
+        assertBackgroundNetworkAccess(false);
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(false);
+        removeRestrictBackgroundWhitelist(mUid);
+
+        Log.v(TAG, "Whitelisted for Battery Saver but not for Data Saver.");
+        addPowerSaveModeWhitelist(TEST_APP2_PKG);
+        removeRestrictBackgroundWhitelist(mUid);
+        assertBackgroundNetworkAccess(true);
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(true);
+        removePowerSaveModeWhitelist(TEST_APP2_PKG);
+
+        Log.v(TAG, "Whitelisted for both.");
+        addRestrictBackgroundWhitelist(mUid);
+        addPowerSaveModeWhitelist(TEST_APP2_PKG);
+        assertBackgroundNetworkAccess(true);
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(true);
+        removePowerSaveModeWhitelist(TEST_APP2_PKG);
+        assertBackgroundNetworkAccess(false);
+        removeRestrictBackgroundWhitelist(mUid);
+
+        Log.v(TAG, "Blacklisted for Data Saver, not whitelisted for Battery Saver.");
+        addRestrictBackgroundBlacklist(mUid);
+        removePowerSaveModeWhitelist(TEST_APP2_PKG);
+        assertBackgroundNetworkAccess(false);
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(false);
+        removeRestrictBackgroundBlacklist(mUid);
+
+        Log.v(TAG, "Blacklisted for Data Saver, whitelisted for Battery Saver.");
+        addRestrictBackgroundBlacklist(mUid);
+        addPowerSaveModeWhitelist(TEST_APP2_PKG);
+        assertBackgroundNetworkAccess(true);
+        assertsForegroundAlwaysHasNetworkAccess();
+        assertBackgroundNetworkAccess(true);
+        removeRestrictBackgroundBlacklist(mUid);
+        removePowerSaveModeWhitelist(TEST_APP2_PKG);
+    }
+}
diff --git a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/Common.java b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/Common.java
index ed58184..d827921 100644
--- a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/Common.java
+++ b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/Common.java
@@ -34,10 +34,11 @@
             "com.android.cts.net.hostside.app2.action.CHECK_NETWORK";
     static final String ACTION_RECEIVER_READY =
             "com.android.cts.net.hostside.app2.action.RECEIVER_READY";
+    static final String ACTION_FINISH_ACTIVITY =
+            "com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY";
     static final String EXTRA_ACTION = "com.android.cts.net.hostside.app2.extra.ACTION";
     static final String EXTRA_RECEIVER_NAME =
             "com.android.cts.net.hostside.app2.extra.RECEIVER_NAME";
-    static final char RESULT_SEPARATOR = ';';
 
     static int getUid(Context context) {
         final String packageName = context.getPackageName();
diff --git a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyActivity.java b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
index 7c6b504..444b696 100644
--- a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
+++ b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
@@ -15,8 +15,15 @@
  */
 package com.android.cts.net.hostside.app2;
 
+import static com.android.cts.net.hostside.app2.Common.ACTION_FINISH_ACTIVITY;
 import static com.android.cts.net.hostside.app2.Common.TAG;
+
 import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
 import android.util.Log;
 
 /**
@@ -25,6 +32,18 @@
 public class MyActivity extends Activity {
 
     @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        registerReceiver(new BroadcastReceiver() {
+
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                Log.d(TAG, "Finishing MyActivity");
+                MyActivity.this.finish();
+            }}, new IntentFilter(ACTION_FINISH_ACTIVITY));
+    }
+
+    @Override
     protected void onStart() {
         super.onStart();
         Log.d(TAG, "MyActivity.onStart()");
diff --git a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
index b876276..114d5c1 100644
--- a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
+++ b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
@@ -17,6 +17,7 @@
 package com.android.cts.net.hostside.app2;
 
 import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
+
 import static com.android.cts.net.hostside.app2.Common.ACTION_CHECK_NETWORK;
 import static com.android.cts.net.hostside.app2.Common.ACTION_GET_COUNTERS;
 import static com.android.cts.net.hostside.app2.Common.ACTION_GET_RESTRICT_BACKGROUND_STATUS;
@@ -24,7 +25,6 @@
 import static com.android.cts.net.hostside.app2.Common.EXTRA_ACTION;
 import static com.android.cts.net.hostside.app2.Common.EXTRA_RECEIVER_NAME;
 import static com.android.cts.net.hostside.app2.Common.MANIFEST_RECEIVER;
-import static com.android.cts.net.hostside.app2.Common.RESULT_SEPARATOR;
 import static com.android.cts.net.hostside.app2.Common.TAG;
 import static com.android.cts.net.hostside.app2.Common.getUid;
 
diff --git a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
index bbafd4c..1afc3d6 100644
--- a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
+++ b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
@@ -35,7 +35,7 @@
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        Log.d(TAG, "MyForegroundService.onStartCommand: " + intent);
+        Log.d(TAG, "MyForegroundService.onStartCommand(): " + intent);
         startForeground(42, new Notification.Builder(this)
             .setSmallIcon(R.drawable.ic_dialog_alert) // any icon is fine
             .build());
diff --git a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index 38802d7..ec375d6 100644
--- a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -121,6 +121,16 @@
                 "testBackgroundNetworkAccess_enabled");
     }
 
+    public void testDataAndBatterySaverModes_meteredNetwork() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest",
+                "testDataAndBatterySaverModes_meteredNetwork");
+    }
+
+    public void testDataAndBatterySaverModes_nonMeteredNetwork() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest",
+                "testDataAndBatterySaverModes_nonMeteredNetwork");
+    }
+
     private void assertRestrictBackgroundWhitelist(int uid, boolean expected) throws Exception {
         final int max_tries = 5;
         boolean actual = false;
diff --git a/libs/deviceutil/src/android/cts/util/MediaUtils.java b/libs/deviceutil/src/android/cts/util/MediaUtils.java
index 721ff47..7ab806d 100755
--- a/libs/deviceutil/src/android/cts/util/MediaUtils.java
+++ b/libs/deviceutil/src/android/cts/util/MediaUtils.java
@@ -43,6 +43,9 @@
 public class MediaUtils {
     private static final String TAG = "MediaUtils";
 
+    /*
+     *  ----------------------- HELPER METHODS FOR SKIPPING TESTS -----------------------
+     */
     private static final int ALL_AV_TRACKS = -1;
 
     private static final MediaCodecList sMCL = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
@@ -149,6 +152,10 @@
         return result;
     }
 
+    /*
+     *  ------------------- HELPER METHODS FOR CHECKING CODEC SUPPORT -------------------
+     */
+
     public static MediaCodec getDecoder(MediaFormat format) {
         String decoder = sMCL.findDecoderForFormat(format);
         if (decoder != null) {
@@ -423,6 +430,10 @@
         return check(canDecode(format), "no decoder for " + format);
     }
 
+    /*
+     *  ----------------------- HELPER METHODS FOR MEDIA HANDLING -----------------------
+     */
+
     public static MediaExtractor createMediaExtractorForMimeType(
             Context context, int resourceId, String mimeTypePrefix)
             throws IOException {
@@ -450,65 +461,172 @@
         return extractor;
     }
 
-    /**
-     * return the average value of the passed array.
+    /*
+     *  ------------------ HELPER METHODS FOR STATISTICS AND REPORTING ------------------
      */
-    public static double getAverage(double[] data) {
-        int num = data.length;
-        if (num == 0) {
-            return 0;
+
+    // TODO: migrate this into com.android.compatibility.common.util.Stat
+    public static class Stats {
+        /** does not support NaN or Inf in |data| */
+        public Stats(double[] data) {
+            mData = data;
+            if (mData != null) {
+                mNum = mData.length;
+            }
         }
 
-        double sum = data[0];
-        for (int i = 1; i < num; i++) {
-            sum += data[i];
+        public int getNum() {
+            return mNum;
         }
-        return sum / num;
+
+        /** calculate mSumX and mSumXX */
+        private void analyze() {
+            if (mAnalyzed) {
+                return;
+            }
+
+            if (mData != null) {
+                for (double x : mData) {
+                    if (!(x >= mMinX)) { // mMinX may be NaN
+                        mMinX = x;
+                    }
+                    if (!(x <= mMaxX)) { // mMaxX may be NaN
+                        mMaxX = x;
+                    }
+                    mSumX += x;
+                    mSumXX += x * x;
+                }
+            }
+            mAnalyzed = true;
+        }
+
+        /** returns the maximum or NaN if it does not exist */
+        public double getMin() {
+            analyze();
+            return mMinX;
+        }
+
+        /** returns the minimum or NaN if it does not exist */
+        public double getMax() {
+            analyze();
+            return mMaxX;
+        }
+
+        /** returns the average or NaN if it does not exist. */
+        public double getAverage() {
+            analyze();
+            if (mNum == 0) {
+                return Double.NaN;
+            } else {
+                return mSumX / mNum;
+            }
+        }
+
+        /** returns the standard deviation or NaN if it does not exist. */
+        public double getStdev() {
+            analyze();
+            if (mNum == 0) {
+                return Double.NaN;
+            } else {
+                double average = mSumX / mNum;
+                return Math.sqrt(mSumXX / mNum - average * average);
+            }
+        }
+
+        /** returns the statistics for the moving average over n values */
+        public Stats movingAverage(int n) {
+            if (n < 1 || mNum < n) {
+                return new Stats(null);
+            } else if (n == 1) {
+                return this;
+            }
+
+            double[] avgs = new double[mNum - n + 1];
+            double sum = 0;
+            for (int i = 0; i < mNum; ++i) {
+                sum += mData[i];
+                if (i >= n - 1) {
+                    avgs[i - n + 1] = sum / n;
+                    sum -= mData[i - n + 1];
+                }
+            }
+            return new Stats(avgs);
+        }
+
+        /** calculate mSortedData */
+        private void sort() {
+            if (mSorted || mNum == 0) {
+                return;
+            }
+            mSortedData = Arrays.copyOf(mData, mNum);
+            Arrays.sort(mSortedData);
+            mSorted = true;
+        }
+
+        /** returns an array of percentiles for the points using nearest rank */
+        public double[] getPercentiles(double... points) {
+            sort();
+            double[] res = new double[points.length];
+            for (int i = 0; i < points.length; ++i) {
+                if (mNum < 1 || points[i] < 0 || points[i] > 100) {
+                    res[i] = Double.NaN;
+                } else {
+                    res[i] = mSortedData[(int)Math.round(points[i] / 100 * (mNum - 1))];
+                }
+            }
+            return res;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof Stats) {
+                Stats other = (Stats)o;
+                if (other.mNum != mNum) {
+                    return false;
+                } else if (mNum == 0) {
+                    return true;
+                }
+                return Arrays.equals(mData, other.mData);
+            }
+            return false;
+        }
+
+        private double[] mData;
+        private double mSumX = 0;
+        private double mSumXX = 0;
+        private double mMinX = Double.NaN;
+        private double mMaxX = Double.NaN;
+        private int mNum = 0;
+        private boolean mAnalyzed = false;
+        private double[] mSortedData;
+        private boolean mSorted = false;
     }
 
+    /*
+     *  ------------------ HELPER METHODS FOR ACHIEVABLE FRAME RATES ------------------
+     */
+
     /**
-     * return the standard deviation value of the passed array
+     * logs results for achievable frame rates test
      */
-    public static double getStdev(double[] data) {
-        double average = getAverage(data);
-        int num = data.length;
-        if (num == 0) {
-            return 0;
-        }
-        double variance = 0;
-        for (int i = 0; i < num; ++i) {
-            variance += (data[i] - average) * (data[i] - average);
-        }
-        variance /= num;
-        return Math.sqrt(variance);
-    }
-
-    public static double[] calculateMovingAverage(double[] array, int n) {
-        int num = array.length;
-        if (num < n) {
-            return null;
-        }
-        int avgsNum = num - n + 1;
-        double[] avgs = new double[avgsNum];
-        double sum = array[0];
-        for (int i = 1; i < n; ++i) {
-            sum += array[i];
-        }
-        avgs[0] = sum / n;
-
-        for (int i = n; i < num; ++i) {
-            sum = sum - array[i - n] + array[i];
-            avgs[i - n + 1] = sum / n;
-        }
-        return avgs;
-    }
-
-    public static String logResults(DeviceReportLog log, String prefix,
-            double min, double max, double avg, double stdev) {
+    public static String logAchievableRatesResults(DeviceReportLog log, String prefix,
+            Stats stats) {
         String msg = prefix;
-        msg += " min=" + Math.round(min / 1000) + " max=" + Math.round(max / 1000) +
-                " avg=" + Math.round(avg / 1000) + " stdev=" + Math.round(stdev / 1000);
-        log.addValue(msg, 1000000000 / min, ResultType.HIGHER_BETTER, ResultUnit.FPS);
+        msg += " num=" + stats.getNum()
+                + " avg=" + Math.round(stats.getAverage() / 1000)
+                + " stdev=" + Math.round(stats.getStdev() / 1000);
+        String[] labels = {
+                "min", "p5", "p10", "p20", "p30", "p40", "p50", "p60", "p70", "p80", "p90", "p95",
+                "max" };
+        double[] percentiles = stats.getPercentiles(new double[] {
+                0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 100 });
+
+        for (int i = 0; i < labels.length; ++i) {
+            msg += " " + labels[i] + "=" + Math.round(percentiles[i] / 1000);
+        }
+
+        log.addValue(msg, 1000000000 / stats.getMin(), ResultType.HIGHER_BETTER, ResultUnit.FPS);
+        Log.i(TAG, msg);
         return msg;
     }
 
diff --git a/tests/camera/libctscamera2jni/native-camera-jni.cpp b/tests/camera/libctscamera2jni/native-camera-jni.cpp
index 90c34db..db687bf 100644
--- a/tests/camera/libctscamera2jni/native-camera-jni.cpp
+++ b/tests/camera/libctscamera2jni/native-camera-jni.cpp
@@ -1213,7 +1213,7 @@
             ACameraDevice_request_template templateId =
                     static_cast<ACameraDevice_request_template>(t);
             ret = ACameraDevice_createCaptureRequest(device, templateId, &request);
-            if (ret == ACAMERA_ERROR_UNSUPPORTED) {
+            if (ret == ACAMERA_ERROR_INVALID_PARAMETER) {
                 // template not supported. skip
                 continue;
             }
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidAnnotatedBuilder.java b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidAnnotatedBuilder.java
deleted file mode 100644
index 05c6623..0000000
--- a/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidAnnotatedBuilder.java
+++ /dev/null
@@ -1,89 +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 com.android.cts.core.runner.support;
-
-import android.support.test.internal.runner.junit4.AndroidAnnotatedBuilder;
-import android.support.test.internal.util.AndroidRunnerParams;
-import android.support.test.runner.AndroidJUnit4;
-import junit.framework.TestCase;
-import org.junit.runner.RunWith;
-import org.junit.runner.Runner;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.JUnit4;
-import org.junit.runners.model.RunnerBuilder;
-
-/**
- * Extends {@link AndroidAnnotatedBuilder} to add support for passing the
- * {@link AndroidRunnerParams} object to the constructor of any {@link RunnerBuilder}
- * implementation that is not a {@link BlockJUnit4ClassRunner}.
- *
- * <p>If {@link AndroidRunnerParams#isSkipExecution()} is {@code true} the super class will create
- * a {@link RunnerBuilder} that will fire appropriate events as if the tests are being run but will
- * not actually run the test. Unfortunately, when it does that it appears to assume that the runner
- * extends {@link BlockJUnit4ClassRunner}, returns a skipping {@link RunnerBuilder} appropriate for
- * that and ignores the actual {@code runnerClass}. That is a problem because it will not work for
- * custom {@link RunnerBuilder} instances that do not extend {@link BlockJUnit4ClassRunner}.
- *
- * <p>Therefore, when skipping execution this does some additional checks to make sure that the
- * {@code runnerClass} does extend {@link BlockJUnit4ClassRunner} before calling the overridden
- * method.
- *
- * <p>It then attempts to construct a {@link RunnerBuilder} by calling the constructor with the
- * signature {@code <init>(Class, AndroidRunnerParams)}. If that doesn't exist it falls back to
- * the overridden behavior.
- */
-class ExtendedAndroidAnnotatedBuilder extends AndroidAnnotatedBuilder {
-
-    private final AndroidRunnerParams runnerParams;
-
-    public ExtendedAndroidAnnotatedBuilder(RunnerBuilder suiteBuilder,
-            AndroidRunnerParams runnerParams) {
-        super(suiteBuilder, runnerParams);
-        this.runnerParams = runnerParams;
-    }
-
-    @Override
-    public Runner runnerForClass(Class<?> testClass) throws Exception {
-
-        RunWith annotation = testClass.getAnnotation(RunWith.class);
-        if (annotation != null) {
-            Class<? extends Runner> runnerClass = annotation.value();
-
-            // If the runner is expected to skip execution and it is a JUnit4, AndroidJUnit4 or
-            // a JUnit3 test class then return a special skipping runner.
-            if (runnerParams.isSkipExecution()) {
-                if (runnerClass == AndroidJUnit4.class || runnerClass == JUnit4.class
-                        || TestCase.class.isAssignableFrom(testClass)) {
-                    return super.runnerForClass(testClass);
-                }
-            }
-
-            try {
-                // try to build an AndroidJUnit4 runner
-                Runner runner = buildAndroidRunner(runnerClass, testClass);
-                if (runner != null) {
-                    return runner;
-                }
-            } catch (NoSuchMethodException e) {
-                // let the super class handle the error for us and throw an InitializationError
-                // exception.
-                return super.buildRunner(runnerClass, testClass);
-            }
-        }
-
-        return null;
-    }
-}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidLogOnlyBuilder.java b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidLogOnlyBuilder.java
new file mode 100644
index 0000000..956ebff
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidLogOnlyBuilder.java
@@ -0,0 +1,96 @@
+/*
+ * 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 com.android.cts.core.runner.support;
+
+import android.support.test.internal.runner.AndroidLogOnlyBuilder;
+import android.support.test.internal.util.AndroidRunnerParams;
+import android.support.test.runner.AndroidJUnit4;
+import junit.framework.TestCase;
+import org.junit.runner.RunWith;
+import org.junit.runner.Runner;
+import org.junit.runners.Parameterized;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.JUnit4;
+import org.junit.runners.model.RunnerBuilder;
+import org.junit.runners.Suite;
+
+import static android.support.test.internal.util.AndroidRunnerBuilderUtil.isJUnit3Test;
+import static android.support.test.internal.util.AndroidRunnerBuilderUtil.isJUnit3TestSuite;
+
+/**
+ * Extends {@link AndroidLogOnlyBuilder} to add support for passing the
+ * {@link AndroidRunnerParams} object to the constructor of any {@link RunnerBuilder}
+ * implementation that is not a {@link BlockJUnit4ClassRunner}.
+ *
+ * <p>If {@link AndroidRunnerParams#isSkipExecution()} is {@code true} the super class will create
+ * a {@link RunnerBuilder} that will fire appropriate events as if the tests are being run but will
+ * not actually run the test. Unfortunately, when it does that it appears to assume that the runner
+ * extends {@link BlockJUnit4ClassRunner}, returns a skipping {@link RunnerBuilder} appropriate for
+ * that and ignores the actual {@code runnerClass}. That is a problem because it will not work for
+ * custom {@link RunnerBuilder} instances that do not extend {@link BlockJUnit4ClassRunner}.
+ *
+ * <p>Therefore, when skipping execution this does some additional checks to make sure that the
+ * {@code runnerClass} does extend {@link BlockJUnit4ClassRunner} before calling the overridden
+ * method.
+ *
+ * <p>It then attempts to construct a {@link RunnerBuilder} by calling the constructor with the
+ * signature {@code <init>(Class, AndroidRunnerParams)}. If that doesn't exist it falls back to
+ * the overridden behavior.
+ *
+ * <p>Another unfortunate behavior of the {@link AndroidLogOnlyBuilder} is that it assumes the
+ * {@link Parameterized} class has a field called DEFAULT_FACTORY. That field is only present
+ * in JUnit 4.12, and not JUnit 4.10 used by tests run by CoreTestRunner.
+ * Therefore these tests are actually skipped by this class and executed even though
+ * isSkipExecution is true.
+ */
+class ExtendedAndroidLogOnlyBuilder extends AndroidLogOnlyBuilder {
+
+    private final AndroidRunnerParams runnerParams;
+
+    public ExtendedAndroidLogOnlyBuilder(AndroidRunnerParams runnerParams) {
+        super(runnerParams);
+        this.runnerParams = runnerParams;
+    }
+
+    @Override
+    public Runner runnerForClass(Class<?> testClass) throws Throwable {
+        if (!runnerParams.isSkipExecution() ||
+                isJUnit3Test(testClass) || isJUnit3TestSuite(testClass)) {
+            return super.runnerForClass(testClass);
+        }
+
+        RunWith annotation = testClass.getAnnotation(RunWith.class);
+
+        if (annotation != null) {
+            Class<? extends Runner> runnerClass = annotation.value();
+            if (runnerClass == AndroidJUnit4.class || runnerClass == JUnit4.class
+                    || TestCase.class.isAssignableFrom(testClass)) {
+                return super.runnerForClass(testClass);
+            }
+            try {
+                // b/28606746 try to build an AndroidJUnit4 runner to avoid BlockJUnit4ClassRunner
+                return runnerClass.getConstructor(Class.class, AndroidRunnerParams.class).newInstance(
+                    testClass, runnerParams);
+            } catch (NoSuchMethodException e) {
+                // Let the super class handle the error for us and throw an InitializationError
+                // exception. Returning null means that this test will be executed.
+                // b/28606746 Some parameterized tests that cannot be skipped fall through this
+                return null;
+            }
+        }
+        return super.runnerForClass(testClass);
+    }
+}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java
index 1f76922..527f9fd 100644
--- a/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java
@@ -15,10 +15,10 @@
  */
 package com.android.cts.core.runner.support;
 
-import android.support.test.internal.runner.junit4.AndroidAnnotatedBuilder;
+import android.support.test.internal.runner.AndroidLogOnlyBuilder;
 import android.support.test.internal.util.AndroidRunnerParams;
-import org.junit.internal.builders.AnnotatedBuilder;
 import org.junit.runners.model.RunnerBuilder;
+import org.junit.runner.Runner;
 
 /**
  * Extends {@link AndroidRunnerBuilder} in order to provide alternate {@link RunnerBuilder}
@@ -26,18 +26,24 @@
  */
 public class ExtendedAndroidRunnerBuilder extends AndroidRunnerBuilder {
 
-    private final AndroidAnnotatedBuilder mAndroidAnnotatedBuilder;
+   private final ExtendedAndroidLogOnlyBuilder androidLogOnlyBuilder;
 
     /**
      * @param runnerParams {@link AndroidRunnerParams} that stores common runner parameters
      */
     public ExtendedAndroidRunnerBuilder(AndroidRunnerParams runnerParams) {
         super(runnerParams, false /* CTSv1 filtered out Test suite() classes. */);
-        mAndroidAnnotatedBuilder = new ExtendedAndroidAnnotatedBuilder(this, runnerParams);
+        androidLogOnlyBuilder = new ExtendedAndroidLogOnlyBuilder(runnerParams);
     }
 
     @Override
-    protected AnnotatedBuilder annotatedBuilder() {
-        return mAndroidAnnotatedBuilder;
+    public Runner runnerForClass(Class<?> testClass) throws Throwable {
+        // Check if this is a dry-run with -e log true argument passed to the runner.
+        Runner runner = androidLogOnlyBuilder.runnerForClass(testClass);
+        if (runner != null) {
+            return runner;
+        }
+        // Otherwise use the default behaviour
+        return super.runnerForClass(testClass);
     }
 }
diff --git a/tests/leanbackjank/Android.mk b/tests/leanbackjank/Android.mk
index b762dc9..5a89666 100644
--- a/tests/leanbackjank/Android.mk
+++ b/tests/leanbackjank/Android.mk
@@ -34,6 +34,7 @@
     ub-uiautomator \
     ub-janktesthelper \
     android-support-v17-leanback \
+    android-support-v7-recyclerview \
     android-support-v4
 
 LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
diff --git a/tests/leanbackjank/AndroidManifest.xml b/tests/leanbackjank/AndroidManifest.xml
index 27cdbe6..35a2e2e 100644
--- a/tests/leanbackjank/AndroidManifest.xml
+++ b/tests/leanbackjank/AndroidManifest.xml
@@ -19,6 +19,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="android.leanbackjank.cts">
 
+  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
   <application>
       <uses-library android:name="android.test.runner"/>
   </application>
diff --git a/tests/leanbackjank/app/res/layout/main.xml b/tests/leanbackjank/app/res/layout/main.xml
index 7a83b69..542c3e3 100644
--- a/tests/leanbackjank/app/res/layout/main.xml
+++ b/tests/leanbackjank/app/res/layout/main.xml
@@ -22,7 +22,7 @@
     android:layout_height="match_parent">
 
     <fragment
-        android:name="android.cts.jank.leanback.ui.MainFragment"
+        android:name="android.leanbackjank.app.ui.MainFragment"
         android:id="@+id/main_browse_fragment"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 79bf8c7..24880e2 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -2497,5 +2497,182 @@
         mMediaCodecPlayer.flush();
         // mMediaCodecPlayer.reset() handled in TearDown();
     }
+
+    /**
+     * Returns list of CodecCapabilities advertising support for the given MIME type.
+     */
+    private static List<CodecCapabilities> getCodecCapabilitiesForMimeType(String mimeType) {
+        int numCodecs = MediaCodecList.getCodecCount();
+        List<CodecCapabilities> caps = new ArrayList<CodecCapabilities>();
+        for (int i = 0; i < numCodecs; i++) {
+            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
+            if (codecInfo.isEncoder()) {
+                continue;
+            }
+
+            String[] types = codecInfo.getSupportedTypes();
+            for (int j = 0; j < types.length; j++) {
+                if (types[j].equalsIgnoreCase(mimeType)) {
+                    caps.add(codecInfo.getCapabilitiesForType(mimeType));
+                }
+            }
+        }
+        return caps;
+    }
+
+    /**
+     * Returns true if there exists a codec supporting the given MIME type that meets VR high
+     * performance requirements.
+     *
+     * The requirements are as follows:
+     *   - At least 972000 blocks per second (where blocks are defined as 16x16 -- note this
+     *   is equivalent to 3840x2160@30fps)
+     *   - At least 4 concurrent instances
+     *   - Feature adaptive-playback present
+     */
+    private static boolean doesMimeTypeHaveVrReadyCodec(String mimeType) {
+        List<CodecCapabilities> caps = getCodecCapabilitiesForMimeType(mimeType);
+        for (CodecCapabilities c : caps) {
+            if (c.getMaxSupportedInstances() < 4) {
+                continue;
+            }
+
+            if (!c.isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) {
+                continue;
+            }
+
+            if (!c.getVideoCapabilities().areSizeAndRateSupported(3840, 2160, 30.0)) {
+                continue;
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    private class DecodeRunnable implements Runnable {
+        private int video;
+        private int frames;
+        private long durationMillis;
+
+        public DecodeRunnable(int video) {
+            this.video = video;
+            this.frames = 0;
+            this.durationMillis = 0;
+        }
+
+        @Override
+        public void run() {
+            long start = System.currentTimeMillis();
+            int actual = 0;
+            try {
+                actual = countFrames(this.video, RESET_MODE_NONE, -1, null);
+            } catch (Exception e) {
+                actual = -1;
+            }
+            long durationMillis = System.currentTimeMillis() - start;
+
+            synchronized (this) {
+                this.frames = actual;
+                this.durationMillis = durationMillis;
+            }
+        }
+
+        public synchronized int getFrames() {
+            return this.frames;
+        }
+
+        public synchronized double getMeasuredFps() {
+            return this.frames / (this.durationMillis / 1000.0);
+        }
+    }
+
+    private void decodeInParallel(int video, int frames, int fps, int parallel) throws Exception {
+        DecodeRunnable[] runnables = new DecodeRunnable[parallel];
+        Thread[] threads = new Thread[parallel];
+
+        for (int i = 0; i < parallel; ++i) {
+            runnables[i] = new DecodeRunnable(video);
+            threads[i] = new Thread(runnables[i]);
+            threads[i].start();
+        }
+
+        for (Thread t : threads) {
+            t.join();
+        }
+
+        for (DecodeRunnable dr : runnables) {
+            assertTrue("Expected to decode " + frames + " frames, found " + dr.getFrames(),
+                    frames == dr.getFrames());
+        }
+
+        for (DecodeRunnable dr : runnables) {
+            Log.d(TAG, "Decoded at " + dr.getMeasuredFps());
+            assertTrue("Expected to decode at " + fps + " fps, measured " + dr.getMeasuredFps(),
+                    fps < dr.getMeasuredFps());
+        }
+    }
+
+    public void testVrHighPerformanceH264() throws Exception {
+        if (!supportsVrHighPerformance()) {
+            MediaUtils.skipTest(TAG, "FEATURE_VR_MODE_HIGH_PERFORMANCE not present");
+            return;
+        }
+
+        boolean h264IsReady = doesMimeTypeHaveVrReadyCodec(MediaFormat.MIMETYPE_VIDEO_AVC);
+        assertTrue("Did not find a VR ready H.264 decoder", h264IsReady);
+
+        // Test throughput by decoding 1920x1080 @ 30fps x 4 instances.
+        decodeInParallel(
+                R.raw.video_1920x1080_mp4_h264_20480kbps_30fps_aac_stereo_128kbps_44100hz, 299, 30,
+                4);
+
+        // Test throughput by decoding 1920x1080 @ 60fps x 2 instances.
+        decodeInParallel(
+                R.raw.video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz, 596, 60,
+                2);
+    }
+
+    public void testVrHighPerformanceHEVC() throws Exception {
+        if (!supportsVrHighPerformance()) {
+            MediaUtils.skipTest(TAG, "FEATURE_VR_MODE_HIGH_PERFORMANCE not present");
+            return;
+        }
+
+        boolean hevcIsReady = doesMimeTypeHaveVrReadyCodec(MediaFormat.MIMETYPE_VIDEO_HEVC);
+        if (!hevcIsReady) {
+            MediaUtils.skipTest(TAG, "HEVC isn't required to be VR ready");
+            return;
+        }
+
+        // Test throughput by decoding 1920x1080 @ 30fps x 4 instances.
+        decodeInParallel(
+                R.raw.video_1920x1080_mp4_hevc_10240kbps_30fps_aac_stereo_128kbps_44100hz, 299, 30,
+                4);
+    }
+
+    public void testVrHighPerformanceVP9() throws Exception {
+        if (!supportsVrHighPerformance()) {
+            MediaUtils.skipTest(TAG, "FEATURE_VR_MODE_HIGH_PERFORMANCE not present");
+            return;
+        }
+
+        boolean vp9IsReady = doesMimeTypeHaveVrReadyCodec(MediaFormat.MIMETYPE_VIDEO_VP9);
+        if (!vp9IsReady) {
+            MediaUtils.skipTest(TAG, "VP9 isn't required to be VR ready");
+            return;
+        }
+
+        // Test throughput by decoding 1920x1080 @ 30fps x 4 instances.
+        decodeInParallel(
+                R.raw.video_1920x1080_webm_vp9_10240kbps_30fps_vorbis_stereo_128kbps_48000hz, 249,
+                30, 4);
+    }
+
+    private boolean supportsVrHighPerformance() {
+        PackageManager pm = mContext.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
+    }
 }
 
diff --git a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
index 7e56a22..7cd73fe 100644
--- a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
@@ -302,14 +302,11 @@
         double fps = (double)outputNum / ((finish - start) / 1000.0);
         mReportLog.addValue(message, fps, ResultType.HIGHER_BETTER, ResultUnit.FPS);
 
-        double[] avgs = MediaUtils.calculateMovingAverage(frameTimeDiff, MOVING_AVERAGE_NUM);
-        double decMin = Stat.getMin(avgs);
-        double decMax = Stat.getMax(avgs);
-        double decAvg = Stat.getAverage(avgs);
-        double decStdev = MediaUtils.getStdev(avgs);
+        MediaUtils.Stats stats =
+            new MediaUtils.Stats(frameTimeDiff).movingAverage(MOVING_AVERAGE_NUM);
         String result =
-                MediaUtils.logResults(mReportLog, testConfig, decMin, decMax, decAvg, decStdev);
-        fps = 1000000000 / decMin;
+                MediaUtils.logAchievableRatesResults(mReportLog, testConfig, stats);
+        fps = 1000000000 / stats.getMin();
         if (surface != null) {
             mMeasuredFps[round] = fps;
             mResultRawData[round] = result;
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-attributes/res/xml/network_security_config.xml b/tests/tests/networksecurityconfig/networksecurityconfig-attributes/res/xml/network_security_config.xml
index 1e68b7d..698444c 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-attributes/res/xml/network_security_config.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-attributes/res/xml/network_security_config.xml
@@ -10,8 +10,8 @@
   <domain-config>
       <domain includeSubdomains="true">android.com</domain>
   </domain-config>
-  <!-- Cleartext traffic is explicitly permitted to google.com and all subdomains -->
+  <!-- Cleartext traffic is explicitly permitted to example.com and all subdomains -->
   <domain-config cleartextTrafficPermitted="true">
-      <domain includeSubdomains="true">google.com</domain>
+      <domain includeSubdomains="true">example.com</domain>
   </domain-config>
 </network-security-config>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-attributes/src/android/security/net/config/cts/TestAttributes.java b/tests/tests/networksecurityconfig/networksecurityconfig-attributes/src/android/security/net/config/cts/TestAttributes.java
index 4d23e5b..f10d0da 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-attributes/src/android/security/net/config/cts/TestAttributes.java
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-attributes/src/android/security/net/config/cts/TestAttributes.java
@@ -34,8 +34,8 @@
         assertTrue(instance.isCleartextTrafficPermitted("android.com"));
         assertTrue(instance.isCleartextTrafficPermitted("foo.android.com"));
         // Domains in a domain-config that explicitly allow cleartext.
-        assertTrue(instance.isCleartextTrafficPermitted("google.com"));
-        assertTrue(instance.isCleartextTrafficPermitted("test.google.com"));
+        assertTrue(instance.isCleartextTrafficPermitted("example.com"));
+        assertTrue(instance.isCleartextTrafficPermitted("test.example.com"));
         // Domain not specified in a domain-config, should use the base-config's value.
         assertTrue(instance.isCleartextTrafficPermitted("example.com"));
     }
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-basic-domain/src/android/security/net/config/cts/DomainConfigTest.java b/tests/tests/networksecurityconfig/networksecurityconfig-basic-domain/src/android/security/net/config/cts/DomainConfigTest.java
index 73ddd33..8e833b1 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-basic-domain/src/android/security/net/config/cts/DomainConfigTest.java
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-basic-domain/src/android/security/net/config/cts/DomainConfigTest.java
@@ -30,7 +30,7 @@
     public void testDefaultConfig() throws Exception {
         // The default config in this case has no trusted CAs, so all connections should fail.
         TestUtils.assertTlsConnectionFails("developer.android.com", 443);
-        TestUtils.assertTlsConnectionFails("google.com", 443);
+        TestUtils.assertTlsConnectionFails("example.com", 443);
     }
 
     public void testHostnameAwareCheckServerTrustedRequired() throws Exception {
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/src/android/security/net/config/cts/CleartextPermittedTest.java b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/src/android/security/net/config/cts/CleartextPermittedTest.java
index 401b5ac..db8e40f 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/src/android/security/net/config/cts/CleartextPermittedTest.java
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/src/android/security/net/config/cts/CleartextPermittedTest.java
@@ -23,8 +23,8 @@
 
 public class CleartextPermittedTest extends TestCase {
     public void testDefaultAllowed() throws Exception {
-        TestUtils.assertCleartextConnectionSucceeds("google.com", 80);
-        TestUtils.assertTlsConnectionSucceeds("google.com", 443);
+        TestUtils.assertCleartextConnectionSucceeds("example.com", 80);
+        TestUtils.assertTlsConnectionSucceeds("example.com", 443);
     }
 
     public void testCleartextBlocked() throws Exception {
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-invalid-pin/src/android/security/net/config/cts/InvalidPinTest.java b/tests/tests/networksecurityconfig/networksecurityconfig-invalid-pin/src/android/security/net/config/cts/InvalidPinTest.java
index fb0444a..3826ba7 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-invalid-pin/src/android/security/net/config/cts/InvalidPinTest.java
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-invalid-pin/src/android/security/net/config/cts/InvalidPinTest.java
@@ -25,7 +25,7 @@
     }
 
     public void testDefaultDomainUnaffected() throws Exception {
-        TestUtils.assertTlsConnectionSucceeds("google.com", 443);
+        TestUtils.assertTlsConnectionSucceeds("example.com", 443);
         TestUtils.assertTlsConnectionSucceeds("developer.android.com", 443);
     }
 }
diff --git a/tests/tests/security/src/android/security/cts/BannedFilesTest.java b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
index 54709b4..95f4a70 100644
--- a/tests/tests/security/src/android/security/cts/BannedFilesTest.java
+++ b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
@@ -150,4 +150,15 @@
         assertTrue("File \"" + file + "\" is setUID", (fs.mode & FileUtils.S_ISUID) == 0);
         assertTrue("File \"" + file + "\" is setGID", (fs.mode & FileUtils.S_ISGID) == 0);
     }
+
+    /**
+     * Detect "rootmydevice" vulnerability
+     *
+     * References:
+     *
+     * http://www.theregister.co.uk/2016/05/09/allwinners_allloser_custom_kernel_has_a_nasty_root_backdoor/
+     */
+    public void testNoSunxiDebug() {
+        assertFalse("/proc/sunxi_debug/sunxi_debug", new File("/proc/sunxi_debug/sunxi_debug").exists());
+    }
 }
diff --git a/tests/tests/shortcutmanager/Android.mk b/tests/tests/shortcutmanager/Android.mk
deleted file mode 100755
index 1f6bd27..0000000
--- a/tests/tests/shortcutmanager/Android.mk
+++ /dev/null
@@ -1,45 +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_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
-    android-support-v4 \
-    mockito-target \
-    ctsdeviceutil \
-    ctstestrunner \
-    ub-uiautomator \
-    ShortcutManagerTestUtils
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsShortcutManagerTestCases
-
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_SDK_VERSION := test_current
-
-include $(BUILD_CTS_PACKAGE)
-#include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/shortcutmanager/AndroidManifest.xml b/tests/tests/shortcutmanager/AndroidManifest.xml
deleted file mode 100755
index 19fe596..0000000
--- a/tests/tests/shortcutmanager/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="android.content.pm.cts.shortcutmanager"
-    android:sharedUserId="android.content.pm.cts.shortcutmanager.packages">
-
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:targetPackage="android.content.pm.cts.shortcutmanager"
-        android:label="CTS tests for ShortcutManager">
-        <meta-data android:name="listener"
-            android:value="com.android.cts.runner.CtsTestRunListener" />
-    </instrumentation>
-
-</manifest>
-
diff --git a/tests/tests/shortcutmanager/AndroidTest.xml b/tests/tests/shortcutmanager/AndroidTest.xml
deleted file mode 100644
index 2955155..0000000
--- a/tests/tests/shortcutmanager/AndroidTest.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.
--->
-<configuration description="Config for ShortcutManager CTS test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsShortcutManagerTestCases.apk" />
-        <option name="test-file-name" value="CtsShortcutManagerPackage1.apk" />
-        <option name="test-file-name" value="CtsShortcutManagerPackage2.apk" />
-        <option name="test-file-name" value="CtsShortcutManagerPackage3.apk" />
-        <option name="test-file-name" value="CtsShortcutManagerPackage4.apk" />
-        <option name="test-file-name" value="CtsShortcutManagerLauncher1.apk" />
-        <option name="test-file-name" value="CtsShortcutManagerLauncher2.apk" />
-        <option name="test-file-name" value="CtsShortcutManagerLauncher3.apk" />
-        <option name="test-file-name" value="CtsShortcutManagerLauncher4.apk" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.content.pm.cts.shortcutmanager" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/tests/tests/shortcutmanager/packages/Android.mk b/tests/tests/shortcutmanager/packages/Android.mk
deleted file mode 100644
index 3d02f9c..0000000
--- a/tests/tests/shortcutmanager/packages/Android.mk
+++ /dev/null
@@ -1,17 +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 $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk b/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk
deleted file mode 100644
index bacca5d..0000000
--- a/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk
+++ /dev/null
@@ -1,75 +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_PACKAGE_NAME := CtsShortcutManagerPackage1
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
-
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.package1
-
-include $(BUILD_CTS_PACKAGE)
-
-#-----------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsShortcutManagerPackage2
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
-
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.package2
-
-include $(BUILD_CTS_PACKAGE)
-
-#-----------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsShortcutManagerPackage3
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
-
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.package3
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml b/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml
deleted file mode 100755
index 039ed5c..0000000
--- a/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml
+++ /dev/null
@@ -1,33 +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="android.content.pm.cts.shortcutmanager.packages"
-    android:sharedUserId="android.content.pm.cts.shortcutmanager.packages">
-
-    <application>
-        <activity android:name="Launcher">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
-                <category android:name="android.intent.category.HOME" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
-
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk b/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk
deleted file mode 100644
index 793fa66..0000000
--- a/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk
+++ /dev/null
@@ -1,34 +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_PACKAGE_NAME := CtsShortcutManagerPackage4
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
-
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.package4
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk b/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk
deleted file mode 100644
index 8f9babd..0000000
--- a/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk
+++ /dev/null
@@ -1,74 +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_PACKAGE_NAME := CtsShortcutManagerLauncher1
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
-
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.launcher1
-
-include $(BUILD_CTS_PACKAGE)
-
-#-----------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsShortcutManagerLauncher2
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
-
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.launcher2
-
-include $(BUILD_CTS_PACKAGE)
-
-#-----------------------------------------------------------
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsShortcutManagerLauncher3
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
-
-LOCAL_SDK_VERSION := current
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_AAPT_FLAGS += --rename-manifest-package android.content.pm.cts.shortcutmanager.packages.launcher3
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/AndroidManifest.xml b/tests/tests/shortcutmanager/packages/packagemanifest/AndroidManifest.xml
deleted file mode 100755
index 463757d..0000000
--- a/tests/tests/shortcutmanager/packages/packagemanifest/AndroidManifest.xml
+++ /dev/null
@@ -1,33 +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="android.content.pm.cts.shortcutmanager.packages"
-    android:sharedUserId="android.content.pm.cts.shortcutmanager.packages">
-
-    <application>
-        <activity android:name="android.content.pm.cts.shortcutmanager.packages.Launcher">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
-                <category android:name="android.intent.category.HOME" />
-            </intent-filter>
-        </activity>
-    </application>
-</manifest>
-
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml b/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml
deleted file mode 100755
index 05c9db7..0000000
--- a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +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="android.content.pm.cts.shortcutmanager.packages">
-
-    <application>
-    </application>
-</manifest>
-
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerAidlCallPermissionTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerAidlCallPermissionTest.java
deleted file mode 100644
index 30ef0cf..0000000
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerAidlCallPermissionTest.java
+++ /dev/null
@@ -1,24 +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 android.content.pm.cts;
-
-/**
- * - Command line command permissions
- * - Internal AIDL call permissions.
- * - Faking parameter to the AIDL call (user-ID)
- */
-public class ShortcutManagerAidlCallPermissionTest {
-}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerCtsTestsBase.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerCtsTestsBase.java
deleted file mode 100644
index de725d6..0000000
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerCtsTestsBase.java
+++ /dev/null
@@ -1,338 +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 android.content.pm.cts;
-
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.pm.LauncherApps;
-import android.content.pm.ShortcutInfo;
-import android.content.pm.ShortcutManager;
-import android.graphics.drawable.Icon;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.support.annotation.NonNull;
-import android.test.InstrumentationTestCase;
-import android.text.TextUtils;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public abstract class ShortcutManagerCtsTestsBase extends InstrumentationTestCase {
-
-    private static class SpoofingContext extends ContextWrapper {
-        private final String mPackageName;
-
-        public SpoofingContext(Context base, String packageName) {
-            super(base);
-            mPackageName = packageName;
-        }
-
-        @Override
-        public String getPackageName() {
-            return mPackageName;
-        }
-    }
-
-    private Context mCurrentCallerPackage;
-    private int mUserId;
-    private UserHandle mUserHandle;
-
-    private String mOriginalLauncher;
-
-    protected Context mPackageContext1;
-    protected Context mPackageContext2;
-    protected Context mPackageContext3;
-    protected Context mPackageContext4;
-
-    protected Context mLauncherContext1;
-    protected Context mLauncherContext2;
-    protected Context mLauncherContext3;
-    protected Context mLauncherContext4;
-
-    protected LauncherApps mLauncherApps1;
-    protected LauncherApps mLauncherApps2;
-    protected LauncherApps mLauncherApps3;
-    protected LauncherApps mLauncherApps4;
-
-    private Map<Context, ShortcutManager> mManagers = new HashMap<>();
-    private Map<Context, LauncherApps> mLauncherAppses = new HashMap<>();
-
-    private ShortcutManager mCurrentManager;
-    private LauncherApps mCurrentLauncherApps;
-
-    private static class ShortcutActivity extends Activity {
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mUserId = getTestContext().getUserId();
-        mUserHandle = android.os.Process.myUserHandle();
-
-        final String config = getOverrideConfig();
-        if (config != null) {
-            overrideConfig(getInstrumentation(), config);
-        }
-        mOriginalLauncher = getDefaultLauncher(getInstrumentation());
-
-        mPackageContext1 = new SpoofingContext(getTestContext(),
-                "android.content.pm.cts.shortcutmanager.packages.package1");
-        mPackageContext2 = new SpoofingContext(getTestContext(),
-                "android.content.pm.cts.shortcutmanager.packages.package2");
-        mPackageContext3 = new SpoofingContext(getTestContext(),
-                "android.content.pm.cts.shortcutmanager.packages.package3");
-        mPackageContext4 = new SpoofingContext(getTestContext(),
-                "android.content.pm.cts.shortcutmanager.packages.package4");
-        mLauncherContext1 = new SpoofingContext(getTestContext(),
-                "android.content.pm.cts.shortcutmanager.packages.launcher1");
-        mLauncherContext2 = new SpoofingContext(getTestContext(),
-                "android.content.pm.cts.shortcutmanager.packages.launcher2");
-        mLauncherContext3 = new SpoofingContext(getTestContext(),
-                "android.content.pm.cts.shortcutmanager.packages.launcher3");
-        mLauncherContext4 = new SpoofingContext(getTestContext(),
-                "android.content.pm.cts.shortcutmanager.packages.launcher4");
-
-        mLauncherApps1 = new LauncherApps(mLauncherContext1);
-        mLauncherApps2 = new LauncherApps(mLauncherContext2);
-        mLauncherApps3 = new LauncherApps(mLauncherContext3);
-        mLauncherApps4 = new LauncherApps(mLauncherContext4);
-
-        clearShortcuts(getInstrumentation(), mUserId, mPackageContext1.getPackageName());
-        clearShortcuts(getInstrumentation(), mUserId, mPackageContext2.getPackageName());
-        clearShortcuts(getInstrumentation(), mUserId, mPackageContext3.getPackageName());
-        clearShortcuts(getInstrumentation(), mUserId, mPackageContext4.getPackageName());
-
-        setCurrentCaller(mPackageContext1);
-
-        // Make sure shortcuts are removed.
-        withCallers(getAllPublishers(), new Runnable() {
-            @Override
-            public void run() {
-                assertEquals("for " + getCurrentCallingPackage(),
-                        0, getManager().getDynamicShortcuts().size());
-                assertEquals("for " + getCurrentCallingPackage(),
-                        0, getManager().getPinnedShortcuts().size());
-            }
-        });
-        // This was calling the wrong lambda.
-//        withCallers(getAllPublishers(), () -> {
-//            assertEquals("for " + getCurrentCallingPackage(),
-//                    0, getManager().getDynamicShortcuts().size());
-//            assertEquals("for " + getCurrentCallingPackage(),
-//                    0, getManager().getPinnedShortcuts().size());
-//        });
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        resetConfig(getInstrumentation());
-
-        if (!TextUtils.isEmpty(mOriginalLauncher)) {
-            setDefaultLauncher(getInstrumentation(), mOriginalLauncher);
-        }
-
-        super.tearDown();
-    }
-
-    protected Context getTestContext() {
-        return getInstrumentation().getContext();
-    }
-
-    protected UserHandle getUserHandle() {
-        return mUserHandle;
-    }
-
-    protected List<Context> getAllPublishers() {
-        // 4 has a different signature, so we can't call for it.
-        return list(mPackageContext1, mPackageContext2, mPackageContext3);
-    }
-
-    protected List<Context> getAllLaunchers() {
-        // 4 has a different signature, so we can't call for it.
-        return list(mLauncherContext1, mLauncherContext2, mLauncherContext3);
-    }
-
-    protected List<Context> getAllCallers() {
-        return list(
-                mPackageContext1, mPackageContext2, mPackageContext3, mPackageContext4,
-                mLauncherContext1, mLauncherContext2, mLauncherContext3, mLauncherContext4);
-    }
-
-    protected void withCallers(List<Context> callers, Runnable r) {
-        for (Context c : callers) {
-            runWithCaller(c, r);
-        }
-    }
-
-    protected String getOverrideConfig() {
-        return null;
-    }
-
-    protected void setCurrentCaller(Context callerContext) {
-        mCurrentCallerPackage = callerContext;
-
-        if (!mManagers.containsKey(mCurrentCallerPackage)) {
-            mManagers.put(mCurrentCallerPackage, new ShortcutManager(mCurrentCallerPackage));
-        }
-        mCurrentManager = mManagers.get(mCurrentCallerPackage);
-
-        if (!mLauncherAppses.containsKey(mCurrentCallerPackage)) {
-            mLauncherAppses.put(mCurrentCallerPackage, new LauncherApps(mCurrentCallerPackage));
-        }
-        mCurrentLauncherApps = mLauncherAppses.get(mCurrentCallerPackage);
-    }
-
-    protected Context getCurrentCallerContext() {
-        return mCurrentCallerPackage;
-    }
-
-    protected String getCurrentCallingPackage() {
-        return getCurrentCallerContext().getPackageName();
-    }
-
-    protected ShortcutManager getManager() {
-        return mCurrentManager;
-    }
-
-    protected LauncherApps getLauncherApps() {
-        return mCurrentLauncherApps;
-    }
-
-    protected void runWithCaller(Context callerContext, Runnable r) {
-        final Context prev = mCurrentCallerPackage;
-
-        setCurrentCaller(callerContext);
-
-        r.run();
-
-        setCurrentCaller(prev);
-    }
-
-    public static Bundle makeBundle(Object... keysAndValues) {
-        assertTrue((keysAndValues.length % 2) == 0);
-
-        if (keysAndValues.length == 0) {
-            return null;
-        }
-        final Bundle ret = new Bundle();
-
-        for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
-            final String key = keysAndValues[i].toString();
-            final Object value = keysAndValues[i + 1];
-
-            if (value == null) {
-                ret.putString(key, null);
-            } else if (value instanceof Integer) {
-                ret.putInt(key, (Integer) value);
-            } else if (value instanceof String) {
-                ret.putString(key, (String) value);
-            } else if (value instanceof Bundle) {
-                ret.putBundle(key, (Bundle) value);
-            } else {
-                fail("Type not supported yet: " + value.getClass().getName());
-            }
-        }
-        return ret;
-    }
-
-    /**
-     * Make a shortcut with an ID.
-     */
-    protected ShortcutInfo makeShortcut(String id) {
-        return makeShortcut(id, "Title-" + id);
-    }
-
-    /**
-     * Make a shortcut with an ID and a title.
-     */
-    protected ShortcutInfo makeShortcut(String id, String title) {
-        return makeShortcut(
-                id, title, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
-    }
-
-    /**
-     * Make a shortcut with an ID and icon.
-     */
-    protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
-        return makeShortcut(
-                id, "Title-" + id, /* activity =*/ null, icon,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
-    }
-
-    /**
-     * Make multiple shortcuts with IDs.
-     */
-    protected List<ShortcutInfo> makeShortcuts(String... ids) {
-        final ArrayList<ShortcutInfo> ret = new ArrayList();
-        for (String id : ids) {
-            ret.add(makeShortcut(id));
-        }
-        return ret;
-    }
-
-    protected ShortcutInfo.Builder makeShortcutBuilder() {
-        return new ShortcutInfo.Builder(getCurrentCallerContext());
-    }
-
-    /**
-     * Make a shortcut with details.
-     */
-    protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
-            Icon icon, Intent intent, int weight) {
-        final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(getCurrentCallerContext())
-                .setId(id)
-                .setTitle(title)
-                .setWeight(weight)
-                .setIntent(intent);
-        if (icon != null) {
-            b.setIcon(icon);
-        }
-        if (activity != null) {
-            b.setActivityComponent(activity);
-        }
-        final ShortcutInfo s = b.build();
-
-        return s;
-    }
-
-    /**
-     * Make an intent.
-     */
-    protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) {
-        final Intent intent = new Intent(action);
-        intent.setComponent(makeComponent(clazz));
-        intent.replaceExtras(makeBundle(bundleKeysAndValues));
-        return intent;
-    }
-
-    /**
-     * Make an component name, with the client context.
-     */
-    @NonNull
-    protected ComponentName makeComponent(Class<?> clazz) {
-        return new ComponentName(getCurrentCallerContext(), clazz);
-    }
-
-}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerDynamicCountTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerDynamicCountTest.java
deleted file mode 100644
index 110960a..0000000
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerDynamicCountTest.java
+++ /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.
- */
-package android.content.pm.cts;
-
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicShortcutCountExceeded;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
-
-public class ShortcutManagerDynamicCountTest extends ShortcutManagerCtsTestsBase {
-
-    @Override
-    protected String getOverrideConfig() {
-        return "reset_interval_sec=999999,"
-                + "max_updates_per_interval=999999,"
-                + "max_shortcuts=3,"
-                + "max_icon_dimension_dp=128,"
-                + "max_icon_dimension_dp_lowram=32,"
-                + "icon_format=PNG,"
-                + "icon_quality=100";
-    }
-
-    public void testSetDynamicShortcuts() {
-        runWithCaller(mPackageContext1, () -> {
-            getManager().setDynamicShortcuts(list(makeShortcut("s1")));
-            getManager().setDynamicShortcuts(list(
-                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")));
-
-            assertDynamicShortcutCountExceeded(() -> {
-                getManager().setDynamicShortcuts(list(
-                        makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
-                        makeShortcut("s4")));
-            });
-        });
-    }
-}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerNoThrottlingTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerNoThrottlingTest.java
deleted file mode 100644
index 92b1a46..0000000
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerNoThrottlingTest.java
+++ /dev/null
@@ -1,159 +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 android.content.pm.cts;
-
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackNotReceived;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackReceived;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.checkAssertSuccess;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.resetAll;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.setDefaultLauncher;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.waitUntil;
-
-import static org.mockito.Mockito.mock;
-
-import android.content.pm.LauncherApps;
-import android.content.pm.ShortcutInfo;
-import android.content.pm.ShortcutManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.util.List;
-
-/**
- * Tests for {@link ShortcutManager} and {@link ShortcutInfo}.
- *
- * In this test, we tests the main functionalities of those, without throttling.  We
- */
-@SmallTest
-public class ShortcutManagerNoThrottlingTest extends ShortcutManagerCtsTestsBase {
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    @Override
-    protected String getOverrideConfig() {
-        return "reset_interval_sec=999999,"
-                + "max_updates_per_interval=999999,"
-                + "max_shortcuts=10,"
-                + "max_icon_dimension_dp=128,"
-                + "max_icon_dimension_dp_lowram=32,"
-                + "icon_format=PNG,"
-                + "icon_quality=100";
-    }
-
-    public void testShortcutInfoMissingMandatoryFields() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                "ID must be provided",
-                () -> new ShortcutInfo.Builder(getTestContext()).build());
-        assertExpectException(
-                IllegalArgumentException.class, "title must be provided", () -> {
-            ShortcutInfo si = new ShortcutInfo.Builder(getTestContext()).setId("id").build();
-            getManager().setDynamicShortcuts(list(si));
-        });
-        assertExpectException(
-                NullPointerException.class, "Intent must be provided", () -> {
-            ShortcutInfo si = new ShortcutInfo.Builder(getTestContext()).setId("id").setTitle("x")
-                    .build();
-            getManager().setDynamicShortcuts(list(si));
-        });
-    }
-
-    /**
-     * Create shortcuts from different packages and make sure they're really different.
-     */
-    public void testSpoofingPublisher() {
-        runWithCaller(mPackageContext1, () -> {
-            ShortcutInfo s1 = makeShortcut("s1", "title1");
-            getManager().setDynamicShortcuts(list(s1));
-        });
-        runWithCaller(mPackageContext2, () -> {
-            ShortcutInfo s1 = makeShortcut("s1", "title2");
-            getManager().setDynamicShortcuts(list(s1));
-        });
-        runWithCaller(mPackageContext3, () -> {
-            ShortcutInfo s1 = makeShortcut("s1", "title3");
-            getManager().setDynamicShortcuts(list(s1));
-        });
-
-        runWithCaller(mPackageContext1, () -> {
-            final List<ShortcutInfo> list = getManager().getDynamicShortcuts();
-            assertEquals(1, list.size());
-            assertEquals("title1", list.get(0).getTitle());
-        });
-        runWithCaller(mPackageContext2, () -> {
-            final List<ShortcutInfo> list = getManager().getDynamicShortcuts();
-            assertEquals(1, list.size());
-            assertEquals("title2", list.get(0).getTitle());
-        });
-        runWithCaller(mPackageContext3, () -> {
-            final List<ShortcutInfo> list = getManager().getDynamicShortcuts();
-            assertEquals(1, list.size());
-            assertEquals("title3", list.get(0).getTitle());
-        });
-    }
-
-    public void testSpoofingLauncher() {
-        final LauncherApps.Callback c0_1 = mock(LauncherApps.Callback.class);
-        final LauncherApps.Callback c0_2 = mock(LauncherApps.Callback.class);
-        final LauncherApps.Callback c0_3 = mock(LauncherApps.Callback.class);
-        final Handler h = new Handler(Looper.getMainLooper());
-
-        runWithCaller(mLauncherContext1, () -> getLauncherApps().registerCallback(c0_1, h));
-        runWithCaller(mLauncherContext2, () -> getLauncherApps().registerCallback(c0_2, h));
-        runWithCaller(mLauncherContext3, () -> getLauncherApps().registerCallback(c0_3, h));
-
-        // Change the default launcher
-        setDefaultLauncher(getInstrumentation(), mLauncherContext2);
-
-        runWithCaller(mLauncherContext1,
-                () -> assertFalse(getLauncherApps().hasShortcutHostPermission()));
-        runWithCaller(mLauncherContext2,
-                () -> assertTrue(getLauncherApps().hasShortcutHostPermission()));
-        runWithCaller(mLauncherContext3,
-                () -> assertFalse(getLauncherApps().hasShortcutHostPermission()));
-
-        // Call a publisher API and make sure only launcher2 gets it.
-
-        resetAll(list(c0_1, c0_2, c0_3));
-
-        runWithCaller(mPackageContext1, () -> {
-            ShortcutInfo s1 = makeShortcut("s1", "title1");
-            getManager().setDynamicShortcuts(list(s1));
-        });
-
-        // Because of the handlers, callback calls are not synchronous.
-        waitUntil("Launcher 2 didn't receive message", () ->
-            checkAssertSuccess(() ->
-                assertCallbackReceived(c0_2, android.os.Process.myUserHandle(),
-                        mPackageContext1.getPackageName(), "s1")
-            )
-        );
-
-        assertCallbackNotReceived(c0_1);
-        assertCallbackNotReceived(c0_3);
-    }
-}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerSpoofDetectionTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerSpoofDetectionTest.java
deleted file mode 100644
index 37658ae..0000000
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerSpoofDetectionTest.java
+++ /dev/null
@@ -1,134 +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 android.content.pm.cts;
-
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
-
-import static org.mockito.Mockito.mock;
-
-import android.content.Context;
-import android.content.pm.LauncherApps;
-import android.content.pm.LauncherApps.ShortcutQuery;
-import android.content.pm.ShortcutInfo;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.ParcelFileDescriptor;
-
-import java.io.IOException;
-
-public class ShortcutManagerSpoofDetectionTest extends ShortcutManagerCtsTestsBase {
-
-    @Override
-    protected String getOverrideConfig() {
-        return "reset_interval_sec=999999,"
-                + "max_updates_per_interval=999999,"
-                + "max_shortcuts=10,"
-                + "max_icon_dimension_dp=128,"
-                + "max_icon_dimension_dp_lowram=32,"
-                + "icon_format=PNG,"
-                + "icon_quality=100";
-    }
-
-    public void assertCallingPackageMismatch(String method, Context callerContext, Runnable r) {
-        assertExpectException(
-                "Caller=" + callerContext.getPackageName() + ", method=" + method,
-                SecurityException.class, "Calling package name mismatch",
-                () -> runWithCaller(callerContext, () -> r.run())
-        );
-    }
-
-    public void testPublisherSpoofing() {
-        assertCallingPackageMismatch("setDynamicShortcuts", mPackageContext4, () -> {
-            getManager().setDynamicShortcuts(list(makeShortcut("s1")));
-        });
-        assertCallingPackageMismatch("addDynamicShortcut", mPackageContext4, () -> {
-            getManager().addDynamicShortcuts(list(makeShortcut("s1")));
-        });
-        assertCallingPackageMismatch("deleteDynamicShortcut", mPackageContext4, () -> {
-            getManager().removeDynamicShortcuts(list("s1"));
-        });
-        assertCallingPackageMismatch("deleteAllDynamicShortcuts", mPackageContext4, () -> {
-            getManager().removeAllDynamicShortcuts();
-        });
-        assertCallingPackageMismatch("getDynamicShortcuts", mPackageContext4, () -> {
-            getManager().getDynamicShortcuts();
-        });
-        assertCallingPackageMismatch("getPinnedShortcuts", mPackageContext4, () -> {
-            getManager().getPinnedShortcuts();
-        });
-        assertCallingPackageMismatch("updateShortcuts", mPackageContext4, () -> {
-            getManager().updateShortcuts(list(makeShortcut("s1")));
-        });
-        assertCallingPackageMismatch("getMaxDynamicShortcutCount", mPackageContext4, () -> {
-            getManager().getMaxDynamicShortcutCount();
-        });
-        assertCallingPackageMismatch("getRemainingCallCount", mPackageContext4, () -> {
-            getManager().getRemainingCallCount();
-        });
-        assertCallingPackageMismatch("getRateLimitResetTime", mPackageContext4, () -> {
-            getManager().getRateLimitResetTime();
-        });
-        assertCallingPackageMismatch("getIconMaxDimensions", mPackageContext4, () -> {
-            getManager().getIconMaxDimensions();
-        });
-    }
-
-    public void testLauncherSpoofing() {
-        assertCallingPackageMismatch("hasShortcutHostPermission", mLauncherContext4, () -> {
-            getLauncherApps().hasShortcutHostPermission();
-        });
-
-        assertCallingPackageMismatch("registerCallback", mLauncherContext4, () -> {
-            final LauncherApps.Callback c = mock(LauncherApps.Callback.class);
-            getLauncherApps().registerCallback(c, new Handler(Looper.getMainLooper()));
-        });
-
-        assertCallingPackageMismatch("getShortcuts", mLauncherContext4, () -> {
-            ShortcutQuery q = new ShortcutQuery();
-            getLauncherApps().getShortcuts(q, getUserHandle());
-        });
-
-        assertCallingPackageMismatch("pinShortcuts", mLauncherContext4, () -> {
-            getLauncherApps().pinShortcuts(
-                    mPackageContext1.getPackageName(), list(), getUserHandle());
-        });
-
-        assertCallingPackageMismatch("getShortcutIconFd 1", mLauncherContext4, () -> {
-            ParcelFileDescriptor pfd = getLauncherApps().getShortcutIconFd(makeShortcut("s"));
-            try {
-                pfd.close();
-            } catch (IOException e) {
-            }
-        });
-        assertCallingPackageMismatch("getShortcutIconFd 2", mLauncherContext4, () -> {
-            ParcelFileDescriptor pfd = getLauncherApps().getShortcutIconFd(
-                    mPackageContext1.getPackageName(), "s1", getUserHandle());
-            try {
-                pfd.close();
-            } catch (IOException e) {
-            }
-        });
-
-        assertCallingPackageMismatch("startShortcut 1", mLauncherContext4, () -> {
-            getLauncherApps().startShortcut(makeShortcut("s"), null, null);
-        });
-        assertCallingPackageMismatch("startShortcut 2", mLauncherContext4, () -> {
-            getLauncherApps().startShortcut(mPackageContext1.getPackageName(), "s1",
-                    null, null, getUserHandle());
-        });
-    }
-}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerThrottlingTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerThrottlingTest.java
deleted file mode 100644
index 8347bc0..0000000
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/ShortcutManagerThrottlingTest.java
+++ /dev/null
@@ -1,227 +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 android.content.pm.cts;
-
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
-
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
-
-import java.util.List;
-import java.util.function.BooleanSupplier;
-
-public class ShortcutManagerThrottlingTest extends ShortcutManagerCtsTestsBase {
-    private static final String CONFIG_BASE =
-            "max_updates_per_interval=5,"
-            + "max_shortcuts=10,"
-            + "max_icon_dimension_dp=128,"
-            + "max_icon_dimension_dp_lowram=32,"
-            + "icon_format=PNG,"
-            + "icon_quality=100";
-
-    private static final String CONFIG_3SEC = CONFIG_BASE + ",reset_interval_sec=3";
-
-    @Override
-    protected String getOverrideConfig() {
-        return CONFIG_3SEC;
-    }
-
-    private void resetThrottling() {
-        resetAllThrottling(getInstrumentation());
-        assertEquals(5, getManager().getRemainingCallCount());
-    }
-
-    private void waitUntilReset() {
-        final long resetTime = getManager().getRateLimitResetTime();
-        final long sleepTime = resetTime - System.currentTimeMillis();
-
-        if (sleepTime > 0) {
-            try {
-                Thread.sleep(sleepTime);
-            } catch (InterruptedException e) {
-                throw new RuntimeException(e);
-            }
-        }
-    }
-
-    private void clearDynamicShortcuts() {
-        getManager().removeAllDynamicShortcuts();
-        assertEquals(0, getManager().getDynamicShortcuts().size());
-    }
-
-    /**
-     * Run the given test, except for making it's okay to get an AssertionError, when the test took
-     * longer and the reset has happened.
-     */
-    private void runButOkayIfItTakesLonger(Runnable r) {
-        final long nextResetTime = getManager().getRateLimitResetTime();
-
-        try {
-            r.run();
-        } catch (AssertionError e) {
-            if (System.currentTimeMillis() < nextResetTime) {
-                throw e;
-            }
-        }
-    }
-
-    private void checkThrottled(BooleanSupplier apiCall, Runnable nonThrottledAssert,
-            Runnable throttledAssert) {
-        resetThrottling();
-
-        runButOkayIfItTakesLonger(() -> {
-            // Can call 5 times successfully.
-            assertTrue(apiCall.getAsBoolean());
-            nonThrottledAssert.run();
-            assertEquals(4, getManager().getRemainingCallCount());
-
-            assertTrue(apiCall.getAsBoolean());
-            nonThrottledAssert.run();
-            assertEquals(3, getManager().getRemainingCallCount());
-
-            assertTrue(apiCall.getAsBoolean());
-            nonThrottledAssert.run();
-            assertEquals(2, getManager().getRemainingCallCount());
-
-            assertTrue(apiCall.getAsBoolean());
-            nonThrottledAssert.run();
-            assertEquals(1, getManager().getRemainingCallCount());
-
-            assertTrue(apiCall.getAsBoolean());
-            nonThrottledAssert.run();
-            assertEquals(0, getManager().getRemainingCallCount());
-
-            // Now throttled.
-            assertFalse(apiCall.getAsBoolean());
-            throttledAssert.run();
-            assertEquals(0, getManager().getRemainingCallCount());
-
-            // Still throttled.
-            assertFalse(apiCall.getAsBoolean());
-            throttledAssert.run();
-
-            assertEquals(0, getManager().getRemainingCallCount());
-        });
-
-        // However, it shouldn't affect other packages.
-        runWithCaller(mPackageContext3, () -> {
-            assertEquals(5, getManager().getRemainingCallCount());
-        });
-
-        // Wait until reset, then retry.
-        waitUntilReset();
-        assertEquals(5, getManager().getRemainingCallCount());
-
-        runButOkayIfItTakesLonger(() -> {
-
-            assertTrue(apiCall.getAsBoolean());
-            nonThrottledAssert.run();
-            assertEquals(4, getManager().getRemainingCallCount());
-        });
-    }
-
-    /**
-     * Make sure {@link android.content.pm.ShortcutManager#setDynamicShortcuts(List)} correctly
-     * throttles calls.
-     *
-     * <p>Suppressed for now -- because when an instrumentation test is running, the process
-     * will be in the PROCESS_STATE_FOREGROUND_SERVICE state, so none of calls will be throttled.
-     * Need a different way to verify this.
-     */
-    @Suppress
-    @LargeTest
-    public void testThrottled_setDynamicShortcuts() {
-        runWithCaller(mPackageContext1, () -> {
-            checkThrottled(
-                    () -> {
-                        clearDynamicShortcuts();
-                        return getManager().setDynamicShortcuts(list(makeShortcut("s1")));
-                    }, () -> { // Non-throttled assert.
-                        assertEquals(1, getManager().getDynamicShortcuts().size());
-                    }, () -> { // Throttled assert.
-                        assertEquals(0, getManager().getDynamicShortcuts().size());
-                    });
-        });
-    }
-
-    private void checkNotThrottled(Runnable apiCall) {
-        resetThrottling();
-
-        // Can call more than 5 times.
-        apiCall.run();
-        assertEquals(5, getManager().getRemainingCallCount());
-
-        apiCall.run();
-        assertEquals(5, getManager().getRemainingCallCount());
-
-        apiCall.run();
-        assertEquals(5, getManager().getRemainingCallCount());
-
-        apiCall.run();
-        assertEquals(5, getManager().getRemainingCallCount());
-
-        apiCall.run();
-        assertEquals(5, getManager().getRemainingCallCount());
-
-        apiCall.run();
-        assertEquals(5, getManager().getRemainingCallCount());
-
-        apiCall.run();
-        assertEquals(5, getManager().getRemainingCallCount());
-    }
-
-    public void testNotThrottled_delete() {
-        runWithCaller(mPackageContext1, () -> {
-            checkNotThrottled(() -> getManager().removeAllDynamicShortcuts());
-
-            checkNotThrottled(() -> getManager().removeDynamicShortcuts(list("s1")));
-        });
-    }
-
-    public void testNotThrottled_getShortcuts() {
-        // Preparation: Create some shortcuts, and pin some.
-        runWithCaller(mPackageContext1, () -> {
-            getManager().setDynamicShortcuts(list(makeShortcut("s1"), makeShortcut("s2")));
-        });
-
-        setDefaultLauncher(getInstrumentation(), mLauncherContext2);
-        runWithCaller(mLauncherContext2, () -> {
-            getLauncherApps().pinShortcuts(
-                    mPackageContext1.getPackageName(), list("s2"), getUserHandle());
-        });
-
-        // Then check.
-        runWithCaller(mPackageContext1, () -> {
-            resetThrottling();
-            checkNotThrottled(() ->
-                assertShortcutIds(getManager().getDynamicShortcuts(), "s1", "s2"));
-
-            checkNotThrottled(() ->
-                assertShortcutIds(getManager().getPinnedShortcuts(), "s2"));
-        });
-    }
-
-    public void testNotThrottled_misc() {
-        runWithCaller(mPackageContext1, () -> {
-            checkNotThrottled(() -> getManager().getIconMaxDimensions());
-
-            checkNotThrottled(() -> getManager().getRateLimitResetTime());
-
-            checkNotThrottled(() ->
-                    assertEquals(10, getManager().getMaxDynamicShortcutCount()));
-        });
-    }
-}
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 6a431a2..3f667f5 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -85,13 +85,13 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
 import android.widget.EditText;
+import android.widget.FrameLayout;
 import android.widget.LinearLayout;
-import android.widget.ListView;
 
 import java.lang.reflect.Constructor;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
+import java.util.Collections;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -1131,6 +1131,69 @@
         assertEquals(view, viewList.get(0));
     }
 
+    public void testAddFocusablesWithoutTouchMode() {
+        View view = new View(mActivity);
+        assertFalse("test sanity", view.isInTouchMode());
+        focusableInTouchModeTest(view, false);
+    }
+
+    public void testAddFocusablesInTouchMode() {
+        View view = spy(new View(mActivity));
+        when(view.isInTouchMode()).thenReturn(true);
+        focusableInTouchModeTest(view, true);
+    }
+
+    private void focusableInTouchModeTest(View view, boolean inTouchMode) {
+        ArrayList<View> views = new ArrayList<View>();
+
+        view.setFocusableInTouchMode(false);
+        view.setFocusable(true);
+
+        view.addFocusables(views, View.FOCUS_FORWARD);
+        if (inTouchMode) {
+            assertEquals(Collections.emptyList(), views);
+        } else {
+            assertEquals(Collections.singletonList(view), views);
+        }
+
+
+        views.clear();
+        view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_ALL);
+        assertEquals(Collections.singletonList(view), views);
+
+        views.clear();
+        view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_TOUCH_MODE);
+        assertEquals(Collections.emptyList(), views);
+
+        view.setFocusableInTouchMode(true);
+
+        views.clear();
+        view.addFocusables(views, View.FOCUS_FORWARD);
+        assertEquals(Collections.singletonList(view), views);
+
+        views.clear();
+        view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_ALL);
+        assertEquals(Collections.singletonList(view), views);
+
+        views.clear();
+        view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_TOUCH_MODE);
+        assertEquals(Collections.singletonList(view), views);
+
+        view.setFocusable(false);
+
+        views.clear();
+        view.addFocusables(views, View.FOCUS_FORWARD);
+        assertEquals(Collections.emptyList(), views);
+
+        views.clear();
+        view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_ALL);
+        assertEquals(Collections.emptyList(), views);
+
+        views.clear();
+        view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_TOUCH_MODE);
+        assertEquals(Collections.emptyList(), views);
+    }
+
     public void testGetRootView() {
         MockView view = new MockView(mActivity);
 
diff --git a/tests/tests/widget/src/android/widget/cts/AttachDetachAwareView.java b/tests/tests/widget/src/android/widget/cts/AttachDetachAwareView.java
new file mode 100644
index 0000000..491e951
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/AttachDetachAwareView.java
@@ -0,0 +1,41 @@
+/*
+ * 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 android.widget.cts;
+
+import android.content.Context;
+import android.view.View;
+
+class AttachDetachAwareView extends View {
+    int mOnAttachCount = 0;
+    int mOnDetachCount = 0;
+
+    public AttachDetachAwareView(Context context) {
+        super(context);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        mOnAttachCount++;
+        super.onAttachedToWindow();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        mOnDetachCount++;
+        super.onDetachedFromWindow();
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/DummyAdapter.java b/tests/tests/widget/src/android/widget/cts/DummyAdapter.java
new file mode 100644
index 0000000..0e1a40c
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/DummyAdapter.java
@@ -0,0 +1,69 @@
+/*
+ * 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 android.widget.cts;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+class DummyAdapter extends BaseAdapter {
+    int mCount;
+    // these are views w/ special types and are returned as requested
+    View[] mSpecialViews;
+
+    public DummyAdapter(int count, View... specialViews) {
+        mCount = count;
+        mSpecialViews = specialViews;
+    }
+
+    @Override
+    public int getCount() {
+        return mCount;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return 0;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return mSpecialViews.length + 1;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return position < mSpecialViews.length ? position : mSpecialViews.length;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        if (position < mSpecialViews.length) {
+            return mSpecialViews[position];
+        }
+        if (convertView == null) {
+            convertView = new View(parent.getContext());
+            convertView.setMinimumHeight(200);
+        }
+        return convertView;
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewTest.java b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
index 8698280..7b83416 100644
--- a/tests/tests/widget/src/android/widget/cts/GridViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
@@ -16,6 +16,7 @@
 
 package android.widget.cts;
 
+import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.cts.R;
 
 
@@ -47,6 +48,7 @@
 import android.widget.ImageView;
 import android.widget.ListAdapter;
 import android.widget.AdapterView.OnItemClickListener;
+import android.widget.cts.util.ViewTestUtils;
 
 /**
  * Test {@link GridView}.
@@ -566,6 +568,81 @@
         assertEquals(child0.getLeft(), child1.getLeft());
     }
 
+    @MediumTest
+    public void testFullyDetachUnusedViewOnScroll() {
+        mGridView = findGridViewById(R.id.gridview);
+        final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
+            mGridView.setAdapter(new DummyAdapter(1000, theView));
+        });
+        assertEquals("test sanity", 1, theView.mOnAttachCount);
+        assertEquals("test sanity", 0, theView.mOnDetachCount);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
+            mGridView.scrollListBy(mGridView.getHeight() * 2);
+        });
+        assertNull("test sanity, unused view should be removed", theView.getParent());
+        assertEquals("unused view should be detached", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
+            mGridView.scrollListBy(-mGridView.getHeight() * 2);
+            // listview limits scroll to 1 page which is why we call it twice here.
+            mGridView.scrollListBy(-mGridView.getHeight() * 2);
+        });
+        assertNotNull("test sanity, view should be re-added", theView.getParent());
+        assertEquals("view should receive another attach call", 2, theView.mOnAttachCount);
+        assertEquals("view should not receive a detach call", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+    }
+
+    @MediumTest
+    public void testFullyDetachUnusedViewOnReLayout() {
+        mGridView = findGridViewById(R.id.gridview);
+        final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
+            mGridView.setAdapter(new DummyAdapter(1000, theView));
+        });
+        assertEquals("test sanity", 1, theView.mOnAttachCount);
+        assertEquals("test sanity", 0, theView.mOnDetachCount);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
+            mGridView.setSelection(800);
+        });
+        assertNull("test sanity, unused view should be removed", theView.getParent());
+        assertEquals("unused view should be detached", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
+            mGridView.setSelection(0);
+        });
+        assertNotNull("test sanity, view should be re-added", theView.getParent());
+        assertEquals("view should receive another attach call", 2, theView.mOnAttachCount);
+        assertEquals("view should not receive a detach call", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+    }
+
+    @MediumTest
+    public void testFullyDetachUnusedViewOnScrollForFocus() {
+        mGridView = findGridViewById(R.id.gridview);
+        final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, () -> {
+            mGridView.setAdapter(new DummyAdapter(1000, theView));
+        });
+        assertEquals("test sanity", 1, theView.mOnAttachCount);
+        assertEquals("test sanity", 0, theView.mOnDetachCount);
+        while(theView.getParent() != null) {
+            assertEquals("the view should NOT be detached", 0, theView.mOnDetachCount);
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+            ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, null);
+        }
+        assertEquals("the view should be detached", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+        while(theView.getParent() == null) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+            ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mGridView, null);
+        }
+        assertEquals("the view should be re-attached", 2, theView.mOnAttachCount);
+        assertEquals("the view should not recieve another detach", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+    }
+
     private static class MockGridView extends GridView {
         private boolean mCalledOnMeasure = false;
         private boolean mCalledOnFocusChanged = false;
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewTest.java b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
index b5a92e9..13f5fe7 100644
--- a/tests/tests/widget/src/android/widget/cts/ListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
@@ -16,6 +16,7 @@
 
 package android.widget.cts;
 
+import android.widget.BaseAdapter;
 import android.widget.cts.R;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -615,6 +616,130 @@
         listView.layout(0, 0, 100, 100);
     }
 
+    @MediumTest
+    public void testFullDetachHeaderViewOnScroll() {
+        final AttachDetachAwareView header = new AttachDetachAwareView(mActivity);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.setAdapter(new DummyAdapter(1000));
+            mListView.addHeaderView(header);
+        });
+        assertEquals("test sanity", 1, header.mOnAttachCount);
+        assertEquals("test sanity", 0, header.mOnDetachCount);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.scrollListBy(mListView.getHeight() * 3);
+        });
+        assertNull("test sanity, header should be removed", header.getParent());
+        assertEquals("header view should be detached", 1, header.mOnDetachCount);
+        assertFalse(header.isTemporarilyDetached());
+    }
+
+    @MediumTest
+    public void testFullDetachHeaderViewOnRelayout() {
+        final AttachDetachAwareView header = new AttachDetachAwareView(mActivity);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.setAdapter(new DummyAdapter(1000));
+            mListView.addHeaderView(header);
+        });
+        assertEquals("test sanity", 1, header.mOnAttachCount);
+        assertEquals("test sanity", 0, header.mOnDetachCount);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.setSelection(800);
+        });
+        assertNull("test sanity, header should be removed", header.getParent());
+        assertEquals("header view should be detached", 1, header.mOnDetachCount);
+        assertFalse(header.isTemporarilyDetached());
+    }
+
+    @MediumTest
+    public void testFullDetachHeaderViewOnScrollForFocus() {
+        final AttachDetachAwareView header = new AttachDetachAwareView(mActivity);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.setAdapter(new DummyAdapter(1000));
+            mListView.addHeaderView(header);
+        });
+        assertEquals("test sanity", 1, header.mOnAttachCount);
+        assertEquals("test sanity", 0, header.mOnDetachCount);
+        while(header.getParent() != null) {
+            assertEquals("header view should NOT be detached", 0, header.mOnDetachCount);
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+            ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, null);
+        }
+        assertEquals("header view should be detached", 1, header.mOnDetachCount);
+        assertFalse(header.isTemporarilyDetached());
+    }
+
+    @MediumTest
+    public void testFullyDetachUnusedViewOnScroll() {
+        final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.setAdapter(new DummyAdapter(1000, theView));
+        });
+        assertEquals("test sanity", 1, theView.mOnAttachCount);
+        assertEquals("test sanity", 0, theView.mOnDetachCount);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.scrollListBy(mListView.getHeight() * 2);
+        });
+        assertNull("test sanity, unused view should be removed", theView.getParent());
+        assertEquals("unused view should be detached", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.scrollListBy(-mListView.getHeight() * 2);
+            // listview limits scroll to 1 page which is why we call it twice here.
+            mListView.scrollListBy(-mListView.getHeight() * 2);
+        });
+        assertNotNull("test sanity, view should be re-added", theView.getParent());
+        assertEquals("view should receive another attach call", 2, theView.mOnAttachCount);
+        assertEquals("view should not receive a detach call", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+    }
+
+    @MediumTest
+    public void testFullyDetachUnusedViewOnReLayout() {
+        final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.setAdapter(new DummyAdapter(1000, theView));
+        });
+        assertEquals("test sanity", 1, theView.mOnAttachCount);
+        assertEquals("test sanity", 0, theView.mOnDetachCount);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.setSelection(800);
+        });
+        assertNull("test sanity, unused view should be removed", theView.getParent());
+        assertEquals("unused view should be detached", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.setSelection(0);
+        });
+        assertNotNull("test sanity, view should be re-added", theView.getParent());
+        assertEquals("view should receive another attach call", 2, theView.mOnAttachCount);
+        assertEquals("view should not receive a detach call", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+    }
+
+    @MediumTest
+    public void testFullyDetachUnusedViewOnScrollForFocus() {
+        final AttachDetachAwareView theView = new AttachDetachAwareView(mActivity);
+        ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, () -> {
+            mListView.setAdapter(new DummyAdapter(1000, theView));
+        });
+        assertEquals("test sanity", 1, theView.mOnAttachCount);
+        assertEquals("test sanity", 0, theView.mOnDetachCount);
+        while(theView.getParent() != null) {
+            assertEquals("the view should NOT be detached", 0, theView.mOnDetachCount);
+            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+            ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, null);
+        }
+        assertEquals("the view should be detached", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+        while(theView.getParent() == null) {
+            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
+            ViewTestUtils.runOnMainAndDrawSync(getInstrumentation(), mListView, null);
+        }
+        assertEquals("the view should be re-attached", 2, theView.mOnAttachCount);
+        assertEquals("the view should not recieve another detach", 1, theView.mOnDetachCount);
+        assertFalse(theView.isTemporarilyDetached());
+    }
+
     private class MockView extends View {
 
         public boolean onMeasureCalled = false;
diff --git a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
index dd1a3a0..a827813 100644
--- a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
+++ b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
@@ -591,18 +591,15 @@
             }
 
             if (mTestConfig.mTestResult) {
-                double[] avgs = MediaUtils.calculateMovingAverage(
-                        mEncoderFrameTimeDiff[i], MOVING_AVERAGE_NUM);
-                double encMin = Stat.getMin(avgs);
-                double encMax = Stat.getMax(avgs);
-                double encAvg = MediaUtils.getAverage(mEncoderFrameTimeDiff[i]);
-                double encStdev = MediaUtils.getStdev(avgs);
+                MediaUtils.Stats encStats =
+                    new MediaUtils.Stats(mEncoderFrameTimeDiff[i])
+                            .movingAverage(MOVING_AVERAGE_NUM);
                 String prefix = "codec=" + encoderName + " round=" + i +
                         " EncInputFormat=" + mEncInputFormat +
                         " EncOutputFormat=" + mEncOutputFormat;
                 String result =
-                        MediaUtils.logResults(mReportLog, prefix, encMin, encMax, encAvg, encStdev);
-                double measuredEncFps = 1000000000 / encMin;
+                        MediaUtils.logAchievableRatesResults(mReportLog, prefix, encStats);
+                double measuredEncFps = 1000000000 / encStats.getMin();
                 resultRawData[i] = result;
                 measuredFps[i] = measuredEncFps;
                 if (!encTestPassed) {
@@ -610,16 +607,13 @@
                             encoderName, mimeType, w, h, measuredEncFps);
                 }
 
-                avgs = MediaUtils.calculateMovingAverage(
-                        mDecoderFrameTimeDiff[i], MOVING_AVERAGE_NUM);
-                double decMin = Stat.getMin(avgs);
-                double decMax = Stat.getMax(avgs);
-                double decAvg = MediaUtils.getAverage(mDecoderFrameTimeDiff[i]);
-                double decStdev = MediaUtils.getStdev(avgs);
+                MediaUtils.Stats decStats =
+                    new MediaUtils.Stats(mDecoderFrameTimeDiff[i])
+                            .movingAverage(MOVING_AVERAGE_NUM);
                 prefix = "codec=" + decoderName + " size=" + w + "x" + h + " round=" + i +
                         " DecOutputFormat=" + mDecOutputFormat;
-                MediaUtils.logResults(mReportLog, prefix, decMin, decMax, decAvg, decStdev);
-                double measuredDecFps = 1000000000 / decMin;
+                MediaUtils.logAchievableRatesResults(mReportLog, prefix, decStats);
+                double measuredDecFps = 1000000000 / decStats.getMin();
                 if (!decTestPassed) {
                     decTestPassed = MediaUtils.verifyResults(
                             decoderName, mimeType, w, h, measuredDecFps);
diff --git a/tests/vr/src/android/vr/cts/VrDisplayTest.java b/tests/vr/src/android/vr/cts/VrDisplayTest.java
index 6b8b302..9dfdf96 100644
--- a/tests/vr/src/android/vr/cts/VrDisplayTest.java
+++ b/tests/vr/src/android/vr/cts/VrDisplayTest.java
@@ -95,4 +95,25 @@
         assertTrue(displayWidth >= 1920);
         assertTrue(displayHeight >= 1080);
     }
+
+    /**
+     * Tests that the display dimensions are between 4.7" and 6".
+     */
+    public void testDisplayDimensions() {
+        mActivity = getGlEsActivity(1, 1);
+        if (!mActivity.supportsVrHighPerformance())
+            return;
+
+        WindowManager windowManager = (WindowManager)mActivity.getSystemService(
+            Context.WINDOW_SERVICE);
+        DisplayMetrics metrics = new DisplayMetrics();
+        windowManager.getDefaultDisplay().getRealMetrics(metrics);
+
+        double width = metrics.widthPixels / metrics.xdpi;
+        double height = metrics.heightPixels / metrics.ydpi;
+        double diagonalLength = Math.sqrt(width * width + height * height);
+
+        assertTrue(diagonalLength >= 4.7);
+        assertTrue(diagonalLength <= 6.);
+    }
 }