Merge "Use RequiredFeatureRule to test for LiveTv feature" into rvc-dev
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index b4ead04..0161c90 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -16,6 +16,7 @@
 
 package android.appsecurity.cts;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -23,11 +24,18 @@
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.Log;
+import com.android.server.role.RoleManagerServiceDumpProto;
+import com.android.server.role.RoleProto;
+import com.android.server.role.RoleUserStateProto;
+import com.android.tradefed.device.CollectingByteOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
 import com.android.tradefed.util.AbiUtils;
 
+import com.google.protobuf.MessageLite;
+import com.google.protobuf.Parser;
+
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
@@ -38,7 +46,6 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -662,6 +669,51 @@
         }
     }
 
+    private <T extends MessageLite> T getDump(Parser<T> parser, String command) throws Exception {
+        final CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
+        getDevice().executeShellCommand(command, receiver);
+        return parser.parseFrom(receiver.getOutput());
+    }
+
+    private List<RoleUserStateProto> getAllUsersRoleStates() throws Exception {
+        final RoleManagerServiceDumpProto dumpProto =
+                getDump(RoleManagerServiceDumpProto.parser(), "dumpsys role --proto");
+        final List<RoleUserStateProto> res = new ArrayList<>();
+        for (RoleUserStateProto userState : dumpProto.getUserStatesList()) {
+            for (int i : mUsers) {
+                if (i == userState.getUserId()) {
+                    res.add(userState);
+                    break;
+                }
+            }
+        }
+        return res;
+    }
+
+    @Test
+    public void testSystemGalleryExists() throws Exception {
+        final List<RoleUserStateProto> usersRoleStates = getAllUsersRoleStates();
+
+        assertEquals("Unexpected number of users returned by dumpsys role",
+                mUsers.length, usersRoleStates.size());
+
+        for (RoleUserStateProto userState : usersRoleStates) {
+            final List<RoleProto> roles = userState.getRolesList();
+            boolean systemGalleryRoleFound = false;
+
+            // Iterate through the roles until we find the System Gallery role
+            for (RoleProto roleProto : roles) {
+                if ("android.app.role.SYSTEM_GALLERY".equals(roleProto.getName())) {
+                    assertEquals(1, roleProto.getHoldersList().size());
+                    systemGalleryRoleFound = true;
+                    break;
+                }
+            }
+            assertTrue("SYSTEM_GALLERY not defined for user " + userState.getUserId(),
+                    systemGalleryRoleFound);
+        }
+    }
+
     private boolean access(String path) throws DeviceNotAvailableException {
         final long nonce = System.nanoTime();
         return getDevice().executeShellCommand("ls -la " + path + " && echo " + nonce)
diff --git a/hostsidetests/appsecurity/test-apps/AccessSerialModern/src/android/os/cts/AccessSerialModernTest.java b/hostsidetests/appsecurity/test-apps/AccessSerialModern/src/android/os/cts/AccessSerialModernTest.java
index 0cb9136..bd17748 100644
--- a/hostsidetests/appsecurity/test-apps/AccessSerialModern/src/android/os/cts/AccessSerialModernTest.java
+++ b/hostsidetests/appsecurity/test-apps/AccessSerialModern/src/android/os/cts/AccessSerialModernTest.java
@@ -35,14 +35,7 @@
     public void testAccessSerialPermissionNeeded() throws Exception {
         // Build.SERIAL should not provide the device serial for modern apps.
         // We don't know the serial but know that it should be the dummy
-        // value returned to unauthorized callers, so make sure that value
-        assertTrue("Build.SERIAL must not work for modern apps",
-                Build.UNKNOWN.equals(Build.SERIAL));
-
-        // Now grant ourselves READ_PHONE_STATE
-        grantReadPhoneStatePermission();
-
-        // Build.SERIAL should not provide the device serial for modern apps.
+        // value returned to unauthorized callers, so make sure that value is returned.
         assertTrue("Build.SERIAL must not work for modern apps",
                 Build.UNKNOWN.equals(Build.SERIAL));
 
@@ -60,10 +53,4 @@
                     + e);
         }
     }
-
-    private void grantReadPhoneStatePermission() {
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
-                InstrumentationRegistry.getContext().getPackageName(),
-                android.Manifest.permission.READ_PHONE_STATE);
-    }
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java
index 8dc1d69..c9576f7 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.READ_CONTACTS;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
+import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
@@ -77,6 +78,11 @@
                 KEYGUARD_DISABLE_FEATURES_NONE);
     }
 
+    public void testSetKeyguardDisabledSecureCameraLogged() {
+        mDevicePolicyManager.setKeyguardDisabledFeatures(
+                ADMIN_RECEIVER_COMPONENT, KEYGUARD_DISABLE_SECURE_CAMERA);
+    }
+
     public void testSetUserRestrictionLogged() {
         mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT,
                 UserManager.DISALLOW_CONFIG_LOCATION);
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
index da99b21..673e166 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
@@ -33,6 +33,7 @@
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
 
     <application
         android:testOnly="true"
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index ef05138..d0e2deb 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -1800,6 +1800,21 @@
     }
 
     @Test
+    public void testSetKeyguardDisabledSecureCameraLogged() throws Exception {
+        if (!mHasFeature || !isStatsdEnabled(getDevice())) {
+            return;
+        }
+        assertMetricsLogged(getDevice(), () -> {
+            executeDeviceTestMethod(
+                    ".DevicePolicyLoggingTest", "testSetKeyguardDisabledSecureCameraLogged");
+        }, new DevicePolicyEventWrapper.Builder(EventId.SET_KEYGUARD_DISABLED_FEATURES_VALUE)
+                .setAdminPackageName(DEVICE_ADMIN_PKG)
+                .setInt(KEYGUARD_DISABLE_SECURE_CAMERA)
+                .setStrings(NOT_CALLED_FROM_PARENT)
+                .build());
+    }
+
+    @Test
     public void testSetKeyguardDisabledFeatures() throws Exception {
         if (!mHasFeature) {
             return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
index 7a61083..8551757 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
@@ -263,6 +263,12 @@
                 mUserId);
     }
 
+    @Test
+    @Override
+    public void testSetKeyguardDisabledSecureCameraLogged() {
+        // Managed profiles are not allowed to set keyguard disabled secure camera
+    }
+
     @FlakyTest
     @Override
     @Test
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
index 754b571..b0d86c8 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
@@ -420,6 +420,10 @@
 
     @Test
     public void testPersonalAppsSuspensionNormalApp() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+
         installAppAsUser(DEVICE_ADMIN_APK, mPrimaryUserId);
         // Initially the app should be launchable.
         assertCanStartPersonalApp(DEVICE_ADMIN_PKG, true);
@@ -433,6 +437,10 @@
 
     @Test
     public void testPersonalAppsSuspensionInstalledApp() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+
         setPersonalAppsSuspended(true);
 
         installAppAsUser(DUMMY_IME_APK, mPrimaryUserId);
diff --git a/hostsidetests/incrementalinstall/app/Android.bp b/hostsidetests/incrementalinstall/app/Android.bp
index 535ac0b..7b2455b 100644
--- a/hostsidetests/incrementalinstall/app/Android.bp
+++ b/hostsidetests/incrementalinstall/app/Android.bp
@@ -12,9 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// v1 implementation of test app built with v1 manifest.
 android_test_helper_app {
     name: "IncrementalTestApp",
-    srcs: ["src/**/*.java"],
+    srcs: ["v1/src/**/*.java"],
     dex_preopt: {
         enabled: false,
     },
@@ -31,4 +32,51 @@
     sdk_version: "test_current",
     export_package_resources: true,
     aapt_include_all_resources: true,
+    manifest: "AndroidManifestV1.xml",
+}
+
+// v2 implementation of test app built with v1 manifest for zero version update test.
+android_test_helper_app {
+    name: "IncrementalTestApp2_v1",
+    srcs: ["v2/src/**/*.java"],
+    dex_preopt: {
+        enabled: false,
+    },
+    optimize: {
+        enabled: false,
+    },
+    test_suites: [
+        "cts",
+    ],
+    v4_signature: true,
+    static_libs: [
+        "incremental-install-common-lib",
+    ],
+    sdk_version: "test_current",
+    export_package_resources: true,
+    aapt_include_all_resources: true,
+    manifest: "AndroidManifestV1.xml",
+}
+
+// v2 implementation of test app built with v2 manifest for version update test.
+android_test_helper_app {
+    name: "IncrementalTestApp2_v2",
+    srcs: ["v2/src/**/*.java"],
+    dex_preopt: {
+        enabled: false,
+    },
+    optimize: {
+        enabled: false,
+    },
+    test_suites: [
+        "cts",
+    ],
+    v4_signature: true,
+    static_libs: [
+        "incremental-install-common-lib",
+    ],
+    sdk_version: "test_current",
+    export_package_resources: true,
+    aapt_include_all_resources: true,
+    manifest: "AndroidManifestV2.xml",
 }
