Merge "Camera: Handle case where BatteryInfo intent not available" into qt-dev
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 2513993..92a100b 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -16,6 +16,7 @@
                       tests/tests/content/
                       tests/tests/graphics/
                       tests/tests/hardware/
+		      tests/tests/permission2/
                       tests/tests/preference/
                       tests/tests/print/
                       tests/tests/text/
diff --git a/apps/CtsVerifier/res/layout/cf_main.xml b/apps/CtsVerifier/res/layout/cf_main.xml
index 1ff35cc..8a4fb7f 100644
--- a/apps/CtsVerifier/res/layout/cf_main.xml
+++ b/apps/CtsVerifier/res/layout/cf_main.xml
@@ -87,6 +87,11 @@
                 android:id="@+id/format_selection"
                 android:layout_width="fill_parent"
                 android:layout_height="wrap_content"/>
+            <Button
+                android:id="@+id/next_button"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/cf_next_button" />
 
         </LinearLayout>
 
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 3ecfab7..50eac36 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1318,10 +1318,12 @@
     the right view must be horizontally mirrored relative to the left
     view.\n - Note that the frame rate of the right view may be much
     lower than on the left; this is not an indication of a failed
-    test.
+    test.\n - The next button triggers the next resolution and format
+    combination of the current camera to show; this is optional.
     </string>
     <string name="cf_preview_label">Normal preview</string>
     <string name="cf_format_label">Processed callback data</string>
+    <string name="cf_next_button">Next</string>
 
     <!-- Strings for Camera Video -->
     <string name="record_button_text">Test</string>
@@ -4990,6 +4992,10 @@
         BubbleMetadata is configured on the notification and user actions. Bubbles are special
         notifications that appear as a floating button on the screen, in addition to the notification
         in the notification shade.</string>
+    <string name="bubbles_notification_test_enable_bubbles_title">Enable Bubbles for CTS Verifier</string>
+    <string name="bubbles_notification_test_enable_bubbles_verify">Click the button below and enable
+        bubbles for the verifier app on the resulting screen, if they aren\'t enabled already.</string>
+    <string name="bubbles_notification_enable_bubbles_button">Enable bubbles for CTS Verifier</string>
     <string name="bubbles_notification_test_title_1">Step 1: send a bubble with notification</string>
     <string name="bubbles_notification_test_verify_1">Click the button below and verify that there is a
         bubble on the screen and a notification in the notification shade.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/admin/PolicySerializationTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/admin/PolicySerializationTestActivity.java
index 72c54c2..9b54ed3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/admin/PolicySerializationTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/admin/PolicySerializationTestActivity.java
@@ -94,9 +94,6 @@
             }
         });
 
-        mPolicyItems.add(new PasswordQualityPolicy(this));
-        mPolicyItems.add(new PasswordMinimumLengthPolicy(this));
-
         if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)) {
             mPolicyItems.add(new MaximumFailedPasswordsForWipePolicy(this));
         }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
index 9c5b31d..3421f65 100755
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
@@ -40,6 +40,7 @@
 import android.view.TextureView;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
+import android.widget.Button;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.Spinner;
@@ -51,6 +52,7 @@
 import java.util.HashSet;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Optional;
 import java.util.TreeSet;
 
 /**
@@ -99,14 +101,39 @@
     private boolean mProcessInProgress = false;
     private boolean mProcessingFirstFrame = false;
 
-    private TreeSet<String> mTestedCombinations = new TreeSet<String>();
-    private TreeSet<String> mUntestedCombinations = new TreeSet<String>();
+    private final TreeSet<CameraCombination> mTestedCombinations = new TreeSet<>(COMPARATOR);
+    private final TreeSet<CameraCombination> mUntestedCombinations = new TreeSet<>(COMPARATOR);
 
     private int mAllCombinationsSize = 0;
 
     // Menu to show the test progress
     private static final int MENU_ID_PROGRESS = Menu.FIRST + 1;
 
+    private class CameraCombination {
+        private final int cameraIndex;
+        private final int resolutionIndex;
+        private final int formatIndex;
+
+        private CameraCombination(int cameraIndex, int resolutionIndex, int formatIndex) {
+            this.cameraIndex = cameraIndex;
+            this.resolutionIndex = resolutionIndex;
+            this.formatIndex = formatIndex;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("Camera %d, %dx%d, %s", cameraIndex,
+                mPreviewSizes.get(resolutionIndex).width,
+                mPreviewSizes.get(resolutionIndex).height,
+                mPreviewFormatNames.get(mPreviewFormats.get(formatIndex)));
+        }
+    }
+
+    private static final Comparator<CameraCombination> COMPARATOR =
+        Comparator.<CameraCombination, Integer>comparing(c -> c.cameraIndex)
+            .thenComparing(c -> c.resolutionIndex)
+            .thenComparing(c -> c.formatIndex);
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -130,7 +157,6 @@
         String[] cameraNames = new String[numCameras];
         for (int i = 0; i < numCameras; i++) {
             cameraNames[i] = "Camera " + i;
-            mUntestedCombinations.add("All combinations for Camera " + i + "\n");
         }
         mCameraSpinner = (Spinner) findViewById(R.id.cameras_selection);
         mCameraSpinner.setAdapter(
@@ -171,6 +197,35 @@
         yTotal.setConcat(y2r, yOffset);
 
         mYuv2RgbFilter = new ColorMatrixColorFilter(yTotal);
+
+        Button mNextButton = findViewById(R.id.next_button);
+        mNextButton.setOnClickListener(v -> {
+                setUntestedCombination();
+                startPreview();
+        });
+    }
+
+    /**
+     * Set an untested combination of resolution and format for the current camera.
+     * Triggered by next button click.
+     */
+    private void setUntestedCombination() {
+        Optional<CameraCombination> combination = mUntestedCombinations.stream().filter(
+            c -> c.cameraIndex == mCurrentCameraId).findFirst();
+        if (!combination.isPresent()) {
+            Toast.makeText(this, "All Camera " + mCurrentCameraId + " tests are done.",
+                Toast.LENGTH_SHORT).show();
+            return;
+        }
+
+        // There is untested combination for the current camera, set the next untested combination.
+        int mResolutionIndex = combination.get().resolutionIndex;
+        int mFormatIndex = combination.get().formatIndex;
+
+        mNextPreviewSize = mPreviewSizes.get(mResolutionIndex);
+        mResolutionSpinner.setSelection(mResolutionIndex);
+        mNextPreviewFormat = mPreviewFormats.get(mFormatIndex);
+        mFormatSpinner.setSelection(mFormatIndex);
     }
 
     @Override
@@ -183,13 +238,13 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         boolean ret = true;
         switch (item.getItemId()) {
-        case MENU_ID_PROGRESS:
-            showCombinationsDialog();
-            ret = true;
-            break;
-        default:
-            ret = super.onOptionsItemSelected(item);
-            break;
+            case MENU_ID_PROGRESS:
+                showCombinationsDialog();
+                ret = true;
+                break;
+            default:
+                ret = super.onOptionsItemSelected(item);
+                break;
         }
         return ret;
     }
@@ -222,17 +277,19 @@
     public String getTestDetails() {
         StringBuilder reportBuilder = new StringBuilder();
         reportBuilder.append("Tested combinations:\n");
-        for (String combination: mTestedCombinations) {
+        for (CameraCombination combination: mTestedCombinations) {
             reportBuilder.append(combination);
+            reportBuilder.append("\n");
         }
+
         reportBuilder.append("Untested combinations:\n");
-        for (String combination: mUntestedCombinations) {
+        for (CameraCombination combination: mUntestedCombinations) {
             reportBuilder.append(combination);
+            reportBuilder.append("\n");
         }
         return reportBuilder.toString();
     }
 
-
     public void onSurfaceTextureAvailable(SurfaceTexture surface,
             int width, int height) {
         mPreviewTexture = surface;
@@ -240,7 +297,7 @@
                 || mFormatView.getMeasuredHeight() != height) {
             mPreviewTexWidth = mFormatView.getMeasuredWidth();
             mPreviewTexHeight = mFormatView.getMeasuredHeight();
-         } else {
+        } else {
             mPreviewTexWidth = width;
             mPreviewTexHeight = height;
         }
@@ -310,8 +367,6 @@
 
             };
 
-
-
     private void setUpCamera(int id) {
         shutdownCamera();
 
@@ -331,7 +386,7 @@
                 if (lhs.height > rhs.height) return 1;
                 return 0;
             }
-        };
+        }
 
         SizeCompare s = new SizeCompare();
         TreeSet<Camera.Size> sortedResolutions = new TreeSet<Camera.Size>(s);
@@ -365,13 +420,11 @@
 
         // Update untested entries
 
-        mUntestedCombinations.remove("All combinations for Camera " + id + "\n");
-        for (Camera.Size previewSize: mPreviewSizes) {
-            for (int previewFormat: mPreviewFormats) {
-                String combination = "Camera " + id + ", "
-                        + previewSize.width + "x" + previewSize.height
-                        + ", " + mPreviewFormatNames.get(previewFormat)
-                        + "\n";
+        for (int resolutionIndex = 0; resolutionIndex < mPreviewSizes.size(); resolutionIndex++) {
+            for (int formatIndex = 0; formatIndex < mPreviewFormats.size(); formatIndex++) {
+                CameraCombination combination = new CameraCombination(
+                    id, resolutionIndex, formatIndex);
+
                 if (!mTestedCombinations.contains(combination)) {
                     mUntestedCombinations.add(combination);
                 }
@@ -571,14 +624,16 @@
                 mFormatView.setImageBitmap(mCallbackBitmap);
                 if (mProcessingFirstFrame) {
                     mProcessingFirstFrame = false;
-                    String combination = "Camera " + mCurrentCameraId + ", "
-                            + mPreviewSize.width + "x" + mPreviewSize.height
-                            + ", " + mPreviewFormatNames.get(mPreviewFormat)
-                            + "\n";
+
+                    CameraCombination combination = new CameraCombination(
+                        mCurrentCameraId,
+                        mResolutionSpinner.getSelectedItemPosition(),
+                        mFormatSpinner.getSelectedItemPosition());
+
                     mUntestedCombinations.remove(combination);
                     mTestedCombinations.add(combination);
 
-                    displayToast(combination.replace("\n", ""));
+                    displayToast(combination.toString());
 
                     if (mTestedCombinations.size() == mAllCombinationsSize) {
                         setPassButtonEnabled(true);
@@ -617,7 +672,8 @@
     }
 
     private void displayToast(String combination) {
-        Toast.makeText(this, "\"" + combination + "\"\n" + " has been tested.", Toast.LENGTH_LONG).show();
+        Toast.makeText(this, "\"" + combination + "\"\n" + " has been tested.", Toast.LENGTH_SHORT)
+            .show();
     }
 
     public void onPreviewFrame(byte[] data, Camera camera) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
index d5c81fe..fd1c457 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/BubblesVerifierActivity.java
@@ -29,6 +29,7 @@
 import android.graphics.Color;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.TextView;
@@ -100,6 +101,7 @@
             runNextTestOrShowSummary();
         });
 
+        mTests.add(new EnableBubbleTest());
         mTests.add(new SendBubbleTest());
         mTests.add(new SuppressNotifTest());
         mTests.add(new AddNotifTest());
@@ -178,6 +180,38 @@
         }
     }
 
+    private class EnableBubbleTest extends BubblesTestStep {
+
+        @Override
+        public int getButtonText() {
+            return R.string.bubbles_notification_enable_bubbles_button;
+        }
+
+
+        @Override
+        public int getTestTitle() {
+            return R.string.bubbles_notification_test_enable_bubbles_title;
+        }
+
+        @Override
+        public int getTestDescription() {
+            return R.string.bubbles_notification_test_enable_bubbles_verify;
+        }
+
+        @Override
+        public void performTestAction() {
+            final String packageName = getApplicationContext().getPackageName();
+            final int appUid = getApplicationInfo().uid;
+            final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
+            intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
+            intent.putExtra(Settings.EXTRA_APP_UID, appUid);
+            intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+            startActivity(intent);
+        }
+    }
+
     private class SendBubbleTest extends BubblesTestStep {
 
         @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
index a3de878..1b14d2b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
@@ -304,7 +304,14 @@
 
             if (!TextUtils.isEmpty(id)) {
                 AutomaticZenRule rule = mNm.getAutomaticZenRule(id);
-                if (Objects.equals(ruleToCreate, rule)) {
+                if (rule != null && ruleToCreate.getName().equals(rule.getName())
+                        && ruleToCreate.getOwner().equals(rule.getOwner())
+                        && ruleToCreate.getConditionId().equals(rule.getConditionId())
+                        && ruleToCreate.isEnabled() == rule.isEnabled()
+                        && ruleToCreate.getInterruptionFilter() == rule.getInterruptionFilter()
+                        && Objects.equals(ruleToCreate.getConfigurationActivity(),
+                        rule.getConfigurationActivity())
+                        && Objects.equals(ruleToCreate.getZenPolicy(), rule.getZenPolicy())) {
                     status = PASS;
                 } else {
                     logFail("created rule doesn't equal actual rule");
diff --git a/apps/OomCatcher/Android.mk b/apps/OomCatcher/Android.mk
index 7f47e03..e14cde5 100644
--- a/apps/OomCatcher/Android.mk
+++ b/apps/OomCatcher/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_SDK_VERSION := current
 
-LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
index 23df503..93f6f19 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgrade.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk
index 11f8674..2faf2d4 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/arm/CtsShimPrivUpgradeWrongSHA.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
index fc9f02e..f0cc8b6 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgrade.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA.apk
index bf49682..d7e0826 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/apk/x86/CtsShimPrivUpgradeWrongSHA.apk
Binary files differ
diff --git a/hostsidetests/devicepolicy/app/DeviceAdmin/api29/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAdmin/api29/AndroidManifest.xml
index a0bf3c0..326e61f 100644
--- a/hostsidetests/devicepolicy/app/DeviceAdmin/api29/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAdmin/api29/AndroidManifest.xml
@@ -17,8 +17,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.cts.deviceadmin29" >
 
-    <!-- STOPSHIP(b/114173216): Uncomment this once Q's API level is finalized -->
-    <!--<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="29"/>-->
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="29"/>
 
     <application
         android:testOnly="true">
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/InstallUpdateTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/InstallUpdateTest.java
index e6bf9c0..1cbf5b2 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/InstallUpdateTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/InstallUpdateTest.java
@@ -53,14 +53,6 @@
                 InstallSystemUpdateCallback.UPDATE_ERROR_FILE_NOT_FOUND);
     }
 
-    public void testInstallUpdate_failWrongVersion() throws InterruptedException {
-        assertUpdateError(
-                "wrongVersion.zip",
-                isDeviceAB()
-                        ? InstallSystemUpdateCallback.UPDATE_ERROR_INCORRECT_OS_VERSION
-                        : InstallSystemUpdateCallback.UPDATE_ERROR_UNKNOWN);
-    }
-
     public void testInstallUpdate_failNoZipOtaFile() throws InterruptedException {
         assertUpdateError("notZip.zi",
                 isDeviceAB()
diff --git a/hostsidetests/devicepolicy/res/wrongVersion.zip b/hostsidetests/devicepolicy/res/wrongVersion.zip
deleted file mode 100644
index 3dfcfa8..0000000
--- a/hostsidetests/devicepolicy/res/wrongVersion.zip
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index f26733c..6130759 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -549,6 +549,8 @@
                 Collections.singletonMap(ARG_NETWORK_LOGGING_BATCH_COUNT, Integer.toString(1)));
         // Reboot the device, so the security event IDs are re-set.
         rebootAndWaitUntilReady();
+        // Make sure BOOT_COMPLETED is completed before proceeding.
+        waitForBroadcastIdle();
         // First batch after reboot: retrieve and verify the events.
         executeDeviceTestMethod(".NetworkLoggingTest", "testNetworkLoggingAndRetrieval",
                 Collections.singletonMap(ARG_NETWORK_LOGGING_BATCH_COUNT, Integer.toString(1)));
@@ -1028,7 +1030,6 @@
             return;
         }
 
-        pushUpdateFileToDevice("wrongVersion.zip");
         pushUpdateFileToDevice("notZip.zi");
         pushUpdateFileToDevice("empty.zip");
         pushUpdateFileToDevice("wrongPayload.zip");
diff --git a/hostsidetests/rollback/app/src/com/android/cts/rollback/host/app/HostTestHelper.java b/hostsidetests/rollback/app/src/com/android/cts/rollback/host/app/HostTestHelper.java
index c7a75a7..1e8040d 100644
--- a/hostsidetests/rollback/app/src/com/android/cts/rollback/host/app/HostTestHelper.java
+++ b/hostsidetests/rollback/app/src/com/android/cts/rollback/host/app/HostTestHelper.java
@@ -292,4 +292,42 @@
 
         // At this point, the host test driver will reboot the device to complete the uninstall.
     }
+
+    /**
+     * Tests that apex update expires existing rollbacks for that apex.
+     * Enable rollback phase.
+     */
+    @Test
+    public void testApexRollbackExpirationEnableRollback() throws Exception {
+        assertThat(Utils.getInstalledVersion(TestApp.Apex)).isEqualTo(1);
+
+        Install.single(TestApp.Apex2).setStaged().setEnableRollback().commit();
+
+        // At this point, the host test driver will reboot the device and run
+        // testApexRollbackExpirationUpdateApex().
+    }
+
+    /**
+     * Tests that apex update expires existing rollbacks for that apex.
+     * Update apex phase.
+     */
+    @Test
+    public void testApexRollbackExpirationUpdateApex() throws Exception {
+        assertThat(Utils.getInstalledVersion(TestApp.Apex)).isEqualTo(2);
+        assertThat(Utils.getAvailableRollback(TestApp.Apex)).isNotNull();
+        Install.single(TestApp.Apex3).setStaged().commit();
+
+        // At this point, the host test driver will reboot the device and run
+        // testApexRollbackExpirationConfirmExpiration().
+    }
+
+    /**
+     * Tests that apex update expires existing rollbacks for that apex.
+     * Confirm expiration phase.
+     */
+    @Test
+    public void testApexRollbackExpirationConfirmExpiration() throws Exception {
+        assertThat(Utils.getInstalledVersion(TestApp.Apex)).isEqualTo(3);
+        assertThat(Utils.getAvailableRollback(TestApp.Apex)).isNull();
+    }
 }
diff --git a/hostsidetests/rollback/src/com/android/cts/rollback/host/RollbackManagerHostTest.java b/hostsidetests/rollback/src/com/android/cts/rollback/host/RollbackManagerHostTest.java
index e9192dd..60e154c 100644
--- a/hostsidetests/rollback/src/com/android/cts/rollback/host/RollbackManagerHostTest.java
+++ b/hostsidetests/rollback/src/com/android/cts/rollback/host/RollbackManagerHostTest.java
@@ -147,4 +147,20 @@
         getDevice().reboot();
         run("testApexAndApkConfirmRollback");
     }