\ No newline at end of file
diff --git a/hostsidetests/incrementalinstall/app/AndroidManifest.xml b/hostsidetests/incrementalinstall/app/AndroidManifestV1.xml
similarity index 96%
rename from hostsidetests/incrementalinstall/app/AndroidManifest.xml
rename to hostsidetests/incrementalinstall/app/AndroidManifestV1.xml
index a1d900c..68d6d3d 100644
--- a/hostsidetests/incrementalinstall/app/AndroidManifest.xml
+++ b/hostsidetests/incrementalinstall/app/AndroidManifestV1.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.incrementalinstall.incrementaltestapp"
           android:versionCode="1"
-          android:versionName="1.0" >
+          android:versionName="1.0">
 
     <application android:label="IncrementalTestApp">
         <activity android:name=".MainActivity">
diff --git a/hostsidetests/incrementalinstall/app/AndroidManifest.xml b/hostsidetests/incrementalinstall/app/AndroidManifestV2.xml
similarity index 93%
copy from hostsidetests/incrementalinstall/app/AndroidManifest.xml
copy to hostsidetests/incrementalinstall/app/AndroidManifestV2.xml
index a1d900c..27cfbb9 100644
--- a/hostsidetests/incrementalinstall/app/AndroidManifest.xml
+++ b/hostsidetests/incrementalinstall/app/AndroidManifestV2.xml
@@ -17,8 +17,8 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.incrementalinstall.incrementaltestapp"
-          android:versionCode="1"
-          android:versionName="1.0" >
+          android:versionCode="2"
+          android:versionName="2.0">
 
     <application android:label="IncrementalTestApp">
         <activity android:name=".MainActivity">
diff --git a/hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/MainActivity.java b/hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/MainActivity.java
similarity index 97%
rename from hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/MainActivity.java
rename to hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/MainActivity.java
index 980757d..86a9acd 100644
--- a/hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/MainActivity.java
+++ b/hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/MainActivity.java
@@ -43,6 +43,7 @@
         PACKAGE_NAME = getApplicationContext().getPackageName();
 
         broadcastStatus(Consts.SupportedComponents.ON_CREATE_COMPONENT, true);
+        broadcastStatus(Consts.SupportedComponents.ON_CREATE_COMPONENT_2, false);
         loadDynamicAsset();
         loadDynamicCode();
         loadCompressedNativeLib();
diff --git a/hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/dynamiccode/DynamicCodeShim.java b/hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/dynamiccode/DynamicCodeShim.java
similarity index 100%
rename from hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/dynamiccode/DynamicCodeShim.java
rename to hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/dynamiccode/DynamicCodeShim.java
diff --git a/hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/dynamiccode/IDynamicCode.java b/hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/dynamiccode/IDynamicCode.java
similarity index 100%
rename from hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/dynamiccode/IDynamicCode.java
rename to hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/dynamiccode/IDynamicCode.java
diff --git a/hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/nativelib/CompressedNativeLib.java b/hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/nativelib/CompressedNativeLib.java
similarity index 100%
rename from hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/nativelib/CompressedNativeLib.java
rename to hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/nativelib/CompressedNativeLib.java
diff --git a/hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/nativelib/UncompressedNativeLib.java b/hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/nativelib/UncompressedNativeLib.java
similarity index 100%
rename from hostsidetests/incrementalinstall/app/src/android/incrementalinstall/incrementaltestapp/nativelib/UncompressedNativeLib.java
rename to hostsidetests/incrementalinstall/app/v1/src/android/incrementalinstall/incrementaltestapp/nativelib/UncompressedNativeLib.java
diff --git a/hostsidetests/incrementalinstall/app/v2/src/android/incrementalinstall/incrementaltestapp/MainActivity.java b/hostsidetests/incrementalinstall/app/v2/src/android/incrementalinstall/incrementaltestapp/MainActivity.java
new file mode 100644
index 0000000..0ae6138
--- /dev/null
+++ b/hostsidetests/incrementalinstall/app/v2/src/android/incrementalinstall/incrementaltestapp/MainActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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.incrementalinstall.incrementaltestapp;
+
+import static android.incrementalinstall.common.Consts.COMPONENT_STATUS_KEY;
+import static android.incrementalinstall.common.Consts.INCREMENTAL_TEST_APP_STATUS_RECEIVER_ACTION;
+import static android.incrementalinstall.common.Consts.TARGET_COMPONENT_KEY;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.incrementalinstall.common.Consts;
+import android.os.Bundle;
+
+/** A second implementation of MainActivity to verify version updates. */
+public class MainActivity extends Activity {
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        for (String component : Consts.SupportedComponents.getAllComponents()) {
+            broadcastStatus(component,
+                    component.equals(Consts.SupportedComponents.ON_CREATE_COMPONENT_2));
+        }
+    }
+
+    private void broadcastStatus(String component, boolean status) {
+        Intent intent = new Intent(INCREMENTAL_TEST_APP_STATUS_RECEIVER_ACTION);
+        intent.putExtra(TARGET_COMPONENT_KEY, component);
+        intent.putExtra(COMPONENT_STATUS_KEY, status);
+        sendBroadcast(intent);
+    }
+}
diff --git a/hostsidetests/incrementalinstall/appvalidator/src/android/incrementalinstall/inrementaltestappvalidation/AppValidationTest.java b/hostsidetests/incrementalinstall/appvalidator/src/android/incrementalinstall/inrementaltestappvalidation/AppValidationTest.java
index 1338fe6..6654d5b 100644
--- a/hostsidetests/incrementalinstall/appvalidator/src/android/incrementalinstall/inrementaltestappvalidation/AppValidationTest.java
+++ b/hostsidetests/incrementalinstall/appvalidator/src/android/incrementalinstall/inrementaltestappvalidation/AppValidationTest.java
@@ -17,6 +17,7 @@
 package android.incrementalinstall.inrementaltestappvalidation;
 
 import static android.incrementalinstall.common.Consts.INCREMENTAL_TEST_APP_STATUS_RECEIVER_ACTION;
+import static android.incrementalinstall.common.Consts.INSTALLED_VERSION_CODE_TAG;
 import static android.incrementalinstall.common.Consts.IS_INCFS_INSTALLATION_TAG;
 import static android.incrementalinstall.common.Consts.LOADED_COMPONENTS_TAG;
 import static android.incrementalinstall.common.Consts.NOT_LOADED_COMPONENTS_TAG;
@@ -77,19 +78,44 @@
     }
 
     @Test
-    public void testInstallationType() throws Exception{
+    public void testInstallationTypeAndVersion() throws Exception {
         boolean isIncfsInstallation = Boolean.parseBoolean(InstrumentationRegistry.getArguments()
                 .getString(IS_INCFS_INSTALLATION_TAG));
-        assertEquals(isIncfsInstallation, new PathChecker().isIncFsPath(getAppSourceDir()));
+        int versionCode = Integer.parseInt(InstrumentationRegistry.getArguments()
+                .getString(INSTALLED_VERSION_CODE_TAG));
+        InstalledAppInfo installedAppInfo = getInstalledAppInfo();
+        assertEquals(isIncfsInstallation,
+                new PathChecker().isIncFsPath(installedAppInfo.installationPath));
+        assertEquals(versionCode, installedAppInfo.versionCode);
     }
 
-    private void launchTestApp() throws Exception{
+    private void launchTestApp() throws Exception {
         mDevice.executeShellCommand(String.format("am start %s/.MainActivity", mPackageToLaunch));
     }
 
-    private String getAppSourceDir() throws Exception{
-        String output = mDevice.executeShellCommand("pm list packages -f " + mPackageToLaunch);
-        // Output of the command is package:<path>/apk=<package_name>, we just need the <path>.
-        return output.substring("package:".length(), output.lastIndexOf("/"));
+    private InstalledAppInfo getInstalledAppInfo() throws Exception {
+        // Output of the command is package:<path>/apk=<package_name> versionCode:<version>, we
+        // just need the <path> and <version>.
+        String output = mDevice.executeShellCommand(
+                "pm list packages -f --show-versioncode " + mPackageToLaunch);
+        // outputSplits[0] will contain path information and outputSplits[1] will contain
+        // versionCode.
+        String[] outputSplits = output.split(" ");
+        String installationPath = outputSplits[0].trim().substring("package:".length(),
+                output.lastIndexOf("/"));
+        int versionCode = Integer.parseInt(
+                outputSplits[1].trim().substring("versionCode:".length()));
+        return new InstalledAppInfo(installationPath, versionCode);
+    }
+
+    private class InstalledAppInfo {
+
+        private final String installationPath;
+        private final int versionCode;
+
+        InstalledAppInfo(String installedPath, int versionCode) {
+            this.installationPath = installedPath;
+            this.versionCode = versionCode;
+        }
     }
 }
diff --git a/hostsidetests/incrementalinstall/common/src/android/incrementalinstall/common/Consts.java b/hostsidetests/incrementalinstall/common/src/android/incrementalinstall/common/Consts.java
index 30ffb3a..e185e6f 100644
--- a/hostsidetests/incrementalinstall/common/src/android/incrementalinstall/common/Consts.java
+++ b/hostsidetests/incrementalinstall/common/src/android/incrementalinstall/common/Consts.java
@@ -27,9 +27,12 @@
     // Tag for the components that should not be loaded, sent from Host to app validator.
     public static final String NOT_LOADED_COMPONENTS_TAG = "NOT_LOADED_COMPONENTS";
 
-    // Tag for the components that should not be loaded, sent from Host to app validator.
+    // Tag for installation type (incremental or not), sent from Host to app validator.
     public static final String IS_INCFS_INSTALLATION_TAG = "IS_INCFS";
 
+    // Tag for the version of the installed app, sent from Host to app validator.
+    public static final String INSTALLED_VERSION_CODE_TAG = "VERSION_CODE";
+
     // Action broadcast from test app after attempting to load a component.
     public static final String INCREMENTAL_TEST_APP_STATUS_RECEIVER_ACTION =
             "android.incrementalinstall.incrementaltestapp.INCREMENTAL_TEST_APP_RECEIVER_ACTION";
@@ -43,13 +46,14 @@
     public static class SupportedComponents {
 
         public static final String ON_CREATE_COMPONENT = "onCreate";
+        public static final String ON_CREATE_COMPONENT_2 = "onCreate2";
         public static final String DYNAMIC_ASSET_COMPONENT = "dynamicAsset";
         public static final String DYNAMIC_CODE_COMPONENT = "dynamicCode";
         public static final String COMPRESSED_NATIVE_COMPONENT = "compressedNative";
         public static final String UNCOMPRESSED_NATIVE_COMPONENT = "unCompressedNative";
 
         public static String[] getAllComponents() {
-            return new String[]{ON_CREATE_COMPONENT, DYNAMIC_ASSET_COMPONENT,
+            return new String[]{ON_CREATE_COMPONENT, ON_CREATE_COMPONENT_2, DYNAMIC_ASSET_COMPONENT,
                     DYNAMIC_CODE_COMPONENT, COMPRESSED_NATIVE_COMPONENT,
                     UNCOMPRESSED_NATIVE_COMPONENT};
         }
diff --git a/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java b/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java
index 3e769e4..98b0ffe 100644
--- a/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java
+++ b/hostsidetests/incrementalinstall/src/android/incrementalinstall/cts/IncrementalInstallTest.java
@@ -20,6 +20,7 @@
 import static android.incrementalinstall.common.Consts.SupportedComponents.DYNAMIC_ASSET_COMPONENT;
 import static android.incrementalinstall.common.Consts.SupportedComponents.DYNAMIC_CODE_COMPONENT;
 import static android.incrementalinstall.common.Consts.SupportedComponents.ON_CREATE_COMPONENT;
+import static android.incrementalinstall.common.Consts.SupportedComponents.ON_CREATE_COMPONENT_2;
 import static android.incrementalinstall.common.Consts.SupportedComponents.UNCOMPRESSED_NATIVE_COMPONENT;
 
 import static org.junit.Assert.assertFalse;
@@ -70,11 +71,15 @@
     private static final String VALIDATION_HELPER_CLASS =
             VALIDATION_HELPER_PKG + ".AppValidationTest";
     private static final String VALIDATION_HELPER_METHOD = "testAppComponentsInvoked";
-    private static final String INSTALLATION_TYPE_HELPER_METHOD = "testInstallationType";
+    private static final String INSTALLATION_TYPE_HELPER_METHOD = "testInstallationTypeAndVersion";
 
     private static final String TEST_APP_PACKAGE_NAME =
             "android.incrementalinstall.incrementaltestapp";
     private static final String TEST_APP_BASE_APK_NAME = "IncrementalTestApp.apk";
+    // apk for zero version update test (has version 1).
+    private static final String TEST_APP_BASE_APK_2_V1_NAME = "IncrementalTestApp2_v1.apk";
+    // apk for version update test (has version 2).
+    private static final String TEST_APP_BASE_APK_2_V2_NAME = "IncrementalTestApp2_v2.apk";
     private static final String TEST_APP_DYNAMIC_ASSET_NAME = "IncrementalTestAppDynamicAsset.apk";
     private static final String TEST_APP_DYNAMIC_CODE_NAME = "IncrementalTestAppDynamicCode.apk";
     private static final String TEST_APP_COMPRESSED_NATIVE_NAME =
@@ -84,10 +89,10 @@
 
     private static final String SIG_SUFFIX = ".idsig";
     private static final String INSTALL_SUCCESS_OUTPUT = "Success";
-
     private static final long DEFAULT_TEST_TIMEOUT_MS = 60 * 1000L;
     private static final long DEFAULT_MAX_TIMEOUT_TO_OUTPUT_MS = 60 * 1000L; // 1min
-
+    private final int TEST_APP_V1_VERSION = 1;
+    private final int TEST_APP_V2_VERSION = 2;
     private CompatibilityBuildHelper mBuildHelper;
 
     @Before
@@ -109,7 +114,8 @@
         assertTrue(
                 installWithAdbInstaller(TEST_APP_BASE_APK_NAME).contains(INSTALL_SUCCESS_OUTPUT));
         verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
-        verifyInstallationType(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
         validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT);
     }
 
@@ -118,7 +124,8 @@
         assertTrue(
                 installWithAdbInstaller(TEST_APP_BASE_APK_NAME).contains(INSTALL_SUCCESS_OUTPUT));
         verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
-        verifyInstallationType(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
         validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT);
         uninstallApp(TEST_APP_PACKAGE_NAME);
         verifyPackageNotInstalled(TEST_APP_PACKAGE_NAME);
@@ -162,7 +169,8 @@
         assertTrue(installWithAdbInstaller(TEST_APP_BASE_APK_NAME,
                 TEST_APP_DYNAMIC_ASSET_NAME).contains(INSTALL_SUCCESS_OUTPUT));
         verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
-        verifyInstallationType(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
         validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT, DYNAMIC_ASSET_COMPONENT);
     }
 
@@ -171,7 +179,8 @@
         assertTrue(installWithAdbInstaller(TEST_APP_BASE_APK_NAME,
                 TEST_APP_DYNAMIC_CODE_NAME).contains(INSTALL_SUCCESS_OUTPUT));
         verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
-        verifyInstallationType(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
         validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT, DYNAMIC_CODE_COMPONENT);
     }
 
@@ -182,7 +191,8 @@
         assertTrue(installWithAdbInstaller(TEST_APP_BASE_APK_NAME,
                 TEST_APP_COMPRESSED_NATIVE_NAME).contains(INSTALL_SUCCESS_OUTPUT));
         verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
-        verifyInstallationType(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
         validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT, COMPRESSED_NATIVE_COMPONENT);
     }
 
@@ -193,7 +203,8 @@
         assertTrue(installWithAdbInstaller(TEST_APP_BASE_APK_NAME,
                 TEST_APP_UNCOMPRESSED_NATIVE_NAME).contains(INSTALL_SUCCESS_OUTPUT));
         verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
-        verifyInstallationType(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
         validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT,
                 UNCOMPRESSED_NATIVE_COMPONENT);
     }
@@ -203,7 +214,8 @@
         assertTrue(
                 installWithAdbInstaller(TEST_APP_BASE_APK_NAME).contains(INSTALL_SUCCESS_OUTPUT));
         verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
-        verifyInstallationType(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
         validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT);
         // Adb cannot add a split to an existing install, so we'll use pm to install just the
         // dynamic code
@@ -214,14 +226,53 @@
         getDevice().executeShellCommand(String.format("pm install -p %s %s", TEST_APP_PACKAGE_NAME,
                 deviceLocalPath + TEST_APP_DYNAMIC_CODE_NAME));
         // Verify IFS->NonIFS migration.
-        verifyInstallationType(TEST_APP_PACKAGE_NAME, /* isIncfs= */ false);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ false,
+                TEST_APP_V1_VERSION);
         validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT, DYNAMIC_CODE_COMPONENT);
     }
 