+
+    /**
+     * Tests that apex update expires existing rollbacks for that apex.
+     */
+    @Test
+    public void testApexRollbackExpiration() throws Exception {
+        assumeTrue("Device does not support updating APEX", isApexUpdateSupported());
+
+        uninstallShimApexIfNecessary();
+        run("testApexRollbackExpirationEnableRollback");
+        getDevice().reboot();
+        run("testApexRollbackExpirationUpdateApex");
+        getDevice().reboot();
+        run("testApexRollbackExpirationConfirmExpiration");
+    }
+
 }
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/Android.mk
index e9ffee4..0bd5a7c 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/Android.mk
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2014-9803/Android.mk
@@ -21,7 +21,7 @@
 LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
 LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 
-LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
 LOCAL_CTS_TEST_PACKAGE := android.security.cts
 
 LOCAL_ARM_MODE := arm
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
index 68f06d5..6ddd9f1 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
@@ -141,6 +141,7 @@
             if (deviceToReboot != null) {
                 deviceToReboot.nonBlockingReboot();
                 deviceToReboot.waitForDeviceAvailable();
+                updateKernelStartTime();
             }
         }
         fail("\"" + ptr + "\" is an exposed kernel pointer.");
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
index 388fd0a..71c34c2 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
@@ -16,6 +16,7 @@
 
 package android.accessibilityservice.cts;
 
+import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.filterWindowsChangeTypesAndWindowTitle;
 import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.filterWindowsChangedWithChangeTypes;
 import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.findWindowByTitle;
 import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.getActivityTitle;
@@ -275,8 +276,8 @@
                         autoCompleteTextView.setAdapter(adapter);
                         autoCompleteTextView.showDropDown();
                     }),
-                    filterWindowsChangedWithChangeTypes(WINDOWS_CHANGE_CHILDREN),
-                    TIMEOUT_ASYNC_PROCESSING);
+                    filterWindowsChangeTypesAndWindowTitle(sUiAutomation, WINDOWS_CHANGE_CHILDREN,
+                            mActivityTitle.toString()), TIMEOUT_ASYNC_PROCESSING);
         } catch (TimeoutException exception) {
             throw new RuntimeException(
                     "Failed to get window changed event when showing dropdown", exception);
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/AccessibilityEventFilterUtils.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/AccessibilityEventFilterUtils.java
index 3da457a..790246e 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/AccessibilityEventFilterUtils.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/AccessibilityEventFilterUtils.java
@@ -14,13 +14,20 @@
 
 package android.accessibilityservice.cts.utils;
 
+import static org.hamcrest.CoreMatchers.allOf;
 import static org.hamcrest.CoreMatchers.both;
+
+import android.app.UiAutomation;
 import android.app.UiAutomation.AccessibilityEventFilter;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityWindowInfo;
+
+import androidx.annotation.NonNull;
 
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeMatcher;
 
+import java.util.List;
 import java.util.function.BiPredicate;
 
 /**
@@ -45,6 +52,13 @@
         return (both(new AccessibilityEventTypeMatcher(eventType)).and(matchResourceName))::matches;
     }
 
+    public static AccessibilityEventFilter filterWindowsChangeTypesAndWindowTitle(
+            @NonNull UiAutomation uiAutomation, int changeTypes, @NonNull String title) {
+        return allOf(new AccessibilityEventTypeMatcher(AccessibilityEvent.TYPE_WINDOWS_CHANGED),
+                new WindowChangesMatcher(changeTypes),
+                new WindowTitleMatcher(uiAutomation, title))::matches;
+    }
+
     public static class AccessibilityEventTypeMatcher extends TypeSafeMatcher<AccessibilityEvent> {
         private int mType;
 
@@ -125,4 +139,32 @@
             description.appendText("Matching to " + mDescription + " " + mProperty.toString());
         }
     }
+
+    public static class WindowTitleMatcher extends TypeSafeMatcher<AccessibilityEvent> {
+        private final UiAutomation mUiAutomation;
+        private final String mTitle;
+
+        public WindowTitleMatcher(@NonNull UiAutomation uiAutomation, @NonNull String title) {
+            super();
+            mUiAutomation = uiAutomation;
+            mTitle = title;
+        }
+
+        @Override
+        protected boolean matchesSafely(AccessibilityEvent event) {
+            final List<AccessibilityWindowInfo> windows = mUiAutomation.getWindows();
+            final int eventWindowId = event.getWindowId();
+            for (AccessibilityWindowInfo info : windows) {
+                if (eventWindowId == info.getId() && mTitle.equals(info.getTitle())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("With window title " + mTitle);
+        }
+    }
 }
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index 56badff..a576e62 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -401,6 +401,18 @@
                   android:resizeableActivity="true"
                   android:turnScreenOn="true"/>
 
+        <activity android:name="android.app.stubs.BubblesTestNotEmbeddableActivity"
+                  android:resizeableActivity="true"
+                  android:documentLaunchMode="always"
+                  android:exported="true"
+        />
+
+        <activity android:name="android.app.stubs.BubblesTestNotDocumentLaunchModeActivity"
+                  android:resizeableActivity="true"
+                  android:allowEmbedded="true"
+                  android:exported="true"
+        />
+
         <service android:name="android.app.stubs.BubblesTestService"
                  android:label="BubblesTestsService"
                  android:exported="true">
diff --git a/tests/app/app/src/android/app/stubs/BubblesTestActivity.java b/tests/app/app/src/android/app/stubs/BubblesTestActivity.java
index 5a80de4..36f51c3 100644
--- a/tests/app/app/src/android/app/stubs/BubblesTestActivity.java
+++ b/tests/app/app/src/android/app/stubs/BubblesTestActivity.java
@@ -56,7 +56,7 @@
     public void sendBubble(int i) {
         Context context = getApplicationContext();
 
-        final Intent intent = new Intent();
+        final Intent intent = new Intent(context, BubblesTestActivity.class);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
         intent.setAction(Intent.ACTION_MAIN);
diff --git a/tests/app/app/src/android/app/stubs/BubblesTestNotDocumentLaunchModeActivity.java b/tests/app/app/src/android/app/stubs/BubblesTestNotDocumentLaunchModeActivity.java
new file mode 100644
index 0000000..8601ed2
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/BubblesTestNotDocumentLaunchModeActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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.app.stubs;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Used by NotificationManagerTest for testing policy around bubbles.
+ */
+public class BubblesTestNotDocumentLaunchModeActivity extends Activity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+}
diff --git a/tests/app/app/src/android/app/stubs/BubblesTestNotEmbeddableActivity.java b/tests/app/app/src/android/app/stubs/BubblesTestNotEmbeddableActivity.java
new file mode 100644
index 0000000..ced310a
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/BubblesTestNotEmbeddableActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 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.app.stubs;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Used by NotificationManagerTest for testing policy around bubbles.
+ */
+public class BubblesTestNotEmbeddableActivity extends Activity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+}
+
diff --git a/tests/app/app/src/android/app/stubs/BubblesTestService.java b/tests/app/app/src/android/app/stubs/BubblesTestService.java
index fadf00c..6ff579b 100644
--- a/tests/app/app/src/android/app/stubs/BubblesTestService.java
+++ b/tests/app/app/src/android/app/stubs/BubblesTestService.java
@@ -59,8 +59,9 @@
     }
 
     private Notification getNotificationForTest(final int testCase, final Context context) {
+        final Intent intent = new Intent(context, BubblesTestActivity.class);
         final PendingIntent pendingIntent =
-                PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), 0);
+                PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
         Notification.Builder nb = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
                 .setContentTitle("foofoo")
                 .setContentIntent(pendingIntent)
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 559a7bf..3513f21 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -51,6 +51,8 @@
 import android.app.UiAutomation;
 import android.app.stubs.AutomaticZenRuleActivity;
 import android.app.stubs.BubblesTestActivity;
+import android.app.stubs.BubblesTestNotDocumentLaunchModeActivity;
+import android.app.stubs.BubblesTestNotEmbeddableActivity;
 import android.app.stubs.BubblesTestService;
 import android.app.stubs.R;
 import android.app.stubs.TestNotificationListener;
@@ -180,6 +182,14 @@
         }
     }
 
+    private void toggleBubbleSetting(boolean enabled) throws InterruptedException {
+        SystemUtil.runWithShellPermissionIdentity(() ->
+                Settings.Secure.putInt(mContext.getContentResolver(),
+                        Settings.Secure.NOTIFICATION_BUBBLES, enabled ? 1 : 0));
+        Thread.sleep(500); // wait for ranking update
+
+    }
+
     private void insertSingleContact(String name, String phone, String email, boolean starred) {
         final ArrayList<ContentProviderOperation> operationList =
                 new ArrayList<ContentProviderOperation>();
@@ -367,7 +377,7 @@
 
     private void sendAndVerifyBubble(final int id, Notification.Builder builder,
             Notification.BubbleMetadata data, boolean shouldBeBubble) {
-        final Intent intent = new Intent(Intent.ACTION_MAIN, Threads.CONTENT_URI);
+        final Intent intent = new Intent(mContext, BubblesTestActivity.class);
 
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -1072,11 +1082,7 @@
         }
 
         // turn on bubbles globally
-        SystemUtil.runWithShellPermissionIdentity(() ->
-                Settings.Secure.putInt(mContext.getContentResolver(),
-                        Settings.Secure.NOTIFICATION_BUBBLES, 1));
-
-        Thread.sleep(500); // wait for ranking update
+        toggleBubbleSetting(true);
 
         assertEquals(1, Settings.Secure.getInt(
                 mContext.getContentResolver(), Settings.Secure.NOTIFICATION_BUBBLES));
@@ -1102,25 +1108,21 @@
             }
 
             // turn off bubbles globally
-            SystemUtil.runWithShellPermissionIdentity(() ->
-                    Settings.Secure.putInt(mContext.getContentResolver(),
-                            Settings.Secure.NOTIFICATION_BUBBLES, 0));
-
-            Thread.sleep(500); // wait for ranking update
+            toggleBubbleSetting(false);
 
             rankingMap = mListener.mRankingMap;
             outRanking = new NotificationListenerService.Ranking();
             for (String key : rankingMap.getOrderedKeys()) {
                 if (key.contains(mListener.getPackageName())) {
+                    rankingMap.getRanking(key, outRanking);
                     assertFalse(outRanking.canBubble());
                 }
             }
 
             mListener.resetData();
         } finally {
-            SystemUtil.runWithShellPermissionIdentity(() ->
-                    Settings.Secure.putInt(mContext.getContentResolver(),
-                            Settings.Secure.NOTIFICATION_BUBBLES, 0));
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
         }
     }
 
@@ -2398,24 +2400,267 @@
                 badNumberString);
     }
 
-    public void testNotificationManagerBubblePolicy_flagForMessage_failsNoRemoteInput() {
-        Person person = new Person.Builder()
-                .setName("bubblebot")
-                .build();
-        Notification.Builder nb = new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
-                .setContentTitle("foo")
-                .setStyle(new Notification.MessagingStyle(person)
-                        .setConversationTitle("Bubble Chat")
-                        .addMessage("Hello?",
-                                SystemClock.currentThreadTimeMillis() - 300000, person)
-                        .addMessage("Is it me you're looking for?",
-                                SystemClock.currentThreadTimeMillis(), person)
-                )
-                .setSmallIcon(android.R.drawable.sym_def_app_icon);
-        sendAndVerifyBubble(1, nb, null /* use default metadata */, false);
+    public void testNotificationManagerBubblePolicy_flagForMessage_failsNoRemoteInput()
+            throws InterruptedException {
+        try {
+            // turn on bubbles globally
+            toggleBubbleSetting(true);
+
+            Person person = new Person.Builder()
+                    .setName("bubblebot")
+                    .build();
+            Notification.Builder nb = new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
+                    .setContentTitle("foo")
+                    .setStyle(new Notification.MessagingStyle(person)
+                            .setConversationTitle("Bubble Chat")
+                            .addMessage("Hello?",
+                                    SystemClock.currentThreadTimeMillis() - 300000, person)
+                            .addMessage("Is it me you're looking for?",
+                                    SystemClock.currentThreadTimeMillis(), person)
+                    )
+                    .setSmallIcon(android.R.drawable.sym_def_app_icon);
+            sendAndVerifyBubble(1, nb, null /* use default metadata */, false);
+        } finally {
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
+        }
     }
 
-    public void testNotificationManagerBubblePolicy_flagForMessage_succeeds() {
+    public void testNotificationManagerBubblePolicy_flagForMessage_succeeds()
+            throws InterruptedException {
+        try {
+            // turn on bubbles globally
+            toggleBubbleSetting(true);
+
+            Person person = new Person.Builder()
+                    .setName("bubblebot")
+                    .build();
+
+            RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel(
+                    "reply").build();
+            PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+            Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
+            Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
+                    inputIntent).addRemoteInput(remoteInput)
+                    .build();
+
+            Notification.Builder nb = new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
+                    .setContentTitle("foo")
+                    .setStyle(new Notification.MessagingStyle(person)
+                            .setConversationTitle("Bubble Chat")
+                            .addMessage("Hello?",
+                                    SystemClock.currentThreadTimeMillis() - 300000, person)
+                            .addMessage("Is it me you're looking for?",
+                                    SystemClock.currentThreadTimeMillis(), person)
+                    )
+                    .setActions(replyAction)
+                    .setSmallIcon(android.R.drawable.sym_def_app_icon);
+
+            boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
+            sendAndVerifyBubble(1, nb, null /* use default metadata */, shouldBeBubble);
+        } finally {
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
+        }
+    }
+
+    public void testNotificationManagerBubblePolicy_flagForPhonecall() throws InterruptedException {
+        try {
+            // turn on bubbles globally
+            toggleBubbleSetting(true);
+
+            Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
+            serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_SUCCESS);
+            mContext.startService(serviceIntent);
+
+            boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
+            if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
+                    true /* shouldExist */, shouldBeBubble)) {
+                fail("couldn't find posted notification bubble with id=" + BUBBLE_NOTIF_ID);
+            }
+
+        } finally {
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
+        }
+    }
+
+    public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoPerson()
+            throws InterruptedException {
+        try {
+            // turn on bubbles globally
+            toggleBubbleSetting(true);
+
+            Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
+            serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_NO_PERSON);
+            mContext.startService(serviceIntent);
+
+            if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
+                    true /* shouldExist */, false /* shouldBeBubble */)) {
+                fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
+                        + " or it was a bubble when it shouldn't be");
+            }
+        } finally {
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
+        }
+    }
+
+    public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoForeground()
+            throws InterruptedException {
+        try {
+            // turn on bubbles globally
+            toggleBubbleSetting(true);
+
+            Person person = new Person.Builder()
+                    .setName("bubblebot")
+                    .build();
+            Notification.Builder nb = new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
+                    .setContentTitle("foo")
+                    .setCategory(CATEGORY_CALL)
+                    .addPerson(person)
+                    .setSmallIcon(android.R.drawable.sym_def_app_icon);
+            sendAndVerifyBubble(1, nb, null /* use default metadata */, false /* shouldBeBubble */);
+
+        } finally {
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
+        }
+    }
+
+    public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoCategory()
+            throws InterruptedException {
+        try {
+            // turn on bubbles globally
+            toggleBubbleSetting(true);
+
+            Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
+            serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_NO_CATEGORY);
+            mContext.startService(serviceIntent);
+
+            if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
+                    true /* shouldExist */, false /* shouldBeBubble */)) {
+                fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
+                        + " or it was a bubble when it shouldn't be");
+            }
+
+        } finally {
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
+        }
+
+    }
+
+    public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoMetadata()
+            throws InterruptedException {
+        try {
+            // turn on bubbles globally
+            toggleBubbleSetting(true);
+
+            Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
+            serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_NO_BUBBLE_METADATA);
+            mContext.startService(serviceIntent);
+
+            if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
+                    true /* shouldExist */, false /* shouldBeBubble */)) {
+                fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
+                        + " or it was a bubble when it shouldn't be");
+            }
+        } finally {
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
+        }
+    }
+
+    public void testNotificationManagerBubblePolicy_noFlagForAppNotForeground()
+            throws InterruptedException {
+        try {
+            // turn on bubbles globally
+            toggleBubbleSetting(true);
+
+            sendAndVerifyBubble(1, null /* use default notif */, null /* use default metadata */,
+                    false /* shouldBeBubble */);
+        } finally {
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
+        }
+    }
+
+    public void testNotificationManagerBubblePolicy_flagForAppForeground() throws Exception {
+        try {
+            // turn on bubbles globally
+            toggleBubbleSetting(true);
+
+            final CountDownLatch latch = new CountDownLatch(2);
+            BroadcastReceiver receiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    latch.countDown();
+                }
+            };
+            IntentFilter filter = new IntentFilter(BubblesTestActivity.BUBBLE_ACTIVITY_OPENED);
+            mContext.registerReceiver(receiver, filter);
+
+            // Start & get the activity
+            BubblesTestActivity a = (BubblesTestActivity) launchSendBubbleActivity();
+
+            // Make sure device is unlocked
+            KeyguardManager keyguardManager =
+                    (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+            keyguardManager.requestDismissKeyguard(a, new KeyguardManager.KeyguardDismissCallback() {
+                @Override
+                public void onDismissSucceeded() {
+                    latch.countDown();
+                }
+            });
+            try {
+                latch.await(100, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+
+            // Should be foreground now
+            a.sendBubble(1);
+
+            if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
+                    true /* shouldExist */, true /* shouldBeBubble */)) {
+                fail("couldn't find posted notification bubble with id=" + BUBBLE_NOTIF_ID);
+            }
+
+            // Make ourselves not foreground
+            HomeHelper homeHelper = new HomeHelper();
+            homeHelper.goHome();
+
+            // The notif should be allowed to update as a bubble
+            a.sendBubble(2);
+
+            boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
+
+            if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
+                    true /* shouldExist */, shouldBeBubble)) {
+                fail("couldn't find posted notification bubble with id=" + BUBBLE_NOTIF_ID);
+            }
+
+            // Cancel the notif
+            cancelAndPoll(BUBBLE_NOTIF_ID);
+
+            // Send it again when not foreground, this should not be a bubble & just be a notif
+            a.sendBubble(3);
+            if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
+                    true /* shouldExist */, false /* shouldBeBubble */)) {
+                fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
+                        + " or it was a bubble when it shouldn't be");
+            }
+
+            mContext.unregisterReceiver(receiver);
+            homeHelper.close();
+        } finally {
+            // turn off bubbles globally
+            toggleBubbleSetting(false);
+        }
+    }
+
+    public void testNotificationManagerBubblePolicy_noFlag_notEmbeddable() throws Exception {
         Person person = new Person.Builder()
                 .setName("bubblebot")
                 .build();
@@ -2439,138 +2684,51 @@
                 .setActions(replyAction)
                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
 
-        boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
-        sendAndVerifyBubble(1, nb, null /* use default metadata */, shouldBeBubble);
+        final Intent intent = new Intent(mContext, BubblesTestNotEmbeddableActivity.class);
+        final PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, intent, 0);
+
+        Notification.BubbleMetadata.Builder metadataBuilder =
+                new Notification.BubbleMetadata.Builder()
+                        .setIntent(pendingIntent)
+                        .setIcon(Icon.createWithResource(mContext, R.drawable.black));
+
+        sendAndVerifyBubble(1, nb, metadataBuilder.build(), false);
     }
 