-    private void verifyInstallationType(String packageName, boolean isIncfs) throws Exception {
+    @Test
+    public void testZeroVersionUpdateAdbInstall() throws Exception {
+        assertTrue(
+                installWithAdbInstaller(TEST_APP_BASE_APK_NAME).contains(INSTALL_SUCCESS_OUTPUT));
+        verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
+        validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT);
+        // Install second implementation of app with the same version code.
+        assertTrue(
+                installWithAdbInstaller(/* shouldUpdate= */ true,
+                        TEST_APP_BASE_APK_2_V1_NAME).contains(
+                        INSTALL_SUCCESS_OUTPUT));
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
+        validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT_2);
+    }
+
+    @Test
+    public void testVersionUpdateAdbInstall() throws Exception {
+        assertTrue(
+                installWithAdbInstaller(TEST_APP_BASE_APK_NAME).contains(INSTALL_SUCCESS_OUTPUT));
+        verifyPackageInstalled(TEST_APP_PACKAGE_NAME);
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V1_VERSION);
+        validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT);
+        // Install second implementation of app with the same version code.
+        assertTrue(
+                installWithAdbInstaller(/* shouldUpdate= */ true,
+                        TEST_APP_BASE_APK_2_V2_NAME).contains(
+                        INSTALL_SUCCESS_OUTPUT));
+        verifyInstallationTypeAndVersion(TEST_APP_PACKAGE_NAME, /* isIncfs= */ true,
+                TEST_APP_V2_VERSION);
+        validateAppLaunch(TEST_APP_PACKAGE_NAME, ON_CREATE_COMPONENT_2);
+    }
+
+    private void verifyInstallationTypeAndVersion(String packageName, boolean isIncfs,
+            int versionCode) throws Exception {
         Map<String, String> args = new HashMap<>();
         args.put(Consts.PACKAGE_TO_LAUNCH_TAG, packageName);
         args.put(Consts.IS_INCFS_INSTALLATION_TAG, Boolean.toString(isIncfs));
+        args.put(Consts.INSTALLED_VERSION_CODE_TAG, Integer.toString(versionCode));
         boolean result = runDeviceTests(
                 getDevice(), TEST_RUNNER, VALIDATION_HELPER_PKG, VALIDATION_HELPER_CLASS,
                 INSTALLATION_TYPE_HELPER_METHOD,
diff --git a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml b/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
index 3d27390..d824593 100644
--- a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
+++ b/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
@@ -43,7 +43,8 @@
 
         <service android:name=".StatsdCtsBackgroundService" android:exported="true" />
         <activity android:name=".StatsdCtsForegroundActivity" android:exported="true" />
-        <service android:name=".StatsdCtsForegroundService" android:exported="true" />
+        <service android:name=".StatsdCtsForegroundService"
+                 android:foregroundServiceType="camera|microphone" android:exported="true" />
 
         <activity
             android:name=".VideoPlayerActivity"
diff --git a/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java b/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
index d7cca3e..90a266c 100644
--- a/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
+++ b/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
@@ -173,7 +173,6 @@
             Thread.sleep(500);
             assertWithMessage("Failed to start checkpoint : %s", result.getStderr()).that(
                     result.getStatus()).isEqualTo(CommandStatus.SUCCESS);
-            rebootUserspaceAndWaitForBootComplete();
             getDevice().executeShellV2Command("cmd lock_settings set-pin 1543");
             installApk(BOOT_COMPLETED_TEST_APP_APK);
             runDeviceTest(BOOT_COMPLETED_TEST_APP_PACKAGE_NAME, "BootCompletedUserspaceRebootTest",
@@ -207,8 +206,8 @@
                 getProperty("init.userspace_reboot.sigterm.timeoutmillis", "");
         try {
             // Explicitly set a very low value to make sure that safety mechanism kicks in.
-            getDevice().setProperty("init.userspace_reboot.sigkill.timeoutmillis", "500");
-            getDevice().setProperty("init.userspace_reboot.sigterm.timeoutmillis", "500");
+            getDevice().setProperty("init.userspace_reboot.sigkill.timeoutmillis", "10");
+            getDevice().setProperty("init.userspace_reboot.sigterm.timeoutmillis", "10");
             rebootUserspaceAndWaitForBootComplete();
             assertUserspaceRebootFailed();
             assertLastBootReasonIs("userspace_failed,shutdown_aborted");
@@ -259,10 +258,12 @@
      * userspace reboot succeeded.
      */
     private void rebootUserspaceAndWaitForBootComplete() throws Exception {
+        Duration timeout = Duration.ofMillis(getDevice().getIntProperty(
+                "init.userspace_reboot.watchdog.timeoutmillis", 0)).plusMinutes(2);
         setProperty("test.userspace_reboot.requested", "1");
         getDevice().rebootUserspaceUntilOnline();
-        assertWithMessage("Device did not boot withing 2 minutes").that(
-                getDevice().waitForBootComplete(Duration.ofMinutes(2).toMillis())).isTrue();
+        assertWithMessage("Device did not boot within %s", timeout).that(
+                getDevice().waitForBootComplete(timeout.toMillis())).isTrue();
     }
 
     /**
diff --git a/tests/app/src/android/app/cts/BaseProcessInstrumentation.java b/tests/app/src/android/app/cts/BaseProcessInstrumentation.java
index 344747a..3ab4337 100644
--- a/tests/app/src/android/app/cts/BaseProcessInstrumentation.java
+++ b/tests/app/src/android/app/cts/BaseProcessInstrumentation.java
@@ -23,7 +23,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
-import android.util.Log;
+import android.os.Handler;
+import android.os.Looper;
 
 public class BaseProcessInstrumentation extends Instrumentation {
     final String mMainProc;
@@ -63,6 +64,17 @@
             // We are running in a secondary proc, just report it.
             //Log.i("xxx", "Instrumentation adding result in " + proc);
             addResults(result);
+            // Just in case something messes up, if it takes too long for this instrumentation
+            // process to finish, then we will force it to finish.
+            new Handler(Looper.myLooper()).postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    Bundle result = new Bundle();
+                    result.putString("FAILURE",
+                            "Timed out waiting for sub-instrumentation to complete");
+                    finish(Activity.RESULT_CANCELED, result);
+                }
+            }, 20 * 1000);
         }
     }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index 8fa55d0..9b49073 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -48,6 +48,7 @@
 import android.service.autofill.FillResponse;
 import android.service.autofill.SaveCallback;
 import android.util.Log;
+import android.view.inputmethod.InlineSuggestionsRequest;
 
 import androidx.annotation.Nullable;
 
@@ -234,7 +235,8 @@
         }
         mHandler.post(
                 () -> sReplier.onFillRequest(request.getFillContexts(), request.getClientState(),
-                        cancellationSignal, callback, request.getFlags()));
+                        cancellationSignal, callback, request.getFlags(),
+                        request.getInlineSuggestionsRequest()));
     }
 
     @Override
@@ -362,15 +364,18 @@
         public final CancellationSignal cancellationSignal;
         public final FillCallback callback;
         public final int flags;
+        public final InlineSuggestionsRequest inlineRequest;
 
         private FillRequest(List<FillContext> contexts, Bundle data,
-                CancellationSignal cancellationSignal, FillCallback callback, int flags) {
+                CancellationSignal cancellationSignal, FillCallback callback, int flags,
+                InlineSuggestionsRequest inlineRequest) {
             this.contexts = contexts;
             this.data = data;
             this.cancellationSignal = cancellationSignal;
             this.callback = callback;
             this.flags = flags;
             this.structure = contexts.get(contexts.size() - 1).getStructure();
+            this.inlineRequest = inlineRequest;
         }
 
         @Override
@@ -602,7 +607,8 @@
         }
 
         private void onFillRequest(List<FillContext> contexts, Bundle data,
-                CancellationSignal cancellationSignal, FillCallback callback, int flags) {
+                CancellationSignal cancellationSignal, FillCallback callback, int flags,
+                InlineSuggestionsRequest inlineRequest) {
             try {
                 CannedFillResponse response = null;
                 try {
@@ -676,7 +682,7 @@
                 addException(t);
             } finally {
                 Helper.offer(mFillRequests, new FillRequest(contexts, data, cancellationSignal,
-                        callback, flags), CONNECTION_TIMEOUT.ms());
+                        callback, flags, inlineRequest), CONNECTION_TIMEOUT.ms());
             }
         }
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityCommonTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityCommonTestCase.java
index e200cb8..48a2be9 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityCommonTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityCommonTestCase.java
@@ -148,6 +148,11 @@
         final FillContext fillContext = request.contexts.get(request.contexts.size() - 1);
         assertThat(fillContext.getFocusedId())
                 .isEqualTo(findAutofillIdByResourceId(fillContext, ID_USERNAME));
+        if (isInlineMode()) {
+            assertThat(request.inlineRequest).isNotNull();
+        } else {
+            assertThat(request.inlineRequest).isNull();
+        }
 
         // Make sure initial focus was properly set.
         assertWithMessage("Username node is not focused").that(
diff --git a/tests/framework/base/windowmanager/Android.bp b/tests/framework/base/windowmanager/Android.bp
index 0415b9a..cf35fd0 100644
--- a/tests/framework/base/windowmanager/Android.bp
+++ b/tests/framework/base/windowmanager/Android.bp
@@ -21,3 +21,8 @@
     name: "cts-wm-aspect-ratio-test-base",
     srcs: ["src/android/server/wm/AspectRatioTestsBase.java"],
 }
+
+filegroup {
+    name: "cts-wm-decor-inset-test-base",
+    srcs: ["src/android/server/wm/DecorInsetTestsBase.java"],
+}
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index c3d5bce..f5c744f 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -338,6 +338,11 @@
             </intent-filter>
         </activity>
 
+        <activity
+            android:name="android.server.wm.DecorInsetTestsBase$TestActivity"
+            android:label="DecorInsetTestsBase.TestActivity"
+            android:exported="true" />
+
         <activity android:name="android.server.wm.WindowCtsActivity"
                   android:theme="@android:style/Theme.Material.NoActionBar"
                   android:screenOrientation="locked"
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DecorInsetTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DecorInsetTests.java
new file mode 100644
index 0000000..8997f60
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DecorInsetTests.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 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.server.wm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.Intent;
+import android.platform.test.annotations.Presubmit;
+import android.view.WindowInsets;
+
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Build/Install/Run:
+ *  atest CtsWindowManagerDeviceTestCases:DecorInsetTests
+ */
+@Presubmit
+public class DecorInsetTests extends DecorInsetTestsBase {
+
+    @Test
+    public void testDecorView_consumesAllInsets_byDefault() throws Throwable {
+        TestActivity activity = mDecorActivity.launchActivity(new Intent()
+                .putExtra(ARG_LAYOUT_STABLE, false)
+                .putExtra(ARG_LAYOUT_FULLSCREEN, false)
+                .putExtra(ARG_LAYOUT_HIDE_NAV, false)
+                .putExtra(ARG_DECOR_FITS_SYSTEM_WINDOWS, true));
+        activity.mLaidOut.await(4, TimeUnit.SECONDS);
+
+        assertNotNull("test setup failed", activity.mLastDecorInsets);
+        assertNull("unexpected content insets", activity.mLastContentInsets);
+    }
+
+    @Test
+    public void testDecorView_consumesNavBar_ifLayoutHideNavIsNotSet() throws Throwable {
+        TestActivity activity = mDecorActivity.launchActivity(new Intent()
+                .putExtra(ARG_LAYOUT_STABLE, true)
+                .putExtra(ARG_LAYOUT_FULLSCREEN, true)
+                .putExtra(ARG_LAYOUT_HIDE_NAV, false)
+                .putExtra(ARG_DECOR_FITS_SYSTEM_WINDOWS, true));
+        activity.mLaidOut.await(4, TimeUnit.SECONDS);
+
+        assertNotNull("test setup failed", activity.mLastDecorInsets);
+        assertEquals("unexpected bottom inset: ", 0, activity.mLastContentInsets.getInsets(
+                WindowInsets.Type.systemBars()).bottom);
+    }
+
+    @Test
+    public void testDecorView_doesntConsumeNavBar_ifLayoutHideNavIsSet() throws Throwable {
+        TestActivity activity = mDecorActivity.launchActivity(new Intent()
+                .putExtra(ARG_LAYOUT_STABLE, true)
+                .putExtra(ARG_LAYOUT_FULLSCREEN, false)
+                .putExtra(ARG_LAYOUT_HIDE_NAV, true)
+                .putExtra(ARG_DECOR_FITS_SYSTEM_WINDOWS, true));
+        activity.mLaidOut.await(4, TimeUnit.SECONDS);
+
+        assertNotNull("test setup failed", activity.mLastDecorInsets);
+        assertEquals("insets were unexpectedly consumed: ",
+                activity.mLastDecorInsets.getSystemWindowInsets(),
+                activity.mLastContentInsets.getSystemWindowInsets());
+    }
+
+    @Test
+    public void testDecorView_doesntConsumeNavBar_ifDecorDoesntFitSystemWindows() throws Throwable {
+        TestActivity activity = mDecorActivity.launchActivity(new Intent()
+                .putExtra(ARG_LAYOUT_STABLE, true)
+                .putExtra(ARG_LAYOUT_FULLSCREEN, false)
+                .putExtra(ARG_LAYOUT_HIDE_NAV, false)
+                .putExtra(ARG_DECOR_FITS_SYSTEM_WINDOWS, false));
+        activity.mLaidOut.await(4, TimeUnit.SECONDS);
+
+        assertNotNull("test setup failed", activity.mLastDecorInsets);
+        assertEquals("insets were unexpectedly consumed: ",
+                activity.mLastDecorInsets.getSystemWindowInsets(),
+                activity.mLastContentInsets.getSystemWindowInsets());
+    }
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DecorInsetTestsBase.java b/tests/framework/base/windowmanager/src/android/server/wm/DecorInsetTestsBase.java
new file mode 100644
index 0000000..10b3d0d
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DecorInsetTestsBase.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 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.server.wm;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.Window;
+import android.view.WindowInsets;
+
+import androidx.annotation.Nullable;
+import androidx.test.rule.ActivityTestRule;
+
+import org.junit.Rule;
+
+import java.util.concurrent.CountDownLatch;
+
+public class DecorInsetTestsBase {
+
+    public static final String ARG_DECOR_FITS_SYSTEM_WINDOWS = "decorFitsSystemWindows";
+    public static final String ARG_LAYOUT_STABLE = "flagLayoutStable";
+    public static final String ARG_LAYOUT_FULLSCREEN = "flagLayoutFullscreen";
+    public static final String ARG_LAYOUT_HIDE_NAV = "flagLayoutHideNav";
+
+    @Rule
+    public ActivityTestRule<TestActivity> mDecorActivity = new ActivityTestRule<>(
+            TestActivity.class, false /* initialTouchMode */,
+            false /* launchActivity */);
+
+    public static class TestActivity extends Activity {
+        WindowInsets mLastContentInsets;
+        WindowInsets mLastDecorInsets;
+        final CountDownLatch mLaidOut = new CountDownLatch(1);
+
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+
+            getWindow().setDecorFitsSystemWindows(
+                    getIntent().getBooleanExtra(ARG_DECOR_FITS_SYSTEM_WINDOWS, false));
+
+            View view = new View(this);
+            view.setSystemUiVisibility(intentToSysuiVisibility(getIntent()));
+
+            view.setOnApplyWindowInsetsListener((v, wi) -> {
+                mLastContentInsets = wi;
+                return WindowInsets.CONSUMED;
+            });
+            setContentView(view);
+            getWindow().getDecorView().setOnApplyWindowInsetsListener((v, wi) -> {
+                mLastDecorInsets = wi;
+                return v.onApplyWindowInsets(wi);
+            });
+
+            view.getViewTreeObserver().addOnGlobalLayoutListener(
+                    new ViewTreeObserver.OnGlobalLayoutListener() {
+                @Override
+                public void onGlobalLayout() {
+                    view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                    mLaidOut.countDown();
+                }
+            });
+        }
+
+        private static int intentToSysuiVisibility(Intent intent) {
+            int vis = 0;
+            vis |= intent.getBooleanExtra(ARG_LAYOUT_HIDE_NAV, false)
+                    ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0;
+            vis |= intent.getBooleanExtra(ARG_LAYOUT_FULLSCREEN, false)
+                    ? View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN : 0;
+            vis |= intent.getBooleanExtra(ARG_LAYOUT_STABLE, false)
+                    ? View.SYSTEM_UI_FLAG_LAYOUT_STABLE : 0;
+            return vis;
+        }
+    }
+}
diff --git a/tests/framework/base/windowmanager/testsdk29/Android.bp b/tests/framework/base/windowmanager/testsdk29/Android.bp
new file mode 100644
index 0000000..5f8806b
--- /dev/null
+++ b/tests/framework/base/windowmanager/testsdk29/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2020 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 {
+    name: "CtsWindowManagerSdk29TestCases",
+    defaults: ["cts_defaults"],
+
+    srcs: [
+        "src/**/*.java",
+        ":cts-wm-decor-inset-test-base",
+    ],
+
+    // Intentionally don't set the compile SDK to 29, because we want to test
+    // usage of R APIs with 29 targetSdk behavior
+
+    static_libs: [
+        "androidx.test.rules",
+        "cts-wm-util",
+    ],
+
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+}
diff --git a/tests/framework/base/windowmanager/testsdk29/AndroidManifest.xml b/tests/framework/base/windowmanager/testsdk29/AndroidManifest.xml
new file mode 100644
index 0000000..faa11fe
--- /dev/null
+++ b/tests/framework/base/windowmanager/testsdk29/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.server.wm.cts.testsdk29">
+
+    <uses-sdk android:targetSdkVersion="29" />
+
+    <application android:label="CtsWindowManagerSdk28TestCases">
+        <uses-library android:name="android.test.runner" />
+
+        <activity
+            android:name="android.server.wm.DecorInsetTestsBase$TestActivity"
+            android:label="DecorInsetTestsBase.TestActivity"
+            android:exported="true" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.server.wm.cts.testsdk29" />
+
+</manifest>
diff --git a/tests/framework/base/windowmanager/testsdk29/AndroidTest.xml b/tests/framework/base/windowmanager/testsdk29/AndroidTest.xml
new file mode 100644
index 0000000..6d1f8d8
--- /dev/null
+++ b/tests/framework/base/windowmanager/testsdk29/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<configuration description="Config for CTS ActivityManager SDK 29 compatibility test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+    <!-- Instant apps and multi-abi not supported. -->
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsWindowManagerSdk29TestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.server.wm.cts.testsdk29" />
+        <option name="runtime-hint" value="1m" />
+    </test>
+</configuration>
diff --git a/tests/framework/base/windowmanager/testsdk29/OWNERS b/tests/framework/base/windowmanager/testsdk29/OWNERS
new file mode 100644
index 0000000..f93c21b
--- /dev/null
+++ b/tests/framework/base/windowmanager/testsdk29/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 99608
+include ../../OWNERS
diff --git a/tests/framework/base/windowmanager/testsdk29/src/android/server/wm/DecorInsetSdk29Tests.java b/tests/framework/base/windowmanager/testsdk29/src/android/server/wm/DecorInsetSdk29Tests.java
new file mode 100644
index 0000000..6d6d93d
--- /dev/null
+++ b/tests/framework/base/windowmanager/testsdk29/src/android/server/wm/DecorInsetSdk29Tests.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 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.server.wm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.Intent;
+import android.platform.test.annotations.Presubmit;
+import android.view.WindowInsets;
+
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Build/Install/Run:
+ *  atest CtsWindowManagerSdk29TestCases:DecorInsetSdk29Tests
+ */
+@Presubmit
+public class DecorInsetSdk29Tests extends DecorInsetTestsBase {
+
+    @Test
+    public void testDecorView_consumesAllInsets_byDefault() throws Throwable {
+        TestActivity activity = mDecorActivity.launchActivity(new Intent()
+                .putExtra(ARG_LAYOUT_STABLE, false)
+                .putExtra(ARG_LAYOUT_FULLSCREEN, false)
+                .putExtra(ARG_LAYOUT_HIDE_NAV, false)
+                .putExtra(ARG_DECOR_FITS_SYSTEM_WINDOWS, true));
+        activity.mLaidOut.await(4, TimeUnit.SECONDS);
+
+        assertNotNull("test setup failed", activity.mLastDecorInsets);
+        assertNull("unexpected content insets", activity.mLastContentInsets);
+    }
+
+    @Test
+    public void testDecorView_consumesNavBar_ifLayoutHideNavIsNotSet() throws Throwable {
+        TestActivity activity = mDecorActivity.launchActivity(new Intent()
+                .putExtra(ARG_LAYOUT_STABLE, true)
+                .putExtra(ARG_LAYOUT_FULLSCREEN, true)
+                .putExtra(ARG_LAYOUT_HIDE_NAV, false)
+                .putExtra(ARG_DECOR_FITS_SYSTEM_WINDOWS, true));
+        activity.mLaidOut.await(4, TimeUnit.SECONDS);
+
+        assertNotNull("test setup failed", activity.mLastDecorInsets);
+        assertEquals("unexpected bottom inset: ", 0, activity.mLastContentInsets.getInsets(
+                WindowInsets.Type.systemBars()).bottom);
+    }
+
+    @Test
+    public void testDecorView_doesntConsumeNavBar_ifLayoutHideNavIsSet() throws Throwable {
+        TestActivity activity = mDecorActivity.launchActivity(new Intent()
+                .putExtra(ARG_LAYOUT_STABLE, true)
+                .putExtra(ARG_LAYOUT_FULLSCREEN, false)
+                .putExtra(ARG_LAYOUT_HIDE_NAV, true)
+                .putExtra(ARG_DECOR_FITS_SYSTEM_WINDOWS, true));
+        activity.mLaidOut.await(4, TimeUnit.SECONDS);
+
+        assertNotNull("test setup failed", activity.mLastDecorInsets);
+        assertEquals("insets were unexpectedly consumed: ",
+                activity.mLastDecorInsets.getSystemWindowInsets(),
+                activity.mLastContentInsets.getSystemWindowInsets());
+    }
+
+    @Test
+    public void testDecorView_doesntConsumeNavBar_ifDecorDoesntFitSystemWindows() throws Throwable {
+        TestActivity activity = mDecorActivity.launchActivity(new Intent()
+                .putExtra(ARG_LAYOUT_STABLE, true)
+                .putExtra(ARG_LAYOUT_FULLSCREEN, false)
+                .putExtra(ARG_LAYOUT_HIDE_NAV, false)
+                .putExtra(ARG_DECOR_FITS_SYSTEM_WINDOWS, false));
+        activity.mLaidOut.await(4, TimeUnit.SECONDS);
+
+        assertNotNull("test setup failed", activity.mLastDecorInsets);
+        assertEquals("insets were unexpectedly consumed: ",
+                activity.mLastDecorInsets.getSystemWindowInsets(),
+                activity.mLastContentInsets.getSystemWindowInsets());
+    }
+}
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index b215647..935fc7c 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -64,6 +64,13 @@
 import android.widget.TextView;
 import android.widget.inline.InlinePresentationSpec;
 
+import androidx.annotation.AnyThread;
+import androidx.annotation.CallSuper;
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -73,13 +80,6 @@
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
-import androidx.annotation.AnyThread;
-import androidx.annotation.CallSuper;
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.WorkerThread;
-
 /**
  * Mock IME for end-to-end tests.
  */
@@ -703,7 +703,7 @@
                 sSuggestionView.removeAllViews();
                 final int size = mSuggestionViews.size();
                 for (int i = 0; i < size; i++) {
-                    if(mSuggestionViews.get(i) == null) {
+                    if (mSuggestionViews.get(i) == null) {
                         continue;
                     }
                     ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
@@ -759,7 +759,7 @@
                     AsyncTask.THREAD_POOL_EXECUTOR,
                     suggestionView -> {
                         Log.d(TAG, "new inline suggestion view ready");
-                        if(suggestionView != null) {
+                        if (suggestionView != null) {
                             suggestionViews[index] = suggestionView;
                             sizes[index] = size;
                         }
@@ -1002,7 +1002,7 @@
         }
 
         public void onSuggestionViewUpdated() {
-            recordEventInternal("onSuggestionViewUpdated", () -> {}, new Bundle());
+            recordEventInternal("onSuggestionViewUpdated", () -> { }, new Bundle());
         }
     }
 }
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
index 3d318b6..9090648 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
@@ -18,8 +18,6 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
-import static org.junit.Assume.assumeTrue;
-
 import android.app.UiAutomation;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/EditorInfoTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/EditorInfoTest.java
index d783104..0492189 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/EditorInfoTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/EditorInfoTest.java
@@ -324,7 +324,6 @@
     }
 
     private static CharSequence nullToEmpty(CharSequence source) {
-        return (source == null) ?
-                new SpannableStringBuilder("") : source;
+        return (source == null) ? new SpannableStringBuilder("") : source;
     }
 }
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java
index 653507d..9a4e85c 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java
@@ -116,7 +116,7 @@
         editText.post(() -> {
             final ViewTreeObserver observerForEditText = editText.getViewTreeObserver();
             observerForEditText.addOnWindowFocusChangeListener((hasFocus) ->
-                outEditHasWindowFocusRef.set(editText.hasWindowFocus()));
+                    outEditHasWindowFocusRef.set(editText.hasWindowFocus()));
             outEditHasWindowFocusRef.set(editText.hasWindowFocus());
         });
         return editText;
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/ImeInsetsControllerTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/ImeInsetsControllerTest.java
index 0c05bf3..b27b5a6 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/ImeInsetsControllerTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/ImeInsetsControllerTest.java
@@ -18,8 +18,10 @@
 
 import static android.view.WindowInsets.CONSUMED;
 import static android.view.WindowInsets.Type.ime;
+
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectBindInput;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectCommand;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
@@ -38,6 +40,11 @@
 import android.widget.EditText;
 import android.widget.LinearLayout;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.filters.MediumTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
 import com.android.cts.mockime.ImeEventStream;
 import com.android.cts.mockime.ImeSettings;
 import com.android.cts.mockime.MockImeSession;
@@ -49,11 +56,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.test.filters.MediumTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-
 @MediumTest
 public class ImeInsetsControllerTest extends EndToEndImeTestBase {
     private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
@@ -121,13 +123,13 @@
                 editText.getWindowInsetsController().addOnControllableInsetsChangedListener(
                         new OnControllableInsetsChangedListener() {
 
-                            boolean controlling = false;
+                            boolean mControlling = false;
 
                             @Override
                             public void onControllableInsetsChanged(
                                     @NonNull WindowInsetsController controller, int typeMask) {
-                                if ((typeMask & ime()) != 0 && !controlling) {
-                                    controlling = true;
+                                if ((typeMask & ime()) != 0 && !mControlling) {
+                                    mControlling = true;
                                     controller.controlWindowInsetsAnimation(ime(), -1, null, null,
                                             createControlListener(animController, controlLatch));
                                 }
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InlineSuggestionInfoTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InlineSuggestionInfoTest.java
index 8cd7e2f..0ce65c6 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InlineSuggestionInfoTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InlineSuggestionInfoTest.java
@@ -23,8 +23,8 @@
 
 import android.os.Parcel;
 import android.util.Size;
-import android.widget.inline.InlinePresentationSpec;
 import android.view.inputmethod.InlineSuggestionInfo;
+import android.widget.inline.InlinePresentationSpec;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InlineSuggestionTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InlineSuggestionTest.java
index 9310963..3a3d15e 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InlineSuggestionTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InlineSuggestionTest.java
@@ -25,10 +25,10 @@
 import android.os.AsyncTask;
 import android.os.Parcel;
 import android.util.Size;
-import android.widget.inline.InlineContentView;
-import android.widget.inline.InlinePresentationSpec;
 import android.view.inputmethod.InlineSuggestion;
 import android.view.inputmethod.InlineSuggestionInfo;
+import android.widget.inline.InlineContentView;
+import android.widget.inline.InlinePresentationSpec;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
index 2db7ee1..761feee 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
@@ -23,10 +23,10 @@
 import static android.view.inputmethod.cts.util.TestUtils.waitOnMainUntil;
 
 import static com.android.cts.mockime.ImeEventStreamTestUtils.EventFilterMode.CHECK_EXIT_EVENT_ONLY;
-import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEventWithKeyValue;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.editorMatcher;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectCommand;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEventWithKeyValue;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.notExpectEvent;
 
 import static org.junit.Assert.assertEquals;
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
index 48e8ca3..dcb7246 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
@@ -19,8 +19,8 @@
 import static android.view.inputmethod.cts.util.TestUtils.getOnMainSync;
 import static android.view.inputmethod.cts.util.TestUtils.runOnMainSync;
 
-import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEventWithKeyValue;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEventWithKeyValue;
 import static com.android.cts.mockime.ImeEventStreamTestUtils.notExpectEvent;
 
 import static org.junit.Assert.assertFalse;
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java b/tests/inputmethod/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
index e6e8e30..206fdc8 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
@@ -58,12 +58,14 @@
             @Override
             public void evaluate() throws Throwable {
                 final Map<String, String> initialValues = new HashMap<>();
-                Arrays.stream(DOZE_SETTINGS).forEach(k -> initialValues.put(k, getSecureSetting(k)));
+                Arrays.stream(DOZE_SETTINGS).forEach(
+                        k -> initialValues.put(k, getSecureSetting(k)));
                 try {
                     Arrays.stream(DOZE_SETTINGS).forEach(k -> putSecureSetting(k, "0"));
                     base.evaluate();
                 } finally {
-                    Arrays.stream(DOZE_SETTINGS).forEach(k -> putSecureSetting(k, initialValues.get(k)));
+                    Arrays.stream(DOZE_SETTINGS).forEach(
+                            k -> putSecureSetting(k, initialValues.get(k)));
                 }
             }
         };
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java
index c3e889d..40eb468 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java
@@ -19,7 +19,6 @@
 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
 
 import android.app.Instrumentation;
-import android.app.KeyguardManager;
 import android.content.Context;
 import android.os.PowerManager;
 
@@ -121,7 +120,7 @@
         final PowerManager pm = context.getSystemService(PowerManager.class);
         runShellCommand("input keyevent KEYCODE_WAKEUP");
         CommonTestUtils.waitUntil("Device does not wake up after 5 seconds", 5,
-                () -> pm!= null && pm.isInteractive());
+                () -> pm != null && pm.isInteractive());
     }
 
     /**
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/UnlockScreenRule.java b/tests/inputmethod/src/android/view/inputmethod/cts/util/UnlockScreenRule.java
index 2763095..fd2d98d 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/util/UnlockScreenRule.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/util/UnlockScreenRule.java
@@ -40,7 +40,7 @@
         return new Statement() {
             @Override
             public void evaluate() throws Throwable {
-                if (pm!= null && !pm.isInteractive()) {
+                if (pm != null && !pm.isInteractive()) {
                     TestUtils.turnScreenOn();
                 }
                 if (km != null && km.isKeyguardLocked()) {
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java b/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java
index 427cf11..b817a2c 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java
@@ -23,8 +23,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
@@ -96,7 +94,7 @@
             @Override
             public void onWindowFocusChanged(boolean hasWindowFocus) {
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG,"onWindowFocusChanged for view=" + this
+                    Log.v(TAG, "onWindowFocusChanged for view=" + this
                             + ", hasWindowfocus: " + hasWindowFocus);
                 }
             }
diff --git a/tests/tests/database/src/android/database/cts/SQLiteCantOpenDatabaseExceptionTest.java b/tests/tests/database/src/android/database/cts/SQLiteCantOpenDatabaseExceptionTest.java
new file mode 100644
index 0000000..69a8bbe
--- /dev/null
+++ b/tests/tests/database/src/android/database/cts/SQLiteCantOpenDatabaseExceptionTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 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.database.cts;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteCantOpenDatabaseException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabase.OpenParams;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.io.File;
+
+public class SQLiteCantOpenDatabaseExceptionTest  extends AndroidTestCase {
+    private static final String TAG = "SQLiteCantOpenDatabaseExceptionTest";
+
+    private File getDatabaseFile(String name) {
+        final Context c = getContext();
+        c.deleteDatabase(name);
+
+        // getDatabasePath() doesn't like a filename with a / in it, so we can't use it directly.
+        return new File(getContext().getDatabasePath("a").getParentFile(), name);
+    }
+
+    private void callWithExceptedMessage(File file, String expectedMessagePatter) {
+        try {
+            SQLiteDatabase.openDatabase(file, new OpenParams.Builder().build());
+            fail("SQLiteCantOpenDatabaseException was not thrown");
+        } catch (SQLiteCantOpenDatabaseException e) {
+            Log.i(TAG, "Caught excepted exception: " + e.getMessage(), e);
+            if (e.getMessage().startsWith("Cannot open database") &&
+                    e.getMessage().matches(expectedMessagePatter)) {
+                return; // pass
+            }
+            fail("Unexpected exception message: " + e.getMessage());
+        }
+    }
+
+    /** DB's directory doesn't exist. */
+    public void testDirectoryDoesNotExist() {
+        final File file = getDatabaseFile("nonexisitentdir/mydb.db");
+
+        callWithExceptedMessage(file, ".*: Directory .* doesn't exist");
+    }
+
+    /** File doesn't exist */
+    public void testFileDoesNotExist() {
+        final File file = getDatabaseFile("mydb.db");
+
+        callWithExceptedMessage(file, ".*: File .* doesn't exist");
+    }
+
+    /** File exists, but not readable. */
+    public void testFileNotReadable() {
+        final File file = getDatabaseFile("mydb.db");
+
+        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(file, null);
+        db.close();
+
+        file.setReadable(false);
+
+        callWithExceptedMessage(file, ".*: File .* not readable");
+    }
+
+    /** Directory with the given name exists already. */
+    public void testPathIsADirectory() {
+        final File file = getDatabaseFile("mydb.db");
+
+        file.mkdirs();
+
+        callWithExceptedMessage(file, ".*: Path .* is a directory");
+    }
+}
diff --git a/tests/tests/media/res/raw/sinesweepoggalbumart.ogg b/tests/tests/media/res/raw/sinesweepoggalbumart.ogg
new file mode 100644
index 0000000..00ad4ad
--- /dev/null
+++ b/tests/tests/media/res/raw/sinesweepoggalbumart.ogg
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 0a431d8..cdfa22f 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -375,6 +375,11 @@
         assertNotNull("couldn't retrieve album art", mRetriever.getEmbeddedPicture());
     }
 
+    public void testAlbumArtInOgg() throws Exception {
+        setDataSourceFd(R.raw.sinesweepoggalbumart);
+        assertNotNull("couldn't retrieve album art from ogg", mRetriever.getEmbeddedPicture());
+    }
+
     public void testSetDataSourcePath() {
         copyMeidaFile();
         File file = new File(Environment.getExternalStorageDirectory(), TEST_MEDIA_FILE);
diff --git a/tests/tests/nfc/Android.bp b/tests/tests/nfc/Android.bp
new file mode 100644
index 0000000..a962b53
--- /dev/null
+++ b/tests/tests/nfc/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2020 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 {
+    name: "CtsNfcTestCases",
+    defaults: ["cts_defaults"],
+    static_libs: [
+        "ctstestrunner-axt",
+        "compatibility-device-util-axt",
+    ],
+    srcs: ["src/**/*.java"],
+    // was: sdk_version: "current",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts",
+        "general-tests",
+    ],
+}
diff --git a/tests/tests/nfc/AndroidManifest.xml b/tests/tests/nfc/AndroidManifest.xml
new file mode 100644
index 0000000..ce89ee5
--- /dev/null
+++ b/tests/tests/nfc/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.nfc.cts"
+          android:targetSandboxVersion="2">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.NFC" />
+    <uses-permission android:name="android.permission.NFC_PREFERRED_PAYMENT_INFO" />
+    <application>
+        <uses-library android:name="android.test.runner"/>
+
+        <service android:name=".CtsMyHostApduService" android:exported="true"
+                 android:permission="android.permission.BIND_NFC_SERVICE">
+            <intent-filter>
+                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+            </intent-filter>
+            <meta-data android:name="android.nfc.cardemulation.host_apdu_service"
+                       android:resource="@xml/payment_aid_list"/>
+        </service>
+    </application>
+
+    <!-- This is a self-instrumenting test package. -->
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:label="CTS tests for Nfc CardEmulation API"
+                     android:targetPackage="android.nfc.cts">
+        <meta-data android:name="listener"
+                   android:value="com.android.cts.runner.CtsTestRunListener"/>
+    </instrumentation>
+
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/nfc/AndroidTest.xml b/tests/tests/nfc/AndroidTest.xml
new file mode 100644
index 0000000..f4a5ea2
--- /dev/null
+++ b/tests/tests/nfc/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS Nfc test cases">
+    <option name="test-suite-tag" value="cts"/>
+    <option name="config-descriptor:metadata" key="component" value="systems"/>
+    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <option name="not-shardable" value="true" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true"/>
+        <option name="test-file-name" value="CtsNfcTestCases.apk"/>
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="android.nfc.cts"/>
+        <option name="runtime-hint" value="10m10s"/>
+    </test>
+</configuration>
diff --git a/tests/tests/nfc/OWNERS b/tests/tests/nfc/OWNERS
new file mode 100644
index 0000000..d92b2ab
--- /dev/null
+++ b/tests/tests/nfc/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 48448
+alisher@google.com
+jackcwyu@google.com
+georgekgchang@google.com
+zachoverflow@google.com
diff --git a/tests/tests/nfc/res/values/strings.xml b/tests/tests/nfc/res/values/strings.xml
new file mode 100644
index 0000000..64f9905
--- /dev/null
+++ b/tests/tests/nfc/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<resources>
+    <string name="CtsPaymentService">CTS Nfc Test Service</string>
+</resources>
diff --git a/tests/tests/nfc/res/xml/payment_aid_list.xml b/tests/tests/nfc/res/xml/payment_aid_list.xml
new file mode 100644
index 0000000..02c6de1
--- /dev/null
+++ b/tests/tests/nfc/res/xml/payment_aid_list.xml
@@ -0,0 +1,8 @@
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/CtsPaymentService">
+    <aid-group android:description="@string/CtsPaymentService" android:category="payment">
+        <aid-filter android:name="A000000004101011"/>
+        <aid-filter android:name="A000000004101012"/>
+        <aid-filter android:name="A000000004101013"/>
+    </aid-group>
+</host-apdu-service>
diff --git a/tests/tests/nfc/src/android/nfc/cts/CtsMyHostApduService.java b/tests/tests/nfc/src/android/nfc/cts/CtsMyHostApduService.java
new file mode 100644
index 0000000..0e32bbd
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/CtsMyHostApduService.java
@@ -0,0 +1,16 @@
+package android.nfc.cts;
+
+import android.nfc.cardemulation.*;
+import android.os.Bundle;
+
+public class CtsMyHostApduService extends HostApduService {
+    @Override
+    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
+        return new byte[0];
+    }
+
+    @Override
+    public void onDeactivated(int reason) {
+        return;
+    }
+}
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java
new file mode 100644
index 0000000..a7a8f60
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 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.nfc.cts;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.pm.PackageManager;
+import android.nfc.NfcAdapter;
+import android.nfc.cardemulation.CardEmulation;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class NfcPreferredPaymentTest {
+
+    private final static String mRouteDestination = "Host";
+    private final static String mDescription = "CTS Nfc Test Service";
+    private final static List<String> mAids = Arrays.asList("A000000004101011",
+                                                            "A000000004101012",
+                                                            "A000000004101013");
+    private NfcAdapter mAdapter;
+    private CardEmulation mCardEmulation;
+
+    private boolean supportsHardware() {
+        final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_NFC);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        assumeTrue(supportsHardware());
+        mAdapter = NfcAdapter.getDefaultAdapter(InstrumentationRegistry.getContext());
+        assertNotNull(mAdapter);
+        mCardEmulation = CardEmulation.getInstance(mAdapter);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /** Tests getAidsForPreferredPaymentService API */
+    @Test
+    public void testAidsForPreferredPaymentService() {
+        try {
+            List<String> aids = mCardEmulation.getAidsForPreferredPaymentService();
+
+            assertTrue("Retrieve incorrect preferred payment aid list", mAids.equals(aids));
+        } catch (Exception e) {
+            fail("Unexpected Exception " + e);
+        }
+    }
+
+    /** Tests getRouteDestinationForPreferredPaymentService API */
+    @Test
+    public void testRouteDestinationForPreferredPaymentService() {
+        try {
+            String routeDestination =
+                    mCardEmulation.getRouteDestinationForPreferredPaymentService();
+
+            assertTrue("Retrieve incorrect preferred payment route destination",
+                    routeDestination.equals(mRouteDestination));
+        } catch (Exception e) {
+            fail("Unexpected Exception " + e);
+        }
+    }
+
+    /** Tests getDescriptionForPreferredPaymentService API */
+    @Test
+    public void testDescriptionForPreferredPaymentService() {
+        try {
+            CharSequence description = mCardEmulation.getDescriptionForPreferredPaymentService();
+
+            assertTrue("Retrieve incorrect preferred payment description",
+                description.toString().equals(mDescription.toString()));
+        } catch (Exception e) {
+            fail("Unexpected Exception " + e);
+        }
+    }
+
+}
diff --git a/tests/tests/os/src/android/os/cts/EnvironmentTest.java b/tests/tests/os/src/android/os/cts/EnvironmentTest.java
index 0b02291..a23854a 100644
--- a/tests/tests/os/src/android/os/cts/EnvironmentTest.java
+++ b/tests/tests/os/src/android/os/cts/EnvironmentTest.java
@@ -15,11 +15,17 @@
  */
 package android.os.cts;
 
+import static androidx.test.InstrumentationRegistry.getContext;
+
+import android.app.AppOpsManager;
 import android.os.Environment;
+import android.os.Process;
 import android.platform.test.annotations.AppModeFull;
 import android.system.Os;
 import android.system.StructStatVfs;
 
+import androidx.test.InstrumentationRegistry;
+
 import junit.framework.TestCase;
 
 import java.io.BufferedReader;
@@ -127,4 +133,50 @@
               + minInodes + "," + maxInodes + "]");
         }
     }
+
+    public void testIsExternalStorageManager() throws Exception {
+        final int initialMode = getContext().getSystemService(AppOpsManager.class)
+                .unsafeCheckOpNoThrow(AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE, Process.myUid(),
+                        getContext().getPackageName());
+
+        try {
+            setAppOpsModeForUid(Process.myUid(), AppOpsManager.MODE_DEFAULT,
+                    AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE);
+            // By default, this test app is not an external storage manager
+            assertFalse(Environment.isExternalStorageManager());
+            // Allow the external storage manager app-op to the test app. This mirrors what happens
+            // when the user grants this special app access to an app.
+            setAppOpsModeForUid(Process.myUid(), AppOpsManager.MODE_ALLOWED,
+                    AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE);
+            // Once we allow the right app-op for the test, it becomes an external storage manager
+            assertTrue(Environment.isExternalStorageManager());
+        } finally {
+            setAppOpsModeForUid(Process.myUid(), initialMode,
+                    AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE);
+        }
+    }
+
+    /**
+     * Sets {@code mode} for the given {@code ops} and the given {@code uid}.
+     *
+     * <p>This method drops shell permission identity.
+     */
+    private static void setAppOpsModeForUid(int uid, int mode, String... ops) {
+        if (ops == null) {
+            return;
+        }
+        InstrumentationRegistry.getInstrumentation()
+                .getUiAutomation()
+                .adoptShellPermissionIdentity();
+        try {
+            for (String op : ops) {
+                InstrumentationRegistry.getContext().getSystemService(AppOpsManager.class)
+                        .setUidMode(op, uid, mode);
+            }
+        } finally {
+            InstrumentationRegistry.getInstrumentation()
+                    .getUiAutomation()
+                    .dropShellPermissionIdentity();
+        }
+    }
 }