-    public void testNotificationManagerBubblePolicy_flagForPhonecall() {
-        Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
-        serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_SUCCESS);
-        mContext.startService(serviceIntent);
-
-        boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
-        if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
-                true /* shouldExist */, shouldBeBubble)) {
-            fail("couldn't find posted notification bubble with id=" + BUBBLE_NOTIF_ID);
-        }
-    }
-
-    public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoPerson() {
-        Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
-        serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_NO_PERSON);
-        mContext.startService(serviceIntent);
-
-        if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
-                true /* shouldExist */, false /* shouldBeBubble */)) {
-            fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
-                    + " or it was a bubble when it shouldn't be");
-        }
-    }
-
-    public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoForeground() {
+    public void testNotificationManagerBubblePolicy_noFlag_notDocumentLaunchModeAlways() throws Exception {
         Person person = new Person.Builder()
                 .setName("bubblebot")
                 .build();
+
+        RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build();
+        PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
+        Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon);
+        Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply",
+                inputIntent).addRemoteInput(remoteInput)
+                .build();
+
         Notification.Builder nb = new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
                 .setContentTitle("foo")
-                .setCategory(CATEGORY_CALL)
-                .addPerson(person)
+                .setStyle(new Notification.MessagingStyle(person)
+                        .setConversationTitle("Bubble Chat")
+                        .addMessage("Hello?",
+                                SystemClock.currentThreadTimeMillis() - 300000, person)
+                        .addMessage("Is it me you're looking for?",
+                                SystemClock.currentThreadTimeMillis(), person)
+                )
+                .setActions(replyAction)
                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
-        sendAndVerifyBubble(1, nb, null /* use default metadata */, false /* shouldBeBubble */);
-    }
 
-    public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoCategory() {
-        Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
-        serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_NO_CATEGORY);
-        mContext.startService(serviceIntent);
+        final Intent intent = new Intent(mContext, BubblesTestNotDocumentLaunchModeActivity.class);
+        final PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, intent, 0);
 
-        if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
-                true /* shouldExist */, false /* shouldBeBubble */)) {
-            fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
-                    + " or it was a bubble when it shouldn't be");
-        }
-    }
+        Notification.BubbleMetadata.Builder metadataBuilder =
+                new Notification.BubbleMetadata.Builder()
+                        .setIntent(pendingIntent)
+                        .setIcon(Icon.createWithResource(mContext, R.drawable.black));
 
-    public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoMetadata() {
-        Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
-        serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_NO_BUBBLE_METADATA);
-        mContext.startService(serviceIntent);
-
-        if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
-                true /* shouldExist */, false /* shouldBeBubble */)) {
-            fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
-                    + " or it was a bubble when it shouldn't be");
-        }
-    }
-
-    public void testNotificationManagerBubblePolicy_noFlagForAppNotForeground() {
-        sendAndVerifyBubble(1, null /* use default notif */, null /* use default metadata */,
-                false /* shouldBeBubble */);
-    }
-
-    public void testNotificationManagerBubblePolicy_flagForAppForeground() throws Exception {
-        final CountDownLatch latch = new CountDownLatch(2);
-        BroadcastReceiver receiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                latch.countDown();
-            }
-        };
-        IntentFilter filter = new IntentFilter(BubblesTestActivity.BUBBLE_ACTIVITY_OPENED);
-        mContext.registerReceiver(receiver, filter);
-
-        // Start & get the activity
-        BubblesTestActivity a = (BubblesTestActivity) launchSendBubbleActivity();
-
-        // Make sure device is unlocked
-        KeyguardManager keyguardManager =
-                (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
-        keyguardManager.requestDismissKeyguard(a, new KeyguardManager.KeyguardDismissCallback() {
-            @Override
-            public void onDismissSucceeded() {
-                latch.countDown();
-            }
-        });
-        try {
-            latch.await(100, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-
-        // Should be foreground now
-        a.sendBubble(1);
-
-        if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
-                true /* shouldExist */, true /* shouldBeBubble */)) {
-            fail("couldn't find posted notification bubble with id=" + BUBBLE_NOTIF_ID);
-        }
-
-        // Make ourselves not foreground
-        HomeHelper homeHelper = new HomeHelper();
-        homeHelper.goHome();
-
-        // The notif should be allowed to update as a bubble
-        a.sendBubble(2);
-
-        boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
-
-        if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
-                true /* shouldExist */, shouldBeBubble)) {
-            fail("couldn't find posted notification bubble with id=" + BUBBLE_NOTIF_ID);
-        }
-
-        // Cancel the notif
-        cancelAndPoll(BUBBLE_NOTIF_ID);
-
-        // Send it again when not foreground, this should not be a bubble & just be a notif
-        a.sendBubble(3);
-        if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
-                true /* shouldExist */, false /* shouldBeBubble */)) {
-            fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
-                    + " or it was a bubble when it shouldn't be");
-        }
-
-        mContext.unregisterReceiver(receiver);
-        homeHelper.close();
+        sendAndVerifyBubble(1, nb, metadataBuilder.build(), false);
     }
 }
diff --git a/tests/attentionservice/src/android/attentionservice/cts/CtsAttentionServiceDeviceTest.java b/tests/attentionservice/src/android/attentionservice/cts/CtsAttentionServiceDeviceTest.java
index 5e41cf4..45a7247 100644
--- a/tests/attentionservice/src/android/attentionservice/cts/CtsAttentionServiceDeviceTest.java
+++ b/tests/attentionservice/src/android/attentionservice/cts/CtsAttentionServiceDeviceTest.java
@@ -21,9 +21,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assume.assumeTrue;
+
 import android.platform.test.annotations.AppModeFull;
 import android.provider.DeviceConfig;
 import android.service.attention.AttentionService;
+import android.text.TextUtils;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
@@ -45,6 +48,8 @@
     private static final String SERVICE_ENABLED = "service_enabled";
     private static final String FAKE_SERVICE_PACKAGE =
             CtsTestAttentionService.class.getPackage().getName();
+    private final boolean isTestable =
+            !TextUtils.isEmpty(getAttentionServiceComponent());
 
     @Rule
     public final DeviceConfigStateChangerRule mLookAllTheseRules =
@@ -55,6 +60,7 @@
 
     @Before
     public void setUp() {
+        assumeTrue("Feature not available on this device. Skipping test.", isTestable);
         clearTestableAttentionService();
         CtsTestAttentionService.reset();
         bindToTestService();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 3413422..31fd320 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -1414,6 +1414,21 @@
     }
 
     /**
+     * Asserts {@link View#isAutofilled()} state of the given view, waiting if necessarity to avoid
+     * race conditions.
+     */
+    public static void assertViewAutofillState(@NonNull View view, boolean expected)
+            throws Exception {
+        Timeouts.FILL_TIMEOUT.run("assertViewAutofillState(" + view + ", " + expected + ")",
+                () -> {
+                    final boolean actual = view.isAutofilled();
+                    Log.v(TAG, "assertViewAutofillState(): expected=" + expected + ", actual="
+                            + actual);
+                    return actual == expected ? "not_used" : null;
+                });
+    }
+
+    /**
      * Allows the test to draw overlaid windows.
      *
      * <p>Should call {@link #disallowOverlays()} afterwards.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index e4d77bc..b7241b3 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -32,6 +32,7 @@
 import static android.autofillservice.cts.Helper.assertTextIsSanitized;
 import static android.autofillservice.cts.Helper.assertTextOnly;
 import static android.autofillservice.cts.Helper.assertValue;
+import static android.autofillservice.cts.Helper.assertViewAutofillState;
 import static android.autofillservice.cts.Helper.disallowOverlays;
 import static android.autofillservice.cts.Helper.dumpStructure;
 import static android.autofillservice.cts.Helper.findAutofillIdByResourceId;
@@ -985,6 +986,7 @@
 
         // Check the results.
         mActivity.assertAutoFilled();
+        assertViewAutofillState(mActivity.getPassword(), true);
 
         // Try to login, it will fail.
         final String loginMessage = mActivity.tapLogin();
@@ -993,6 +995,7 @@
 
         // Set right password...
         mActivity.onPassword((v) -> v.setText("dude"));
+        assertViewAutofillState(mActivity.getPassword(), false);
 
         // ... and try again
         final String expectedMessage = getWelcomeMessage("dude");
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index 40a9589..2e56a02 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -1024,6 +1024,7 @@
         try {
             file = Helper.createTestFile("screenshot.png");
             if (file != null) {
+                Log.i(TAG, "Taking screenshot on " + file);
                 final Bitmap screenshot = takeScreenshot();
                 Helper.dumpBitmap(screenshot, file);
             }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/augmented/AugmentedLoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/augmented/AugmentedLoginActivityTest.java
index dea07e3..64c2d78 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/augmented/AugmentedLoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/augmented/AugmentedLoginActivityTest.java
@@ -21,6 +21,7 @@
 import static android.autofillservice.cts.Helper.ID_USERNAME;
 import static android.autofillservice.cts.Helper.assertHasFlags;
 import static android.autofillservice.cts.Helper.assertTextAndValue;
+import static android.autofillservice.cts.Helper.assertViewAutofillState;
 import static android.autofillservice.cts.Helper.findNodeByResourceId;
 import static android.autofillservice.cts.LoginActivity.getWelcomeMessage;
 import static android.autofillservice.cts.UiBot.LANDSCAPE;
@@ -349,6 +350,72 @@
 
     @Test
     @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough")
+    public void testCancellationSignalCalled_retriggerAugmentedAutofill() throws Exception {
+        // Set services
+        enableService();
+        enableAugmentedService();
+
+        // Set expectations
+        final EditText username = mActivity.getUsername();
+        final AutofillId usernameId = username.getAutofillId();
+        final AutofillValue expectedFocusedValue = username.getAutofillValue();
+        sReplier.addResponse(NO_RESPONSE);
+        sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder()
+                .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me")
+                        .setField(usernameId, "dude")
+                        .setField(mActivity.getPassword().getAutofillId(), "sweet")
+                        .build(), usernameId)
+                .build());
+
+        final OneTimeCancellationSignalListener listener =
+                new OneTimeCancellationSignalListener(AUGMENTED_FILL_TIMEOUT.ms() + 5000);
+
+        // Trigger autofill
+        mActivity.onUsername(View::requestFocus);
+        sReplier.getNextFillRequest();
+        final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest();
+
+        // Assert request
+        assertBasicRequestInfo(request, mActivity, usernameId, expectedFocusedValue);
+        mAugmentedUiBot.assertUiShown(usernameId, "Augment Me");
+
+        final CancellationSignal cancellationSignal = request.cancellationSignal;
+
+        assertThat(cancellationSignal).isNotNull();
+        cancellationSignal.setOnCancelListener(listener);
+
+        // Move focus away to make sure Augmented Autofill UI is gone.
+        mActivity.clearFocus();
+        mAugmentedUiBot.assertUiGone();
+
+        // Set expectations for username again.
+        sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder()
+                .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me")
+                        .setField(usernameId, "dude")
+                        .setField(mActivity.getPassword().getAutofillId(), "sweet")
+                        .build(), usernameId)
+                .build());
+
+        // Tap on username again
+        mActivity.onUsername(View::requestFocus);
+        final AugmentedFillRequest request2 = sAugmentedReplier.getNextFillRequest();
+
+        // Assert first request cancelled
+        listener.assertOnCancelCalled();
+
+        // Assert request
+        assertBasicRequestInfo(request2, mActivity, usernameId, expectedFocusedValue);
+        final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me");
+
+        // ...and autofill this time
+        mActivity.expectAutoFill("dude", "sweet");
+        ui.click();
+        mActivity.assertAutoFilled();
+        mAugmentedUiBot.assertUiGone();
+    }
+
+    @Test
+    @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough")
     public void testAugmentedAutoFill_multipleRequests() throws Exception {
         // Set services
         enableService();
@@ -418,6 +485,50 @@
     }
 
     @Test
+    @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough")
+    public void testAugmentedAutoFill_thenEditField() throws Exception {
+        // Set services
+        enableService();
+        enableAugmentedService();
+
+        // Set expectations
+        final EditText username = mActivity.getUsername();
+        final AutofillId usernameId = username.getAutofillId();
+        final AutofillValue expectedFocusedValue = username.getAutofillValue();
+        sReplier.addResponse(NO_RESPONSE);
+        sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder()
+                .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me")
+                        .setField(usernameId, "dude")
+                        .build(), usernameId)
+                .build());
+        mActivity.expectAutoFill("dude");
+
+        // Trigger autofill
+        mActivity.onUsername(View::requestFocus);
+        sReplier.getNextFillRequest();
+        final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest();
+
+        // Assert request
+        assertBasicRequestInfo(request, mActivity, usernameId, expectedFocusedValue);
+
+        // Make sure standard Autofill UI is not shown.
+        mUiBot.assertNoDatasetsEver();
+
+        // Make sure Augmented Autofill UI is shown.
+        final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me");
+
+        // Autofill
+        ui.click();
+        mActivity.assertAutoFilled();
+        mAugmentedUiBot.assertUiGone();
+        assertViewAutofillState(mActivity.getUsername(), true);
+
+        // Now change value and make sure autofill status is changed
+        mActivity.onUsername((v) -> v.setText("I AM GROOT"));
+        assertViewAutofillState(mActivity.getUsername(), false);
+    }
+
+    @Test
     public void testAugmentedAutoFill_callback() throws Exception {
         // Set services
         enableService();
diff --git a/tests/camera/src/android/hardware/camera2/cts/HeifWriterTest.java b/tests/camera/src/android/hardware/camera2/cts/HeifWriterTest.java
index 060c022..0cb5c1b 100644
--- a/tests/camera/src/android/hardware/camera2/cts/HeifWriterTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/HeifWriterTest.java
@@ -66,7 +66,12 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mFilePath = mContext.getExternalFilesDir(null).getPath();
+
+        File filesDir = mContext.getPackageManager().isInstantApp()
+                ? mContext.getFilesDir()
+                : mContext.getExternalFilesDir(null);
+
+        mFilePath = filesDir.getPath();
     }
 
     @Override
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index 2ceda1e..b7510e6 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -1377,12 +1377,14 @@
             Log.i(TAG, String.format(
                     "Testing Camera %s for abandoning surface of a repeating request", id));
 
-            openDevice(id);
-            if (!mStaticInfo.isColorOutputSupported()) {
+            StaticMetadata staticInfo = mAllStaticInfo.get(id);
+            if (!staticInfo.isColorOutputSupported()) {
                 Log.i(TAG, "Camera " + id + " does not support color output, skipping");
                 continue;
             }
 
+            openDevice(id);
+
             try {
 
                 SurfaceTexture preview = new SurfaceTexture(/*random int*/ 1);
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
index 80d570b..4cd0046 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
@@ -48,6 +48,7 @@
 import com.android.ex.camera2.blocking.BlockingSessionCallback;
 import com.android.ex.camera2.blocking.BlockingStateCallback;
 
+import java.io.File;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -115,7 +116,12 @@
         mHandler = new Handler(mHandlerThread.getLooper());
         mCameraListener = new BlockingStateCallback();
         mCollector = new CameraErrorCollector();
-        mDebugFileNameBase = getContext().getExternalFilesDir(null).getPath();
+
+        File filesDir = mContext.getPackageManager().isInstantApp()
+                ? mContext.getFilesDir()
+                : mContext.getExternalFilesDir(null);
+
+        mDebugFileNameBase = filesDir.getPath();
 
         mAllStaticInfo = new HashMap<String, StaticMetadata>();
         List<String> hiddenPhysicalIds = new ArrayList<>();
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index b2b7828..1f8b792 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -59,6 +59,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -135,7 +136,12 @@
         mHandler = new Handler(mHandlerThread.getLooper());
         mCameraListener = new BlockingStateCallback();
         mCollector = new CameraErrorCollector();
-        mDebugFileNameBase = mContext.getExternalFilesDir(null).getPath();
+
+        File filesDir = mContext.getPackageManager().isInstantApp()
+                ? mContext.getFilesDir()
+                : mContext.getExternalFilesDir(null);
+
+        mDebugFileNameBase = filesDir.getPath();
 
         mAllStaticInfo = new HashMap<String, StaticMetadata>();
         List<String> hiddenPhysicalIds = new ArrayList<>();
diff --git a/tests/camera/src/android/hardware/cts/CameraTest.java b/tests/camera/src/android/hardware/cts/CameraTest.java
index 51605f0..b6fe28a 100644
--- a/tests/camera/src/android/hardware/cts/CameraTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraTest.java
@@ -150,6 +150,7 @@
      */
     private void initializeMessageLooper(final int cameraId) throws IOException {
         final ConditionVariable startDone = new ConditionVariable();
+        final CameraCtsActivity activity = mActivityRule.getActivity();
         new Thread() {
             @Override
             public void run() {
@@ -161,7 +162,7 @@
                 mLooper = Looper.myLooper();
                 try {
                     mIsExternalCamera = CameraUtils.isExternal(
-                            mActivityRule.getActivity().getApplicationContext(), cameraId);
+                            activity.getApplicationContext(), cameraId);
                 } catch (Exception e) {
                     Log.e(TAG, "Unable to query external camera!" + e);
                 }
@@ -185,8 +186,13 @@
             fail("initializeMessageLooper: start timeout");
         }
         assertNotNull("Fail to open camera.", mCamera);
-        mCamera.setPreviewDisplay(mActivityRule.getActivity().getSurfaceView().getHolder());
-        mJpegPath = mActivityRule.getActivity().getExternalFilesDir(null).getPath() + "/test.jpg";
+        mCamera.setPreviewDisplay(activity.getSurfaceView().getHolder());
+
+        File parent = activity.getPackageManager().isInstantApp()
+                ? activity.getFilesDir()
+                : activity.getExternalFilesDir(null);
+
+        mJpegPath = parent.getPath() + "/test.jpg";
     }
 
     /*
diff --git a/tests/camera/src/android/hardware/multiprocess/camera/cts/MediaRecorderCameraActivity.java b/tests/camera/src/android/hardware/multiprocess/camera/cts/MediaRecorderCameraActivity.java
index 1f12cea..186706b 100644
--- a/tests/camera/src/android/hardware/multiprocess/camera/cts/MediaRecorderCameraActivity.java
+++ b/tests/camera/src/android/hardware/multiprocess/camera/cts/MediaRecorderCameraActivity.java
@@ -58,7 +58,12 @@
         mErrorServiceConnection.start();
 
         mMediaRecorder = new MediaRecorder();
-        mOutputPath = new File(getExternalFilesDir(null), "record.out").getAbsolutePath();
+
+        File filesDir = getPackageManager().isInstantApp()
+                ? getFilesDir()
+                : getExternalFilesDir(null);
+
+        mOutputPath = new File(filesDir, "record.out").getAbsolutePath();
     }
 
     @Override
diff --git a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
index 3ed4cfe..77fa6dd 100644
--- a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
+++ b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
@@ -61,6 +61,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestRule;
@@ -178,6 +179,7 @@
                 APP_A_FOREGROUND_ACTIVITY);
     }
 
+    @Ignore // test temporarily disabled due to bg activity start grace period introduction
     @Test
     public void testActivityNotBlockedwhenForegroundActivityLaunchInSameTask() throws Exception {
         // Start foreground activity, and foreground activity able to launch background activity
@@ -208,6 +210,7 @@
                 APP_A_FOREGROUND_ACTIVITY);
     }
 
+    @Ignore // test temporarily disabled due to bg activity start grace period introduction
     @Test
     public void testActivityNotBlockedWhenForegroundActivityLaunchInDifferentTask()
             throws Exception {
@@ -240,6 +243,7 @@
         assertTaskStack(null, APP_A_BACKGROUND_ACTIVITY);
     }
 
+    @Ignore // test temporarily disabled due to bg activity start grace period introduction
     @Test
     @FlakyTest(bugId = 130800326)
     public void testActivityBlockedWhenForegroundActivityRestartsItself() throws Exception {
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
index 4228c26..418c201 100644
--- a/tests/tests/content/AndroidTest.xml
+++ b/tests/tests/content/AndroidTest.xml
@@ -40,7 +40,6 @@
         <option name="test-file-name" value="CtsContentTestCases.apk" />
         <option name="test-file-name" value="CtsContentDirectBootUnawareTestApp.apk" />
         <option name="test-file-name" value="CtsContentPartiallyDirectBootAwareTestApp.apk" />
-        <option name="test-file-name" value="CtsContentDirectBootAwareTestApp.apk" />
         <option name="test-file-name" value="CtsSyncAccountAccessStubs.apk" />
         <option name="test-file-name" value="CtsBinderPermissionTestService.apk" />
     </target_preparer>
diff --git a/tests/tests/content/DirectBootAwareTestApp/Android.bp b/tests/tests/content/DirectBootAwareTestApp/Android.bp
deleted file mode 100644
index 17ccda1..0000000
--- a/tests/tests/content/DirectBootAwareTestApp/Android.bp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2019 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.
-
-android_test_helper_app {
-    name: "CtsContentDirectBootAwareTestApp",
-    defaults: ["cts_defaults"],
-    sdk_version: "current",
-    // tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "vts",
-        "general-tests",
-    ],
-}
diff --git a/tests/tests/content/DirectBootAwareTestApp/AndroidManifest.xml b/tests/tests/content/DirectBootAwareTestApp/AndroidManifest.xml
deleted file mode 100644
index b4753b9..0000000
--- a/tests/tests/content/DirectBootAwareTestApp/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  ~ Copyright (C) 2019 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.cts.directbootaware">
-
-    <application
-        android:directBootAware="true"
-        android:hasCode="false"
-        android:label="Direct Boot Aware Test App" />
-</manifest>
diff --git a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
index 728bcbe..7260c3c 100644
--- a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
@@ -57,8 +57,6 @@
             "android.content.cts.directbootunaware";
     private static final String PARTIALLY_DIRECT_BOOT_AWARE_PACKAGE_NAME =
             "android.content.cts.partiallydirectbootaware";
-    private static final String DIRECT_BOOT_AWARE_PACKAGE_NAME =
-            "android.content.cts.directbootaware";
 
     private ApplicationInfo mApplicationInfo;
     private String mPackageName;
@@ -217,11 +215,4 @@
                 PARTIALLY_DIRECT_BOOT_AWARE_PACKAGE_NAME, 0);
         assertTrue(applicationInfo.isEncryptionAware());
     }
-
-    @Test
-    public void testDirectBootAwareAppIsEncryptionAware() throws Exception {
-        ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo(
-                DIRECT_BOOT_AWARE_PACKAGE_NAME, 0);
-        assertTrue(applicationInfo.isEncryptionAware());
-    }
 }
diff --git a/tests/tests/gesture/AndroidTest.xml b/tests/tests/gesture/AndroidTest.xml
index 10d1e6a..0c1c200 100644
--- a/tests/tests/gesture/AndroidTest.xml
+++ b/tests/tests/gesture/AndroidTest.xml
@@ -17,6 +17,7 @@
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="framework" />
     <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsGestureTestCases.apk" />
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index 91a6acf..f01665a 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -183,6 +183,12 @@
         playVideoWithRetries(uri, headers, cookies, null /* width */, null /* height */, playTime);
     }
 
+    protected void playLiveAudioOnlyTest(
+            Uri uri, Map<String, String> headers, List<HttpCookie> cookies,
+            int playTime) throws Exception {
+        playVideoWithRetries(uri, headers, cookies, -1 /* width */, -1 /* height */, playTime);
+    }
+
     protected void playVideoWithRetries(
             Uri uri, Map<String, String> headers, List<HttpCookie> cookies,
             Integer width, Integer height, int playTime) throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 8f63a75..789d1ba 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -187,7 +187,7 @@
 
         // Play stream for 60 seconds
         // limit rate to workaround multiplication overflow in framework
-        localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS);
+        localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS, false /*isAudioOnly*/);
     }
 
     public void testHlsWithHeadersCookies() throws Exception {
@@ -215,7 +215,7 @@
 
         // Play stream for 60 seconds
         // limit rate to workaround multiplication overflow in framework
-        localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS);
+        localHlsTest("hls_variant/index.m3u8", 60 * 1000, LOCAL_HLS_BITS_PER_MS, false /*isAudioOnly*/);
     }
 
     public void testHlsSampleAes_bbb_audio_only_overridable() throws Exception {
@@ -228,7 +228,7 @@
             // if url override provided
             playLiveAudioOnlyTest(mInputUrl, 60 * 1000);
         } else {
-            localHlsTest("audio_only/index.m3u8", 60 * 1000, -1);
+            localHlsTest("audio_only/index.m3u8", 60 * 1000, -1, true /*isAudioOnly*/);
         }
 
     }
@@ -239,7 +239,7 @@
         }
 
         // Play stream for 60 seconds
-        localHlsTest("unmuxed_1500k/index.m3u8", 60 * 1000, -1);
+        localHlsTest("unmuxed_1500k/index.m3u8", 60 * 1000, -1, false /*isAudioOnly*/);
     }
 
 
@@ -379,21 +379,21 @@
         if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
             return; // skip
         }
-        localHlsTest("hls.m3u8", false, false);
+        localHlsTest("hls.m3u8", false, false, false /*isAudioOnly*/);
     }
 
     public void testPlayHlsStreamWithQueryString() throws Throwable {
         if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
             return; // skip
         }
-        localHlsTest("hls.m3u8", true, false);
+        localHlsTest("hls.m3u8", true, false, false /*isAudioOnly*/);
     }
 
     public void testPlayHlsStreamWithRedirect() throws Throwable {
         if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
             return; // skip
         }
-        localHlsTest("hls.m3u8", false, true);
+        localHlsTest("hls.m3u8", false, true, false /*isAudioOnly*/);
     }
 
     public void testPlayHlsStreamWithTimedId3() throws Throwable {
@@ -576,19 +576,19 @@
         worker.quit();
     }
 
-    private void localHlsTest(final String name, boolean appendQueryString, boolean redirect)
-            throws Exception {
-        localHlsTest(name, null, null, appendQueryString, redirect, 10, -1);
+    private void localHlsTest(final String name, boolean appendQueryString,
+            boolean redirect, boolean isAudioOnly) throws Exception {
+        localHlsTest(name, null, null, appendQueryString, redirect, 10, -1, isAudioOnly);
     }
 
-    private void localHlsTest(final String name, int playTime, int bitsPerMs)
+    private void localHlsTest(final String name, int playTime, int bitsPerMs, boolean isAudioOnly)
             throws Exception {
-        localHlsTest(name, null, null, false, false, playTime, bitsPerMs);
+        localHlsTest(name, null, null, false, false, playTime, bitsPerMs, isAudioOnly);
     }
 
     private void localHlsTest(String name, Map<String, String> headers, List<HttpCookie> cookies,
-            boolean appendQueryString, boolean redirect, int playTime, int bitsPerMs)
-            throws Exception {
+            boolean appendQueryString, boolean redirect, int playTime, int bitsPerMs,
+            boolean isAudioOnly) throws Exception {
         if (bitsPerMs >= 0) {
             mServer = new CtsTestServer(mContext) {
                 @Override
@@ -609,8 +609,11 @@
             if (appendQueryString) {
                 stream_url += "?foo=bar/baz";
             }
-
-            playLiveVideoTest(Uri.parse(stream_url), headers, cookies, playTime);
+            if (isAudioOnly) {
+                playLiveAudioOnlyTest(Uri.parse(stream_url), headers, cookies, playTime);
+            } else {
+                playLiveVideoTest(Uri.parse(stream_url), headers, cookies, playTime);
+            }
         } finally {
             mServer.shutdown();
         }
diff --git a/tests/tests/os/assets/minijail/isolated-common.policy b/tests/tests/os/assets/minijail/isolated-common.policy
index a8f4e25..11205ae 100644
--- a/tests/tests/os/assets/minijail/isolated-common.policy
+++ b/tests/tests/os/assets/minijail/isolated-common.policy
@@ -75,6 +75,7 @@
 # madvise: advice==MADV_DONTNEED
 madvise: arg2 == 4; return EPERM
 
+membarrier: 1
 memfd_create: return EPERM
 mkdirat: return EPERM
 mknodat: return EPERM
diff --git a/tests/tests/packageinstaller/nopermission/src/android.packageinstaller.nopermission.cts/NoPermissionTests.kt b/tests/tests/packageinstaller/nopermission/src/android.packageinstaller.nopermission.cts/NoPermissionTests.kt
index e99476a..10c2efa 100644
--- a/tests/tests/packageinstaller/nopermission/src/android.packageinstaller.nopermission.cts/NoPermissionTests.kt
+++ b/tests/tests/packageinstaller/nopermission/src/android.packageinstaller.nopermission.cts/NoPermissionTests.kt
@@ -183,9 +183,4 @@
     fun uninstallTestPackage() {
         uiDevice.executeShellCommand("pm uninstall $TEST_APK_PACKAGE_NAME")
     }
-
-    @After
-    fun resetAppOps() {
-        AppOpsUtils.reset(packageName)
-    }
 }
diff --git a/tests/tests/permission/telephony/src/android/permission/cts/telephony/TelephonyManagerPermissionTest.java b/tests/tests/permission/telephony/src/android/permission/cts/telephony/TelephonyManagerPermissionTest.java
index 227ef5b..32e4296 100644
--- a/tests/tests/permission/telephony/src/android/permission/cts/telephony/TelephonyManagerPermissionTest.java
+++ b/tests/tests/permission/telephony/src/android/permission/cts/telephony/TelephonyManagerPermissionTest.java
@@ -275,6 +275,30 @@
         }
     }
 