diff --git a/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java b/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
index 9a862d7..da99ff0 100644
--- a/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
+++ b/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
@@ -265,6 +265,17 @@
 
             if (supportUICCReaders()) {
                 assertGreaterOrEqual(uiccReaders.size(), 1);
+                // Test API getUiccReader(int slotNumber)
+                // The result should be the same as getReaders() with UICC reader prefix
+                for (int i = 1; i <= uiccReaders.size(); i++) {
+                    try {
+                        Reader uiccReader = seService.getUiccReader(i);
+                        if (!uiccReaders.contains(uiccReader))
+                            fail("Incorrect reader object - getUiccReader(" + i + ")");
+                    } catch (IllegalArgumentException e) {
+                        fail("Fail to get Reader object by calling getUiccReader(" + i + ")");
+                    }
+                }
             } else {
                 assertTrue(uiccReaders.size() == 0);
             }
diff --git a/tests/tests/textclassifier/src/android/view/textclassifier/cts/ConversationActionsTest.java b/tests/tests/textclassifier/src/android/view/textclassifier/cts/ConversationActionsTest.java
index 843891f..3434aba 100644
--- a/tests/tests/textclassifier/src/android/view/textclassifier/cts/ConversationActionsTest.java
+++ b/tests/tests/textclassifier/src/android/view/textclassifier/cts/ConversationActionsTest.java
@@ -150,9 +150,9 @@
                 new ConversationActions.Message.Builder(PERSON)
                         .setText(TEXT)
                         .build();
-
         ConversationActions.Request request =
                 new ConversationActions.Request.Builder(Collections.singletonList(message))
+                        .setMaxSuggestions(-1) // The default value.
                         .build();
 
         ConversationActions.Request recovered =
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java
index de47fbf..84cbd00 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java
@@ -130,12 +130,6 @@
         bindMediaProjectionService();
     }
 
-    @Override
-    public void onStop() {
-        super.onStop();
-        mSettingsSession.close();
-    }
-
     public void dismissPermissionDialog() {
         // The permission dialog will be auto-opened by the activity - find it and accept
         UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
@@ -180,6 +174,7 @@
             unbindService(mConnection);
             mProjectionServiceBound = false;
         }
+        mSettingsSession.close();
     }
 
     @Override