+    /**
+     * Verify that getNetworkType and getDataNetworkType requires Permission.
+     * <p>
+     * Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE}.
+     */
+    @Test
+    public void testGetNetworkType() {
+        if (!mHasTelephony) {
+            return;
+        }
+
+        if (mTelephonyManager.getNetworkType() != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
+            fail("getNetworkType should return UNKNOWN");
+        }
+
+        try {
+            mTelephonyManager.getDataNetworkType();
+            fail("getDataNetworkType did not throw a SecurityException");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
     private static Context getContext() {
         return InstrumentationRegistry.getContext();
     }
diff --git a/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java b/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java
index 031aa65..586c74c 100644
--- a/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java
@@ -16,16 +16,18 @@
 
 package android.permission2.cts;
 
+import static android.permission2.cts.Utils.eventually;
+
 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
-import static org.junit.Assert.fail;
+
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.fail;
+
 import android.Manifest;
 import android.Manifest.permission;
 import android.app.AppOpsManager;
 import android.content.BroadcastReceiver;
-
-
 import android.content.Context;
 import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
@@ -34,18 +36,19 @@
 import android.platform.test.annotations.AppModeFull;
 import android.util.ArraySet;
 
-import java.util.Collections;
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.util.Collections;
 import java.util.Set;
 
 import javax.annotation.Nullable;
 
-import androidx.annotation.NonNull;
-import androidx.test.platform.app.InstrumentationRegistry;
-
 /**
  * Tests for restricted permission behaviors.
  */
@@ -69,19 +72,6 @@
 
     private static @NonNull BroadcastReceiver sCommandReceiver;
 
-    public interface ThrowingRunnable extends Runnable {
-        void runOrThrow() throws Exception;
-
-        @Override
-        default void run() {
-            try {
-                runOrThrow();
-            } catch (Exception ex) {
-                throw new RuntimeException(ex);
-            }
-        }
-    }
-
     @BeforeClass
     public static void setUpOnce() {
         sCommandReceiver = new CommandBroadcastReceiver();
@@ -99,81 +89,65 @@
     @Test
     @AppModeFull
     public void testDefaultAllRestrictedPermissionsWhitelistedAtInstall() throws Exception {
-        try {
-            // Install with no changes to whitelisted permissions, not attempting to grant.
-            installRestrictedPermissionUserApp(null /*whitelistedPermissions*/,
-                    null /*grantedPermissions*/);
+        // Install with no changes to whitelisted permissions, not attempting to grant.
+        installRestrictedPermissionUserApp(null /*whitelistedPermissions*/,
+                null /*grantedPermissions*/);
 
-            // All restricted permission should be whitelisted.
-            assertAllRestrictedPermissionWhitelisted();
+        // All restricted permission should be whitelisted.
+        assertAllRestrictedPermissionWhitelisted();
 
-            // No restricted permission should be granted.
-            assertNoRestrictedPermissionGranted();
-        } finally {
-            uninstallApp();
-        }
+        // No restricted permission should be granted.
+        assertNoRestrictedPermissionGranted();
     }
 
     @Test
     @AppModeFull
     public void testSomeRestrictedPermissionsWhitelistedAtInstall() throws Exception {
-        try {
-            // Whitelist only these permissions.
-            final Set<String> whitelistedPermissions = new ArraySet<>(2);
-            whitelistedPermissions.add(Manifest.permission.SEND_SMS);
-            whitelistedPermissions.add(Manifest.permission.READ_CALL_LOG);
+        // Whitelist only these permissions.
+        final Set<String> whitelistedPermissions = new ArraySet<>(2);
+        whitelistedPermissions.add(Manifest.permission.SEND_SMS);
+        whitelistedPermissions.add(Manifest.permission.READ_CALL_LOG);
 
-            // Install with some whitelisted permissions, not attempting to grant.
-            installRestrictedPermissionUserApp(whitelistedPermissions, null /*grantedPermissions*/);
+        // Install with some whitelisted permissions, not attempting to grant.
+        installRestrictedPermissionUserApp(whitelistedPermissions, null /*grantedPermissions*/);
 
-            // Some restricted permission should be whitelisted.
-            assertRestrictedPermissionWhitelisted(whitelistedPermissions);
+        // Some restricted permission should be whitelisted.
+        eventually(() -> assertRestrictedPermissionWhitelisted(whitelistedPermissions));
 
-            // No restricted permission should be granted.
-            assertNoRestrictedPermissionGranted();
-        } finally {
-            uninstallApp();
-        }
+        // No restricted permission should be granted.
+        assertNoRestrictedPermissionGranted();
     }
 
     @Test
     @AppModeFull
     public void testNoneRestrictedPermissionWhitelistedAtInstall() throws Exception {
-        try {
-            // Install with all whitelisted permissions, not attempting to grant.
-            installRestrictedPermissionUserApp(Collections.emptySet(),
-                    null /*grantedPermissions*/);
+        // Install with all whitelisted permissions, not attempting to grant.
+        installRestrictedPermissionUserApp(Collections.emptySet(),
+                null /*grantedPermissions*/);
 
-            // No restricted permission should be whitelisted.
-            assertNoRestrictedPermissionWhitelisted();
+        // No restricted permission should be whitelisted.
+        assertNoRestrictedPermissionWhitelisted();
 
-            // No restricted permission should be granted.
-            assertNoRestrictedPermissionGranted();
-        } finally {
-            uninstallApp();
-        }
+        // No restricted permission should be granted.
+        assertNoRestrictedPermissionGranted();
     }
 
     @Test
     @AppModeFull
     public void testSomeRestrictedPermissionsGrantedAtInstall() throws Exception {
-        try {
-            // Grant only these permissions.
-            final Set<String> grantedPermissions = new ArraySet<>(1);
-            grantedPermissions.add(Manifest.permission.SEND_SMS);
-            grantedPermissions.add(Manifest.permission.READ_CALL_LOG);
+        // Grant only these permissions.
+        final Set<String> grantedPermissions = new ArraySet<>(1);
+        grantedPermissions.add(Manifest.permission.SEND_SMS);
+        grantedPermissions.add(Manifest.permission.READ_CALL_LOG);
 
-            // Install with no whitelisted permissions attempting to grant.
-            installRestrictedPermissionUserApp(null /*whitelistedPermissions*/, grantedPermissions);
+        // Install with no whitelisted permissions attempting to grant.
+        installRestrictedPermissionUserApp(null /*whitelistedPermissions*/, grantedPermissions);
 
-            // All restricted permission should be whitelisted.
-            assertAllRestrictedPermissionWhitelisted();
+        // All restricted permission should be whitelisted.
+        assertAllRestrictedPermissionWhitelisted();
 
-            // Some restricted permission should be granted.
-            assertRestrictedPermissionGranted(grantedPermissions);
-        } finally {
-            uninstallApp();
-        }
+        // Some restricted permission should be granted.
+        assertRestrictedPermissionGranted(grantedPermissions);
     }
 
     @Test
@@ -195,206 +169,204 @@
     @Test
     @AppModeFull
     public void testAllRestrictedPermissionsGrantedAtInstall() throws Exception {
-        try {
-            // Install with whitelisted permissions attempting to grant.
-            installRestrictedPermissionUserApp(null /*whitelistedPermissions*/,
-                    Collections.emptySet());
+        // Install with whitelisted permissions attempting to grant.
+        installRestrictedPermissionUserApp(null /*whitelistedPermissions*/,
+                Collections.emptySet());
 
-            // All restricted permission should be whitelisted.
-            assertAllRestrictedPermissionWhitelisted();
+        // All restricted permission should be whitelisted.
+        assertAllRestrictedPermissionWhitelisted();
 
-            // Some restricted permission should be granted.
-            assertAllRestrictedPermissionGranted();
-        } finally {
-            uninstallApp();
-        }
+        // Some restricted permission should be granted.
+        assertAllRestrictedPermissionGranted();
     }
 
     @Test
     @AppModeFull
     public void testWhitelistAccessControl() throws Exception {
-        try {
-            // Install with no whitelisted permissions not attempting to grant.
-            installRestrictedPermissionUserApp(Collections.emptySet(),
-                    Collections.emptySet());
+        // Install with no whitelisted permissions not attempting to grant.
+        installRestrictedPermissionUserApp(Collections.emptySet(),
+                Collections.emptySet());
 
-            assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
-                    PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM);
+        assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
+                PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM);
 
-            assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
-                    PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE);
+        assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
+                PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE);
 
-            assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
-                    PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
-        } finally {
-            uninstallApp();
-        }
+        assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
+                PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
     }
 
     @Test
     @AppModeFull
     public void testStorageTargetingSdk28DefaultWhitelistedHasFullAccess() throws Exception {
-        try {
-            // Install with whitelisted permissions.
-            installApp(APK_USES_STORAGE_DEFAULT_28, null /*whitelistedPermissions*/);
+        // Install with whitelisted permissions.
+        installApp(APK_USES_STORAGE_DEFAULT_28, null /*whitelistedPermissions*/);
 
-            // Check expected storage mode
-            assertHasFullStorageAccess();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected storage mode
+        assertHasFullStorageAccess();
     }
 
     @Test
     @AppModeFull
     public void testStorageTargetingSdk28DefaultNotWhitelistedHasIsolatedAccess() throws Exception {
-        try {
-            // Install with no whitelisted permissions.
-            installApp(APK_USES_STORAGE_DEFAULT_28, Collections.emptySet());
+        // Install with no whitelisted permissions.
+        installApp(APK_USES_STORAGE_DEFAULT_28, Collections.emptySet());
 
-            // Check expected storage mode
-            assertHasIsolatedStorageAccess();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected storage mode
+        assertHasIsolatedStorageAccess();
     }
 
     @Test
     @AppModeFull
     public void testStorageTargetingSdk28OptInWhitelistedHasIsolatedAccess() throws Exception {
-        try {
-            // Install with whitelisted permissions.
-            installApp(APK_USES_STORAGE_OPT_IN_28, null /*whitelistedPermissions*/);
+        // Install with whitelisted permissions.
+        installApp(APK_USES_STORAGE_OPT_IN_28, null /*whitelistedPermissions*/);
 
-            // Check expected storage mode
-            assertHasIsolatedStorageAccess();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected storage mode
+        assertHasIsolatedStorageAccess();
     }
 
     @Test
     @AppModeFull
     public void testStorageTargetingSdk28OptInNotWhitelistedHasIsolatedAccess() throws Exception {
-        try {
-            // Install with whitelisted permissions.
-            installApp(APK_USES_STORAGE_OPT_IN_28, null /*whitelistedPermissions*/);
+        // Install with whitelisted permissions.
+        installApp(APK_USES_STORAGE_OPT_IN_28, null /*whitelistedPermissions*/);
 
-            // Check expected storage mode
-            assertHasIsolatedStorageAccess();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected storage mode
+        assertHasIsolatedStorageAccess();
     }
 
     @Test
     @AppModeFull
     public void testStorageTargetingSdk29DefaultWhitelistedHasIsolatedAccess() throws Exception {
-        try {
-            // Install with whitelisted permissions.
-            installApp(APK_USES_STORAGE_DEFAULT_29, Collections.emptySet());
+        // Install with whitelisted permissions.
+        installApp(APK_USES_STORAGE_DEFAULT_29, Collections.emptySet());
 
-            // Check expected storage mode
-            assertHasIsolatedStorageAccess();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected storage mode
+        assertHasIsolatedStorageAccess();
     }
 
     @Test
     @AppModeFull
     public void testStorageTargetingSdk29DefaultNotWhitelistedHasIsolatedAccess() throws Exception {
-        try {
-            // Install with no whitelisted permissions.
-            installApp(APK_USES_STORAGE_DEFAULT_29, null /*whitelistedPermissions*/);
+        // Install with no whitelisted permissions.
+        installApp(APK_USES_STORAGE_DEFAULT_29, null /*whitelistedPermissions*/);
 
-            // Check expected storage mode
-            assertHasIsolatedStorageAccess();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected storage mode
+        assertHasIsolatedStorageAccess();
     }
 
     @Test
     @AppModeFull
     public void testStorageTargetingSdk29OptOutWhitelistedHasFullAccess() throws Exception {
-        try {
-            // Install with whitelisted permissions.
-            installApp(APK_USES_STORAGE_OPT_OUT_29, null /*whitelistedPermissions*/);
+        // Install with whitelisted permissions.
+        installApp(APK_USES_STORAGE_OPT_OUT_29, null /*whitelistedPermissions*/);
 
-            // Check expected storage mode
-            assertHasFullStorageAccess();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected storage mode
+        assertHasFullStorageAccess();
     }
 
     @Test
     @AppModeFull
     public void testStorageTargetingSdk29OptOutNotWhitelistedHasIsolatedAccess() throws Exception {
-        try {
-            // Install with no whitelisted permissions.
-            installApp(APK_USES_STORAGE_OPT_OUT_29, Collections.emptySet() );
+        // Install with no whitelisted permissions.
+        installApp(APK_USES_STORAGE_OPT_OUT_29, Collections.emptySet());
 
-            // Check expected storage mode
-            assertHasIsolatedStorageAccess();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected storage mode
+        assertHasIsolatedStorageAccess();
     }
 
     @Test
     @AppModeFull
-    public void testStorageDoesNotChangeOnUpdate() throws Exception {
-        try {
-            // Install with whitelisted permissions.
-            installApp(APK_USES_STORAGE_DEFAULT_28, null /*whitelistedPermissions*/);
+    public void testStorageTargetingSdk29CanOptOutViaUpdate() throws Exception {
+        installApp(APK_USES_STORAGE_DEFAULT_29, null);
+        installApp(APK_USES_STORAGE_OPT_OUT_29, null);
 
-            // Check expected storage mode
-            assertHasFullStorageAccess();
+        eventually(this::assertHasFullStorageAccess);
+    }
 
-            // Install with whitelisted permissions.
-            installApp(APK_USES_STORAGE_OPT_IN_28, null /*whitelistedPermissions*/);
+    @Test
+    @AppModeFull
+    public void testStorageTargetingSdk29CanOptOutViaDowngradeTo28() throws Exception {
+        installApp(APK_USES_STORAGE_DEFAULT_29, null);
+        installApp(APK_USES_STORAGE_DEFAULT_28, null);
 
-            // Check expected storage mode
-            assertHasFullStorageAccess();
+        eventually(this::assertHasFullStorageAccess);
+    }
 
-            // Install with whitelisted permissions.
-            installApp(APK_USES_STORAGE_DEFAULT_29, null /*whitelistedPermissions*/);
+    @Test
+    @AppModeFull
+    public void testStorageTargetingSdk28CanRemoveOptInViaUpdate() throws Exception {
+        installApp(APK_USES_STORAGE_OPT_IN_28, null);
+        installApp(APK_USES_STORAGE_DEFAULT_28, null);
 
-            // Check expected storage mode
-            assertHasFullStorageAccess();
-        } finally {
-            uninstallApp();
-        }
+        eventually(this::assertHasFullStorageAccess);
+    }
+
+    @Test
+    @AppModeFull
+    public void testStorageTargetingSdk28CanRemoveOptInByOptingOut() throws Exception {
+        installApp(APK_USES_STORAGE_OPT_IN_28, null);
+        installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+
+        eventually(this::assertHasFullStorageAccess);
+    }
+
+    @Test
+    @AppModeFull
+    public void testStorageTargetingSdk28DoesNotLooseAccessWhenOptingIn() throws Exception {
+        installApp(APK_USES_STORAGE_DEFAULT_28, null);
+        installApp(APK_USES_STORAGE_OPT_IN_28, null);
+
+        eventually(this::assertHasFullStorageAccess);
+    }
+
+    @Test
+    @AppModeFull
+    public void testStorageTargetingSdk28DoesNotLooseAccessViaUpdate() throws Exception {
+        installApp(APK_USES_STORAGE_DEFAULT_28, null);
+        installApp(APK_USES_STORAGE_DEFAULT_29, null);
+
+        eventually(this::assertHasFullStorageAccess);
+    }
+
+    @Test
+    @AppModeFull
+    public void testStorageTargetingSdk29DoesNotLooseAccessViaUpdate() throws Exception {
+        installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+        installApp(APK_USES_STORAGE_DEFAULT_29, null);
+
+        eventually(this::assertHasFullStorageAccess);
+    }
+
+    @Test
+    @AppModeFull
+    public void testStorageTargetingSdk29DoesNotLooseAccessWhenOptingIn() throws Exception {
+        installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+        installApp(APK_USES_STORAGE_OPT_IN_28, null);
+
+        eventually(this::assertHasFullStorageAccess);
     }
 
     @Test
     @AppModeFull
     public void testCannotControlStorageWhitelistPostInstall1() throws Exception {
-        try {
-            // Install with whitelisted permissions.
-            installApp(APK_USES_STORAGE_DEFAULT_28, null /*whitelistedPermissions*/);
+        // Install with whitelisted permissions.
+        installApp(APK_USES_STORAGE_DEFAULT_28, null /*whitelistedPermissions*/);
 
-            // Check expected state of restricted permissions.
-            assertCannotUnWhitelistStorage();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected state of restricted permissions.
+        assertCannotUnWhitelistStorage();
     }
 
     @Test
     @AppModeFull
     public void testCannotControlStorageWhitelistPostInstall2() throws Exception {
-        try {
-            // Install with no whitelisted permissions.
-            installApp(APK_USES_STORAGE_DEFAULT_28, Collections.emptySet());
+        // Install with no whitelisted permissions.
+        installApp(APK_USES_STORAGE_DEFAULT_28, Collections.emptySet());
 
-            // Check expected state of restricted permissions.
-            assertCannotWhitelistStorage();
-        } finally {
-            uninstallApp();
-        }
+        // Check expected state of restricted permissions.
+        assertCannotWhitelistStorage();
     }
 
     private void assertHasFullStorageAccess() throws Exception {
@@ -609,17 +581,17 @@
                     PackageManager.GET_PERMISSIONS);
 
             for (String permission : packageInfo.requestedPermissions) {
+                String op = AppOpsManager.permissionToOp(permission);
+
                 if (expectedWhitelistedPermissions != null
                         && expectedWhitelistedPermissions.contains(permission)) {
-                    assertThat(appOpsManager.unsafeCheckOpNoThrow(
-                            AppOpsManager.permissionToOp(permission),
-                            packageInfo.applicationInfo.uid, PKG))
-                            .isEqualTo(AppOpsManager.MODE_ALLOWED);
+                    assertThat(
+                            appOpsManager.unsafeCheckOpNoThrow(op, packageInfo.applicationInfo.uid,
+                                    PKG)).named(op).isEqualTo(AppOpsManager.MODE_ALLOWED);
                 } else {
-                    assertThat(appOpsManager.unsafeCheckOpNoThrow(
-                            AppOpsManager.permissionToOp(permission),
-                            packageInfo.applicationInfo.uid, PKG))
-                            .isEqualTo(AppOpsManager.MODE_DEFAULT);
+                    assertThat(
+                            appOpsManager.unsafeCheckOpNoThrow(op, packageInfo.applicationInfo.uid,
+                                    PKG)).named(op).isEqualTo(AppOpsManager.MODE_DEFAULT);
                 }
             }
         });
@@ -705,7 +677,7 @@
     private void installApp(@NonNull String app, @Nullable Set<String> whitelistedPermissions,
             @Nullable Set<String> grantedPermissions) throws Exception {
         // Install the app and whitelist/grant all permission if requested.
-        final StringBuilder command = new StringBuilder("pm install ");
+        final StringBuilder command = new StringBuilder("pm install -r ");
         if (whitelistedPermissions != null) {
             command.append("--restrict-permissions ");
         }
@@ -713,7 +685,8 @@
             command.append("-g ");
         }
         command.append(app);
-        runShellCommand(command.toString());
+        String installResult = runShellCommand(command.toString());
+        assertThat(installResult.trim()).isEqualTo("Success");
 
         // Whitelist subset of permissions if requested
         if (whitelistedPermissions != null && !whitelistedPermissions.isEmpty()) {
@@ -738,7 +711,8 @@
         }
     }
 
-    private void uninstallApp() {
+    @After
+    public void uninstallApp() {
         runShellCommand("pm uninstall " + PKG);
     }
 
@@ -746,7 +720,7 @@
         return InstrumentationRegistry.getInstrumentation().getContext();
     }
 
-    private static void runWithShellPermissionIdentity(@NonNull ThrowingRunnable command)
+    private static void runWithShellPermissionIdentity(@NonNull Utils.ThrowingRunnable command)
             throws Exception {
         InstrumentationRegistry.getInstrumentation().getUiAutomation()
                 .adoptShellPermissionIdentity();
diff --git a/tests/tests/permission2/src/android/permission2/cts/Utils.java b/tests/tests/permission2/src/android/permission2/cts/Utils.java
new file mode 100644
index 0000000..7cf2f4d
--- /dev/null
+++ b/tests/tests/permission2/src/android/permission2/cts/Utils.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 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 andf
+ * limitations under the License.
+ */
+
+package android.permission2.cts;
+
+import androidx.annotation.NonNull;
+
+public class Utils {
+    private static final long TIMEOUT_MILLIS = 30000;
+
+    public interface ThrowingRunnable extends Runnable {
+        void runOrThrow() throws Exception;
+
+        @Override
+        default void run() {
+            try {
+                runOrThrow();
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    /**
+     * Make sure that a {@link ThrowingRunnable} eventually finishes without throwing a {@link
+     * Exception}.
+     *
+     * @param r The {@link ThrowingRunnable} to run.
+     */
+    public static void eventually(@NonNull ThrowingRunnable r) throws Exception {
+        long start = System.currentTimeMillis();
+
+        while (true) {
+            try {
+                r.runOrThrow();
+                return;
+            } catch (Throwable e) {
+                if (System.currentTimeMillis() - start < TIMEOUT_MILLIS) {
+                    try {
+                        Thread.sleep(100);
+                    } catch (InterruptedException ignored) {
+                        throw e;
+                    }
+                } else {
+                    throw e;
+                }
+            }
+        }
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
index c31491d..9e71c69 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
@@ -300,6 +300,30 @@
         assertTrue(queryLong(uri, MediaColumns.DATE_ADDED) >= startTime);
     }
 
+    @Test
+    public void testInPlaceUpdate_mediaFileWithInvalidRelativePath() throws Exception {
+        final File file = new File(ProviderTestUtils.stageDownloadDir(mVolumeName),
+                "test" + System.nanoTime() + ".jpg");
+        ProviderTestUtils.stageFile(R.raw.scenery, file);
+        Log.d(TAG, "Staged image file at " + file.getAbsolutePath());
+
+        final ContentValues insertValues = new ContentValues();
+        insertValues.put(MediaColumns.DATA, file.getAbsolutePath());
+        insertValues.put(MediaStore.Images.ImageColumns.DESCRIPTION, "Not a cat photo");
+        final Uri uri = mResolver.insert(mExternalImages, insertValues);
+        assertEquals(0, queryLong(uri, MediaStore.Images.ImageColumns.IS_PRIVATE));
+        assertStringColumn(uri, MediaStore.Images.ImageColumns.DESCRIPTION, "Not a cat photo");
+
+        final ContentValues updateValues = new ContentValues();
+        updateValues.put(FileColumns.MEDIA_TYPE, FileColumns.MEDIA_TYPE_IMAGE);
+        updateValues.put(FileColumns.MIME_TYPE, "image/jpeg");
+        updateValues.put(MediaStore.Images.ImageColumns.IS_PRIVATE, 1);
+        int updateRows = mResolver.update(uri, updateValues, null, null);
+        assertEquals(1, updateRows);
+        // Only interested in update not throwing exception. No need in checking whenever values
+        // were actually updates, as it is not in the scope of this test.
+    }
+
     private long queryLong(Uri uri, String columnName) {
         try (Cursor c = mResolver.query(uri, new String[] { columnName }, null, null, null)) {
             assertTrue(c.moveToFirst());
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
index 0150f2f..177fddb 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
@@ -19,6 +19,7 @@
 import static android.provider.cts.MediaStoreTest.TAG;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -313,7 +314,7 @@
         final Uri pendingUri = MediaStoreUtils.createPending(mContext, params);
         final Uri publishUri;
         try (PendingSession session = MediaStoreUtils.openPending(mContext, pendingUri)) {
-            try (InputStream in = mContext.getResources().openRawResource(R.raw.volantis);
+            try (InputStream in = mContext.getResources().openRawResource(R.raw.lg_g4_iso_800_jpg);
                  OutputStream out = session.openOutputStream()) {
                 android.os.FileUtils.copy(in, out);
             }
@@ -328,14 +329,19 @@
             final ExifInterface exif = new ExifInterface(is);
             final float[] latLong = new float[2];
             exif.getLatLong(latLong);
-            assertEquals(37.42303, latLong[0], 0.001);
-            assertEquals(-122.162025, latLong[1], 0.001);
+            assertEquals(53.83451, latLong[0], 0.001);
+            assertEquals(10.69585, latLong[1], 0.001);
+
+            String xmp = exif.getAttribute(ExifInterface.TAG_XMP);
+            assertTrue("Failed to read XMP longitude", xmp.contains("53,50.070500N"));
+            assertTrue("Failed to read XMP latitude", xmp.contains("10,41.751000E"));
+            assertTrue("Failed to read non-location XMP", xmp.contains("LensDefaults"));
         }
         // As owner, we should be able to request the original bytes
         try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(originalUri, "r")) {
         }
 
-        // Now remove ownership, which means that Exif should be redacted
+        // Now remove ownership, which means that Exif/XMP location data should be redacted
         ProviderTestUtils.executeShellCommand(
                 "content update --uri " + publishUri + " --bind owner_package_name:n:",
                 InstrumentationRegistry.getInstrumentation().getUiAutomation());
@@ -345,6 +351,11 @@
             exif.getLatLong(latLong);
             assertEquals(0, latLong[0], 0.001);
             assertEquals(0, latLong[1], 0.001);
+
+            String xmp = exif.getAttribute(ExifInterface.TAG_XMP);
+            assertFalse("Failed to redact XMP longitude", xmp.contains("53,50.070500N"));
+            assertFalse("Failed to redact XMP latitude", xmp.contains("10,41.751000E"));
+            assertTrue("Redacted non-location XMP", xmp.contains("LensDefaults"));
         }
         // We can't request original bytes unless we have permission
         try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(originalUri, "r")) {
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
index 521b12b..06f0222 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
@@ -191,7 +191,7 @@
         Bitmap src = BitmapFactory.decodeResource(mContext.getResources(), R.raw.scenery,opts);
         String stringUrl = null;
         try{
-            stringUrl = Media.insertImage(mContentResolver, src, null, null);
+            stringUrl = Media.insertImage(mContentResolver, src, "cts" + System.nanoTime(), null);
         } catch (UnsupportedOperationException e) {
             // the tests will be aborted because the image will be put in sdcard
             fail("There is no sdcard attached! " + e.getMessage());
@@ -223,7 +223,7 @@
         assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
 
         // insert image, then delete it via the files table
-        stringUrl = Media.insertImage(mContentResolver, src, null, null);
+        stringUrl = Media.insertImage(mContentResolver, src, "cts" + System.nanoTime(), null);
         c = mContentResolver.query(Uri.parse(stringUrl),
                 new String[]{ Media._ID, Media.DATA}, null, null, null);
         c.moveToFirst();
@@ -300,7 +300,8 @@
 
         // insert an image
         Bitmap src = BitmapFactory.decodeResource(mContext.getResources(), R.raw.scenery);
-        Uri uri = Uri.parse(Media.insertImage(mContentResolver, src, "test", "test description"));
+        Uri uri = Uri.parse(Media.insertImage(mContentResolver, src, "cts" + System.nanoTime(),
+                "test description"));
         long imageId = ContentUris.parseId(uri);
 
         assertNotNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
@@ -313,7 +314,8 @@
         assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
 
         // insert again
-        uri = Uri.parse(Media.insertImage(mContentResolver, src, "test", "test description"));
+        uri = Uri.parse(Media.insertImage(mContentResolver, src, "cts" + System.nanoTime(),
+                "test description"));
         imageId = ContentUris.parseId(uri);
 
         // query its thumbnail again
@@ -326,6 +328,8 @@
         assertEquals("unexpected number of updated rows",
                 1, mContentResolver.update(uri, values, null /* where */, null /* where args */));
 
+        SystemClock.sleep(1000);
+
         // image was marked as regular file in the database, which should have deleted its thumbnail
         assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
         assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
@@ -359,7 +363,8 @@
         Uri url[] = new Uri[3];
         try{
             for (int i = 0; i < url.length; i++) {
-                url[i] = Uri.parse(Media.insertImage(mContentResolver, src, null, null));
+                url[i] = Uri.parse(
+                        Media.insertImage(mContentResolver, src, "cts" + System.nanoTime(), null));
                 mRowsAdded.add(url[i]);
                 long origId = Long.parseLong(url[i].getLastPathSegment());
                 Bitmap foo = MediaStore.Images.Thumbnails.getThumbnail(mContentResolver,
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
index 65c5154..fdf46ce3 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
@@ -21,6 +21,7 @@
 import static android.provider.cts.ProviderTestUtils.assertNotExists;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -54,10 +55,12 @@
 import org.junit.runners.Parameterized.Parameter;
 import org.junit.runners.Parameterized.Parameters;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
 
 @Presubmit
 @RunWith(Parameterized.class)
@@ -200,7 +203,7 @@
 
     /**
      * This test doesn't hold
-     * {@link android.Manifest.permission#ACCESS_MEDIA_LOCATION}, so Exif
+     * {@link android.Manifest.permission#ACCESS_MEDIA_LOCATION}, so Exif and XMP
      * location information should be redacted.
      */
     @Test
@@ -232,6 +235,14 @@
             assertEquals("+37.4217-122.0834/",
                     mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION));
         }
+        try (InputStream in = mContentResolver.openInputStream(publishUri)) {
+            byte[] bytes = FileUtils.readInputStreamFully(in);
+            byte[] xmpBytes = Arrays.copyOfRange(bytes, 3269, 3269 + 13197);
+            String xmp = new String(xmpBytes);
+            assertTrue("Failed to read XMP longitude", xmp.contains("10,41.751000E"));
+            assertTrue("Failed to read XMP latitude", xmp.contains("53,50.070500N"));
+            assertTrue("Failed to read non-location XMP", xmp.contains("13166/7763"));
+        }
         // As owner, we should be able to request the original bytes
         try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(originalUri, "r")) {
         }
@@ -246,6 +257,14 @@
             assertEquals(null,
                     mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION));
         }
+        try (InputStream in = mContentResolver.openInputStream(publishUri)) {
+            byte[] bytes = FileUtils.readInputStreamFully(in);
+            byte[] xmpBytes = Arrays.copyOfRange(bytes, 3269, 3269 + 13197);
+            String xmp = new String(xmpBytes);
+            assertFalse("Failed to redact XMP longitude", xmp.contains("10,41.751000E"));
+            assertFalse("Failed to redact XMP latitude", xmp.contains("53,50.070500N"));
+            assertTrue("Redacted non-location XMP", xmp.contains("13166/7763"));
+        }
         // We can't request original bytes unless we have permission
         try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(originalUri, "r")) {
             fail("Able to read original content without ACCESS_MEDIA_LOCATION");
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
index 6d9a4bd..32ea780 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
@@ -164,6 +164,8 @@
         assertEquals("unexpected number of updated rows",
                 1, mResolver.update(uri, values, null /* where */, null /* where args */));
 
+        SystemClock.sleep(1000);
+
         // video was marked as regular file in the database, which should have deleted its thumbnail
         assertNull(Thumbnails.getThumbnail(mResolver, Long.valueOf(uri.getLastPathSegment()),
                 Thumbnails.MINI_KIND, null /* options */));
diff --git a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
index 220ef47..e748360 100644
--- a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
@@ -183,6 +183,14 @@
                 "android.provider.cts");
     }
 
+    static File stageDownloadDir(String volumeName) throws IOException {
+        if (MediaStore.VOLUME_EXTERNAL.equals(volumeName)) {
+            volumeName = MediaStore.VOLUME_EXTERNAL_PRIMARY;
+        }
+        return Environment.buildPath(MediaStore.getVolumePath(volumeName),
+                Environment.DIRECTORY_DOWNLOADS, "android.provider.cts");
+    }
+
     static File stageFile(int resId, File file) throws IOException {
         // The caller may be trying to stage into a location only available to
         // the shell user, so we need to perform the entire copy as the shell
diff --git a/tests/tests/secure_element/access_control/AccessControlApp1/Android.mk b/tests/tests/secure_element/access_control/AccessControlApp1/Android.mk
index ef992e6..8a78d0c 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp1/Android.mk
+++ b/tests/tests/secure_element/access_control/AccessControlApp1/Android.mk
@@ -28,7 +28,7 @@
 	ctstestrunner-axt \
 	compatibility-device-util-axt
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 29
 LOCAL_JAVA_LIBRARIES += android.test.runner
 LOCAL_JAVA_LIBRARIES += android.test.base
 # Tag this module as a cts test artifact
diff --git a/tests/tests/secure_element/access_control/AccessControlApp1/OWNERS b/tests/tests/secure_element/access_control/AccessControlApp1/OWNERS
deleted file mode 100644
index 9af5f4d..0000000
--- a/tests/tests/secure_element/access_control/AccessControlApp1/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 456592
-kandoiruchi@google.com
\ No newline at end of file
diff --git a/tests/tests/secure_element/access_control/AccessControlApp1/apk/signed-CtsSecureElementAccessControlTestCases1.apk b/tests/tests/secure_element/access_control/AccessControlApp1/apk/signed-CtsSecureElementAccessControlTestCases1.apk
index 28cb203..d82007a 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp1/apk/signed-CtsSecureElementAccessControlTestCases1.apk
+++ b/tests/tests/secure_element/access_control/AccessControlApp1/apk/signed-CtsSecureElementAccessControlTestCases1.apk
Binary files differ
diff --git a/tests/tests/secure_element/access_control/AccessControlApp2/Android.mk b/tests/tests/secure_element/access_control/AccessControlApp2/Android.mk
index 38f12ee..494125f 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp2/Android.mk
+++ b/tests/tests/secure_element/access_control/AccessControlApp2/Android.mk
@@ -28,7 +28,7 @@
        ctstestrunner-axt \
        compatibility-device-util-axt
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 29
 LOCAL_JAVA_LIBRARIES += android.test.runner
 LOCAL_JAVA_LIBRARIES += android.test.base
 # Tag this module as a cts test artifact
diff --git a/tests/tests/secure_element/access_control/AccessControlApp2/OWNERS b/tests/tests/secure_element/access_control/AccessControlApp2/OWNERS
deleted file mode 100644
index 9af5f4d..0000000
--- a/tests/tests/secure_element/access_control/AccessControlApp2/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 456592
-kandoiruchi@google.com
\ No newline at end of file
diff --git a/tests/tests/secure_element/access_control/AccessControlApp2/apk/signed-CtsSecureElementAccessControlTestCases2.apk b/tests/tests/secure_element/access_control/AccessControlApp2/apk/signed-CtsSecureElementAccessControlTestCases2.apk
index 1769767..6c8cb70 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp2/apk/signed-CtsSecureElementAccessControlTestCases2.apk
+++ b/tests/tests/secure_element/access_control/AccessControlApp2/apk/signed-CtsSecureElementAccessControlTestCases2.apk
Binary files differ
diff --git a/tests/tests/secure_element/access_control/AccessControlApp3/Android.mk b/tests/tests/secure_element/access_control/AccessControlApp3/Android.mk
index 335c08a..11f0200 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp3/Android.mk
+++ b/tests/tests/secure_element/access_control/AccessControlApp3/Android.mk
@@ -28,7 +28,7 @@
 	ctstestrunner-axt \
 	compatibility-device-util-axt
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 29
 LOCAL_JAVA_LIBRARIES += android.test.runner
 LOCAL_JAVA_LIBRARIES += android.test.base
 # Tag this module as a cts test artifact
diff --git a/tests/tests/secure_element/access_control/AccessControlApp3/OWNERS b/tests/tests/secure_element/access_control/AccessControlApp3/OWNERS
deleted file mode 100644
index 9af5f4d..0000000
--- a/tests/tests/secure_element/access_control/AccessControlApp3/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 456592
-kandoiruchi@google.com
\ No newline at end of file
diff --git a/tests/tests/secure_element/access_control/AccessControlApp3/apk/signed-CtsSecureElementAccessControlTestCases3.apk b/tests/tests/secure_element/access_control/AccessControlApp3/apk/signed-CtsSecureElementAccessControlTestCases3.apk
index ab07811..4d8f5e3 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp3/apk/signed-CtsSecureElementAccessControlTestCases3.apk
+++ b/tests/tests/secure_element/access_control/AccessControlApp3/apk/signed-CtsSecureElementAccessControlTestCases3.apk
Binary files differ
diff --git a/tests/tests/secure_element/access_control/OWNERS b/tests/tests/secure_element/access_control/OWNERS
new file mode 100644
index 0000000..853b7c3
--- /dev/null
+++ b/tests/tests/secure_element/access_control/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 456592
+zachoverflow@google.com
+jackcwyu@google.com
+tokuda@google.com
+georgekgchang@google.com
+jimmychchang@google.com
diff --git a/tests/tests/security/src/android/security/cts/RenderTarget.java b/tests/tests/security/src/android/security/cts/RenderTarget.java
new file mode 100644
index 0000000..3c0d1c4
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/RenderTarget.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2019 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.security.cts;
+
+import static android.opengl.EGL14.EGL_ALPHA_SIZE;
+import static android.opengl.EGL14.EGL_BLUE_SIZE;
+import static android.opengl.EGL14.EGL_CONFIG_CAVEAT;
+import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION;
+import static android.opengl.EGL14.EGL_DEFAULT_DISPLAY;
+import static android.opengl.EGL14.EGL_DEPTH_SIZE;
+import static android.opengl.EGL14.EGL_GREEN_SIZE;
+import static android.opengl.EGL14.EGL_HEIGHT;
+import static android.opengl.EGL14.EGL_NONE;
+import static android.opengl.EGL14.EGL_NO_CONTEXT;
+import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT;
+import static android.opengl.EGL14.EGL_RED_SIZE;
+import static android.opengl.EGL14.EGL_RENDERABLE_TYPE;
+import static android.opengl.EGL14.EGL_SURFACE_TYPE;
+import static android.opengl.EGL14.EGL_WIDTH;
+import static android.opengl.EGL14.EGL_WINDOW_BIT;
+import static android.opengl.EGL14.eglChooseConfig;
+import static android.opengl.EGL14.eglCreateContext;
+import static android.opengl.EGL14.eglCreatePbufferSurface;
+import static android.opengl.EGL14.eglGetDisplay;
+import static android.opengl.EGL14.eglInitialize;
+import static android.opengl.EGL14.eglMakeCurrent;
+import static android.opengl.GLES20.glDeleteTextures;
+import static android.opengl.GLES20.glGenTextures;
+
+import android.graphics.SurfaceTexture;
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.util.Log;
+import android.view.Surface;
+
+public final class RenderTarget {
+    static final String TAG = "RenderTarget";
+
+    private static final int SETUP_THREAD = 1;
+    private static final int CREATE_SINK = 2;
+    private static final int DESTROY_SINK = 3;
+    private static final int UPDATE_TEX_IMAGE = 4;
+
+    private static final Handler sHandler;
+    static {
+        HandlerThread thread = new HandlerThread("RenderTarget-GL");
+        thread.start();
+        sHandler = new Handler(thread.getLooper(), new RenderTargetThread());
+        sHandler.sendEmptyMessage(SETUP_THREAD);
+    }
+
+    public static RenderTarget create() {
+        GenericFuture<RenderTarget> future = new GenericFuture<>();
+        Message.obtain(sHandler, CREATE_SINK, future).sendToTarget();
+        try {
+            return future.get();
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Failed to createSink()", e);
+        }
+    }
+
+    private final SurfaceTexture mSurfaceTexture;
+    private final int mGlTexId;
+    private Surface mSurface;
+
+    private RenderTarget(SurfaceTexture surfaceTexture, int glTexId) {
+        mSurfaceTexture = surfaceTexture;
+        mGlTexId = glTexId;
+        mSurface = new Surface(mSurfaceTexture);
+    }
+
+    public Surface getSurface() {
+        return mSurface;
+    }
+
+    public void setDefaultSize(int width, int height) {
+        mSurfaceTexture.setDefaultBufferSize(width, height);
+    }
+
+    public void destroy() {
+        mSurface = null;
+        Message.obtain(sHandler, DESTROY_SINK, this).sendToTarget();
+    }
+
+    private static class RenderTargetThread implements Handler.Callback,
+            SurfaceTexture.OnFrameAvailableListener {
+        @Override
+        public boolean handleMessage(Message msg) {
+            switch (msg.what) {
+                case SETUP_THREAD:
+                    setupThread();
+                    return true;
+                case CREATE_SINK:
+                    createSink((GenericFuture<RenderTarget>) msg.obj);
+                    return true;
+                case DESTROY_SINK:
+                    destroySink((RenderTarget) msg.obj);
+                    return true;
+                case UPDATE_TEX_IMAGE:
+                    updateTexImage((SurfaceTexture) msg.obj);
+                default:
+                    return false;
+            }
+        }
+
+        private void createSink(GenericFuture<RenderTarget> sinkFuture) {
+            int[] tex = new int[1];
+            glGenTextures(1, tex, 0);
+            SurfaceTexture texture = new SurfaceTexture(tex[0]);
+            texture.setOnFrameAvailableListener(this);
+            sinkFuture.setResult(new RenderTarget(texture, tex[0]));
+        }
+
+        private void destroySink(RenderTarget sink) {
+            sHandler.removeMessages(UPDATE_TEX_IMAGE, sink.mSurfaceTexture);
+            sink.mSurfaceTexture.setOnFrameAvailableListener(null);
+            sink.mSurfaceTexture.release();
+            glDeleteTextures(1, new int[] { sink.mGlTexId }, 0);
+        }
+
+        private void updateTexImage(SurfaceTexture texture) {
+            texture.updateTexImage();
+        }
+
+        private void setupThread() {
+            EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+            if (display == null) {
+                throw new IllegalStateException("eglGetDisplay failed");
+            }
+            int[] version = new int[2];
+            if (!eglInitialize(display, version, 0, version, 1)) {
+                throw new IllegalStateException("eglInitialize failed");
+            }
+            final int[] egl_attribs = new int[] {
+                    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+                    EGL_RED_SIZE, 8,
+                    EGL_GREEN_SIZE, 8,
+                    EGL_BLUE_SIZE, 8,
+                    EGL_ALPHA_SIZE, 8,
+                    EGL_DEPTH_SIZE, 0,
+                    EGL_CONFIG_CAVEAT, EGL_NONE,
+                    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+                    EGL_NONE
+            };
+            EGLConfig[] configs = new EGLConfig[1];
+            int[] num_configs = new int[1];
+            if (!eglChooseConfig(display, egl_attribs, 0, configs, 0, 1, num_configs, 0)
+                    || num_configs[0] <= 0 || configs[0] == null) {
+                throw new IllegalStateException("eglChooseConfig failed");
+            }
+            EGLConfig config = configs[0];
+            final int[] gl_attribs = new int[] {
+                    EGL_CONTEXT_CLIENT_VERSION, 2,
+                    EGL_NONE
+            };
+            EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, gl_attribs, 0);
+            if (context == null) {
+                throw new IllegalStateException("eglCreateContext failed");
+            }
+            final int[] pbuffer_attribs = new int[] { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
+            EGLSurface pbuffer = eglCreatePbufferSurface(display, config, pbuffer_attribs, 0);
+            if (pbuffer == null) {
+                throw new IllegalStateException("create pbuffer surface failed");
+            }
+            if (!eglMakeCurrent(display, pbuffer, pbuffer, context)) {
+                throw new IllegalStateException("Failed to make current");
+            }
+        }
+
+        @Override
+        public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+            Log.i(TAG, "new frame available");
+            Message.obtain(sHandler, UPDATE_TEX_IMAGE, surfaceTexture).sendToTarget();
+        }
+    }
+
+    private static class GenericFuture<T> {
+        private boolean mHasResult = false;
+        private T mResult;
+        public void setResult(T result) {
+            synchronized (this) {
+                if (mHasResult) {
+                    throw new IllegalStateException("Result already set");
+                }
+                mHasResult = true;
+                mResult = result;
+                notifyAll();
+            }
+        }
+
+        public T get() throws InterruptedException {
+            synchronized (this) {
+                while (!mHasResult) {
+                    wait();
+                }
+                return mResult;
+            }
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 7b9cef0..b0e15e1 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -845,7 +845,8 @@
                 mp.setOnErrorListener(mpcl);
                 mp.setOnPreparedListener(mpcl);
                 mp.setOnCompletionListener(mpcl);
-                Surface surface = getDummySurface();
+                RenderTarget renderTarget = RenderTarget.create();
+                Surface surface = renderTarget.getSurface();
                 mp.setSurface(surface);
                 AssetFileDescriptor fd = null;
                 try {
@@ -858,6 +859,7 @@
                 }
                 Looper.loop();
                 mp.release();
+                renderTarget.destroy();
             }
         });
         t.start();
@@ -1109,32 +1111,6 @@
         doStagefrightTestMediaPlayerANR(rid, null);
     }
 
-    private Surface getDummySurface() {
-        int[] textures = new int[1];
-        GLES20.glGenTextures(1, textures, 0);
-        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
-        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
-                GLES20.GL_TEXTURE_MIN_FILTER,
-                GLES20.GL_NEAREST);
-        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
-                GLES20.GL_TEXTURE_MAG_FILTER,
-                GLES20.GL_LINEAR);
-        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
-                GLES20.GL_TEXTURE_WRAP_S,
-                GLES20.GL_CLAMP_TO_EDGE);
-        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
-                GLES20.GL_TEXTURE_WRAP_T,
-                GLES20.GL_CLAMP_TO_EDGE);
-        SurfaceTexture surfaceTex = new SurfaceTexture(textures[0]);
-        surfaceTex.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
-            @Override
-            public void onFrameAvailable(SurfaceTexture surfaceTexture) {
-                Log.i(TAG, "new frame available");
-            }
-        });
-        return new Surface(surfaceTex);
-    }
-
     public JSONArray getCrashReport(String testname, long timeout)
         throws InterruptedException {
         Log.i(TAG, CrashUtils.UPLOAD_REQUEST);
@@ -1297,7 +1273,8 @@
                 mp.setOnErrorListener(mpcl);
                 mp.setOnPreparedListener(mpcl);
                 mp.setOnCompletionListener(mpcl);
-                Surface surface = getDummySurface();
+                RenderTarget renderTarget = RenderTarget.create();
+                Surface surface = renderTarget.getSurface();
                 mp.setSurface(surface);
                 AssetFileDescriptor fd = null;
                 try {
@@ -1320,6 +1297,7 @@
 
                 Looper.loop();
                 mp.release();
+                renderTarget.destroy();
             }
         });
 
@@ -1440,9 +1418,10 @@
                 Log.i(TAG, "Decoding track " + t + " using codec " + codecName);
                 ex.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
                 MediaCodec codec = MediaCodec.createByCodecName(codecName);
+                RenderTarget renderTarget = RenderTarget.create();
                 Surface surface = null;
                 if (mime.startsWith("video/")) {
-                    surface = getDummySurface();
+                    surface = renderTarget.getSurface();
                 }
                 try {
                     codec.configure(format, surface, null, 0);
@@ -1484,6 +1463,7 @@
                     // local exceptions ignored, not security issues
                 } finally {
                     codec.release();
+                    renderTarget.destroy();
                 }
             }
             ex.unselectTrack(t);
@@ -1921,7 +1901,8 @@
                 mp.setOnErrorListener(mpl);
                 mp.setOnPreparedListener(mpl);
                 mp.setOnCompletionListener(mpl);
-                Surface surface = getDummySurface();
+                RenderTarget renderTarget = RenderTarget.create();
+                Surface surface = renderTarget.getSurface();
                 mp.setSurface(surface);
                 AssetFileDescriptor fd = null;
                 try {
@@ -1943,6 +1924,7 @@
 
                 Looper.loop();
                 mp.release();
+                renderTarget.destroy();
             }
         });
 
diff --git a/tests/tests/systemui/OWNERS b/tests/tests/systemui/OWNERS
index 958a89a..583baa0 100644
--- a/tests/tests/systemui/OWNERS
+++ b/tests/tests/systemui/OWNERS
@@ -1,2 +1,4 @@
 # Bug component: 136515
 evanlaird@google.com
+felkachang@google.com
+
diff --git a/tests/tests/systemui/src/android/systemui/cts/TouchHelper.java b/tests/tests/systemui/src/android/systemui/cts/TouchHelper.java
new file mode 100644
index 0000000..1ad74b9
--- /dev/null
+++ b/tests/tests/systemui/src/android/systemui/cts/TouchHelper.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 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.systemui.cts;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.os.SystemClock;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+
+public class TouchHelper {
+
+    private static final long REGULAR_CLICK_LENGTH = 100;
+    private final UiAutomation mUiAutomation;
+    private long mDownTime = 0;
+
+    public TouchHelper(Instrumentation instrumentation) {
+        mUiAutomation = instrumentation.getUiAutomation();
+    }
+
+    /**
+     * To click (x, y) without checking the boundary.
+     *
+     * @param x the x position on the screen
+     * @param y the y position on the screen
+     * @return true if the click event inject success, otherwise false
+     */
+    public boolean click(int x, int y) {
+        if (touchDown(x, y)) {
+            SystemClock.sleep(REGULAR_CLICK_LENGTH);
+            if (touchUp(x, y)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean touchDown(int x, int y) {
+        mDownTime = SystemClock.uptimeMillis();
+        MotionEvent event = getMotionEvent(mDownTime, mDownTime, MotionEvent.ACTION_DOWN, x, y);
+        return injectEventSync(event);
+    }
+
+    private boolean touchUp(int x, int y) {
+        final long eventTime = SystemClock.uptimeMillis();
+        MotionEvent event = getMotionEvent(mDownTime, eventTime, MotionEvent.ACTION_UP, x, y);
+        mDownTime = 0;
+        return injectEventSync(event);
+    }
+
+    private static MotionEvent getMotionEvent(long downTime, long eventTime, int action,
+            float x, float y) {
+
+        MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
+        properties.id = 0;
+        properties.toolType = MotionEvent.TOOL_TYPE_FINGER;
+
+        MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
+        coords.pressure = 1;
+        coords.size = 1;
+        coords.x = x;
+        coords.y = y;
+
+        return MotionEvent.obtain(downTime, eventTime, action, 1,
+                new MotionEvent.PointerProperties[] { properties },
+                new MotionEvent.PointerCoords[] { coords },
+                0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
+    }
+
+    private boolean injectEventSync(InputEvent event) {
+        return mUiAutomation.injectInputEvent(event, true);
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/systemui/src/android/systemui/cts/WindowInsetsActivity.java b/tests/tests/systemui/src/android/systemui/cts/WindowInsetsActivity.java
index 30ee9b8..7543c20 100644
--- a/tests/tests/systemui/src/android/systemui/cts/WindowInsetsActivity.java
+++ b/tests/tests/systemui/src/android/systemui/cts/WindowInsetsActivity.java
@@ -16,11 +16,16 @@
 
 package android.systemui.cts;
 
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+
 import android.annotation.MainThread;
 import android.graphics.Insets;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.DisplayCutout;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,6 +40,7 @@
 
 public class WindowInsetsActivity extends LightBarBaseActivity implements View.OnClickListener,
         View.OnApplyWindowInsetsListener {
+    private static final int DISPLAY_CUTOUT_SLACK_DP = 20;
 
     private TextView mContent;
     private boolean mIsSetViewBound;
@@ -46,6 +52,7 @@
     private Consumer<Boolean> mInitialFinishCallBack;
     private int mClickCount;
     private Consumer<View> mClickConsumer;
+    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
 
 
     /**
@@ -71,12 +78,21 @@
         mContent.setOnApplyWindowInsetsListener(this::onApplyWindowInsets);
         mContent.getRootView().setOnApplyWindowInsetsListener(this::onApplyWindowInsets);
         getWindow().getDecorView().setOnApplyWindowInsetsListener(this::onApplyWindowInsets);
+        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+        getWindow().getAttributes().layoutInDisplayCutoutMode
+                = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        getWindow().setStatusBarColor(0x22ff0000);
+        getWindow().setNavigationBarColor(0x22ff0000);
         mContent.setOnClickListener(this);
         mContent.requestApplyInsets();
         setContentView(mContent);
 
         mContentWindowInsets = getWindow().getDecorView().getRootWindowInsets();
         mInitialFinishCallBack = null;
+
+        getDisplay().getRealMetrics(mDisplayMetrics);
     }
 
     @Override
@@ -198,6 +214,21 @@
             sb.append("content boundary = ").append(mContentBound).append("\n");
         }
 
+        Display display = getDisplay();
+        if (display != null) {
+            sb.append("------------------------").append("\n");
+            DisplayCutout displayCutout = display.getCutout();
+            if (displayCutout != null) {
+                sb.append("displayCutout = ").append(displayCutout.toString()).append("\n");
+            } else {
+                sb.append("Display cut out = null\n");
+            }
+
+            sb.append("real size = (").append(mDisplayMetrics.widthPixels).append(",")
+                    .append(mDisplayMetrics.heightPixels).append(")\n");
+        }
+
+
         mContent.setText(sb.toString());
     }
 
@@ -217,30 +248,30 @@
     /**
      * To count the draggable boundary that has consume the related insets.
      **/
-
     @MainThread
-    public Rect getOperationArea(boolean insetMandatorySystemGesture,
-            boolean insetTappableElements, WindowInsets windowInsets) {
-
-        Insets insets;
-        if (insetMandatorySystemGesture) {
-            insets = windowInsets.getMandatorySystemGestureInsets();
-        } else if (insetTappableElements) {
-            insets = windowInsets.getTappableElementInsets();
-        } else {
-            insets = windowInsets.getSystemGestureInsets();
-        }
-
+    public Rect getOperationArea(Insets insets, WindowInsets windowInsets) {
         int left = insets.left;
-        int top = 0;
-        if (windowInsets.getStableInsetTop() >= insets.top) {
-            top = windowInsets.getStableInsetTop() - insets.top;
-        } else {
-            top = insets.top;
-        }
+        int top = insets.top;
         int right = insets.right;
         int bottom = insets.bottom;
 
+        final DisplayCutout cutout = windowInsets.getDisplayCutout();
+        if (cutout != null) {
+            int slack = (int) (DISPLAY_CUTOUT_SLACK_DP * mDisplayMetrics.density);
+            if (cutout.getSafeInsetLeft() > 0) {
+                left = Math.max(left, cutout.getSafeInsetLeft() + slack);
+            }
+            if (cutout.getSafeInsetTop() > 0) {
+                top = Math.max(top, cutout.getSafeInsetTop() + slack);
+            }
+            if (cutout.getSafeInsetRight() > 0) {
+                right = Math.max(right, cutout.getSafeInsetRight() + slack);
+            }
+            if (cutout.getSafeInsetBottom() > 0) {
+                bottom = Math.max(bottom, cutout.getSafeInsetBottom() + slack);
+            }
+        }
+
         Rect windowBoundary = getViewBound(getContentView());
         Rect rect = new Rect(windowBoundary);
         rect.left += left;
diff --git a/tests/tests/systemui/src/android/systemui/cts/WindowInsetsBehaviorTests.java b/tests/tests/systemui/src/android/systemui/cts/WindowInsetsBehaviorTests.java
index 11d40a0..2ca4156 100644
--- a/tests/tests/systemui/src/android/systemui/cts/WindowInsetsBehaviorTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/WindowInsetsBehaviorTests.java
@@ -23,6 +23,7 @@
 
 import static org.junit.Assume.assumeTrue;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -30,6 +31,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
+import android.os.Bundle;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
 import android.support.test.uiautomator.UiDevice;
@@ -63,9 +65,11 @@
     private static final String DEF_SCREENSHOT_BASE_PATH =
             "/sdcard/WindowInsetsBehaviorTests";
     private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
-    public static final int STEPS = 10;
-    public static final int DIP_INTERVAL = 40;
+    private static final String ARGUMENT_KEY_FORCE_ENABLE = "force_enable_gesture_navigation";
+    private static final int STEPS = 10;
+    private static final int DIP_INTERVAL = 40;
 
+    private final boolean mForceEnableGestureNavigation;
     private final Map<String, Boolean> mSystemGestureOptionsMap;
     private float mPixelsPerDp;
     private UiDevice mDevice;
@@ -73,6 +77,7 @@
     private String mEdgeToEdgeNavigationTitle;
     private String mSystemNavigationTitle;
     private String mGesturePreferenceTitle;
+    private TouchHelper mTouchHelper;
     private boolean mConfiguredInSettings;
 
     private static String getSettingsString(Resources res, String strResName) {
@@ -88,8 +93,16 @@
      * To initial all of options in System Gesture.
      */
     public WindowInsetsBehaviorTests() {
+        Bundle bundle = InstrumentationRegistry.getArguments();
+        mForceEnableGestureNavigation = (bundle != null)
+                && "true".equalsIgnoreCase(bundle.getString(ARGUMENT_KEY_FORCE_ENABLE));
+
         mSystemGestureOptionsMap = new ArrayMap();
 
+        if (!mForceEnableGestureNavigation) {
+            return;
+        }
+
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         PackageManager packageManager = context.getPackageManager();
         Resources res = null;
@@ -173,14 +186,17 @@
         return mDevice.findObject(targetSelector);
     }
 
-
     private boolean launchToSettingsSystemGesture() {
+        if (!mForceEnableGestureNavigation) {
+            return false;
+        }
+
         /* launch to the close to the system gesture fragment */
-        Intent intent = new Intent();
-        intent.setClassName("com.android.settings",
-                "com.android.settings.Settings$SystemDashboardActivity");
-        intent.putExtra(":settings:show_fragment",
-                "com.android.settings.gestures.GestureSettings");
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        ComponentName settingComponent = new ComponentName(SETTINGS_PACKAGE_NAME,
+                String.format("%s.%s$%s", SETTINGS_PACKAGE_NAME, "Settings",
+                        "SystemDashboardActivity"));
+        intent.setComponent(settingComponent);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         mTargetContext.startActivity(intent);
 
@@ -230,6 +246,7 @@
     @Before
     public void setUp() throws Exception {
         mDevice = UiDevice.getInstance(getInstrumentation());
+        mTouchHelper = new TouchHelper(getInstrumentation());
         mTargetContext = getInstrumentation().getTargetContext();
         if (!hasSystemGestureFeature()) {
             return;
@@ -303,7 +320,10 @@
         mActivity.setOnClickConsumer((view) -> {
             latch.countDown();
         });
-        mDevice.click(p.x, p.y);
+        // mDevice.click(p.x, p.y) has the limitation without consideration of the cutout
+        if (!mTouchHelper.click(p.x, p.y)) {
+            fail("Can't inject event at" + p);
+        }
 
         /* wait until the OnClickListener triggered, and then click the next point */
         try {
@@ -313,7 +333,7 @@
         }
 
         if (latch.getCount() > 0) {
-            fail("Doesn't receive onClickEvent");
+            fail("Doesn't receive onClickEvent at " + p);
         }
     }
 
@@ -514,8 +534,9 @@
 
         mainThreadRun(() -> mActivity.setSystemGestureExclusion(true));
         mainThreadRun(() -> mContentViewWindowInsets = mActivity.getDecorViewWindowInsets());
-        mainThreadRun(() -> mDragBound = mActivity.getOperationArea(true,
-                    false, mContentViewWindowInsets));
+        mainThreadRun(() -> mDragBound = mActivity.getOperationArea(
+                mContentViewWindowInsets.getMandatorySystemGestureInsets(),
+                mContentViewWindowInsets));
 
         int dragCount = dragInViewBoundary(mDragBound);
 
@@ -532,35 +553,13 @@
     }
 
     @Test
-    public void mandatorySystemGesture_tapSamplePoints_excludeViewRects_withoutAnyCancel() {
-        assumeTrue(hasSystemGestureFeature());
-
-        mainThreadRun(() -> mActivity.setSystemGestureExclusion(true));
-        mainThreadRun(() -> mContentViewWindowInsets = mActivity.getDecorViewWindowInsets());
-        mainThreadRun(() -> mDragBound = mActivity.getOperationArea(false,
-                true, mContentViewWindowInsets));
-
-        int count = clickAllOfSamplePoints(mDragBound, this::clickAndWaitByUiDevice);
-
-        mainThreadRun(() -> {
-            mClickCount = mActivity.getClickCount();
-            mActionCancelPoints = mActivity.getActionCancelPoints();
-        });
-        mScreenshotTestRule.capture();
-
-        assertEquals("The number of click not match", count, mClickCount);
-        assertEquals("The Number of the canceled points not match", 0,
-                mActionCancelPoints.size());
-    }
-
-    @Test
     public void systemGesture_notExcludeViewRects_withoutAnyCancel() {
         assumeTrue(hasSystemGestureFeature());
 
         mainThreadRun(() -> mActivity.setSystemGestureExclusion(false));
         mainThreadRun(() -> mContentViewWindowInsets = mActivity.getDecorViewWindowInsets());
-        mainThreadRun(() -> mDragBound = mActivity.getOperationArea(false,
-                false, mContentViewWindowInsets));
+        mainThreadRun(() -> mDragBound = mActivity.getOperationArea(
+                mContentViewWindowInsets.getSystemGestureInsets(), mContentViewWindowInsets));
 
         int dragCount = dragInViewBoundary(mDragBound);
 
@@ -577,13 +576,13 @@
     }
 
     @Test
-    public void systemGesture_tapSamplePoints_notExcludeViewRects_withoutAnyCancel() {
+    public void tappableElements_tapSamplePoints_excludeViewRects_withoutAnyCancel() {
         assumeTrue(hasSystemGestureFeature());
 
-        mainThreadRun(() -> mActivity.setSystemGestureExclusion(false));
+        mainThreadRun(() -> mActivity.setSystemGestureExclusion(true));
         mainThreadRun(() -> mContentViewWindowInsets = mActivity.getDecorViewWindowInsets());
-        mainThreadRun(() -> mDragBound = mActivity.getOperationArea(false,
-                true, mContentViewWindowInsets));
+        mainThreadRun(() -> mDragBound = mActivity.getOperationArea(
+                mContentViewWindowInsets.getTappableElementInsets(), mContentViewWindowInsets));
 
         int count = clickAllOfSamplePoints(mDragBound, this::clickAndWaitByUiDevice);
 
@@ -598,19 +597,14 @@
                 mActionCancelPoints.size());
     }
 
-    /**
-     * To tap all possible points except the system gesture area and tappable elements area.
-     * Caution: don't touch system gesture area because it still exists and will trigger cancel
-     * event.
-     */
     @Test
     public void tappableElements_tapSamplePoints_notExcludeViewRects_withoutAnyCancel() {
         assumeTrue(hasSystemGestureFeature());
 
         mainThreadRun(() -> mActivity.setSystemGestureExclusion(false));
         mainThreadRun(() -> mContentViewWindowInsets = mActivity.getDecorViewWindowInsets());
-        mainThreadRun(() -> mDragBound = mActivity.getOperationArea(false,
-                true, mContentViewWindowInsets));
+        mainThreadRun(() -> mDragBound = mActivity.getOperationArea(
+                mContentViewWindowInsets.getTappableElementInsets(), mContentViewWindowInsets));
 
         int count = clickAllOfSamplePoints(mDragBound, this::clickAndWaitByUiDevice);
 
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
index e058947..f1acc16 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
@@ -220,6 +220,6 @@
                         initBlueWebView(hwFence), true, hwFence)
                 .addLayout(R.layout.circle_clipped_webview,
                         initBlueWebView(swFence), false, swFence)
-                .runWithComparer(new MSSIMComparer(0.95));
+                .runWithComparer(new MSSIMComparer(0.94));
     }
 }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewFadingEdgeTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewFadingEdgeTests.java
new file mode 100644
index 0000000..81b1586
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewFadingEdgeTests.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2019 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.uirendering.cts.testclasses;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.uirendering.cts.R;
+import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.ViewInitializer;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class ViewFadingEdgeTests extends ActivityTestBase {
+    class FadingView extends View {
+        public boolean mEnableFadingLeftEdge = false;
+        public boolean mEnableFadingRightEdge = false;
+        public boolean mEnableFadingTopEdge = false;
+        public boolean mEnableFadingBottomEdge = false;
+
+        FadingView(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            canvas.drawColor(Color.RED);
+        }
+
+        @Override
+        protected float getLeftFadingEdgeStrength() {
+            return mEnableFadingLeftEdge ? 1.0f : 0.0f;
+        }
+
+        @Override
+        protected float getRightFadingEdgeStrength() {
+            return mEnableFadingRightEdge ? 1.0f : 0.0f;
+        }
+
+        @Override
+        protected float getTopFadingEdgeStrength() {
+            return mEnableFadingTopEdge ? 1.0f : 0.0f;
+        }
+
+        @Override
+        protected float getBottomFadingEdgeStrength() {
+            return mEnableFadingBottomEdge ? 1.0f : 0.0f;
+        }
+    }
+
+    private FadingView attachFadingView(View parentView) {
+        final FadingView child = new FadingView(parentView.getContext());
+        child.setLayoutParams(new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.MATCH_PARENT,
+                FrameLayout.LayoutParams.MATCH_PARENT));
+
+        FrameLayout root = (FrameLayout) parentView.findViewById(R.id.frame_layout);
+        root.addView(child);
+        return child;
+    }
+
+    @Test
+    public void testCreateLeftFade() {
+        createTest()
+                .addLayout(R.layout.frame_layout, (ViewInitializer) view -> {
+                    final FadingView child = attachFadingView(view);
+                    child.mEnableFadingLeftEdge = true;
+                    child.setFadingEdgeLength(TEST_WIDTH / 2);
+                    child.setHorizontalFadingEdgeEnabled(true);
+                    Assert.assertEquals(0, child.getSolidColor());
+                })
+                .runWithVerifier(new SamplePointVerifier(new Point[] {
+                        new Point(0, 0),
+                        new Point(TEST_WIDTH / 4, 0),
+                        new Point(TEST_WIDTH / 2, 0),
+                        new Point(TEST_WIDTH - 1, 0)
+                }, new int[] {
+                        Color.WHITE,
+                        0xFFFF8080, // gradient halfway between red and white
+                        Color.RED,
+                        Color.RED,
+
+                }, 20)); // Tolerance set to account for interpolation
+    }
+
+    @Test
+    public void testCreateRightFade() {
+        createTest()
+                .addLayout(R.layout.frame_layout, (ViewInitializer) view -> {
+                    final FadingView child = attachFadingView(view);
+                    child.mEnableFadingRightEdge = true;
+                    child.setFadingEdgeLength(TEST_WIDTH / 2);
+                    child.setHorizontalFadingEdgeEnabled(true);
+                    Assert.assertEquals(0, child.getSolidColor());
+                })
+                .runWithVerifier(new SamplePointVerifier(new Point[] {
+                        new Point(0, 0),
+                        new Point(TEST_WIDTH / 2, 0),
+                        new Point((TEST_WIDTH / 4) * 3, 0),
+                        new Point(TEST_WIDTH - 1, 0)
+                }, new int[] {
+                        Color.RED,
+                        Color.RED,
+                        0xFFFF8080, // gradient halfway between red and white
+                        Color.WHITE
+                }, 20)); // Tolerance set to account for interpolation
+    }
+
+    @Test
+    public void testCreateTopFade() {
+        createTest()
+                .addLayout(R.layout.frame_layout, (ViewInitializer) view -> {
+                    final FadingView child = attachFadingView(view);
+                    child.mEnableFadingTopEdge = true;
+                    child.setFadingEdgeLength(TEST_HEIGHT / 2);
+                    child.setVerticalFadingEdgeEnabled(true);
+                    Assert.assertEquals(0, child.getSolidColor());
+                })
+                .runWithVerifier(new SamplePointVerifier(new Point[] {
+                        new Point(0, 0),
+                        new Point(0, TEST_HEIGHT / 4),
+                        new Point(0, TEST_HEIGHT / 2),
+                        new Point(0, TEST_HEIGHT - 1)
+                }, new int[] {
+                        Color.WHITE,
+                        0xFFFF8080, // gradient halfway between red and white
+                        Color.RED,
+                        Color.RED,
+                }, 20)); // Tolerance set to account for interpolation
+    }
+
+    @Test
+    public void testCreateBottomFade() {
+        createTest()
+                .addLayout(R.layout.frame_layout, (ViewInitializer) view -> {
+                    final FadingView child = attachFadingView(view);
+                    child.mEnableFadingBottomEdge = true;
+                    child.setFadingEdgeLength(TEST_HEIGHT / 2);
+                    child.setVerticalFadingEdgeEnabled(true);
+                    Assert.assertEquals(0, child.getSolidColor());
+                })
+                .runWithVerifier(new SamplePointVerifier(new Point[] {
+                        new Point(0, 0),
+                        new Point(0, TEST_HEIGHT / 2),
+                        new Point(0, (TEST_HEIGHT / 4) * 3),
+                        new Point(0, TEST_HEIGHT - 1)
+                }, new int[] {
+                        Color.RED,
+                        Color.RED,
+                        0xFFFF8080, // gradient halfway between red and white
+                        Color.WHITE
+                }, 20)); // Tolerance set to account for interpolation
+    }
+
+    @Test
+    public void testCreateLeftAndRightFade() {
+        createTest()
+                .addLayout(R.layout.frame_layout, (ViewInitializer) view -> {
+                    final FadingView child = attachFadingView(view);
+                    child.mEnableFadingLeftEdge = true;
+                    child.mEnableFadingRightEdge = true;
+                    child.setFadingEdgeLength(TEST_WIDTH / 2);
+                    child.setHorizontalFadingEdgeEnabled(true);
+                    Assert.assertEquals(0, child.getSolidColor());
+                })
+                .runWithVerifier(new SamplePointVerifier(new Point[] {
+                        new Point(0, 0),
+                        new Point(TEST_WIDTH / 4, 0),
+                        new Point(TEST_WIDTH / 2, 0),
+                        new Point((TEST_WIDTH / 4) * 3, 0),
+                        new Point(TEST_WIDTH - 1, 0)
+                }, new int[] {
+                        Color.WHITE,
+                        0xFFFF8080, // gradient halfway between red and white
+                        Color.RED,
+                        0xFFFF8080, // gradient halfway between red and white
+                        Color.WHITE
+                }, 20)); // Tolerance set to account for interpolation
+    }
+}
diff --git a/tests/tests/voiceinteraction/AndroidManifest.xml b/tests/tests/voiceinteraction/AndroidManifest.xml
index 86ae911..393d7a8 100644
--- a/tests/tests/voiceinteraction/AndroidManifest.xml
+++ b/tests/tests/voiceinteraction/AndroidManifest.xml
@@ -16,8 +16,7 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.voiceinteraction.cts"
-    android:targetSandboxVersion="2">
+    package="android.voiceinteraction.cts">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.BIND_VOICE_INTERACTION" />
@@ -36,12 +35,7 @@
       <activity android:name="TestLocalInteractionActivity"
                 android:label="Local Interaction Activity">
           <intent-filter>
-              <action android:name="android.intent.action.VIEW"/>
-              <category android:name="android.intent.category.DEFAULT" />
-              <category android:name="android.intent.category.BROWSABLE" />
-              <data android:scheme="https" />
-              <data android:host="android.voiceinteraction.cts" />
-              <data android:path="/TestLocalInteractionActivity" />
+              <action android:name="android.intent.action.TEST_LOCAL_INTERACTION_ACTIVITY" />
           </intent-filter>
       </activity>
       <receiver android:name="VoiceInteractionTestReceiver"
diff --git a/tests/tests/voiceinteraction/AndroidTest.xml b/tests/tests/voiceinteraction/AndroidTest.xml
index 461fc6b..bbf478d 100644
--- a/tests/tests/voiceinteraction/AndroidTest.xml
+++ b/tests/tests/voiceinteraction/AndroidTest.xml
@@ -19,17 +19,20 @@
     <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="not-shardable" value="true" />
+
+    <!-- Force service to be installed as non-instant mode, always -->
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsVoiceInteractionService.apk" />
-        <option name="test-file-name" value="CtsVoiceInteractionApp.apk" />
-        <option name="test-file-name" value="CtsVoiceInteractionTestCases.apk" />
+        <option name="instant-mode" value="false"/>
+        <option name="force-install-mode" value="FULL"/>
+        <option name="cleanup-apks" value="true"/>
+        <option name="test-file-name" value="CtsVoiceInteractionService.apk"/>
     </target_preparer>
 
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="cmd voiceinteraction set bind-instant-service-allowed true" />
-        <option name="teardown-command" value="cmd voiceinteraction set bind-instant-service-allowed false" />
-     </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsVoiceInteractionTestCases.apk"/>
+        <option name="test-file-name" value="CtsVoiceInteractionApp.apk"/>
+    </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.voiceinteraction.cts" />
diff --git a/tests/tests/voiceinteraction/service/AndroidManifest.xml b/tests/tests/voiceinteraction/service/AndroidManifest.xml
index 2ef0728..b01653c 100644
--- a/tests/tests/voiceinteraction/service/AndroidManifest.xml
+++ b/tests/tests/voiceinteraction/service/AndroidManifest.xml
@@ -24,21 +24,26 @@
               android:label="CTS test voice interaction service"
               android:permission="android.permission.BIND_VOICE_INTERACTION"
               android:process=":interactor"
-              android:exported="true">
+              android:exported="true"
+              android:visibleToInstantApps="true">
           <meta-data android:name="android.voice_interaction"
                      android:resource="@xml/interaction_service" />
           <intent-filter>
               <action android:name="android.service.voice.VoiceInteractionService" />
           </intent-filter>
       </service>
-      <activity android:name=".VoiceInteractionMain">
+      <activity android:name=".VoiceInteractionMain"
+                android:exported="true"
+                android:visibleToInstantApps="true">
           <intent-filter>
               <action android:name="android.intent.action.START_TEST" />
               <category android:name="android.intent.category.DEFAULT" />
           </intent-filter>
       </activity>
       <activity android:name=".SettingsActivity"
-                android:label="Voice Interaction Settings">
+                android:label="Voice Interaction Settings"
+                android:exported="true"
+                android:visibleToInstantApps="true">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.DEFAULT" />
@@ -46,10 +51,14 @@
       </activity>
       <service android:name=".MainInteractionSessionService"
               android:permission="android.permission.BIND_VOICE_INTERACTION"
-              android:process=":session">
+              android:process=":session"
+              android:exported="true"
+              android:visibleToInstantApps="true">
       </service>
       <service android:name=".MainRecognitionService"
-              android:label="CTS Voice Recognition Service">
+              android:label="CTS Voice Recognition Service"
+              android:exported="true"
+              android:visibleToInstantApps="true">
           <intent-filter>
               <action android:name="android.speech.RecognitionService" />
               <category android:name="android.intent.category.DEFAULT" />
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainInteractionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainInteractionService.java
index ca92286..ccd20e5 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainInteractionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainInteractionService.java
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
+import android.net.Uri;
 import android.os.Bundle;
 import android.service.voice.VoiceInteractionService;
 import android.service.voice.VoiceInteractionSession;
@@ -60,10 +61,14 @@
                     // Call to verify onGetSupportedVoiceActions is available.
                     onGetSupportedVoiceActions(Collections.emptySet());
                     args = new Bundle();
-                    Intent intent = new Intent();
-                    intent.setComponent(new ComponentName("android.voiceinteraction.testapp",
-                            "android.voiceinteraction.testapp.TestApp"));
+                    Intent intent = new Intent()
+                            .setAction(Intent.ACTION_VIEW)
+                            .addCategory(Intent.CATEGORY_VOICE)
+                            .addCategory(Intent.CATEGORY_BROWSABLE)
+                            .setData(Uri.parse("https://android.voiceinteraction.testapp"
+                                    + "/TestApp"));
                     args.putParcelable("intent", intent);
+                    Log.v(TAG, "showSession(): " + args);
                     showSession(args, 0);
                 } else {
                     Log.wtf(TAG, "**** Not starting MainInteractionService because" +
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/DirectActionsTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/DirectActionsTest.java
index 2b28f0d..338c361 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/DirectActionsTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/DirectActionsTest.java
@@ -16,24 +16,20 @@
 
 package android.voiceinteraction.cts;
 
-import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
-
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.app.DirectAction;
 import android.content.Intent;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteCallback;
+import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 import android.voiceinteraction.common.Utils;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
 import com.android.compatibility.common.util.ThrowingRunnable;
 
-import org.junit.Before;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -42,6 +38,9 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 /**
  * Tests for the direction action related functions.
  */
@@ -52,16 +51,6 @@
     private final @NonNull SessionControl mSessionControl = new SessionControl();
     private final @NonNull ActivityControl mActivityControl = new ActivityControl();
 
-    // TODO: move to super class
-    @Before
-    public void prepareDevice() throws Exception {
-        // Unlock screen.
-        runShellCommand("input keyevent KEYCODE_WAKEUP");
-
-        // Dismiss keyguard, in case it's set as "Swipe to unlock".
-        runShellCommand("wm dismiss-keyguard");
-    }
-
     @Test
     public void testPerformDirectAction() throws Exception {
         mActivityControl.startActivity();
@@ -86,6 +75,7 @@
         }
     }
 
+    @AppModeFull(reason = "testPerformDirectAction() is enough")
     @Test
     public void testCancelPerformedDirectAction() throws Exception {
         mActivityControl.startActivity();
@@ -110,6 +100,7 @@
         }
     }
 
+    @AppModeFull(reason = "testPerformDirectAction() is enough")
     @Test
     public void testVoiceInteractorDestroy() throws Exception {
         mActivityControl.startActivity();
@@ -127,6 +118,7 @@
         }
     }
 
+    @AppModeFull(reason = "testPerformDirectAction() is enough")
     @Test
     public void testNotifyDirectActionsChanged() throws Exception {
         mActivityControl.startActivity();
@@ -255,11 +247,18 @@
                 latch.countDown();
             });
 
-            final Intent intent = new Intent();
-            intent.setClassName("android.voiceinteraction.testapp",
-                    "android.voiceinteraction.testapp.DirectActionsActivity");
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            intent.putExtra(Utils.DIRECT_ACTIONS_KEY_CALLBACK, callback);
+            final Intent intent = new Intent()
+                    .setAction(Intent.ACTION_VIEW)
+                    .addCategory(Intent.CATEGORY_BROWSABLE)
+                    .setData(Uri.parse("https://android.voiceinteraction.testapp"
+                            + "/DirectActionsActivity"))
+                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                    .putExtra(Utils.DIRECT_ACTIONS_KEY_CALLBACK, callback);
+
+            if (!mContext.getPackageManager().isInstantApp()) {
+                intent.setPackage("android.voiceinteraction.testapp");
+            }
+
             Log.v(TAG, "startActivity: " + intent);
 
             mContext.startActivity(intent);
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/LocalVoiceInteractionTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/LocalVoiceInteractionTest.java
index 880ba90..fdbeb35 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/LocalVoiceInteractionTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/LocalVoiceInteractionTest.java
@@ -57,10 +57,7 @@
 
     private void startTestActivity() throws Exception {
         Intent intent = new Intent()
-                .setAction(Intent.ACTION_VIEW)
-                .addCategory(Intent.CATEGORY_BROWSABLE)
-                .setData(Uri.parse("https://android.voiceinteraction.cts"
-                        + "TestLocalInteractionActivity"));
+                .setAction("android.intent.action.TEST_LOCAL_INTERACTION_ACTIVITY");
         Log.i(TAG, "startTestActivity: " + intent);
         mTestActivity = mActivityTestRule.launchActivity(intent);
     }
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/TestStartActivity.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/TestStartActivity.java
index 11cedd9..b327f5d 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/TestStartActivity.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/TestStartActivity.java
@@ -19,7 +19,6 @@
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Intent;
-import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
 
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionTest.java
index 2ea7e2f..fbb4836 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/VoiceInteractionTest.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
+import android.platform.test.annotations.AppModeFull;
 import android.util.Log;
 import android.voiceinteraction.common.Utils;
 
@@ -39,6 +40,9 @@
 
 import androidx.test.rule.ActivityTestRule;
 
+// TODO: ideally we should split testAll() into multiple tests, and run at least one of them
+// on instant
+@AppModeFull(reason = "DirectActionsTest is enough")
 public class VoiceInteractionTest extends AbstractVoiceInteractionTestCase {
     static final String TAG = "VoiceInteractionTest";
     private static final int TIMEOUT_MS = 20 * 1000;
diff --git a/tests/tests/voiceinteraction/testapp/AndroidManifest.xml b/tests/tests/voiceinteraction/testapp/AndroidManifest.xml
index 4e7156b..c683c66 100644
--- a/tests/tests/voiceinteraction/testapp/AndroidManifest.xml
+++ b/tests/tests/voiceinteraction/testapp/AndroidManifest.xml
@@ -25,15 +25,28 @@
                 android:label="Voice Interaction Test App"
                 android:theme="@android:style/Theme.DeviceDefault">
           <intent-filter>
-              <action android:name="android.intent.action.TEST_APP" />
+              <action android:name="android.intent.action.VIEW"/>
               <category android:name="android.intent.category.DEFAULT" />
+              <category android:name="android.intent.category.BROWSABLE" />
               <category android:name="android.intent.category.VOICE" />
+              <data android:scheme="https" />
+              <data android:host="android.voiceinteraction.testapp" />
+              <data android:path="/TestApp" />
           </intent-filter>
       </activity>
 
        <activity android:name=".DirectActionsActivity"
                 android:label="Direct actions activity"
                 android:exported="true">
+          <intent-filter>
+              <action android:name="android.intent.action.VIEW"/>
+              <category android:name="android.intent.category.DEFAULT" />
+              <category android:name="android.intent.category.BROWSABLE" />
+              <data android:scheme="https" />
+              <data android:host="android.voiceinteraction.testapp" />
+              <data android:path="/DirectActionsActivity" />
+              <category android:name="android.intent.category.VOICE" />
+          </intent-filter>
         </activity>
 
     </application>
diff --git a/tests/tests/widget/AndroidTest.xml b/tests/tests/widget/AndroidTest.xml
index 123b9e7..fd9afe8 100644
--- a/tests/tests/widget/AndroidTest.xml
+++ b/tests/tests/widget/AndroidTest.xml
@@ -17,6 +17,7 @@
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="uitoolkit" />
     <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsWidgetTestCases.apk" />
diff --git a/tools/cts-api-coverage/proto/cts_report.proto b/tools/cts-api-coverage/proto/cts_report.proto
index afb4338..5007c69 100644
--- a/tools/cts-api-coverage/proto/cts_report.proto
+++ b/tools/cts-api-coverage/proto/cts_report.proto
@@ -90,8 +90,12 @@
 // The numbers are in dpi and should match android.util.DisplayMetrics.DENSITY_*
 enum LogicalDensity {
   LDPI = 120;
+  DENSITY_140 = 140;
   MDPI = 160;
+  DENSITY_180 = 180;
+  DENSITY_200 = 200;
   TVDPI = 213;
+  DENSITY_220 = 220;
   HDPI = 240;
   DENSITY_260 = 260;
   DENSITY_280 = 280;
@@ -103,10 +107,12 @@
   // DENSITY_XXHIGH (480 dpi).
   DENSITY_400 = 400;
   DENSITY_420 = 420;
+  DENSITY_440 = 440;
   XXHDPI = 480;
   // Intermediate density for screens that sit somewhere between DENSITY_XXHIGH (480 dpi) and
   // DENSITY_XXXHIGH (640 dpi).
   DENSITY_560 = 560;
+  DENSITY_600 = 600;
   XXXHDPI = 640;
 }
 
@@ -349,4 +355,4 @@
     optional string abi = 6;
   }
   repeated TestPackage test_package = 8;
-}
\ No newline at end of file
+}