Merge "Increase timeout limits for UI activities." into sc-dev
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index d385af2..823616a 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -416,33 +416,40 @@
     auto_scene_switch = False
     logging.info('Manual testing: no tablet defined or testing scene5.')
 
-  # Run through all scenes if user does not supply one and config file doesn't
-  # have specific scene name listed.
-  possible_scenes = _AUTO_SCENES if auto_scene_switch else _ALL_SCENES
-  if not scenes or '<scene-name>' in scenes:
-    scenes = possible_scenes
-  else:
-    # Validate user input scene names
-    valid_scenes = True
-    temp_scenes = []
-    for s in scenes:
-      if s in possible_scenes:
-        temp_scenes.append(s)
-      elif s in _GROUPED_SCENES:
-        expand_scene(s, temp_scenes)
-      else:
-        valid_scenes = False
-        raise ValueError(f'Unknown scene specified: {s}')
-
-    # assign temp_scenes back to scenes and remove duplicates
-    scenes = sorted(set(temp_scenes), key=temp_scenes.index)
-
   logging.info('Running ITS on device: %s, camera: %s, scene: %s',
                device_id, camera_id_combos, scenes)
 
   for camera_id in camera_id_combos:
     test_params_content['camera'] = camera_id
     results = {}
+
+    # Run through all scenes if user does not supply one and config file doesn't
+    # have specific scene name listed.
+    if its_session_utils.SUB_CAMERA_SEPARATOR in camera_id:
+      possible_scenes = list(SUB_CAMERA_TESTS.keys())
+      if auto_scene_switch:
+        possible_scenes.remove('sensor_fusion')
+    else:
+      possible_scenes = _AUTO_SCENES if auto_scene_switch else _ALL_SCENES
+
+    if not scenes or '<scene-name>' in scenes:
+      scenes = possible_scenes
+    else:
+      # Validate user input scene names
+      valid_scenes = True
+      temp_scenes = []
+      for s in scenes:
+        if s in possible_scenes:
+          temp_scenes.append(s)
+        elif s in _GROUPED_SCENES:
+          expand_scene(s, temp_scenes)
+        else:
+          valid_scenes = False
+          raise ValueError(f'Unknown scene specified: {s}')
+
+      # assign temp_scenes back to scenes and remove duplicates
+      scenes = sorted(set(temp_scenes), key=temp_scenes.index)
+
     for s in _ALL_SCENES:
       results[s] = {RESULT_KEY: RESULT_NOT_EXECUTED}
     # A subdir in topdir will be created for each camera_id. All scene test
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/camera/OWNERS
index 8ebd7b8..d1d18b4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/OWNERS
@@ -1,2 +1,2 @@
 # Bug component: 41727
-include platform/frameworks/av:/camera/OWNER
\ No newline at end of file
+include platform/frameworks/av:/camera/OWNERS
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
index cd75746..806d055 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
@@ -96,6 +96,7 @@
             add("scene3");
             add("scene4");
             add("scene5");
+            add("scene6");
             add("scene_change");
             add("sensor_fusion");
         }};
@@ -213,6 +214,10 @@
             add("test_lens_shading_and_color_uniformity");
         }};
 
+    private static final ArrayList<String> mScene6Tests = new ArrayList<String>() {{
+            add("test_zoom");
+        }};
+
     private static final ArrayList<String> mSceneChangeTests = new ArrayList<String>() {{
             add("test_scene_change");
         }};
@@ -235,6 +240,7 @@
             put("scene3",mScene3Tests);
             put("scene4",mScene4Tests);
             put("scene5",mScene5Tests);
+            put("scene6",mScene6Tests);
             put("scene_change",mSceneChangeTests);
             put("sensor_fusion",mSensorFusionTests);
         }};
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java
index e286dea..ab39f9b 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/BedsteadJUnit4.java
@@ -16,11 +16,16 @@
 
 package com.android.bedstead.harrier;
 
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+import com.android.bedstead.harrier.annotations.enterprise.NegativePolicyTest;
+import com.android.bedstead.harrier.annotations.enterprise.PositivePolicyTest;
 import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeNone;
 
 import com.google.common.base.Objects;
 
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runners.BlockJUnit4ClassRunner;
 import org.junit.runners.model.FrameworkMethod;
 import org.junit.runners.model.InitializationError;
@@ -30,6 +35,8 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -41,6 +48,8 @@
  */
 public final class BedsteadJUnit4 extends BlockJUnit4ClassRunner {
 
+    private static final String BEDSTEAD_PACKAGE_NAME = "com.android.bedstead";
+
     // These are annotations which are not included indirectly
     private static final Set<String> sIgnoredAnnotationPackages = new HashSet<>();
     static {
@@ -74,6 +83,8 @@
             List<Annotation> annotations = new ArrayList<>(
                     Arrays.asList(getMethod().getAnnotations()));
 
+            parseEnterpriseAnnotations(annotations);
+
             int index = 0;
             while (index < annotations.size()) {
                 Annotation annotation = annotations.get(index);
@@ -165,18 +176,80 @@
             }
 
             for (Annotation annotation : parameterizedAnnotations) {
+                if (annotation.annotationType().equals(IncludeNone.class)) {
+                    // Special case - does not generate a run
+                    continue;
+                }
                 modifiedTests.add(
                         new BedsteadFrameworkMethod(m.getMethod(), annotation));
             }
         }
 
+        sortMethodsByBedsteadAnnotations(modifiedTests);
+
         return modifiedTests;
     }
 
+    /**
+     * Sort methods so that methods with identical bedstead annotations are together.
+     *
+     * <p>This will also ensure that all tests methods which are not annotated for bedstead will
+     * run before any tests which are annotated.
+     */
+    private void sortMethodsByBedsteadAnnotations(List<FrameworkMethod> modifiedTests) {
+        List<Annotation> bedsteadAnnotationsSortedByMostCommon =
+                bedsteadAnnotationsSortedByMostCommon(modifiedTests);
+
+        modifiedTests.sort((o1, o2) -> {
+            for (Annotation annotation : bedsteadAnnotationsSortedByMostCommon) {
+                boolean o1HasAnnotation = o1.getAnnotation(annotation.annotationType()) != null;
+                boolean o2HasAnnotation = o2.getAnnotation(annotation.annotationType()) != null;
+
+                if (o1HasAnnotation && !o2HasAnnotation) {
+                    // o1 goes to the end
+                    return 1;
+                } else if (o2HasAnnotation && !o1HasAnnotation) {
+                    return -1;
+                }
+            }
+            return 0;
+        });
+    }
+
+    private List<Annotation> bedsteadAnnotationsSortedByMostCommon(List<FrameworkMethod> methods) {
+        Map<Annotation, Integer> annotationCounts = countAnnotations(methods);
+        List<Annotation> annotations = new ArrayList<>(annotationCounts.keySet());
+
+        annotations.removeIf(
+                annotation ->
+                        !annotation.getClass().getCanonicalName().contains(BEDSTEAD_PACKAGE_NAME));
+
+        annotations.sort(Comparator.comparingInt(annotationCounts::get));
+        Collections.reverse(annotations);
+
+        return annotations;
+    }
+
+    private Map<Annotation, Integer> countAnnotations(List<FrameworkMethod> methods) {
+        Map<Annotation, Integer> annotationCounts = new HashMap<>();
+
+        for (FrameworkMethod method : methods) {
+            for (Annotation annotation : method.getAnnotations()) {
+                annotationCounts.put(annotation, annotationCounts.getOrDefault(annotation, 0) + 1);
+            }
+        }
+
+        return annotationCounts;
+    }
+
     private Set<Annotation> getParameterizedAnnotations(FrameworkMethod method) {
         Set<Annotation> parameterizedAnnotations = new HashSet<>();
+        List<Annotation> annotations = new ArrayList<>(Arrays.asList(method.getAnnotations()));
 
-        for (Annotation annotation : method.getMethod().getAnnotations()) {
+        // TODO(scottjonathan): We're doing this twice... does it matter?
+        parseEnterpriseAnnotations(annotations);
+
+        for (Annotation annotation : annotations) {
             if (annotation.annotationType().getAnnotation(ParameterizedAnnotation.class) != null) {
                 parameterizedAnnotations.add(annotation);
             }
@@ -184,4 +257,58 @@
 
         return parameterizedAnnotations;
     }
+
+    /**
+     * Parse enterprise-specific annotations.
+     *
+     * <p>To be used before general annotation processing.
+     */
+    private static void parseEnterpriseAnnotations(List<Annotation> annotations) {
+        int index = 0;
+        while (index < annotations.size()) {
+            Annotation annotation = annotations.get(index);
+            if (annotation instanceof PositivePolicyTest) {
+                annotations.remove(index);
+                Class<?> policy = ((PositivePolicyTest) annotation).policy();
+
+                EnterprisePolicy enterprisePolicy =
+                        policy.getAnnotation(EnterprisePolicy.class);
+                List<Annotation> replacementAnnotations =
+                        Policy.positiveStates(enterprisePolicy);
+
+                annotations.addAll(index, replacementAnnotations);
+                index += replacementAnnotations.size();
+            } else if (annotation instanceof NegativePolicyTest) {
+                annotations.remove(index);
+                Class<?> policy = ((NegativePolicyTest) annotation).policy();
+
+                EnterprisePolicy enterprisePolicy =
+                        policy.getAnnotation(EnterprisePolicy.class);
+                List<Annotation> replacementAnnotations =
+                        Policy.negativeStates(enterprisePolicy);
+
+                annotations.addAll(index, replacementAnnotations);
+                index += replacementAnnotations.size();
+            } else {
+                index++;
+            }
+        }
+    }
+
+    @Override
+    protected List<TestRule> classRules() {
+        List<TestRule> rules = super.classRules();
+
+        for (TestRule rule : rules) {
+            if (rule instanceof DeviceState) {
+                DeviceState deviceState = (DeviceState) rule;
+
+                deviceState.setSkipTestTeardown(true);
+
+                break;
+            }
+        }
+
+        return rules;
+    }
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
index d659569..3384385 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
@@ -79,8 +79,10 @@
     private final Context mContext = ApplicationProvider.getApplicationContext();
     private static final TestApis sTestApis = new TestApis();
     private static final String SKIP_TEST_TEARDOWN_KEY = "skip-test-teardown";
+    private static final String SKIP_CLASS_TEARDOWN_KEY = "skip-class-teardown";
     private static final String SKIP_TESTS_REASON_KEY = "skip-tests-reason";
-    private final boolean mSkipTestTeardown;
+    private boolean mSkipTestTeardown;
+    private boolean mSkipClassTeardown;
     private boolean mSkipTests;
     private String mSkipTestsReason;
 
@@ -90,10 +92,16 @@
         Bundle arguments = InstrumentationRegistry.getArguments();
         mSkipTestTeardown = Boolean.parseBoolean(
                 arguments.getString(SKIP_TEST_TEARDOWN_KEY, "false"));
+        mSkipClassTeardown = Boolean.parseBoolean(
+                arguments.getString(SKIP_CLASS_TEARDOWN_KEY, "false"));
         mSkipTestsReason = arguments.getString(SKIP_TESTS_REASON_KEY, "");
         mSkipTests = !mSkipTestsReason.isEmpty();
     }
 
+    void setSkipTestTeardown(boolean skipTestTeardown) {
+        mSkipTestTeardown = skipTestTeardown;
+    }
+
     @Override public Statement apply(final Statement base,
             final Description description) {
 
@@ -191,7 +199,16 @@
     }
 
     private Statement applySuite(final Statement base, final Description description) {
-        return base;
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                base.evaluate();
+
+                if (!mSkipClassTeardown) {
+                    teardownShareableState();
+                }
+            }
+        };
     }
 
     private void requireRunOnUser(String userType) {
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java
new file mode 100644
index 0000000..3496f86
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/Policy.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier;
+
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeNone;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnDeviceOwnerUser;
+import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility class for enterprise policy tests.
+ */
+@IncludeNone
+@IncludeRunOnDeviceOwnerUser
+@IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser
+public final class Policy {
+
+    private Policy() {
+
+    }
+
+    private static final IncludeNone INCLUDE_NONE_ANNOTATION =
+            Policy.class.getAnnotation(IncludeNone.class);
+    private static final IncludeRunOnDeviceOwnerUser INCLUDE_RUN_ON_DEVICE_OWNER_USER =
+            Policy.class.getAnnotation(IncludeRunOnDeviceOwnerUser.class);
+    private static final IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser
+            INCLUDE_RUN_ON_NON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER =
+            Policy.class.getAnnotation(IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.class);
+
+    /**
+     * Get positive state annotations for the given policy.
+     *
+     * <p>These are states which should be run where the policy is able to be applied.
+     */
+    public static List<Annotation> positiveStates(EnterprisePolicy enterprisePolicy) {
+        List<Annotation> annotations = new ArrayList<>();
+
+        annotations.add(INCLUDE_RUN_ON_DEVICE_OWNER_USER);
+        annotations.add(INCLUDE_RUN_ON_NON_AFFILIATED_DEVICE_OWNER_SECONDARY_USER);
+
+        return annotations;
+    }
+
+    /**
+     * Get negative state annotations for the given policy.
+     *
+     * <p>These are states which should be run where the policy is not able to be applied.
+     */
+    public static List<Annotation> negativeStates(EnterprisePolicy enterprisePolicy) {
+        List<Annotation> annotations = new ArrayList<>();
+
+        annotations.add(INCLUDE_NONE_ANNOTATION);
+
+        return annotations;
+    }
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnterprisePolicy.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnterprisePolicy.java
new file mode 100644
index 0000000..127020b
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/EnterprisePolicy.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations.enterprise;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Used to annotate an enterprise policy for use with {@link NegativePolicyTest} and
+ * {@link PositivePolicyTest}.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface EnterprisePolicy {
+    enum DeviceOwnerControl {
+        /** A policy that can be applied by a Device Owner to all users on the device. */
+        GLOBAL,
+        /** A policy that can be applied by a Device Owner to only the Device Owner's user. */
+        USER,
+        /** A policy that cannot be applied by a Device Owner. */
+        NO
+    }
+
+    enum ProfileOwnerControl {
+        /** A policy that can be applied by a Profile Owner to the profile itself and its parent. */
+        PARENT,
+        /**
+         * A policy that can be applied by a Profile Owner to the profile itself, and to the
+         * parent if it is a COPE profile.
+         */
+        COPE_PARENT,
+        /** A policy that can be applied by a Profile Owner to the profile itself. */
+        PROFILE,
+        /** A policy that cannot be applied by a Profile Owner. */
+        NO
+    }
+
+    DeviceOwnerControl deviceOwner();
+    ProfileOwnerControl profileOwner();
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/NegativePolicyTest.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/NegativePolicyTest.java
new file mode 100644
index 0000000..69fc63f
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/NegativePolicyTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations.enterprise;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark a test as testing the states where a policy is applied (by a Device Owner or Profile Owner)
+ * and it should not apply to the user the test is running on.
+ *
+ * <p>This will generated parameterized runs for all matching states.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface NegativePolicyTest {
+    /**
+     * The policy being tested.
+     *
+     * <p>This is used to calculate which states are required to be tested.
+     */
+    Class<?> policy();
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/PositivePolicyTest.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/PositivePolicyTest.java
new file mode 100644
index 0000000..4564fd8
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/enterprise/PositivePolicyTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations.enterprise;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark a test as testing the states where a policy is applied (by a Device Owner or Profile Owner)
+ * and it should apply to the user the test is running on.
+ *
+ * <p>This will generated parameterized runs for all matching states.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface PositivePolicyTest {
+    /**
+     * The policy being tested.
+     *
+     * <p>This is used to calculate which states are required to be tested.
+     */
+    Class<?> policy();
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeNone.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeNone.java
new file mode 100644
index 0000000..3ad98af
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeNone.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.annotations.parameterized;
+
+import com.android.bedstead.harrier.annotations.meta.ParameterizedAnnotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Parameterize a test but do not generate a run.
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@ParameterizedAnnotation
+public @interface IncludeNone {
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnDeviceOwnerUser.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnDeviceOwnerUser.java
index 89fafaa..8f877eb 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnDeviceOwnerUser.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnDeviceOwnerUser.java
@@ -27,7 +27,7 @@
 /**
  * Parameterize a test so that it runs on the same user as the device owner.
  */
-@Target(ElementType.METHOD)
+@Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @ParameterizedAnnotation
 @RequireRunOnPrimaryUser
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
index f423a7f..0adbb86 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/parameterized/IncludeRunOnNonAffiliatedDeviceOwnerSecondaryUser.java
@@ -28,7 +28,7 @@
  * Parameterize a test so that it runs on a non-affiliated secondary user on a device with a
  * Device Owner.
  */
-@Target(ElementType.METHOD)
+@Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @ParameterizedAnnotation
 @RequireRunOnSecondaryUser
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/TestPolicy.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/TestPolicy.java
new file mode 100644
index 0000000..0b7c557
--- /dev/null
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/TestPolicy.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bedstead.harrier.policies;
+
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.DeviceOwnerControl.NO;
+import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.ProfileOwnerControl.COPE_PARENT;
+
+import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
+
+/** Example Policy until real policies are added. */
+@EnterprisePolicy(profileOwner = COPE_PARENT, deviceOwner = NO)
+public class TestPolicy {
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
index c5933a7..352175a 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
@@ -46,6 +46,7 @@
     private static final String TAG_DEV_KEYS = "dev-keys";
     private static final String VENDOR_SDK_VERSION = "ro.vendor.build.version.sdk";
     private static final String VNDK_VERSION = "ro.vndk.version";
+    private static final String CAMERAX_EXTENSIONS_ENABLED = "ro.camerax.extensions.enabled";
 
     public static final String GOOGLE_SETTINGS_QUERY =
             "content query --uri content://com.google.settings/partner";
@@ -69,6 +70,14 @@
     }
 
     /**
+     * Return the CameraX extensions enabled property value. If the read-only property is unset,
+     * the default value returned will be 'false'.
+     */
+    public static boolean areCameraXExtensionsEnabled() {
+        return getPropertyBoolean(CAMERAX_EXTENSIONS_ENABLED);
+    }
+
+    /**
      * Return the first API level for this product. If the read-only property is unset,
      * this means the first API level is the current API level, and the current API level
      * is returned.
@@ -186,6 +195,17 @@
     }
 
     /**
+     * Retrieves the desired boolean property, returning false if not found.
+     */
+    public static boolean getPropertyBoolean(String property) {
+        String value = getProperty(property);
+        if (value == null) {
+            return false;
+        }
+        return Boolean.parseBoolean(value);
+    }
+
+    /**
      * Retrieves the desired integer property, returning INT_VALUE_IF_UNSET if not found.
      */
     public static int getPropertyInt(String property) {
diff --git a/hostsidetests/appsearch/Android.bp b/hostsidetests/appsearch/Android.bp
index 57a33b8..27193dd 100644
--- a/hostsidetests/appsearch/Android.bp
+++ b/hostsidetests/appsearch/Android.bp
@@ -38,7 +38,7 @@
 }
 
 android_test_helper_app {
-    name: "CtsAppSearchHostTestHelperA",
+    name: "CtsAppSearchHostTestHelper",
     defaults: ["cts_defaults"],
     static_libs: [
         "AppSearchTestUtils",
@@ -48,35 +48,12 @@
         "testng",
     ],
     srcs: [
-        "test-apps/AppSearchHostTestHelperA/src/**/*.java",
+        "test-apps/AppSearchHostTestHelper/src/**/*.java",
     ],
     test_suites: [
         "cts",
         "general-tests",
     ],
-    manifest: "test-apps/AppSearchHostTestHelperA/AndroidManifest.xml",
-    certificate: ":cts-appsearch-hosttest-helper-cert-a",
-    sdk_version: "test_current",
-}
-
-android_test_helper_app {
-    name: "CtsAppSearchHostTestHelperB",
-    defaults: ["cts_defaults"],
-    static_libs: [
-        "AppSearchTestUtils",
-        "androidx.test.ext.junit",
-        "androidx.test.rules",
-        "compatibility-device-util-axt",
-        "testng",
-    ],
-    srcs: [
-        "test-apps/AppSearchHostTestHelperB/src/**/*.java",
-    ],
-    test_suites: [
-        "cts",
-        "general-tests",
-    ],
-    manifest: "test-apps/AppSearchHostTestHelperB/AndroidManifest.xml",
-    certificate: ":cts-appsearch-hosttest-helper-cert-b",
+    manifest: "test-apps/AppSearchHostTestHelper/AndroidManifest.xml",
     sdk_version: "test_current",
 }
diff --git a/hostsidetests/appsearch/AndroidTest.xml b/hostsidetests/appsearch/AndroidTest.xml
index 5b8ebc2..1ee8f59 100644
--- a/hostsidetests/appsearch/AndroidTest.xml
+++ b/hostsidetests/appsearch/AndroidTest.xml
@@ -23,8 +23,7 @@
         <option name="jar" value="CtsAppSearchHostTestCases.jar" />
     </test>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="test-file-name" value="CtsAppSearchHostTestHelperA.apk" />
-        <option name="test-file-name" value="CtsAppSearchHostTestHelperB.apk" />
+        <option name="test-file-name" value="CtsAppSearchHostTestHelper.apk" />
         <option name="cleanup-apks" value="true" />
     </target_preparer>
 </configuration>
diff --git a/hostsidetests/appsearch/certs/Android.bp b/hostsidetests/appsearch/certs/Android.bp
deleted file mode 100644
index 901140c..0000000
--- a/hostsidetests/appsearch/certs/Android.bp
+++ /dev/null
@@ -1,13 +0,0 @@
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_app_certificate {
-  name: "cts-appsearch-hosttest-helper-cert-a",
-  certificate: "cts-appsearch-hosttest-helper-cert-a",
-}
-
-android_app_certificate {
-  name: "cts-appsearch-hosttest-helper-cert-b",
-  certificate: "cts-appsearch-hosttest-helper-cert-b",
-}
diff --git a/hostsidetests/appsearch/certs/README b/hostsidetests/appsearch/certs/README
deleted file mode 100644
index cdf8a8f..0000000
--- a/hostsidetests/appsearch/certs/README
+++ /dev/null
@@ -1,6 +0,0 @@
-# No password, otherwise building during 'atest' will fail waiting on a password
-# These files shouldn't need to change unless you want to generate new certificates to sign the APKs
-#
-# Generated with:
-development/tools/make_key cts-appsearch-hosttest-helper-cert-a '/CN=cts-appsearch-hosttest-helper-cert-a'
-development/tools/make_key cts-appsearch-hosttest-helper-cert-b '/CN=cts-appsearch-hosttest-helper-cert-b'
diff --git a/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-a.pk8 b/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-a.pk8
deleted file mode 100644
index eb83160..0000000
--- a/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-a.pk8
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-a.x509.pem b/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-a.x509.pem
deleted file mode 100644
index 7065ec6..0000000
--- a/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-a.x509.pem
+++ /dev/null
@@ -1,20 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDPzCCAiegAwIBAgIUUqwCW73ktfCzcTEJqfa1CTVDBw0wDQYJKoZIhvcNAQEL
-BQAwLzEtMCsGA1UEAwwkY3RzLWFwcHNlYXJjaC1ob3N0dGVzdC1oZWxwZXItY2Vy
-dC1hMB4XDTIxMDQwNjA3MzAwNloXDTQ4MDgyMjA3MzAwNlowLzEtMCsGA1UEAwwk
-Y3RzLWFwcHNlYXJjaC1ob3N0dGVzdC1oZWxwZXItY2VydC1hMIIBIjANBgkqhkiG
-9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnD4a4zm5nLmMgzvM33YVAZBMJvntXmXT9fTn
-rM5b59zgWYONJOcGuKcPmXvYUFih/v4jSp3X2LWKW2Z+Tod8FpGLbxxgW/PfFD2f
-iDM82qOfUxSLBTquZySTlyhqf2pz0ORSnU5poMKGwBzonYx867Nn7foP3G2qec6E
-UN4al9V9jfKauu/zGPsYi0+K//0dBmchD/h+Y/p3tPXdipBWZn33dJLPUFt111Cp
-8F3O/qAUuNh2M8I5gAd5SOxFOp2khNi9uMVikYhtB5wiFu8Z3MLNVoCcsSxRG00A
-A3rMH1e9CjyGXE0oZGtLTBEn92UoLfguMItw8oPMDZyxFrEQOwIDAQABo1MwUTAd
-BgNVHQ4EFgQUtfAJmXoq7OGAp/DlwsG/HY0Aw6UwHwYDVR0jBBgwFoAUtfAJmXoq
-7OGAp/DlwsG/HY0Aw6UwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
-AQEAUpcoi3yW3xFb5YWY233FW3XP8x7FQAJ/iIShsHQTDF2SOKOdAeFkWOHLmb4F
-/2Ds57Em4yeHupmGC6FIMwahqEPjyVc8uHak4gb9nokt1Zgtnbk/5IT67kYfinke
-FFtfdikE96JFPfjceMeyVxogeZkFqBND8ZiaJkLllXVwpj9JDCulQzOgmFnNYJQl
-zcllmfKbWfNUciZ+z62gIUFVdJHbGcOdENybxvCMjY+KxSZ3Ir9yvk6nBFs4m8Fm
-N965ant2MNbB1UsPmxem0U0h8mtBVAu8Wu39iTlmflwAicBACVyGGtUyLncZ6ed3
-fYluNNV0KjRiwrAM5sXjYAuEUw==
------END CERTIFICATE-----
diff --git a/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-b.pk8 b/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-b.pk8
deleted file mode 100644
index 3113ad3..0000000
--- a/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-b.pk8
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-b.x509.pem b/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-b.x509.pem
deleted file mode 100644
index 4085a04..0000000
--- a/hostsidetests/appsearch/certs/cts-appsearch-hosttest-helper-cert-b.x509.pem
+++ /dev/null
@@ -1,20 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDPzCCAiegAwIBAgIUQA/e31dngLMvDRzj0fY6CdEvIYYwDQYJKoZIhvcNAQEL
-BQAwLzEtMCsGA1UEAwwkY3RzLWFwcHNlYXJjaC1ob3N0dGVzdC1oZWxwZXItY2Vy
-dC1iMB4XDTIxMDQwNjA3MzEyNFoXDTQ4MDgyMjA3MzEyNFowLzEtMCsGA1UEAwwk
-Y3RzLWFwcHNlYXJjaC1ob3N0dGVzdC1oZWxwZXItY2VydC1iMIIBIjANBgkqhkiG
-9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyTSt0WUtqQUXDgz/8S/Wsl3B8YmZYFDxM+n/
-vuPu0MppzhwhwiUXqLsbI5OghRxyQlpXMgVXuVj3vPc5hwLHGseE97jgd0H2Boxn
-d4eiu5lcttnzea5UIz+8QHjIIoXWtfxkqJO68NfxXgqePbcQzVkE0zpc0OtjbO3R
-h8ry6RO25DsXMAfwKVrGEc7Gnj/sf59+jUp0E80XFJ790e/Rckwg6ilv71ndmRg2
-cnGBoxy3Aydx05cvC8GFPpSjtw2tq1Vx8HCHIgsiMeoKs0oqEzYEflrzchzcUPvg
-SU693lLymqjdADZwJSyHdVVTP/33K5ppNcb407omeYEbeXjP/wIDAQABo1MwUTAd
-BgNVHQ4EFgQUQY62T2k7WNB9YW5NGY+hlnnZYI8wHwYDVR0jBBgwFoAUQY62T2k7
-WNB9YW5NGY+hlnnZYI8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
-AQEALrjKluXTpwIr3yxCBI7kjagDWEzeVLjximYbOcZcohDX44NMf7fL2ZpWlLGT
-+FyDCz7ZBycOP28Knb/PQKXrLmA9Vr0l7pSXLAQ6a8/Wp6y0p1Bh4g5kBgid+YCl
-u/ediERiRomPItm7W4pFlBilfaG10QzEj1GtxZC7UrXMy+578AW+Nq5AiM34LVtv
-Q2+Suvzvgne+oQAbnQWNFzMj6mw0AvJpTn0qlC8YR0aJLGqHmpMVJfWo2P2OpFjt
-m2ohVkWrUyeXfDQ5idIPn23NzoTWazasKejg9JMPDwkQqE6Zpzx+SPoomTJSsuoI
-m5Q9D6phWIBrQhgPiX8LY9g21g==
------END CERTIFICATE-----
diff --git a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchHostTestBase.java b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchHostTestBase.java
deleted file mode 100644
index 468997f..0000000
--- a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchHostTestBase.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2021 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.appsearch.cts;
-
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-public abstract class AppSearchHostTestBase extends BaseHostJUnit4Test {
-    protected static final String TARGET_APK_A = "CtsAppSearchHostTestHelperA.apk";
-    protected static final String TARGET_PKG_A = "android.appsearch.app.a";
-    protected static final String TEST_CLASS_A = TARGET_PKG_A + ".AppSearchDeviceTest";
-    protected static final String TARGET_APK_B = "CtsAppSearchHostTestHelperB.apk";
-    protected static final String TARGET_PKG_B = "android.appsearch.app.b";
-    protected static final String TEST_CLASS_B = TARGET_PKG_B + ".AppSearchDeviceTest";
-
-    protected static final long DEFAULT_INSTRUMENTATION_TIMEOUT_MS = 600_000; // 10min
-
-    protected void runDeviceTestAsUserInPkgA(String testMethod, int userId) throws Exception {
-        runDeviceTests(getDevice(), TARGET_PKG_A, TEST_CLASS_A, testMethod, userId,
-                DEFAULT_INSTRUMENTATION_TIMEOUT_MS);
-    }
-
-    protected void runDeviceTestAsUserInPkgB(String testMethod, int userId) throws Exception {
-        runDeviceTests(getDevice(), TARGET_PKG_B, TEST_CLASS_B, testMethod, userId,
-                DEFAULT_INSTRUMENTATION_TIMEOUT_MS);
-    }
-}
diff --git a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTestBase.java b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java
similarity index 62%
rename from hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTestBase.java
rename to hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java
index 8696b69..1dc36b9 100644
--- a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTestBase.java
+++ b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchMultiUserTest.java
@@ -22,6 +22,8 @@
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
 
 import org.junit.After;
 import org.junit.Before;
@@ -39,7 +41,12 @@
  * user.
  */
 @RunWith(DeviceJUnit4ClassRunner.class)
-public class AppSearchMultiUserTestBase extends AppSearchHostTestBase {
+public class AppSearchMultiUserTest extends BaseHostJUnit4Test {
+    private static final String TARGET_APK = "CtsAppSearchHostTestHelper.apk";
+    private static final String TARGET_PKG = "android.appsearch.app";
+    private static final String TEST_CLASS = TARGET_PKG + ".UserDataTest";
+
+    private static final long DEFAULT_INSTRUMENTATION_TIMEOUT_MS = 600_000; // 10min
 
     private int mInitialUserId;
     private int mSecondaryUserId;
@@ -53,26 +60,31 @@
         mSecondaryUserId = getDevice().createUser("Test_User");
         assertThat(getDevice().startUser(mSecondaryUserId)).isTrue();
 
-        installPackageAsUser(TARGET_APK_A, /* grantPermission= */true, mInitialUserId);
-        installPackageAsUser(TARGET_APK_A, /* grantPermission= */true, mSecondaryUserId);
+        installPackageAsUser(TARGET_APK, /* grantPermissions */true, mInitialUserId);
+        installPackageAsUser(TARGET_APK, /* grantPermissions */true, mSecondaryUserId);
 
-        runDeviceTestAsUserInPkgA("clearTestData", mInitialUserId);
-        runDeviceTestAsUserInPkgA("clearTestData", mSecondaryUserId);
+        runDeviceTestAsUser("clearTestData", mInitialUserId);
+        runDeviceTestAsUser("clearTestData", mSecondaryUserId);
     }
 
     @After
     public void tearDown() throws Exception {
-        runDeviceTestAsUserInPkgA("clearTestData", mInitialUserId);
+        runDeviceTestAsUser("clearTestData", mInitialUserId);
         if (mSecondaryUserId > 0) {
             getDevice().removeUser(mSecondaryUserId);
         }
     }
 
+    private void runDeviceTestAsUser(String testMethod, int userId) throws Exception {
+        runDeviceTests(getDevice(), TARGET_PKG, TEST_CLASS, testMethod, userId,
+                DEFAULT_INSTRUMENTATION_TIMEOUT_MS);
+    }
+
     @Test
     public void testMultiUser_documentAccess() throws Exception {
-        runDeviceTestAsUserInPkgA("testPutDocuments", mSecondaryUserId);
-        runDeviceTestAsUserInPkgA("testGetDocuments_exist", mSecondaryUserId);
+        runDeviceTestAsUser("testPutDocuments", mSecondaryUserId);
+        runDeviceTestAsUser("testGetDocuments_exist", mSecondaryUserId);
         // Cannot get the document from another user.
-        runDeviceTestAsUserInPkgA("testGetDocuments_nonexist", mInitialUserId);
+        runDeviceTestAsUser("testGetDocuments_nonexist", mInitialUserId);
     }
 }
diff --git a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchPackageTestBase.java b/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchPackageTestBase.java
deleted file mode 100644
index ef1d089..0000000
--- a/hostsidetests/appsearch/src/android/appsearch/cts/AppSearchPackageTestBase.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2021 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.appsearch.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assume.assumeTrue;
-
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class AppSearchPackageTestBase extends AppSearchHostTestBase {
-
-    private int mPrimaryUserId;
-
-    @Before
-    public void setUp() throws Exception {
-        mPrimaryUserId = getDevice().getPrimaryUserId();
-        installPackageAsUser(TARGET_APK_A, /* grantPermission= */true, mPrimaryUserId);
-        installPackageAsUser(TARGET_APK_B, /* grantPermission= */true, mPrimaryUserId);
-        runDeviceTestAsUserInPkgA("clearTestData", mPrimaryUserId);
-    }
-
-    @Test
-    public void testPackageRemove() throws Exception {
-        // package A grants visibility to package B.
-        runDeviceTestAsUserInPkgA("testPutDocuments", mPrimaryUserId);
-        // query the document from another package.
-        runDeviceTestAsUserInPkgB("testGlobalGetDocuments_exist", mPrimaryUserId);
-        // remove the package.
-        uninstallPackage(TARGET_PKG_A);
-        // query the document from another package, verify the document of package A is removed
-        runDeviceTestAsUserInPkgB("testGlobalGetDocuments_nonexist", mPrimaryUserId);
-    }
-}
diff --git a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/AndroidManifest.xml b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelper/AndroidManifest.xml
similarity index 90%
rename from hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/AndroidManifest.xml
rename to hostsidetests/appsearch/test-apps/AppSearchHostTestHelper/AndroidManifest.xml
index 02545a7..85eca5b 100644
--- a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/AndroidManifest.xml
+++ b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelper/AndroidManifest.xml
@@ -15,12 +15,12 @@
  * limitations under the License.
  -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.appsearch.app.a">
+    package="android.appsearch.app">
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
 
     <instrumentation
         android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="android.appsearch.app.a"  />
+        android:targetPackage="android.appsearch.app"  />
 </manifest>
\ No newline at end of file
diff --git a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchDeviceTest.java b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelper/src/android/appsearch/app/UserDataTest.java
similarity index 79%
rename from hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchDeviceTest.java
rename to hostsidetests/appsearch/test-apps/AppSearchHostTestHelper/src/android/appsearch/app/UserDataTest.java
index b097b63..33c8df5 100644
--- a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperA/src/android/appsearch/app/a/AppSearchDeviceTest.java
+++ b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelper/src/android/appsearch/app/UserDataTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.appsearch.app.a;
+package android.appsearch.app;
 
 import static com.android.server.appsearch.testing.AppSearchTestUtils.checkIsBatchResultSuccess;
 import static com.android.server.appsearch.testing.AppSearchTestUtils.doGet;
@@ -28,7 +28,6 @@
 import android.app.appsearch.AppSearchSessionShim;
 import android.app.appsearch.GenericDocument;
 import android.app.appsearch.GetByUriRequest;
-import android.app.appsearch.PackageIdentifier;
 import android.app.appsearch.PutDocumentsRequest;
 import android.app.appsearch.SetSchemaRequest;
 
@@ -36,15 +35,15 @@
 
 import com.android.server.appsearch.testing.AppSearchSessionShimImpl;
 
-import com.google.common.io.BaseEncoding;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.util.List;
+
 @RunWith(AndroidJUnit4.class)
-public class AppSearchDeviceTest {
+public class UserDataTest {
 
     private static final String DB_NAME = "";
     private static final String NAMESPACE = "namespace";
@@ -63,19 +62,6 @@
                     .setCreationTimestampMillis(12345L)
                     .build();
 
-    private static final String PKG_B = "android.appsearch.app.b";
-
-    // To generate, run `apksigner` on the build APK. e.g.
-    //   ./apksigner verify --print-certs \
-    //   ~/sc-dev/out/soong/.intermediates/cts/tests/appsearch/CtsAppSearchTestHelperA/\
-    //   android_common/CtsAppSearchTestHelperA.apk`
-    // to get the SHA-256 digest. All characters need to be uppercase.
-    //
-    // Note: May need to switch the "sdk_version" of the test app from "test_current" to "30" before
-    // building the apk and running apksigner
-    private static final byte[] PKG_B_CERT_SHA256 = BaseEncoding.base16().decode(
-            "3D7A1AAE7AE8B9949BE93E071F3702AA38695B0F99B5FC4B2E8B364AC78FFDB2");
-
     private AppSearchSessionShim mDb;
 
     @Before
@@ -87,9 +73,8 @@
     @Test
     public void testPutDocuments() throws Exception {
         // Schema registration
-        mDb.setSchema(new SetSchemaRequest.Builder().addSchemas(SCHEMA)
-                .setSchemaTypeVisibilityForPackage(SCHEMA.getSchemaType(), /*visible=*/ true,
-                        new PackageIdentifier(PKG_B, PKG_B_CERT_SHA256)).build()).get();
+        mDb.setSchema(new SetSchemaRequest.Builder().addSchemas(SCHEMA).build())
+                .get();
 
         // Index a document
         AppSearchBatchResult<String, Void> result = checkIsBatchResultSuccess(
diff --git a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperB/AndroidManifest.xml b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperB/AndroidManifest.xml
deleted file mode 100644
index e036572..0000000
--- a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperB/AndroidManifest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2021 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.appsearch.app.b">
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation
-        android:name="androidx.test.runner.AndroidJUnitRunner"
-        android:targetPackage="android.appsearch.app.b"  />
-</manifest>
\ No newline at end of file
diff --git a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperB/src/android/appsearch/app/b/AppSearchDeviceTest.java b/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperB/src/android/appsearch/app/b/AppSearchDeviceTest.java
deleted file mode 100644
index 8159a52..0000000
--- a/hostsidetests/appsearch/test-apps/AppSearchHostTestHelperB/src/android/appsearch/app/b/AppSearchDeviceTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2021 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.appsearch.app.b;
-
-import static com.android.server.appsearch.testing.AppSearchTestUtils.convertSearchResultsToDocuments;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.appsearch.GenericDocument;
-import android.app.appsearch.GlobalSearchSessionShim;
-import android.app.appsearch.SearchSpec;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.server.appsearch.testing.GlobalSearchSessionShimImpl;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-public class AppSearchDeviceTest {
-
-    private static final String NAMESPACE = "namespace";
-    private static final String URI = "uri";
-    private static final GenericDocument DOCUMENT =
-            new GenericDocument.Builder<>(NAMESPACE, URI, "testSchema")
-                    .setPropertyString("subject", "testPut example1")
-                    .setCreationTimestampMillis(12345L)
-                    .build();
-
-    private GlobalSearchSessionShim mGlobalSearch;
-
-    @Before
-    public void setUp() throws Exception {
-        mGlobalSearch = GlobalSearchSessionShimImpl.createGlobalSearchSession().get();
-    }
-
-    @Test
-    public void testGlobalGetDocuments_exist() throws Exception {
-        List<GenericDocument> outDocuments = convertSearchResultsToDocuments(
-                mGlobalSearch.search(/*queryExpression=*/"",
-                        new SearchSpec.Builder().setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
-                                .build()));
-        assertThat(outDocuments).containsExactly(DOCUMENT);
-    }
-
-    @Test
-    public void testGlobalGetDocuments_nonexist() throws Exception {
-        List<GenericDocument> outDocuments = convertSearchResultsToDocuments(
-                mGlobalSearch.search(/*queryExpression=*/"",
-                        new SearchSpec.Builder().setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
-                                .build()));
-        assertThat(outDocuments).isEmpty();
-    }
-}
diff --git a/hostsidetests/blobstore/Android.bp b/hostsidetests/blobstore/Android.bp
index 6c8055f..61b9972 100644
--- a/hostsidetests/blobstore/Android.bp
+++ b/hostsidetests/blobstore/Android.bp
@@ -55,3 +55,51 @@
     "general-tests"
   ]
 }
+
+android_test_helper_app {
+  name: "CtsBlobStoreHostTestHelperPrivA",
+  srcs:  ["test-apps/BlobStoreHostTestHelper/src/**/*.java"],
+  static_libs: [
+    "compatibility-device-util-axt",
+    "androidx.test.ext.junit",
+    "androidx.test.rules",
+    "BlobStoreTestUtils",
+    "truth-prebuilt",
+    "testng",
+  ],
+  manifest : "test-apps/BlobStoreHostTestHelper/AndroidManifest_withPrivPerm.xml",
+  aaptflags: [
+    "--rename-manifest-package com.android.cts.device.blobA",
+    "--rename-instrumentation-target-package com.android.cts.device.blobA"
+  ],
+  sdk_version: "test_current",
+  // Tag this module as a cts test artifact
+  test_suites: [
+    "cts",
+    "general-tests"
+  ]
+}
+
+android_test_helper_app {
+  name: "CtsBlobStoreHostTestHelperPrivB",
+  srcs:  ["test-apps/BlobStoreHostTestHelper/src/**/*.java"],
+  static_libs: [
+    "compatibility-device-util-axt",
+    "androidx.test.ext.junit",
+    "androidx.test.rules",
+    "BlobStoreTestUtils",
+    "truth-prebuilt",
+    "testng",
+  ],
+  manifest : "test-apps/BlobStoreHostTestHelper/AndroidManifest_withPrivPerm.xml",
+  aaptflags: [
+    "--rename-manifest-package com.android.cts.device.blobB",
+    "--rename-instrumentation-target-package com.android.cts.device.blobB",
+  ],
+  sdk_version: "test_current",
+  // Tag this module as a cts test artifact
+  test_suites: [
+    "cts",
+    "general-tests"
+  ]
+}
diff --git a/hostsidetests/blobstore/AndroidTest.xml b/hostsidetests/blobstore/AndroidTest.xml
index b1b6d63..6460e1f 100644
--- a/hostsidetests/blobstore/AndroidTest.xml
+++ b/hostsidetests/blobstore/AndroidTest.xml
@@ -25,6 +25,9 @@
     </test>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="test-file-name" value="CtsBlobStoreHostTestHelper.apk" />
+        <option name="test-file-name" value="CtsBlobStoreHostTestHelperPrivA.apk" />
+        <option name="test-file-name" value="CtsBlobStoreHostTestHelperPrivB.apk" />
+        <option name="install-arg" value="-t" />
         <option name="cleanup-apks" value="true" />
     </target_preparer>
 </configuration>
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
index 8fefcb2..0ed223f 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
@@ -30,6 +30,12 @@
     protected static final String TARGET_APK = "CtsBlobStoreHostTestHelper.apk";
     protected static final String TARGET_PKG = "com.android.cts.device.blob";
 
+    protected static final String TARGET_APK_A = "CtsBlobStoreHostTestHelperPrivA.apk";
+    protected static final String TARGET_PKG_A = "com.android.cts.device.blobA";
+
+    protected static final String TARGET_APK_B = "CtsBlobStoreHostTestHelperPrivB.apk";
+    protected static final String TARGET_PKG_B = "com.android.cts.device.blobB";
+
     private static final long TIMEOUT_BOOT_COMPLETE_MS = 120_000;
     private static final long DEFAULT_INSTRUMENTATION_TIMEOUT_MS = 900_000; // 15min
 
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
index d8cc1a0..ffd5da4 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
@@ -45,8 +45,10 @@
         mSecondaryUserId = getDevice().createUser("Test_User");
         assertThat(getDevice().startUser(mSecondaryUserId)).isTrue();
 
-        installPackageAsUser(TARGET_APK, true /* grantPermissions */, mPrimaryUserId);
-        installPackageAsUser(TARGET_APK, true /* grantPermissions */, mSecondaryUserId);
+        for (String apk : new String[] {TARGET_APK, TARGET_APK_A, TARGET_APK_B}) {
+            installPackageAsUser(apk, true /* grantPermissions */, mPrimaryUserId, "-t");
+            installPackageAsUser(apk, true /* grantPermissions */, mSecondaryUserId, "-t");
+        }
     }
 
     @After
@@ -84,4 +86,34 @@
         runDeviceTestAsUser(TARGET_PKG, TEST_CLASS, "testOpenBlob_shouldThrow", args,
                 mSecondaryUserId);
     }
+
+    @Test
+    public void testBlobAccessAcrossUsers() throws Exception {
+        Map<String, String> args = createArgs(Pair.create(KEY_ALLOW_PUBLIC, String.valueOf(1)));
+        // Commit a blob.
+        runDeviceTestAsUser(TARGET_PKG_A, TEST_CLASS, "testCommitBlob", args,
+                mPrimaryUserId);
+        Map<String, String> argsFromLastTestRun = createArgsFromLastTestRun();
+        // Verify that previously committed blob can be accessed.
+        runDeviceTestAsUser(TARGET_PKG, TEST_CLASS, "testOpenBlob", argsFromLastTestRun,
+                mPrimaryUserId);
+        // Verify that previously committed blob cannot be access from another user.
+        runDeviceTestAsUser(TARGET_PKG, TEST_CLASS, "testOpenBlob_shouldThrow", argsFromLastTestRun,
+                mSecondaryUserId);
+
+        // Verify that previously committed blob can be accessed from another user holding
+        // a priv permission.
+        runDeviceTestAsUser(TARGET_PKG_A, TEST_CLASS, "testOpenBlob", argsFromLastTestRun,
+                mSecondaryUserId);
+        runDeviceTestAsUser(TARGET_PKG_B, TEST_CLASS, "testOpenBlob", argsFromLastTestRun,
+                mSecondaryUserId);
+
+        // Recommit the blob on another user
+        argsFromLastTestRun.putAll(args);
+        runDeviceTestAsUser(TARGET_PKG_B, TEST_CLASS, "testRecommitBlob", argsFromLastTestRun,
+                mSecondaryUserId);
+        // Any package on another user should be able to access the blob
+        runDeviceTestAsUser(TARGET_PKG, TEST_CLASS, "testOpenBlob", argsFromLastTestRun,
+                mSecondaryUserId);
+    }
 }
diff --git a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/AndroidManifest_withPrivPerm.xml b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/AndroidManifest_withPrivPerm.xml
new file mode 100644
index 0000000..fb06cdf
--- /dev/null
+++ b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/AndroidManifest_withPrivPerm.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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="com.android.cts.device.blob">
+
+    <uses-permission android:name="android.permission.ACCESS_BLOBS_ACROSS_USERS" />
+
+    <application android:testOnly="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+            android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.cts.device.blob"  />
+</manifest>
\ No newline at end of file
diff --git a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataCleanupTest.java b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataCleanupTest.java
index b01be92..03d16cc 100644
--- a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataCleanupTest.java
+++ b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataCleanupTest.java
@@ -26,6 +26,7 @@
 import android.os.ParcelFileDescriptor;
 
 import com.android.utils.blob.FakeBlobData;
+import com.android.utils.blob.Utils;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -116,6 +117,28 @@
                 () -> mBlobStoreManager.openBlob(blobHandle));
     }
 
+    @Test
+    public void testRecommitBlob() throws Exception {
+        final BlobHandle blobHandle = getBlobHandleFromArgs();
+        try (ParcelFileDescriptor pfd = mBlobStoreManager.openBlob(blobHandle)) {
+            assertThat(pfd).isNotNull();
+
+            final long sessionId = createSession(blobHandle);
+            assertThat(sessionId).isGreaterThan(0L);
+            try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
+                Utils.writeToSession(session, pfd);
+                if (getShouldAllowPublicFromArgs()) {
+                    session.allowPublicAccess();
+                }
+
+                final CompletableFuture<Integer> callback = new CompletableFuture<>();
+                session.commit(mContext.getMainExecutor(), callback::complete);
+                assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_MS, TimeUnit.MILLISECONDS))
+                        .isEqualTo(0);
+            }
+        }
+    }
+
     private void addSessionIdToResults(long sessionId) {
         final Bundle results = new Bundle();
         results.putLong(KEY_SESSION_ID, sessionId);
diff --git a/hostsidetests/calllog/app/src/android/provider/cts/contacts/testapp/CallLogDirectBootTest.java b/hostsidetests/calllog/app/src/android/provider/cts/contacts/testapp/CallLogDirectBootTest.java
index d16f0bd..d8ca24f 100644
--- a/hostsidetests/calllog/app/src/android/provider/cts/contacts/testapp/CallLogDirectBootTest.java
+++ b/hostsidetests/calllog/app/src/android/provider/cts/contacts/testapp/CallLogDirectBootTest.java
@@ -63,7 +63,8 @@
             Pair<Uri, CallLog.CallComposerLoggingException> result;
             try (InputStream inputStream =
                          mDe.getResources().openRawResource(R.drawable.cupcake)) {
-                CallLog.storeCallComposerPictureAsUser(mDe, android.os.Process.myUserHandle(),
+                CallLog.storeCallComposerPicture(
+                        mDe.createContextAsUser(android.os.Process.myUserHandle(), 0),
                         inputStream,
                         Executors.newSingleThreadExecutor(),
                         new OutcomeReceiver<Uri, CallLog.CallComposerLoggingException>() {
diff --git a/hostsidetests/calllog/src/android/provider/cts/contacts/hostside/ShadowCallLogTest.java b/hostsidetests/calllog/src/android/provider/cts/contacts/hostside/ShadowCallLogTest.java
index 086cf80..272a3df 100644
--- a/hostsidetests/calllog/src/android/provider/cts/contacts/hostside/ShadowCallLogTest.java
+++ b/hostsidetests/calllog/src/android/provider/cts/contacts/hostside/ShadowCallLogTest.java
@@ -29,12 +29,14 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.io.File;
 
 @RunWith(DeviceJUnit4ClassRunner.class)
+@Ignore("Runtime too long and may lock up device when it fails")
 public class ShadowCallLogTest extends BaseHostJUnit4Test {
     private static final String TAG = ShadowCallLogTest.class.getSimpleName();
 
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
index 606bd55..35e3ee2 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
@@ -47,6 +47,7 @@
 import androidx.test.InstrumentationRegistry;
 
 import java.time.Duration;
+import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
@@ -195,6 +196,34 @@
         }
     }
 
+    // Setting and unsetting the lock task packages when the OEM defines policy-exempt apps
+    public void testSetLockTaskPackagesIgnoresExemptApps() {
+        Set<String> policyExemptApps = mDevicePolicyManager.getPolicyExemptApps();
+        if (policyExemptApps.isEmpty()) {
+            Log.v(TAG, "OEM doesn't define any policy exempt app");
+            return;
+        }
+
+        assertWithMessage("lock task packages initially")
+                .that(mDevicePolicyManager.getLockTaskPackages(ADMIN_COMPONENT)).isEmpty();
+
+
+        String[] packages = new String[] { TEST_PACKAGE };
+        Set<String> expectedLockTaskPackages = new HashSet<>(policyExemptApps);
+        expectedLockTaskPackages.add(TEST_PACKAGE);
+
+        mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, packages);
+
+        assertWithMessage("lock task packages after adding %s", TEST_PACKAGE)
+                .that(mDevicePolicyManager.getLockTaskPackages(ADMIN_COMPONENT)).asList()
+                .containsExactlyElementsIn(expectedLockTaskPackages);
+
+
+        mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
+        assertWithMessage("lock task packages after reset")
+                .that(mDevicePolicyManager.getLockTaskPackages(ADMIN_COMPONENT)).isEmpty();
+    }
+
     // Setting and unsetting the lock task features. The actual UI behavior is tested with CTS
     // verifier.
     public void testSetLockTaskFeatures() {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AccountCheckHostSideTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AccountCheckHostSideTest.java
index 17154bc..7078bf9 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AccountCheckHostSideTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/AccountCheckHostSideTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 import android.platform.test.annotations.LargeTest;
 
@@ -28,6 +29,12 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+/**
+ * Set of tests to test setting DO and PO when there is account on the user.
+ *
+ * <p>For example, setting DO or PO shall fail at DPMS.hasIncompatibleAccountsOrNonAdbNoLock when
+ * there was incompatible account on the user.
+ */
 public class AccountCheckHostSideTest extends BaseDevicePolicyTest {
     private static final String APK_NON_TEST_ONLY = "CtsAccountCheckNonTestOnlyOwnerApp.apk";
     private static final String APK_TEST_ONLY = "CtsAccountCheckTestOnlyOwnerApp.apk";
@@ -48,10 +55,40 @@
     private static final String TEST_CLASS =
             "com.android.cts.devicepolicy.accountcheck.AccountCheckTest";
 
+    private static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
+
+    private boolean mDeviceOwnerCanHaveAccounts;
+    private boolean mProfileOwnerCanHaveAccounts;
+    private int mProfileOwnerUserId;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mProfileOwnerUserId = mPrimaryUserId;
+        mDeviceOwnerCanHaveAccounts = !isRestrictionSetOnUser(mDeviceOwnerUserId,
+                DISALLOW_MODIFY_ACCOUNTS);
+        // Optimization to avoid running dumpsys again
+        if (mProfileOwnerUserId == mDeviceOwnerUserId) {
+            mProfileOwnerCanHaveAccounts = mDeviceOwnerCanHaveAccounts;
+        } else {
+            mProfileOwnerCanHaveAccounts = !isRestrictionSetOnUser(mProfileOwnerUserId,
+                    DISALLOW_MODIFY_ACCOUNTS);
+        }
+        CLog.d("mDeviceOwnerUserId: " +  mDeviceOwnerUserId
+                + " mDeviceOwnerCanHaveAccounts: " + mDeviceOwnerCanHaveAccounts
+                + " mProfileOwnerUserId: " + mProfileOwnerUserId
+                + " mProfileOwnerCanHaveAccounts: " + mProfileOwnerCanHaveAccounts);
+        assumeTrue("Neither primary user or device owner user is allowed to add accounts",
+                mDeviceOwnerCanHaveAccounts || mProfileOwnerCanHaveAccounts);
+    }
+
     @Override
     public void tearDown() throws Exception {
         if (getDevice().getInstalledPackageNames().contains(PACKAGE_AUTH)) {
-            runCleanupTestOnlyOwnerAllowingFailure();
+            runCleanupTestOnlyOwnerAllowingFailure(mProfileOwnerUserId);
+            if (mDeviceOwnerUserId != mProfileOwnerUserId) {
+                runCleanupTestOnlyOwnerAllowingFailure(mDeviceOwnerUserId);
+            }
             runCleanupNonTestOnlyOwnerAllowingFailure();
 
             // This shouldn't be needed since we're uninstalling the authenticator,
@@ -67,16 +104,23 @@
     }
 
     private void runTest(String method) throws Exception {
-        runDeviceTests(PACKAGE_AUTH, TEST_CLASS, method);
+        runTestAsUser(method, mProfileOwnerUserId);
+        if (mDeviceOwnerCanHaveAccounts && mProfileOwnerUserId != mDeviceOwnerUserId) {
+            runTestAsUser(method, mDeviceOwnerUserId);
+        }
     }
 
-    private void runCleanupTestOnlyOwner() throws Exception {
-        assertTrue(removeAdmin(OWNER_TEST_ONLY, mPrimaryUserId));
+    private void runTestAsUser(String method, int userId) throws Exception {
+        runDeviceTestsAsUser(PACKAGE_AUTH, TEST_CLASS, method, userId);
     }
 
-    private void runCleanupTestOnlyOwnerAllowingFailure() throws Exception {
+    private void runCleanupTestOnlyOwner(int userId) throws Exception {
+        assertTrue(removeAdmin(OWNER_TEST_ONLY, userId));
+    }
+
+    private void runCleanupTestOnlyOwnerAllowingFailure(int userId) throws Exception {
         try {
-            runCleanupTestOnlyOwner();
+            runCleanupTestOnlyOwner(userId);
         } catch (AssertionError ignore) {
         }
     }
@@ -104,35 +148,47 @@
     }
 
     private void assertTestOnlyInstallable() throws Exception {
-        setDeviceOwnerOrFail(OWNER_TEST_ONLY, mPrimaryUserId);
-        runCleanupTestOnlyOwner();
-
-        setProfileOwnerOrFail(OWNER_TEST_ONLY, mPrimaryUserId);
-        runCleanupTestOnlyOwner();
+        if (mDeviceOwnerCanHaveAccounts) {
+            setDeviceOwnerOrFail(OWNER_TEST_ONLY, mDeviceOwnerUserId);
+            runCleanupTestOnlyOwner(mDeviceOwnerUserId);
+        }
+        if (mProfileOwnerCanHaveAccounts) {
+            setProfileOwnerOrFail(OWNER_TEST_ONLY, mProfileOwnerUserId);
+            runCleanupTestOnlyOwner(mProfileOwnerUserId);
+        }
     }
 
     private void assertNonTestOnlyInstallable() throws Exception {
-        setDeviceOwnerOrFail(OWNER_NON_TEST_ONLY, mPrimaryUserId);
-        runCleanupNonTestOnlyOwner();
-
-        setProfileOwnerOrFail(OWNER_NON_TEST_ONLY, mPrimaryUserId);
-        runCleanupNonTestOnlyOwner();
+        if (mDeviceOwnerCanHaveAccounts) {
+            setDeviceOwnerOrFail(OWNER_NON_TEST_ONLY, mDeviceOwnerUserId);
+            runCleanupNonTestOnlyOwner();
+        }
+        if (mProfileOwnerCanHaveAccounts) {
+            setProfileOwnerOrFail(OWNER_NON_TEST_ONLY, mProfileOwnerUserId);
+            runCleanupNonTestOnlyOwner();
+        }
     }
 
     private void assertTestOnlyNotInstallable() throws Exception {
-        setDeviceOwnerExpectingFailure(OWNER_TEST_ONLY, mPrimaryUserId);
-        runCleanupTestOnlyOwnerAllowingFailure();
-
-        setProfileOwnerExpectingFailure(OWNER_TEST_ONLY, mPrimaryUserId);
-        runCleanupTestOnlyOwnerAllowingFailure();
+        if (mDeviceOwnerCanHaveAccounts) {
+            setDeviceOwnerExpectingFailure(OWNER_TEST_ONLY, mDeviceOwnerUserId);
+            runCleanupTestOnlyOwnerAllowingFailure(mDeviceOwnerUserId);
+        }
+        if (mProfileOwnerCanHaveAccounts) {
+            setProfileOwnerExpectingFailure(OWNER_TEST_ONLY, mProfileOwnerUserId);
+            runCleanupTestOnlyOwnerAllowingFailure(mProfileOwnerUserId);
+        }
     }
 
     private void assertNonTestOnlyNotInstallable() throws Exception {
-        setDeviceOwnerExpectingFailure(OWNER_NON_TEST_ONLY, mPrimaryUserId);
-        runCleanupNonTestOnlyOwnerAllowingFailure();
-
-        setProfileOwnerExpectingFailure(OWNER_NON_TEST_ONLY, mPrimaryUserId);
-        runCleanupNonTestOnlyOwnerAllowingFailure();
+        if (mDeviceOwnerCanHaveAccounts) {
+            setDeviceOwnerExpectingFailure(OWNER_NON_TEST_ONLY, mDeviceOwnerUserId);
+            runCleanupNonTestOnlyOwnerAllowingFailure();
+        }
+        if (mProfileOwnerCanHaveAccounts) {
+            setProfileOwnerExpectingFailure(OWNER_NON_TEST_ONLY, mProfileOwnerUserId);
+            runCleanupNonTestOnlyOwnerAllowingFailure();
+        }
     }
 
     private boolean hasAccounts() throws Exception {
@@ -151,14 +207,28 @@
         return Integer.parseInt(count) > 0;
     }
 
+    /**
+     * This set of tests will test whether DO and PO can be set on the user when
+     * there is/are different types of accounts added on the target test user.
+     */
     @Test
     @LargeTest
     public void testAccountCheck() throws Exception {
-        installAppAsUser(APK_AUTH, mPrimaryUserId);
-        installAppAsUser(APK_NON_TEST_ONLY, mPrimaryUserId);
-        installAppAsUser(APK_TEST_ONLY, mPrimaryUserId);
+        installAppAsUser(APK_AUTH, mProfileOwnerUserId);
+        installAppAsUser(APK_NON_TEST_ONLY, mProfileOwnerUserId);
+        installAppAsUser(APK_TEST_ONLY, mProfileOwnerUserId);
+        runCleanupTestOnlyOwnerAllowingFailure(mProfileOwnerUserId);
 
-        runCleanupTestOnlyOwnerAllowingFailure();
+        // For tests in headless system user mode, test packages need to be installed for
+        // system user even for PO tests since PO will be set via adb command which will require
+        // TestAuthenticator installed on system user.
+        if (mDeviceOwnerUserId != mProfileOwnerUserId) {
+            installAppAsUser(APK_AUTH, mDeviceOwnerUserId);
+            installAppAsUser(APK_NON_TEST_ONLY, mDeviceOwnerUserId);
+            installAppAsUser(APK_TEST_ONLY, mDeviceOwnerUserId);
+            runCleanupTestOnlyOwnerAllowingFailure(mDeviceOwnerUserId);
+        }
+
         runCleanupNonTestOnlyOwnerAllowingFailure();
         removeAllAccountsAllowingFailure();
         try {
@@ -244,11 +314,11 @@
      */
     @Test
     public void testInheritTestOnly() throws Exception {
-        installAppAsUser(APK_TEST_ONLY, mPrimaryUserId);
+        installAppAsUser(APK_TEST_ONLY, mDeviceOwnerUserId);
 
         // Set as DO.
         try {
-            setDeviceOwnerOrFail(OWNER_TEST_ONLY, mPrimaryUserId);
+            setDeviceOwnerOrFail(OWNER_TEST_ONLY, mDeviceOwnerUserId);
         } catch (Throwable e) {
             CLog.e("Unable to install DO, can't continue the test. Skipping.  hasAccounts="
                     + hasAccounts());
@@ -257,17 +327,17 @@
         try {
 
             // Override with a package that's not test-only.
-            installAppAsUser(APK_TEST_ONLY_UPDATE, mPrimaryUserId);
+            installAppAsUser(APK_TEST_ONLY_UPDATE, mDeviceOwnerUserId);
 
             // But DPMS keeps the original test-only flag, so it's still removable.
-            runCleanupTestOnlyOwner();
+            runCleanupTestOnlyOwner(mDeviceOwnerUserId);
 
             return;
         } catch (Throwable e) {
             // If failed, re-install the APK with test-only=true.
             try {
-                installAppAsUser(APK_TEST_ONLY, mPrimaryUserId);
-                runCleanupTestOnlyOwner();
+                installAppAsUser(APK_TEST_ONLY, mDeviceOwnerUserId);
+                runCleanupTestOnlyOwner(mDeviceOwnerUserId);
             } catch (Exception inner) {
                 CLog.e("Unable to clean up after a failure: " + e.getMessage());
             }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index c28da3b..6343bad 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -507,6 +507,13 @@
             stopUserAsync(userId);
         }
         for (int userId : usersCreatedByTests) {
+            removeTestAddedUser(userId);
+        }
+    }
+
+    private void removeTestAddedUser(int userId) throws Exception  {
+        // Don't remove system user or initial user.
+        if (userId != USER_SYSTEM && userId != mInitialUserId) {
             removeUser(userId);
         }
     }
@@ -798,9 +805,8 @@
     protected void setProfileOwnerOrFail(String componentName, int userId)
             throws Exception {
         if (!setProfileOwner(componentName, userId, /*expectFailure*/ false)) {
-            if (userId != 0) { // don't remove system user.
-                removeUser(userId);
-            }
+            // Don't remove system user or initial user that tests require to run on.
+            removeTestAddedUser(userId);
             fail("Failed to set profile owner");
         }
     }
@@ -808,9 +814,7 @@
     protected void setProfileOwnerExpectingFailure(String componentName, int userId)
             throws Exception {
         if (setProfileOwner(componentName, userId, /* expectFailure =*/ true)) {
-            if (userId != 0) { // don't remove system user.
-                removeUser(userId);
-            }
+            removeTestAddedUser(userId);
             fail("Setting profile owner should have failed.");
         }
     }
@@ -1201,6 +1205,52 @@
                 userId, deviceAdminPkg);
     }
 
+    /** Find effective restriction for user */
+    protected boolean isRestrictionSetOnUser(int userId, String restriction) throws Exception {
+        String commandOutput = getDevice().executeShellCommand("dumpsys user");
+        String[] outputLines = commandOutput.split("\\n");
+        Pattern userPattern = Pattern.compile("(^.*)UserInfo\\{" + userId + ":.*$");
+        Pattern restrictionPattern = Pattern.compile("(^.*)Effective\\srestrictions\\:.*$");
+
+        boolean userFound = false;
+        boolean restrictionsFound = false;
+        int lastIndent = -1;
+
+        for (String line : outputLines) {
+            // Starting a new block of user infos
+            if (!line.startsWith(" ".repeat(lastIndent + 1))) {
+                CLog.d("User %d restrictions found, no matched restriction.", userId);
+                return false;
+            }
+            //First, try matching user pattern
+            Matcher userMatcher = userPattern.matcher(line);
+            if (userMatcher.find()) {
+                CLog.d("User %d found in dumpsys, finding restrictions.", userId);
+                userFound = true;
+                lastIndent = userMatcher.group(1).length();
+            }
+
+            // Second, try matching restriction
+            Matcher restrictionMatcher = restrictionPattern.matcher(line);
+            if (userFound && restrictionMatcher.find()) {
+                CLog.d("User %d restrictions found, finding exact restriction.", userId);
+                restrictionsFound = true;
+                lastIndent = restrictionMatcher.group(1).length();
+            }
+
+            if (restrictionsFound && line.contains(restriction)) {
+                return true;
+            }
+        }
+        if (!userFound) {
+            CLog.e("User %d not found in dumpsys.", userId);
+        }
+        if (!restrictionsFound) {
+            CLog.d("User %d found in dumpsys, but restrictions not found.", userId);
+        }
+        return false;
+    }
+
     /**
      * Generates instrumentation arguments that indicate the device-side test is exercising device
      * owner APIs.
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminFeaturesCheckerRule.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminFeaturesCheckerRule.java
index e75056f..b66099e 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminFeaturesCheckerRule.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminFeaturesCheckerRule.java
@@ -206,5 +206,7 @@
     @Retention(RetentionPolicy.RUNTIME)
     @Target({ElementType.METHOD})
     public static @interface TemporaryIgnoreOnHeadlessSystemUserMode {
+        String bugId();
+        String reason();
     }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 0177cf3..e4957dd 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -31,7 +31,6 @@
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.RequiresAdditionalFeatures;
-import com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.TemporaryIgnoreOnHeadlessSystemUserMode;
 import com.android.cts.devicepolicy.metrics.DevicePolicyEventWrapper;
 import com.android.tradefed.log.LogUtil.CLog;
 
@@ -100,13 +99,11 @@
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testProxyStaticProxyTest() throws Exception {
         executeDeviceOwnerTest("proxy.StaticProxyTest");
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testProxyPacProxyTest() throws Exception {
         executeDeviceOwnerTest("proxy.PacProxyTest");
     }
@@ -453,7 +450,6 @@
 
     @FlakyTest(bugId = 127101449)
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testWifiConfigLockdown() throws Exception {
         assumeHasWifiFeature();
 
@@ -470,7 +466,6 @@
      * Execute WifiSetHttpProxyTest as device owner.
      */
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testWifiSetHttpProxyTest() throws Exception {
         assumeHasWifiFeature();
         try (LocationModeSetter locationModeSetter = new LocationModeSetter(getDevice())) {
@@ -501,7 +496,6 @@
 
     // Execute HardwarePropertiesManagerTest as a device owner.
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testHardwarePropertiesManagerAsDeviceOwner() throws Exception {
 
         executeDeviceTestMethod(".HardwarePropertiesManagerTest", "testHardwarePropertiesManager");
@@ -533,7 +527,6 @@
 
     @FlakyTest(bugId = 137096267)
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testAdminActionBookkeeping() throws Exception {
         executeDeviceOwnerTest("AdminActionBookkeepingTest");
         assertMetricsLogged(getDevice(), () -> {
@@ -552,7 +545,6 @@
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testBluetoothRestriction() throws Exception {
         executeDeviceOwnerTest("BluetoothRestrictionTest");
     }
@@ -563,7 +555,6 @@
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testSetLocationEnabled() throws Exception {
         executeDeviceOwnerTest("SetLocationEnabledTest");
     }
@@ -579,7 +570,6 @@
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testDisallowFactoryReset() throws Exception {
         int adminVersion = 24;
         changeUserRestrictionOrFail("no_factory_reset", true, mPrimaryUserId,
@@ -608,7 +598,6 @@
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testDeviceOwnerCanGetDeviceIdentifiers() throws Exception {
         // The Device Owner should have access to all device identifiers.
         executeDeviceTestMethod(".DeviceIdentifiersTest",
@@ -616,7 +605,6 @@
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testPackageInstallCache() throws Exception {
         CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
         final File apk = buildHelper.getTestFile(TEST_APP_APK);
@@ -727,7 +715,6 @@
 
     @FlakyTest(bugId = 134487729)
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testPrivateDnsPolicy() throws Exception {
         executeDeviceOwnerTest("PrivateDnsPolicyTest");
     }
@@ -767,7 +754,6 @@
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     public void testNoHiddenActivityFoundTest() throws Exception {
         try {
             // Install app to primary user
@@ -913,7 +899,6 @@
                 "testListForegroundAffiliatedUsers_onlyForegroundUser");
     }
 
-    @TemporaryIgnoreOnHeadlessSystemUserMode
     @Test
     public void testWifiNetworkConfigurationWithoutFineLocationPermission() throws Exception {
         getDevice().executeShellCommand(String.format(
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
index a42a731..2b49d1c 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
@@ -124,6 +124,12 @@
     }
 
     @Test
+    public void testLockTask_policyExemptApps() throws Exception {
+        runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".LockTaskTest",
+                "testSetLockTaskPackagesIgnoresExemptApps", mDeviceOwnerUserId);
+    }
+
+    @Test
     public void testDelegatedCertInstallerDeviceIdAttestation() throws Exception {
         setUpDelegatedCertInstallerAndRunTests(() ->
                 runDeviceTestsAsUser("com.android.cts.certinstaller",
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ProfileOwnerTest.java
index b2f93d8..eae5c48 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ProfileOwnerTest.java
@@ -57,19 +57,22 @@
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode // TODO(b/183020176): decide if it's needed or fix it
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "183020176",
+            reason = "decide if it's needed or fix it")
     public void testManagement() throws Exception {
         executeProfileOwnerTest("ManagementTest");
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode // TODO(b/183020176): decide if it's needed or fix it
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "183020176",
+            reason = "decide if it's needed or fix it")
     public void testAdminActionBookkeeping() throws Exception {
         executeProfileOwnerTest("AdminActionBookkeepingTest");
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode // TODO(b/183020176): decide if it's needed or fix it
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "183020176",
+            reason = "decide if it's needed or fix it")
     public void testAppUsageObserver() throws Exception {
         executeProfileOwnerTest("AppUsageObserverTest");
     }
diff --git a/hostsidetests/multiuser/TEST_MAPPING b/hostsidetests/multiuser/TEST_MAPPING
index 592aaad..f130cf2 100644
--- a/hostsidetests/multiuser/TEST_MAPPING
+++ b/hostsidetests/multiuser/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit": [
+  "presubmit-large": [
     {
       "name": "CtsMultiUserHostTestCases"
     }
diff --git a/hostsidetests/packagemanager/domainverification/apps/calling/src/com/android/cts/packagemanager/verify/domain/callingapp/DomainVerificationIntentHostTimedTests.kt b/hostsidetests/packagemanager/domainverification/apps/calling/src/com/android/cts/packagemanager/verify/domain/callingapp/DomainVerificationIntentHostTimedTests.kt
index 0d2a790..0526f2e 100644
--- a/hostsidetests/packagemanager/domainverification/apps/calling/src/com/android/cts/packagemanager/verify/domain/callingapp/DomainVerificationIntentHostTimedTests.kt
+++ b/hostsidetests/packagemanager/domainverification/apps/calling/src/com/android/cts/packagemanager/verify/domain/callingapp/DomainVerificationIntentHostTimedTests.kt
@@ -28,7 +28,7 @@
 import org.junit.runners.Parameterized
 
 @RunWith(Parameterized::class)
-class DomainVerificationIntentHostTimedTests : DomainVerificationIntentTestBase() {
+class DomainVerificationIntentHostTimedTests : DomainVerificationIntentTestBase(DOMAIN_1) {
 
     @Test
     fun multipleVerifiedTakeLastFirstInstall() {
diff --git a/hostsidetests/packagemanager/domainverification/device/src/com/android/cts/packagemanager/verify/domain/device/DomainVerificationIntentInvalidHostTests.kt b/hostsidetests/packagemanager/domainverification/device/src/com/android/cts/packagemanager/verify/domain/device/DomainVerificationIntentInvalidHostTests.kt
new file mode 100644
index 0000000..f57d599
--- /dev/null
+++ b/hostsidetests/packagemanager/domainverification/device/src/com/android/cts/packagemanager/verify/domain/device/DomainVerificationIntentInvalidHostTests.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.packagemanager.verify.domain.device
+
+import com.android.cts.packagemanager.verify.domain.android.DomainUtils.DECLARING_PKG_1_COMPONENT
+import com.android.cts.packagemanager.verify.domain.android.DomainUtils.DECLARING_PKG_2_COMPONENT
+import com.android.cts.packagemanager.verify.domain.android.DomainVerificationIntentTestBase
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+class DomainVerificationIntentInvalidHostTests :
+    DomainVerificationIntentTestBase("invalid1", assertResolvesToBrowsersInBefore = false) {
+
+    @Test
+    fun launchInvalidHttpUri() {
+        assertResolvesTo(browsers + DECLARING_PKG_1_COMPONENT + DECLARING_PKG_2_COMPONENT)
+    }
+}
diff --git a/hostsidetests/packagemanager/domainverification/device/src/com/android/cts/packagemanager/verify/domain/device/DomainVerificationIntentStandaloneTests.kt b/hostsidetests/packagemanager/domainverification/device/src/com/android/cts/packagemanager/verify/domain/device/DomainVerificationIntentStandaloneTests.kt
index 8923993..dd456fa 100644
--- a/hostsidetests/packagemanager/domainverification/device/src/com/android/cts/packagemanager/verify/domain/device/DomainVerificationIntentStandaloneTests.kt
+++ b/hostsidetests/packagemanager/domainverification/device/src/com/android/cts/packagemanager/verify/domain/device/DomainVerificationIntentStandaloneTests.kt
@@ -30,7 +30,7 @@
 import org.junit.runners.Parameterized
 
 @RunWith(Parameterized::class)
-class DomainVerificationIntentStandaloneTests : DomainVerificationIntentTestBase() {
+class DomainVerificationIntentStandaloneTests : DomainVerificationIntentTestBase(DOMAIN_1) {
 
     @Test
     fun launchVerified() {
diff --git a/hostsidetests/packagemanager/domainverification/lib/constants/android/src/com/android/cts/packagemanager/verify/domain/android/DomainVerificationIntentTestBase.kt b/hostsidetests/packagemanager/domainverification/lib/constants/android/src/com/android/cts/packagemanager/verify/domain/android/DomainVerificationIntentTestBase.kt
index 7c02587..283332c 100644
--- a/hostsidetests/packagemanager/domainverification/lib/constants/android/src/com/android/cts/packagemanager/verify/domain/android/DomainVerificationIntentTestBase.kt
+++ b/hostsidetests/packagemanager/domainverification/lib/constants/android/src/com/android/cts/packagemanager/verify/domain/android/DomainVerificationIntentTestBase.kt
@@ -30,7 +30,6 @@
 import com.android.cts.packagemanager.verify.domain.java.DomainUtils
 import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DECLARING_PKG_NAME_1
 import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DECLARING_PKG_NAME_2
-import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DOMAIN_1
 import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DOMAIN_UNHANDLED
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
@@ -40,7 +39,10 @@
 import org.junit.runners.Parameterized
 
 @RunWith(Parameterized::class)
-abstract class DomainVerificationIntentTestBase {
+abstract class DomainVerificationIntentTestBase(
+    private val domain: String,
+    private val assertResolvesToBrowsersInBefore: Boolean = true
+) {
 
     companion object {
 
@@ -65,7 +67,7 @@
 
     @Before
     fun findBrowsers() {
-        intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://$DOMAIN_1"))
+        intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://$domain"))
             .applyIntentVariant(intentVariant)
 
         browsers = Intent(Intent.ACTION_VIEW, Uri.parse("https://$DOMAIN_UNHANDLED"))
@@ -88,7 +90,10 @@
         }
 
         this.allResults = allResults
-        assertResolvesTo(browsers)
+
+        if (assertResolvesToBrowsersInBefore) {
+            assertResolvesTo(browsers)
+        }
     }
 
     @Before
@@ -103,19 +108,19 @@
 
     protected fun assertResolvesTo(result: ComponentName) = assertResolvesTo(listOf(result))
 
-    protected fun assertResolvesTo(packageNames: Collection<ComponentName>) {
+    protected fun assertResolvesTo(components: Collection<ComponentName>) {
         // Pass MATCH_DEFAULT_ONLY to mirror startActivity resolution
         assertThat(packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
             .map { it.activityInfo }
             .map { ComponentName(it.packageName, it.name) })
-            .containsExactlyElementsIn(packageNames)
+            .containsExactlyElementsIn(components)
 
         if (intent.hasCategory(Intent.CATEGORY_DEFAULT)) {
             // Verify explicit DEFAULT mirrors MATCH_DEFAULT_ONLY
             assertThat(packageManager.queryIntentActivities(intent, 0)
                 .map { it.activityInfo }
                 .map { ComponentName(it.packageName, it.name) })
-                .containsExactlyElementsIn(packageNames)
+                .containsExactlyElementsIn(components)
         } else {
             // Verify that non-DEFAULT match returns all results
             assertThat(packageManager.queryIntentActivities(intent, 0)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/Android.bp
new file mode 100644
index 0000000..9bf90d3
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/Android.bp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 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.
+ *
+ */
+
+cc_test {
+    name: "CVE-2020-0072",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: [
+        "poc.cpp",
+    ],
+    compile_multilib: "64",
+    shared_libs: [
+        "libnfc-nci",
+    ],
+    include_dirs: [
+        "system/nfc/src/nfc/include",
+        "system/nfc/src/gki/common",
+        "system/nfc/src/gki/ulinux",
+        "system/nfc/src/include",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/poc.cpp
new file mode 100644
index 0000000..048c6c7
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0072/poc.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include "../includes/common.h"
+#include <stdlib.h>
+
+#include <nfc_api.h>
+#include <rw_int.h>
+
+#define NUM_BYTES 1
+
+extern tRW_CB rw_cb;
+void rw_init(void);
+void rw_t2t_handle_rsp(uint8_t *p_data);
+
+void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
+  (void)event;
+  (void)p_rw_data;
+}
+
+int main() {
+  tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
+  rw_init();
+  rw_cb.p_cback = &poc_cback;
+  p_t2t->state = RW_T2T_STATE_DETECT_TLV;
+  p_t2t->tlv_detect = TAG_LOCK_CTRL_TLV;
+  p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
+  p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
+  p_t2t->bytes_count = NUM_BYTES;
+  p_t2t->tlv_value[1] = 0;
+  int index = p_t2t->num_lock_tlvs;
+  uint8_t data[T2T_READ_DATA_LEN];
+  rw_t2t_handle_rsp(data);
+  int ret = (p_t2t->lock_tlv[index].num_bits == p_t2t->tlv_value[1])
+                ? EXIT_VULNERABLE
+                : EXIT_SUCCESS;
+  return ret;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/Android.bp
new file mode 100644
index 0000000..7119250
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/Android.bp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 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.
+ *
+ */
+
+cc_test {
+    name: "CVE-2021-0473",
+    defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+    srcs: [
+        "poc.cpp",
+    ],
+    compile_multilib: "64",
+    shared_libs: [
+        "libnfc-nci",
+    ],
+    include_dirs: [
+        "system/nfc/src/nfc/include",
+        "system/nfc/src/gki/common",
+        "system/nfc/src/gki/ulinux",
+        "system/nfc/src/include",
+    ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/poc.cpp
new file mode 100644
index 0000000..d7650ad
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/poc.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include "../includes/common.h"
+#include <dlfcn.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <vector>
+
+using namespace std;
+
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+void rw_init(void);
+
+tNFC_STATUS rw_t3t_select(uint8_t peerNfcID[NCI_RF_F_UID_LEN],
+                          uint8_t mrtiCheck, uint8_t mrtiUpdate);
+
+static void (*real_GKI_freebuf)(void *ptr) = nullptr;
+static void *(*real_GKI_getpoolbuf)(uint8_t pool_id) = nullptr;
+bool kIsInitialized = false;
+bool kIsVulnerable = false;
+
+struct myPtr {
+  void *ptr = nullptr;
+  bool isFreed = false;
+};
+
+struct myPtr vulnerablePtr;
+
+enum {
+  RW_T3T_STATE_NOT_ACTIVATED,
+  RW_T3T_STATE_IDLE,
+  RW_T3T_STATE_COMMAND_PENDING
+};
+
+void poc_cback(tRW_EVENT, tRW_DATA *) {}
+
+void GKI_start_timer(uint8_t, int32_t, bool) {}
+
+void GKI_stop_timer(uint8_t) {}
+
+void init(void) {
+  real_GKI_freebuf = (void (*)(void *))dlsym(RTLD_NEXT, "_Z11GKI_freebufPv");
+  if (!real_GKI_freebuf) {
+    return;
+  }
+  real_GKI_getpoolbuf =
+      (void *(*)(uint8_t))dlsym(RTLD_NEXT, "_Z14GKI_getpoolbufh");
+  if (!real_GKI_freebuf) {
+    return;
+  }
+  kIsInitialized = true;
+}
+
+void *GKI_getpoolbuf(uint8_t pool_id) {
+  if (!kIsInitialized) {
+    init();
+  }
+  void *ptr = real_GKI_getpoolbuf(pool_id);
+  if (pool_id == NFC_RW_POOL_ID) {
+    vulnerablePtr.ptr = ptr;
+  }
+  return ptr;
+}
+
+void GKI_freebuf(void *ptr) {
+  if (!kIsInitialized) {
+    init();
+  }
+  if (ptr == vulnerablePtr.ptr) {
+    if (vulnerablePtr.isFreed) {
+      kIsVulnerable = true;
+    } else {
+      vulnerablePtr.isFreed = true;
+    }
+  }
+  real_GKI_freebuf(ptr);
+}
+
+int main() {
+  tRW_T3T_CB *p_t3t = &rw_cb.tcb.t3t;
+
+  GKI_init();
+  rw_init();
+  rw_cb.p_cback = &poc_cback;
+
+  uint8_t peerNfcID[NCI_RF_F_UID_LEN];
+  uint8_t mrtiCheck = 1, mrtiUpdate = 1;
+  if (rw_t3t_select(peerNfcID, mrtiCheck, mrtiUpdate) != NFC_STATUS_OK) {
+    return EXIT_FAILURE;
+  }
+
+  tNFC_CONN p_data = {};
+  NFC_HDR nfcHdr = {};
+  p_data.data.p_data = &nfcHdr;
+
+  tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+  p_t3t->rw_state = RW_T3T_STATE_COMMAND_PENDING;
+
+  uint8_t conn_id = NFC_RF_CONN_ID;
+  tNFC_CONN_EVT event = NFC_ERROR_CEVT;
+  p_cb->p_cback(conn_id, event, &p_data);
+  return (kIsVulnerable) ? EXIT_VULNERABLE : EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index eaba89f..912ba28 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -68,6 +68,7 @@
         ITestDevice device;
         CrashUtils.Config config;
         List<String> inputFiles = Collections.emptyList();
+        boolean checkCrash = true;
 
         pocConfig(String binaryName, ITestDevice device) {
             this.binaryName = binaryName;
@@ -688,10 +689,12 @@
                 removeResources(inputFiles, testConfig.inputFilesDestination, testConfig.device);
             }
         }
-        if (testConfig.config == null) {
-            testConfig.config = new CrashUtils.Config();
+        if(testConfig.checkCrash) {
+            if (testConfig.config == null) {
+                testConfig.config = new CrashUtils.Config();
+            }
+            assertNoCrashes(testConfig.device, testConfig.config);
         }
-        assertNoCrashes(testConfig.device, testConfig.config);
     }
 
     /**
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
new file mode 100644
index 0000000..4f355d3
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0072.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2020_0072 extends SecurityTestCase {
+
+    /**
+     * b/147310271
+     * Vulnerability Behaviour: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2020-04")
+    @Test
+    public void testPocCVE_2020_0072() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2020-0072", getDevice());
+        testConfig.checkCrash = false;
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
new file mode 100644
index 0000000..d2dc169
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0473.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0473 extends SecurityTestCase {
+
+    /**
+     * b/179687208
+     * Vulnerability Behavior: EXIT_VULNERABLE (113)
+     */
+    @SecurityTest(minPatchLevel = "2021-05")
+    @Test
+    public void testPocCVE_2021_0473() throws Exception {
+        AdbUtils.assumeHasNfc(getDevice());
+        pocPusher.only64();
+        AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig("CVE-2021-0473", getDevice());
+        testConfig.checkCrash = false;
+        AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+    }
+}
diff --git a/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java b/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java
index 8c132e7..7fa8f1f 100644
--- a/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java
+++ b/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java
@@ -97,9 +97,11 @@
 
     @Before
     public void setUp() throws Exception {
-        Assume.assumeTrue(SystemProperties.getBoolean("sys.fuse.transcode_enabled", false));
-        // TODO(b/182846329): GSI doesn't support transcoding yet, maybe a transcoding issue
-        Assume.assumeFalse(SystemProperties.get("ro.product.system.device").contains("generic"));
+        Assume.assumeTrue("Media transcoding disabled",
+                SystemProperties.getBoolean("sys.fuse.transcode_enabled", false));
+        // TODO(b/182846329): GSI doesn't support transcoding yet
+        Assume.assumeFalse(
+                "Using GSI", SystemProperties.get("ro.build.product").contains("generic"));
 
         TranscodeTestUtils.pollForExternalStorageState();
         TranscodeTestUtils.grantPermission(getContext().getPackageName(),
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTargetActivity.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTargetActivity.java
index 921a769..95f17f8 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTargetActivity.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTargetActivity.java
@@ -16,16 +16,13 @@
 
 package android.view.accessibility.cts;
 
-import android.app.Activity;
-import android.app.KeyguardManager;
-import android.content.Context;
 import android.os.Bundle;
 import android.view.accessibility.cts.R;
 
 /**
  * The accessibility shortcut target activity.
  */
-public class AccessibilityShortcutTargetActivity extends Activity {
+public class AccessibilityShortcutTargetActivity extends AccessibilityTestActivity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityTestActivity.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityTestActivity.java
new file mode 100644
index 0000000..95fe97b
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityTestActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.view.accessibility.cts;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.os.Bundle;
+
+public abstract class AccessibilityTestActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        turnOnScreen();
+        super.onCreate(savedInstanceState);
+    }
+
+    private void turnOnScreen() {
+        setTurnScreenOn(true);
+        setShowWhenLocked(true);
+        KeyguardManager keyguardManager = getSystemService(KeyguardManager.class);
+        keyguardManager.requestDismissKeyguard(this, null);
+    }
+}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/DummyActivity.java b/tests/accessibility/src/android/view/accessibility/cts/DummyActivity.java
index b184fe8..ef70887 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/DummyActivity.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/DummyActivity.java
@@ -16,7 +16,4 @@
 
 package android.view.accessibility.cts;
 
-import android.app.Activity;
-
-public class DummyActivity extends Activity {
-}
+public class DummyActivity extends AccessibilityTestActivity {}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedDisplayTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedDisplayTest.java
index 30b878c..03324b8 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedDisplayTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedDisplayTest.java
@@ -247,7 +247,7 @@
         assertNotNull(mEmbeddedDisplayActivity);
     }
 
-    public static class EmbeddedDisplayParentActivity extends Activity {
+    public static class EmbeddedDisplayParentActivity extends AccessibilityTestActivity {
         private ActivityView mActivityView;
 
         @Override
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/AppSearchMigratorTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/AppSearchMigratorTest.java
new file mode 100644
index 0000000..f0a916d1
--- /dev/null
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/AppSearchMigratorTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.appsearch.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.annotation.NonNull;
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.Migrator;
+
+import org.junit.Test;
+
+public class AppSearchMigratorTest {
+
+    @Test
+    public void testOnUpgrade() {
+        Migrator migrator =
+                new Migrator() {
+                    @Override
+                    public boolean shouldMigrate(int currentVersion, int finalVersion) {
+                        return true;
+                    }
+
+                    @NonNull
+                    @Override
+                    public GenericDocument onUpgrade(
+                            int currentVersion,
+                            int finalVersion,
+                            @NonNull GenericDocument document) {
+                        return new GenericDocument.Builder<>(
+                                        document.getNamespace(),
+                                        document.getUri(),
+                                        document.getSchemaType())
+                                .setCreationTimestampMillis(document.getCreationTimestampMillis())
+                                .setScore(document.getScore())
+                                .setTtlMillis(document.getTtlMillis())
+                                .setPropertyString(
+                                        "migration",
+                                        "Upgrade the document from version "
+                                                + currentVersion
+                                                + " to version "
+                                                + finalVersion)
+                                .build();
+                    }
+
+                    @NonNull
+                    @Override
+                    public GenericDocument onDowngrade(
+                            int currentVersion,
+                            int finalVersion,
+                            @NonNull GenericDocument document) {
+                        return document;
+                    }
+                };
+
+        GenericDocument input =
+                new GenericDocument.Builder<>("namespace", "uri", "schemaType")
+                        .setCreationTimestampMillis(12345L)
+                        .setScore(100)
+                        .setTtlMillis(54321L)
+                        .build();
+
+        GenericDocument expected =
+                new GenericDocument.Builder<>("namespace", "uri", "schemaType")
+                        .setCreationTimestampMillis(12345L)
+                        .setScore(100)
+                        .setTtlMillis(54321L)
+                        .setPropertyString(
+                                "migration", "Upgrade the document from version 3 to version 5")
+                        .build();
+
+        GenericDocument output =
+                migrator.onUpgrade(/*currentVersion=*/ 3, /*finalVersion=*/ 5, input);
+        assertThat(output).isEqualTo(expected);
+    }
+
+    @Test
+    public void testOnDowngrade() {
+        Migrator migrator =
+                new Migrator() {
+                    @Override
+                    public boolean shouldMigrate(int currentVersion, int finalVersion) {
+                        return true;
+                    }
+
+                    @NonNull
+                    @Override
+                    public GenericDocument onUpgrade(
+                            int currentVersion,
+                            int finalVersion,
+                            @NonNull GenericDocument document) {
+                        return document;
+                    }
+
+                    @NonNull
+                    @Override
+                    public GenericDocument onDowngrade(
+                            int currentVersion,
+                            int finalVersion,
+                            @NonNull GenericDocument document) {
+                        return new GenericDocument.Builder<>(
+                                        document.getNamespace(),
+                                        document.getUri(),
+                                        document.getSchemaType())
+                                .setCreationTimestampMillis(document.getCreationTimestampMillis())
+                                .setScore(document.getScore())
+                                .setTtlMillis(document.getTtlMillis())
+                                .setPropertyString(
+                                        "migration",
+                                        "Downgrade the document from version "
+                                                + currentVersion
+                                                + " to version "
+                                                + finalVersion)
+                                .build();
+                    }
+                };
+
+        GenericDocument input =
+                new GenericDocument.Builder<>("namespace", "uri", "schemaType")
+                        .setCreationTimestampMillis(12345L)
+                        .setScore(100)
+                        .setTtlMillis(54321L)
+                        .build();
+
+        GenericDocument expected =
+                new GenericDocument.Builder<>("namespace", "uri", "schemaType")
+                        .setCreationTimestampMillis(12345L)
+                        .setScore(100)
+                        .setTtlMillis(54321L)
+                        .setPropertyString(
+                                "migration", "Downgrade the document from version 6 to version 4")
+                        .build();
+
+        GenericDocument output =
+                migrator.onDowngrade(/*currentVersion=*/ 6, /*finalVersion=*/ 4, input);
+        assertThat(output).isEqualTo(expected);
+    }
+}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/AppSearchSessionCtsTestBase.java b/tests/appsearch/src/com/android/cts/appsearch/external/AppSearchSessionCtsTestBase.java
index dd445e0..adffcf3 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/AppSearchSessionCtsTestBase.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/AppSearchSessionCtsTestBase.java
@@ -57,6 +57,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -126,6 +127,7 @@
     }
 
     @Test
+    @Ignore("TODO(b/177266929)")
     public void testSetSchema_Failure() throws Exception {
         mDb1.setSchema(new SetSchemaRequest.Builder().addSchemas(AppSearchEmail.SCHEMA).build())
                 .get();
@@ -162,6 +164,7 @@
     }
 
     @Test
+    @Ignore("TODO(b/177266929)")
     public void testSetSchema_updateVersion() throws Exception {
         AppSearchSchema schema =
                 new AppSearchSchema.Builder("Email")
@@ -421,6 +424,7 @@
     }
 
     @Test
+    @Ignore("TODO(b/177266929)")
     public void testRemoveSchema() throws Exception {
         // Schema registration
         AppSearchSchema emailSchema =
@@ -486,6 +490,7 @@
     }
 
     @Test
+    @Ignore("TODO(b/177266929)")
     public void testRemoveSchema_twoDatabases() throws Exception {
         // Schema registration in mDb1 and mDb2
         AppSearchSchema emailSchema =
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/GenericDocumentCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/GenericDocumentCtsTest.java
index 121438d..92094c3 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/GenericDocumentCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/GenericDocumentCtsTest.java
@@ -279,11 +279,22 @@
     }
 
     @Test
+    public void testDocument_setEmptyValues() {
+        GenericDocument document =
+                new GenericDocument.Builder<>("namespace", "uri1", "schemaType1")
+                        .setPropertyBoolean("testKey")
+                        .build();
+        assertThat(document.getPropertyBooleanArray("testKey")).isEmpty();
+    }
+
+    @Test
     public void testDocumentInvalid() {
         GenericDocument.Builder<?> builder =
                 new GenericDocument.Builder<>("namespace", "uri1", "schemaType1");
+        String nullString = null;
+
         expectThrows(
                 IllegalArgumentException.class,
-                () -> builder.setPropertyBoolean("test", new boolean[] {}));
+                () -> builder.setPropertyString("testKey", "string1", nullString));
     }
 }
diff --git a/tests/autofillservice/AndroidTest.xml b/tests/autofillservice/AndroidTest.xml
index 7aec376..3186d47 100644
--- a/tests/autofillservice/AndroidTest.xml
+++ b/tests/autofillservice/AndroidTest.xml
@@ -65,10 +65,4 @@
     <option name="collect-on-run-ended-only" value="true" />
     <option name="clean-up" value="false" />
   </metrics_collector>
-  <!-- Automotive tests run on user 10 -->
-  <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
-    <option name="directory-keys" value="/storage/emulated/10/CtsAutoFillServiceTestCases" />
-    <option name="collect-on-run-ended-only" value="true" />
-    <option name="clean-up" value="false" />
-  </metrics_collector>
 </configuration>
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraExtensionCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraExtensionCharacteristicsTest.java
index 4c778a4..5f8c8f9 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraExtensionCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraExtensionCharacteristicsTest.java
@@ -27,6 +27,8 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.PropertyUtil;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -123,6 +125,7 @@
 
     @Test
     public void testExtensionAvailability() throws Exception {
+        boolean extensionsAdvertised = false;
         for (String id : mTestRule.getCameraIdsUnderTest()) {
             StaticMetadata staticMeta =
                     new StaticMetadata(mTestRule.getCameraManager().getCameraCharacteristics(id));
@@ -133,6 +136,9 @@
                     mTestRule.getCameraManager().getCameraExtensionCharacteristics(id);
             ArrayList<Integer> unsupportedExtensions = new ArrayList<>(EXTENSIONS);
             List<Integer> supportedExtensions = extensionChars.getSupportedExtensions();
+            if (!extensionsAdvertised && !supportedExtensions.isEmpty()) {
+                extensionsAdvertised = true;
+            }
             for (Integer extension : supportedExtensions) {
                 verifySupportedExtension(extensionChars, id, extension, SurfaceTexture.class);
                 unsupportedExtensions.remove(extension);
@@ -143,6 +149,10 @@
                 verifyUnsupportedExtension(extensionChars, extension, SurfaceTexture.class);
             }
         }
+        boolean extensionsEnabledProp = PropertyUtil.areCameraXExtensionsEnabled();
+        assertEquals("Extensions system property : " + extensionsEnabledProp + " does not match " +
+                "with the advertised extensions: " + extensionsAdvertised, extensionsEnabledProp,
+                extensionsAdvertised);
     }
 
     @Test
diff --git a/tests/devicepolicy/Android.bp b/tests/devicepolicy/Android.bp
index a71dec7..9ae1302 100644
--- a/tests/devicepolicy/Android.bp
+++ b/tests/devicepolicy/Android.bp
@@ -38,8 +38,5 @@
         "vts10",
         "general-tests",
     ],
-    test_options: {
-        extra_test_configs: ["DevicePolicyWorkProfileTest.xml", "DevicePolicySecondaryUserTest.xml"]
-    },
     sdk_version: "test_current",
 }
diff --git a/tests/devicepolicy/AndroidTest.xml b/tests/devicepolicy/AndroidTest.xml
index 2cff288..1e16d2e 100644
--- a/tests/devicepolicy/AndroidTest.xml
+++ b/tests/devicepolicy/AndroidTest.xml
@@ -21,6 +21,7 @@
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <option name="config-descriptor:metadata" key="parameter" value="multiuser" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="install-arg" value="-t" />
diff --git a/tests/devicepolicy/DevicePolicySecondaryUserTest.xml b/tests/devicepolicy/DevicePolicySecondaryUserTest.xml
deleted file mode 100644
index 798f52e..0000000
--- a/tests/devicepolicy/DevicePolicySecondaryUserTest.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?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 Device Policy test cases on a secondary user">
-    <option name="test-suite-tag" value="cts" />
-    <option name="config-descriptor:metadata" key="component" value="framework" />
-    <!-- Instant apps can never be device admin / profile owner / device owner so positive tests
-         here are not applicable -->
-    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
-    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
-    <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="install-arg" value="-t" />
-        <option name="test-file-name" value="CtsDevicePolicyTestCases.apk" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunOnSecondaryUserTargetPreparer">
-        <option name="test-package-name" value="android.devicepolicy.cts" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.devicepolicy.cts" />
-        <option name="include-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser" />
-        <!--        <option name="instrumentation-arg" key="skip-test-teardown" value="true" />-->
-        <option name="hidden-api-checks" value="false" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/tests/devicepolicy/DevicePolicyWorkProfileTest.xml b/tests/devicepolicy/DevicePolicyWorkProfileTest.xml
deleted file mode 100644
index 1e45241..0000000
--- a/tests/devicepolicy/DevicePolicyWorkProfileTest.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 Device Policy test cases on a work profile">
-    <option name="test-suite-tag" value="cts" />
-    <option name="config-descriptor:metadata" key="component" value="framework" />
-    <!-- Instant apps can never be device admin / profile owner / device owner so positive tests
-         here are not applicable -->
-    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
-    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
-    <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="install-arg" value="-t" />
-        <option name="test-file-name" value="CtsDevicePolicyTestCases.apk" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunOnWorkProfileTargetPreparer">
-        <option name="test-package-name" value="android.devicepolicy.cts" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.devicepolicy.cts" />
-        <option name="include-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile" />
-<!--        <option name="instrumentation-arg" key="skip-test-teardown" value="true" />-->
-        <option name="hidden-api-checks" value="false" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/tests/devicestate/AndroidTest.xml b/tests/devicestate/AndroidTest.xml
index 3b7eadd..ca0266c 100644
--- a/tests/devicestate/AndroidTest.xml
+++ b/tests/devicestate/AndroidTest.xml
@@ -39,10 +39,4 @@
         <option name="collect-on-run-ended-only" value="true" />
         <option name="clean-up" value="false" />
     </metrics_collector>
-    <!-- Automotive tests run on user 10 -->
-    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
-        <option name="directory-keys" value="/storage/emulated/10/CtsDeviceStateManagerTestCases" />
-        <option name="collect-on-run-ended-only" value="true" />
-        <option name="clean-up" value="false" />
-    </metrics_collector>
 </configuration>
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index 6789804..6ce8352 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -258,7 +258,10 @@
              android:launchMode="singleTask"
              android:taskAffinity=".t1"/>
         <activity android:name="android.server.wm.intent.Activities$SingleInstancePerTaskActivity"
-                  android:launchMode="singleInstancePerTask"/>
+             android:launchMode="singleInstancePerTask"/>
+        <activity android:name="android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity"
+             android:launchMode="singleInstancePerTask"
+             android:documentLaunchMode="never"/>
         <activity android:name="android.server.wm.intent.Activities$TaskAffinity1Activity"
              android:allowTaskReparenting="true"
              android:launchMode="standard"
@@ -475,6 +478,15 @@
             <meta-data android:name="android.supports_size_changes"
                        android:value="true"/>
         </activity>
+
+        <service android:name="android.server.wm.WindowContextTests$TestWindowService"
+                 android:exported="true"
+                 android:enabled="true" />
+        <activity android:name="android.server.wm.WindowContextTests$TestActivity"
+                  android:exported="true"
+                  android:resizeableActivity="true"
+                  android:supportsPictureInPicture="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density|touchscreen"/>
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/framework/base/windowmanager/intent_tests/singleInstancePerTask/test-10.json b/tests/framework/base/windowmanager/intent_tests/singleInstancePerTask/test-10.json
new file mode 100644
index 0000000..4d3da8d
--- /dev/null
+++ b/tests/framework/base/windowmanager/intent_tests/singleInstancePerTask/test-10.json
@@ -0,0 +1,45 @@
+{
+    "comment": "Verify the SingleInstancePerTask with documentLaunchMode-never Activity won't be started in new task via NEW_DOCUMENT",
+    "setup": {
+        "initialIntents": [
+            {
+                "flags": "FLAG_ACTIVITY_NEW_TASK",
+                "class": "android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                "package": "android.server.wm.cts",
+                "startForResult": false
+            }
+        ],
+        "act": [
+            {
+                "flags": "FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT",
+                "class": "android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                "package": "android.server.wm.cts",
+                "startForResult": false
+            }
+        ]
+    },
+    "initialState": {
+        "tasks": [
+            {
+                "activities": [
+                    {
+                        "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                        "state": "RESUMED"
+                    }
+                ]
+            }
+        ]
+    },
+    "endState": {
+        "tasks": [
+            {
+                "activities": [
+                    {
+                        "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                        "state": "RESUMED"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/singleInstancePerTask/test-11.json b/tests/framework/base/windowmanager/intent_tests/singleInstancePerTask/test-11.json
new file mode 100644
index 0000000..fe99a1b
--- /dev/null
+++ b/tests/framework/base/windowmanager/intent_tests/singleInstancePerTask/test-11.json
@@ -0,0 +1,45 @@
+{
+    "comment": "Verify the SingleInstancePerTask with documentLaunchMode-never Activity won't be started in new task via NEW_DOCUMENT and MULTIPLE_TASK",
+    "setup": {
+        "initialIntents": [
+            {
+                "flags": "FLAG_ACTIVITY_NEW_TASK",
+                "class": "android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                "package": "android.server.wm.cts",
+                "startForResult": false
+            }
+        ],
+        "act": [
+            {
+                "flags": "FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK",
+                "class": "android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                "package": "android.server.wm.cts",
+                "startForResult": false
+            }
+        ]
+    },
+    "initialState": {
+        "tasks": [
+            {
+                "activities": [
+                    {
+                        "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                        "state": "RESUMED"
+                    }
+                ]
+            }
+        ]
+    },
+    "endState": {
+        "tasks": [
+            {
+                "activities": [
+                    {
+                        "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                        "state": "RESUMED"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/singleInstancePerTask/test-12.json b/tests/framework/base/windowmanager/intent_tests/singleInstancePerTask/test-12.json
new file mode 100644
index 0000000..46616b3
--- /dev/null
+++ b/tests/framework/base/windowmanager/intent_tests/singleInstancePerTask/test-12.json
@@ -0,0 +1,53 @@
+{
+    "comment": "Verify the SingleInstancePerTask with documentLaunchMode-never Activity can be created in a new task with MULTIPLE_TASK flag",
+    "setup": {
+        "initialIntents": [
+            {
+                "flags": "FLAG_ACTIVITY_NEW_TASK",
+                "class": "android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                "package": "android.server.wm.cts",
+                "startForResult": false
+            }
+        ],
+        "act": [
+            {
+                "flags": "FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK",
+                "class": "android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                "package": "android.server.wm.cts",
+                "startForResult": false
+            }
+        ]
+    },
+    "initialState": {
+        "tasks": [
+            {
+                "activities": [
+                    {
+                        "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                        "state": "RESUMED"
+                    }
+                ]
+            }
+        ]
+    },
+    "endState": {
+        "tasks": [
+            {
+                "activities": [
+                    {
+                        "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                        "state": "RESUMED"
+                    }
+                ]
+            },
+            {
+                "activities": [
+                    {
+                        "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstancePerTaskDocumentNeverActivity",
+                        "state": "STOPPED"
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index f5cd8f1..4fc4c3a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -81,6 +81,7 @@
 import static org.hamcrest.Matchers.lessThan;
 import static org.hamcrest.Matchers.lessThanOrEqualTo;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
@@ -167,14 +168,14 @@
     }
 
     @Test
-    public void testMinimumDeviceSize() throws Exception {
+    public void testMinimumDeviceSize() {
         mWmState.assertDeviceDefaultDisplaySizeForMultiWindow(
                 "Devices supporting picture-in-picture must be larger than the default minimum"
                         + " task size");
     }
 
     @Test
-    public void testEnterPictureInPictureMode() throws Exception {
+    public void testEnterPictureInPictureMode() {
         pinnedStackTester(getAmStartCmd(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true")),
                 PIP_ACTIVITY, PIP_ACTIVITY, false /* isFocusable */);
     }
@@ -182,7 +183,7 @@
     // This test is black-listed in cts-known-failures.xml (b/35314835).
     @Ignore
     @Test
-    public void testAlwaysFocusablePipActivity() throws Exception {
+    public void testAlwaysFocusablePipActivity() {
         pinnedStackTester(getAmStartCmd(ALWAYS_FOCUSABLE_PIP_ACTIVITY),
                 ALWAYS_FOCUSABLE_PIP_ACTIVITY, ALWAYS_FOCUSABLE_PIP_ACTIVITY,
                 true /* isFocusable */);
@@ -191,14 +192,14 @@
     // This test is black-listed in cts-known-failures.xml (b/35314835).
     @Ignore
     @Test
-    public void testLaunchIntoPinnedStack() throws Exception {
+    public void testLaunchIntoPinnedStack() {
         pinnedStackTester(getAmStartCmd(LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY),
                 LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY, ALWAYS_FOCUSABLE_PIP_ACTIVITY,
                 true /* isFocusable */);
     }
 
     @Test
-    public void testNonTappablePipActivity() throws Exception {
+    public void testNonTappablePipActivity() {
         // Launch the tap-to-finish activity at a specific place
         launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"),
                 extraString(EXTRA_TAP_TO_FINISH, "true"));
@@ -239,7 +240,7 @@
     }
 
     @Test
-    public void testEnterPipToOtherOrientation() throws Exception {
+    public void testEnterPipToOtherOrientation() {
         // Launch a portrait only app on the fullscreen stack
         launchActivity(TEST_ACTIVITY,
                 extraString(EXTRA_FIXED_ORIENTATION, String.valueOf(ORIENTATION_PORTRAIT)));
@@ -280,7 +281,7 @@
 
     @Test
     @SecurityTest(minPatchLevel="2021-03")
-    public void testEnterPipWithTinyMinimalSize() throws Exception {
+    public void testEnterPipWithTinyMinimalSize() {
         // Launch a PiP activity with minimal size specified and smaller than allowed minimum
         launchActivity(PIP_ACTIVITY_WITH_TINY_MINIMAL_SIZE, extraString(EXTRA_ENTER_PIP, "true"));
         // Wait for animation complete since we are comparing size
@@ -303,16 +304,16 @@
     }
 
     @Test
-    public void testEnterPipAspectRatioMin() throws Exception {
+    public void testEnterPipAspectRatioMin() {
         testEnterPipAspectRatio(MIN_ASPECT_RATIO_NUMERATOR, MIN_ASPECT_RATIO_DENOMINATOR);
     }
 
     @Test
-    public void testEnterPipAspectRatioMax() throws Exception {
+    public void testEnterPipAspectRatioMax() {
         testEnterPipAspectRatio(MAX_ASPECT_RATIO_NUMERATOR, MAX_ASPECT_RATIO_DENOMINATOR);
     }
 
-    private void testEnterPipAspectRatio(int num, int denom) throws Exception {
+    private void testEnterPipAspectRatio(int num, int denom) {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -331,16 +332,16 @@
     }
 
     @Test
-    public void testResizePipAspectRatioMin() throws Exception {
+    public void testResizePipAspectRatioMin() {
         testResizePipAspectRatio(MIN_ASPECT_RATIO_NUMERATOR, MIN_ASPECT_RATIO_DENOMINATOR);
     }
 
     @Test
-    public void testResizePipAspectRatioMax() throws Exception {
+    public void testResizePipAspectRatioMax() {
         testResizePipAspectRatio(MAX_ASPECT_RATIO_NUMERATOR, MAX_ASPECT_RATIO_DENOMINATOR);
     }
 
-    private void testResizePipAspectRatio(int num, int denom) throws Exception {
+    private void testResizePipAspectRatio(int num, int denom) {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -357,18 +358,18 @@
     }
 
     @Test
-    public void testEnterPipExtremeAspectRatioMin() throws Exception {
+    public void testEnterPipExtremeAspectRatioMin() {
         testEnterPipExtremeAspectRatio(MIN_ASPECT_RATIO_NUMERATOR,
                 BELOW_MIN_ASPECT_RATIO_DENOMINATOR);
     }
 
     @Test
-    public void testEnterPipExtremeAspectRatioMax() throws Exception {
+    public void testEnterPipExtremeAspectRatioMax() {
         testEnterPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO_NUMERATOR,
                 MAX_ASPECT_RATIO_DENOMINATOR);
     }
 
-    private void testEnterPipExtremeAspectRatio(int num, int denom) throws Exception {
+    private void testEnterPipExtremeAspectRatio(int num, int denom) {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -381,18 +382,18 @@
     }
 
     @Test
-    public void testSetPipExtremeAspectRatioMin() throws Exception {
+    public void testSetPipExtremeAspectRatioMin() {
         testSetPipExtremeAspectRatio(MIN_ASPECT_RATIO_NUMERATOR,
                 BELOW_MIN_ASPECT_RATIO_DENOMINATOR);
     }
 
     @Test
-    public void testSetPipExtremeAspectRatioMax() throws Exception {
+    public void testSetPipExtremeAspectRatioMax() {
         testSetPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO_NUMERATOR,
                 MAX_ASPECT_RATIO_DENOMINATOR);
     }
 
-    private void testSetPipExtremeAspectRatio(int num, int denom) throws Exception {
+    private void testSetPipExtremeAspectRatio(int num, int denom) {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -415,7 +416,7 @@
     }
 
     @Test
-    public void testDisallowPipLaunchFromStoppedActivity() throws Exception {
+    public void testDisallowPipLaunchFromStoppedActivity() {
         // Launch the bottom pip activity which will launch a new activity on top and attempt to
         // enter pip when it is stopped
         launchActivity(PIP_ON_STOP_ACTIVITY);
@@ -428,7 +429,7 @@
     }
 
     @Test
-    public void testAutoEnterPictureInPicture() throws Exception {
+    public void testAutoEnterPictureInPicture() {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -444,7 +445,7 @@
 
     @Test
     public void testAutoEnterPictureInPictureOnUserLeaveHintWhenPipRequestedNotOverridden()
-            throws Exception {
+            {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -477,7 +478,7 @@
     }
 
     @Test
-    public void testAutoEnterPictureInPictureOnPictureInPictureRequested() throws Exception {
+    public void testAutoEnterPictureInPictureOnPictureInPictureRequested() {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -509,7 +510,7 @@
     }
 
     @Test
-    public void testAutoEnterPictureInPictureLaunchActivity() throws Exception {
+    public void testAutoEnterPictureInPictureLaunchActivity() {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -529,7 +530,7 @@
     }
 
     @Test
-    public void testAutoEnterPictureInPictureFinish() throws Exception {
+    public void testAutoEnterPictureInPictureFinish() {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -543,7 +544,7 @@
     }
 
     @Test
-    public void testAutoEnterPictureInPictureAspectRatio() throws Exception {
+    public void testAutoEnterPictureInPictureAspectRatio() {
         // Launch the PIP activity on pause, and set the aspect ratio
         launchActivity(PIP_ACTIVITY,
                 extraString(EXTRA_ENTER_PIP_ON_PAUSE, "true"),
@@ -565,7 +566,7 @@
     }
 
     @Test
-    public void testAutoEnterPictureInPictureOverPip() throws Exception {
+    public void testAutoEnterPictureInPictureOverPip() {
         // Launch another PIP activity
         launchActivity(LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY);
         waitForEnterPip(ALWAYS_FOCUSABLE_PIP_ACTIVITY);
@@ -585,7 +586,7 @@
     }
 
     @Test
-    public void testDismissPipWhenLaunchNewOne() throws Exception {
+    public void testDismissPipWhenLaunchNewOne() {
         // Launch another PIP activity
         launchActivity(LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY);
         waitForEnterPip(ALWAYS_FOCUSABLE_PIP_ACTIVITY);
@@ -599,7 +600,7 @@
     }
 
     @Test
-    public void testDisallowMultipleTasksInPinnedStack() throws Exception {
+    public void testDisallowMultipleTasksInPinnedStack() {
         // Launch a test activity so that we have multiple fullscreen tasks
         launchActivity(TEST_ACTIVITY);
 
@@ -622,7 +623,7 @@
     }
 
     @Test
-    public void testPipUnPipOverHome() throws Exception {
+    public void testPipUnPipOverHome() {
         // Launch a task behind home to assert that the next fullscreen task isn't visible when
         // leaving PiP.
         launchActivity(TEST_ACTIVITY);
@@ -643,7 +644,7 @@
     }
 
     @Test
-    public void testPipUnPipOverApp() throws Exception {
+    public void testPipUnPipOverApp() {
         // Launch a test activity so that we're not over home
         launchActivity(TEST_ACTIVITY);
 
@@ -661,7 +662,7 @@
     }
 
     @Test
-    public void testRemovePipWithNoFullscreenOrFreeformStack() throws Exception {
+    public void testRemovePipWithNoFullscreenOrFreeformStack() {
         // Launch a pip activity
         launchActivity(PIP_ACTIVITY);
         int windowingMode = mWmState.getTaskByActivity(PIP_ACTIVITY).getWindowingMode();
@@ -675,7 +676,7 @@
     }
 
     @Test
-    public void testRemovePipWithVisibleFullscreenOrFreeformStack() throws Exception {
+    public void testRemovePipWithVisibleFullscreenOrFreeformStack() {
         // Launch a fullscreen/freeform activity, and a pip activity over that
         launchActivity(TEST_ACTIVITY);
         launchActivity(PIP_ACTIVITY);
@@ -691,7 +692,7 @@
     }
 
     @Test
-    public void testRemovePipWithHiddenFullscreenOrFreeformStack() throws Exception {
+    public void testRemovePipWithHiddenFullscreenOrFreeformStack() {
         // Launch a fullscreen/freeform activity, return home and while the fullscreen/freeform
         // stack is hidden, launch a pip activity over home
         launchActivity(TEST_ACTIVITY);
@@ -708,7 +709,7 @@
     }
 
     @Test
-    public void testMovePipToBackWithNoFullscreenOrFreeformStack() throws Exception {
+    public void testMovePipToBackWithNoFullscreenOrFreeformStack() {
         // Start with a clean slate, remove all the stacks but home
         removeRootTasksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
 
@@ -725,7 +726,7 @@
     }
 
     @Test
-    public void testMovePipToBackWithVisibleFullscreenOrFreeformStack() throws Exception {
+    public void testMovePipToBackWithVisibleFullscreenOrFreeformStack() {
         // Launch a fullscreen/freeform activity, and a pip activity over that
         launchActivity(TEST_ACTIVITY);
         launchActivity(PIP_ACTIVITY);
@@ -741,7 +742,7 @@
     }
 
     @Test
-    public void testMovePipToBackWithHiddenFullscreenOrFreeformStack() throws Exception {
+    public void testMovePipToBackWithHiddenFullscreenOrFreeformStack() {
         // Launch a fullscreen/freeform activity, return home and while the fullscreen/freeform
         // stack is hidden, launch a pip activity over home
         launchActivity(TEST_ACTIVITY);
@@ -758,7 +759,7 @@
     }
 
     @Test
-    public void testPinnedStackAlwaysOnTop() throws Exception {
+    public void testPinnedStackAlwaysOnTop() {
         // Launch activity into pinned stack and assert it's on top.
         launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
         waitForEnterPip(PIP_ACTIVITY);
@@ -777,7 +778,7 @@
     }
 
     @Test
-    public void testAppOpsDenyPipOnPause() throws Exception {
+    public void testAppOpsDenyPipOnPause() {
         try (final AppOpsSession appOpsSession = new AppOpsSession(PIP_ACTIVITY)) {
             // Disable enter-pip and try to enter pip
             appOpsSession.setOpToMode(APP_OPS_OP_ENTER_PICTURE_IN_PICTURE, APP_OPS_MODE_IGNORED);
@@ -793,15 +794,60 @@
     }
 
     @Test
-    public void testEnterPipFromTaskWithMultipleActivities() throws Exception {
+    public void testEnterPipFromTaskWithMultipleActivities() {
         // Try to enter picture-in-picture from an activity that has more than one activity in the
         // task and ensure that it works
         launchActivity(LAUNCH_ENTER_PIP_ACTIVITY);
         waitForEnterPip(PIP_ACTIVITY);
+
+        final ActivityTask task = mWmState.getTaskByActivity(LAUNCH_ENTER_PIP_ACTIVITY);
+        assertEquals(1, task.mActivities.size());
         assertPinnedStackExists();
     }
 
     @Test
+    public void testPipFromTaskWithMultipleActivitiesAndExpandPip() {
+        // Try to enter picture-in-picture from an activity that has more than one activity in the
+        // task and ensure pinned task can go back to its original task when expand to fullscreen
+        launchActivity(LAUNCH_ENTER_PIP_ACTIVITY);
+        waitForEnterPip(PIP_ACTIVITY);
+
+        mBroadcastActionTrigger.expandPip();
+        waitForExitPipToFullscreen(PIP_ACTIVITY);
+
+        final ActivityTask task = mWmState.getTaskByActivity(LAUNCH_ENTER_PIP_ACTIVITY);
+        assertEquals(2, task.mActivities.size());
+    }
+
+    @Test
+    public void testPipFromTaskWithMultipleActivitiesAndDismissPip() {
+        // Try to enter picture-in-picture from an activity that has more than one activity in the
+        // task and ensure flags on original task get reset after dismissing pip
+        launchActivity(LAUNCH_ENTER_PIP_ACTIVITY);
+        waitForEnterPip(PIP_ACTIVITY);
+
+        mBroadcastActionTrigger.doAction(ACTION_FINISH);
+        waitForPinnedStackRemoved();
+
+        final ActivityTask task = mWmState.getTaskByActivity(LAUNCH_ENTER_PIP_ACTIVITY);
+        assertFalse(task.mHasChildPipActivity);
+    }
+
+    @Test
+    public void testPipFromTaskWithMultipleActivitiesAndRemoveOriginalTask() {
+        // Try to enter picture-in-picture from an activity that has more than one activity in the
+        // task and ensure pinned task is removed when the original task vanishes
+        launchActivity(LAUNCH_ENTER_PIP_ACTIVITY);
+        waitForEnterPip(PIP_ACTIVITY);
+
+        final int originalTaskId = mWmState.getTaskByActivity(LAUNCH_ENTER_PIP_ACTIVITY).mTaskId;
+        removeRootTask(originalTaskId);
+        waitForPinnedStackRemoved();
+
+        assertPinnedStackDoesNotExist();
+    }
+
+    @Test
     public void testLaunchStoppedActivityWithPiPInSameProcessPreQ() {
         // Try to enter picture-in-picture from an activity that has more than one activity in the
         // task and ensure that it works, for pre-Q app
@@ -826,7 +872,7 @@
     }
 
     @Test
-    public void testEnterPipWithResumeWhilePausingActivityNoStop() throws Exception {
+    public void testEnterPipWithResumeWhilePausingActivityNoStop() {
         /*
          * Launch the resumeWhilePausing activity and ensure that the PiP activity did not get
          * stopped and actually went into the pinned stack.
@@ -854,7 +900,7 @@
     }
 
     @Test
-    public void testDisallowEnterPipActivityLocked() throws Exception {
+    public void testDisallowEnterPipActivityLocked() {
         launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP_ON_PAUSE, "true"));
         ActivityTask task = mWmState.getStackByActivity(PIP_ACTIVITY);
 
@@ -879,7 +925,7 @@
     }
 
     @Test
-    public void testConfigurationChangeOrderDuringTransition() throws Exception {
+    public void testConfigurationChangeOrderDuringTransition() {
         // Launch a PiP activity and ensure configuration change only happened once, and that the
         // configuration change happened after the picture-in-picture and multi-window callbacks
         launchActivity(PIP_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
@@ -960,7 +1006,7 @@
     }
 
     @Test
-    public void testStopBeforeMultiWindowCallbacksOnDismiss() throws Exception {
+    public void testStopBeforeMultiWindowCallbacksOnDismiss() {
         // Launch a PiP activity
         launchActivity(PIP_ACTIVITY);
         int windowingMode = mWmState.getTaskByActivity(PIP_ACTIVITY).getWindowingMode();
@@ -1001,7 +1047,7 @@
     }
 
     @Test
-    public void testPreventSetAspectRatioWhileExpanding() throws Exception {
+    public void testPreventSetAspectRatioWhileExpanding() {
         // Launch the PiP activity
         launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
         waitForEnterPip(PIP_ACTIVITY);
@@ -1014,7 +1060,7 @@
     }
 
     @Test
-    public void testSetRequestedOrientationWhilePinned() throws Exception {
+    public void testSetRequestedOrientationWhilePinned() {
         assumeTrue("Skipping test: no orientation request support", supportsOrientationRequest());
         // Launch the PiP activity fixed as portrait, and enter picture-in-picture
         launchActivity(PIP_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
@@ -1043,7 +1089,7 @@
     }
 
     @Test
-    public void testWindowButtonEntersPip() throws Exception {
+    public void testWindowButtonEntersPip() {
         assumeTrue(!mWmState.isHomeRecentsComponent());
 
         // Launch the PiP activity trigger the window button, ensure that we have entered PiP
@@ -1054,7 +1100,7 @@
     }
 
     @Test
-    public void testFinishPipActivityWithTaskOverlay() throws Exception {
+    public void testFinishPipActivityWithTaskOverlay() {
         // Launch PiP activity
         launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
         waitForEnterPip(PIP_ACTIVITY);
@@ -1075,7 +1121,7 @@
     }
 
     @Test
-    public void testNoResumeAfterTaskOverlayFinishes() throws Exception {
+    public void testNoResumeAfterTaskOverlayFinishes() {
         // Launch PiP activity
         launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
         waitForEnterPip(PIP_ACTIVITY);
@@ -1114,7 +1160,7 @@
     }
 
     @Test
-    public void testLaunchTaskByComponentMatchMultipleTasks() throws Exception {
+    public void testLaunchTaskByComponentMatchMultipleTasks() {
         // Launch a fullscreen activity which will launch a PiP activity in a new task with the same
         // affinity
         launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
@@ -1137,7 +1183,7 @@
     }
 
     @Test
-    public void testLaunchTaskByAffinityMatchMultipleTasks() throws Exception {
+    public void testLaunchTaskByAffinityMatchMultipleTasks() {
         // Launch a fullscreen activity which will launch a PiP activity in a new task with the same
         // affinity, and also launch another activity in the same task, while finishing itself. As
         // a result, the task will not have a component matching the same activity as what it was
@@ -1169,7 +1215,7 @@
     }
 
     @Test
-    public void testLaunchTaskByAffinityMatchSingleTask() throws Exception {
+    public void testLaunchTaskByAffinityMatchSingleTask() {
         // Launch an activity into the pinned stack with a fixed affinity
         launchActivityNoWait(TEST_ACTIVITY_WITH_SAME_AFFINITY,
                 extraString(EXTRA_ENTER_PIP, "true"),
@@ -1191,7 +1237,7 @@
 
     /** Test that reported display size corresponds to fullscreen after exiting PiP. */
     @Test
-    public void testDisplayMetricsPinUnpin() throws Exception {
+    public void testDisplayMetricsPinUnpin() {
         separateTestJournal();
         launchActivity(TEST_ACTIVITY);
         final int defaultWindowingMode = mWmState
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowContextTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowContextTests.java
index 36f9890..756b1ea 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowContextTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowContextTests.java
@@ -16,9 +16,13 @@
 
 package android.server.wm;
 
+import static android.server.wm.WindowManagerTestBase.startActivity;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -29,13 +33,19 @@
 import android.content.ServiceConnection;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.os.Binder;
 import android.os.IBinder;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.Presubmit;
+import android.server.wm.WindowContextTests.TestWindowService.TestToken;
 import android.view.View;
 import android.view.WindowManager;
+import android.window.WindowProviderService;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.rule.ServiceTestRule;
 
 import org.junit.Test;
 
@@ -126,7 +136,7 @@
 
         displayMetricsSession.changeDisplayMetrics(1.2 /* sizeRatio */, 1.1 /* densityRatio */);
 
-        // verify if there is a gicallback from the window context configuration change.
+        // verify if there is a callback from the window context configuration change.
         assertTrue(callbacks.mLatch.await(4, TimeUnit.SECONDS));
         Rect bounds = callbacks.mConfiguration.windowConfiguration.getBounds();
         assertBoundsEquals(displayMetricsSession.getDisplayMetrics(), bounds);
@@ -134,6 +144,113 @@
         windowContext.unregisterComponentCallbacks(callbacks);
     }
 
+    /**
+     * Verify the {@link WindowProviderService} lifecycle:
+     * <ul>
+     *     <li>In {@link WindowProviderService#onCreate()}, register to the DisplayArea with
+     *     given value from {@link WindowProviderService#getWindowType()} and
+     *     {@link WindowProviderService#getWindowContextOptions()}} and receive a
+     *     {@link Configuration} update which matches DisplayArea's metrics.</li>
+     *     <li>After {@link WindowProviderService#attachToWindowToken(IBinder)}, the
+     *     {@link WindowProviderService} must be switched to register to the Window Token and
+     *     receive a configuration update which matches Window Token's metrics.</li>
+     * </ul>
+     */
+    @Test
+    public void testWindowProviderServiceLifecycle() throws Exception {
+        // Start an activity for WindowProviderService to attach
+        TestActivity activity = startActivity(TestActivity.class);
+        final ComponentName activityName = activity.getComponentName();
+
+        // If the device supports multi-window, make this Activity to multi-window mode.
+        // In this way, we can verify if the WindowProviderService's metrics matches
+        // the split-screen Activity's metrics, which is different from TaskDisplayArea's metrics.
+        if (supportsSplitScreenMultiWindow()) {
+            mWmState.computeState(activityName);
+
+            putActivityInPrimarySplit(activityName);
+
+            activity.waitAndAssertConfigurationChanged();
+        }
+
+        // Obtain the TestWindowService instance.
+        final Context context = ApplicationProvider.getApplicationContext();
+        final Intent intent = new Intent(context, TestWindowService.class);
+        final ServiceTestRule serviceRule = new ServiceTestRule();
+        try {
+            TestToken token = (TestToken) serviceRule.bindService(intent);
+            final TestWindowService service = token.getService();
+
+            final WindowManagerState.DisplayArea da = mWmState.getTaskDisplayArea(activityName);
+            final Rect daBounds = da.mFullConfiguration.windowConfiguration.getBounds();
+            final Rect maxDaBounds = da.mFullConfiguration.windowConfiguration.getMaxBounds();
+
+            waitAndAssertWindowMetricsBoundsMatches(service, daBounds, maxDaBounds,
+                    "WindowProviderService bounds must match DisplayArea bounds.");
+
+            // Obtain the Activity's token and attach it to TestWindowService.
+            final IBinder windowToken = activity.getWindow().getAttributes().token;
+            service.attachToWindowToken(windowToken);
+
+            final WindowManager wm = activity.getWindowManager();
+            final Rect currentBounds = wm.getCurrentWindowMetrics().getBounds();
+            final Rect maxBounds = wm.getMaximumWindowMetrics().getBounds();
+
+            // After TestWindowService attaches the Activity's token, which is also a WindowToken,
+            // it is expected to receive a config update which matches the WindowMetrics of
+            // the Activity.
+            waitAndAssertWindowMetricsBoundsMatches(service, currentBounds, maxBounds,
+                    "WindowProviderService bounds must match WindowToken bounds.");
+        } finally {
+            serviceRule.unbindService();
+        }
+    }
+
+    private void waitAndAssertWindowMetricsBoundsMatches(Context context, Rect currentBounds,
+            Rect maxBounds, String message) {
+        final WindowManager wm = context.getSystemService(WindowManager.class);
+        waitForOrFail(message, () -> {
+            final Rect currentWindowBounds = wm.getCurrentWindowMetrics().getBounds();
+            final Rect maxWindowBounds = wm.getMaximumWindowMetrics().getBounds();
+            return currentBounds.equals(currentWindowBounds) && maxBounds.equals(maxWindowBounds);
+        });
+    }
+
+    public static class TestActivity extends WindowManagerTestBase.FocusableActivity {
+        final CountDownLatch mLatch = new CountDownLatch(1);
+
+        @Override
+        public void onConfigurationChanged(@NonNull Configuration newConfig) {
+            super.onConfigurationChanged(newConfig);
+            mLatch.countDown();
+        }
+
+        private void waitAndAssertConfigurationChanged() throws Exception {
+            assertThat(mLatch.await(4, TimeUnit.SECONDS)).isTrue();
+        }
+    }
+
+    public static class TestWindowService extends WindowProviderService {
+        private final IBinder mToken = new TestToken();
+
+        @Override
+        public int getWindowType() {
+            return TYPE_APPLICATION;
+        }
+
+        @Nullable
+        @Override
+        public IBinder onBind(Intent intent) {
+            return mToken;
+        }
+
+        public class TestToken extends Binder {
+            private TestWindowService getService() {
+                return TestWindowService.this;
+            }
+        }
+    }
+
     private static class TestComponentCallbacks implements ComponentCallbacks {
         private Configuration mConfiguration;
         private CountDownLatch mLatch = new CountDownLatch(1);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/intent/Activities.java b/tests/framework/base/windowmanager/src/android/server/wm/intent/Activities.java
index a9cfac9..5dc7ffe 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/intent/Activities.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/intent/Activities.java
@@ -60,6 +60,9 @@
     public static class SingleInstancePerTaskActivity extends BaseActivity {
     }
 
+    public static class SingleInstancePerTaskDocumentNeverActivity extends BaseActivity {
+    }
+
     public static class TaskAffinity1Activity extends BaseActivity {
     }
 
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index 1a575bc..43f1fe9 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -379,6 +379,10 @@
                     .putExtra(EXTRA_DISMISS_KEYGUARD_METHOD, true));
         }
 
+        void expandPip() {
+            mContext.sendBroadcast(createIntentWithAction(ACTION_EXPAND_PIP));
+        }
+
         void expandPipWithAspectRatio(String extraNum, String extraDenom) {
             mContext.sendBroadcast(createIntentWithAction(ACTION_EXPAND_PIP)
                     .putExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR, extraNum)
@@ -691,6 +695,11 @@
         waitForIdle();
     }
 
+    protected void removeRootTask(int taskId) {
+        runWithShellPermission(() -> mAtm.removeTask(taskId));
+        waitForIdle();
+    }
+
     public static String executeShellCommand(String command) {
         log("Shell command: " + command);
         try {
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
index 4d63091..7cb7164 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
@@ -1292,6 +1292,7 @@
         private int mSurfaceHeight;
         boolean mCreatedByOrganizer;
         String mAffinity;
+        boolean mHasChildPipActivity;
 
         ActivityTask(TaskProto proto) {
             super(proto.windowContainer);
@@ -1312,6 +1313,7 @@
             mSurfaceHeight = proto.surfaceHeight;
             mCreatedByOrganizer = proto.createdByOrganizer;
             mAffinity = proto.affinity;
+            mHasChildPipActivity = proto.hasChildPipActivity;
 
             if (proto.resumedActivity != null) {
                 mResumedActivity = proto.resumedActivity.title;
diff --git a/tests/netlegacy22.api/TEST_MAPPING b/tests/netlegacy22.api/TEST_MAPPING
new file mode 100644
index 0000000..38a8470
--- /dev/null
+++ b/tests/netlegacy22.api/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "postsubmit": [
+    {
+      "name": "CtsNetTestCasesLegacyApi22"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java b/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
index f74a027..4c0a31a 100644
--- a/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
+++ b/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
@@ -42,7 +42,7 @@
         runWithTestResultObserver(mResultObserver -> {
 
             ApiComplianceChecker complianceChecker =
-                    new ApiComplianceChecker(mResultObserver, classProvider);
+                    new ApiComplianceChecker(mResultObserver, mClassProvider);
 
             ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
 
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
index 1e96910..9707dd8 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
@@ -26,17 +26,13 @@
 import android.signature.cts.VirtualPath.LocalFilePath;
 import android.signature.cts.VirtualPath.ResourcePath;
 import android.util.Log;
-import java.io.File;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.util.EnumSet;
 import java.util.stream.Stream;
 import java.util.zip.ZipFile;
 import repackaged.android.test.InstrumentationTestCase;
@@ -50,7 +46,7 @@
 
     private TestResultObserver mResultObserver;
 
-    ClassProvider classProvider;
+    ClassProvider mClassProvider;
 
     protected String getGlobalExemptions() {
         return Settings.Global.getString(
@@ -90,7 +86,7 @@
         // out known inaccessible classes.
         // Note that com.android.internal.R.* inner classes are also excluded as they are
         // not part of API though exist in the runtime.
-        classProvider = new ExcludingClassProvider(
+        mClassProvider = new ExcludingClassProvider(
                 new BootClassPathClassesProvider(),
                 name -> name != null && name.startsWith("com.android.internal.R."));
 
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
index 2337ced..10907d0 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
@@ -18,8 +18,6 @@
 
 import java.util.function.Predicate;
 
-import android.os.Bundle;
-import android.provider.Settings;
 import android.signature.cts.DexField;
 import android.signature.cts.DexMember;
 import android.signature.cts.DexMemberChecker;
@@ -127,8 +125,8 @@
                 }
 
             };
-            classProvider.getAllClasses().forEach(klass -> {
-                classProvider.getAllMembers(klass)
+            mClassProvider.getAllClasses().forEach(klass -> {
+                mClassProvider.getAllMembers(klass)
                         .filter(memberFilter)
                         .forEach(member -> {
                             DexMemberChecker.checkSingleMember(member, reflection, jni, observer);
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
index 440430d..2ef70ca 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
@@ -58,7 +58,7 @@
         runWithTestResultObserver(mResultObserver -> {
             Set<JDiffClassDescription> unexpectedClasses = loadUnexpectedClasses();
             for (JDiffClassDescription classDescription : unexpectedClasses) {
-                Class<?> unexpectedClass = findUnexpectedClass(classDescription, classProvider);
+                Class<?> unexpectedClass = findUnexpectedClass(classDescription, mClassProvider);
                 if (unexpectedClass != null) {
                     mResultObserver.notifyFailure(
                             FailureType.UNEXPECTED_CLASS,
@@ -68,7 +68,7 @@
             }
 
             ApiComplianceChecker complianceChecker =
-                    new ApiComplianceChecker(mResultObserver, classProvider);
+                    new ApiComplianceChecker(mResultObserver, mClassProvider);
 
             // Load classes from any API files that form the base which the expected APIs extend.
             loadBaseClasses(complianceChecker);
diff --git a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
index efefdd5..3090d60 100644
--- a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
+++ b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
@@ -36,13 +36,13 @@
 
     private static final String TAG = AnnotationTest.class.getSimpleName();
 
-    private String[] expectedApiFiles;
-    private String annotationForExactMatch;
+    private String[] mExpectedApiFiles;
+    private String mAnnotationForExactMatch;
 
     @Override
     protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
-        expectedApiFiles = getCommaSeparatedList(instrumentationArgs, "expected-api-files");
-        annotationForExactMatch = instrumentationArgs.getString("annotation-for-exact-match");
+        mExpectedApiFiles = getCommaSeparatedList(instrumentationArgs, "expected-api-files");
+        mAnnotationForExactMatch = instrumentationArgs.getString("annotation-for-exact-match");
     }
 
     /**
@@ -78,11 +78,11 @@
             };
             runWithTestResultObserver(resultObserver -> {
                 AnnotationChecker complianceChecker = new AnnotationChecker(resultObserver,
-                        classProvider, annotationForExactMatch, filter);
+                        mClassProvider, mAnnotationForExactMatch, filter);
 
                 ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
 
-                parseApiResourcesAsStream(apiDocumentParser, expectedApiFiles)
+                parseApiResourcesAsStream(apiDocumentParser, mExpectedApiFiles)
                         .forEach(complianceChecker::checkSignatureCompliance);
 
                 // After done parsing all expected API files, perform any deferred checks.
diff --git a/tests/tests/carrierapi/Android.bp b/tests/tests/carrierapi/Android.bp
index 5f5b61d..32b10e5 100644
--- a/tests/tests/carrierapi/Android.bp
+++ b/tests/tests/carrierapi/Android.bp
@@ -21,8 +21,8 @@
     defaults: ["cts_defaults"],
     static_libs: [
         "androidx.test.uiautomator_uiautomator",
-        "ctstestrunner-axt",
         "compatibility-device-util-axt",
+        "ctstestrunner-axt",
         "junit",
         "truth-prebuilt",
     ],
@@ -34,8 +34,8 @@
         "general-tests",
     ],
     libs: [
-        "android.test.runner",
         "android.test.base",
+        "android.test.runner",
     ],
     // This  APK must be signed to match the test SIM's cert whitelist.
     // While "testkey" is the default, there are different per-device testkeys, so
diff --git a/tests/tests/carrierapi/AndroidTest.xml b/tests/tests/carrierapi/AndroidTest.xml
index 8d1174b..9b6d4fe 100644
--- a/tests/tests/carrierapi/AndroidTest.xml
+++ b/tests/tests/carrierapi/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Carrier APIs test cases">
-  <option name="test-suite-tag" value="cts" />
+    <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/ApnDatabaseTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/ApnDatabaseTest.java
index 91ba3fc..59794c5 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/ApnDatabaseTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/ApnDatabaseTest.java
@@ -15,22 +15,19 @@
  */
 package android.carrierapi.cts;
 
-import static junit.framework.TestCase.assertEquals;
+import static com.google.common.truth.Truth.assertWithMessage;
 
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.fail;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
-import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
 import android.provider.Telephony.Carriers;
 import android.util.Log;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
@@ -42,17 +39,16 @@
 import java.util.Map;
 
 /**
- * Build, install and run the tests by running the commands below:
- *  make cts -j64
- *  cts-tradefed run cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.ApnDatabaseTest
+ * Unit tests for the APN database exposed by {@link Carriers}.
+ *
+ * <p>Test using `atest CtsCarrierApiTestCases:ApnDatabaseTest` or `make cts -j64 && cts-tradefed
+ * run cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.ApnDatabaseTest`
  */
 @RunWith(AndroidJUnit4.class)
-public class ApnDatabaseTest {
+public class ApnDatabaseTest extends BaseCarrierApiTest {
     private static final String TAG = "ApnDatabaseTest";
 
     private ContentResolver mContentResolver;
-    private PackageManager mPackageManager;
-    private boolean mHasCellular;
 
     private static final String NAME = "carrierName";
     private static final String APN = "apn";
@@ -72,25 +68,28 @@
     private static final String NETWORK_TYPE_BITMASK = "0";
     private static final String BEARER = "0";
 
-    private static final Map<String, String> APN_MAP = new HashMap<String,String>() {{
-        put(Carriers.NAME, NAME);
-        put(Carriers.APN, APN);
-        put(Carriers.PROXY, PROXY);
-        put(Carriers.PORT, PORT);
-        put(Carriers.MMSC, MMSC);
-        put(Carriers.MMSPROXY, MMSPROXY);
-        put(Carriers.MMSPORT, MMSPORT);
-        put(Carriers.NUMERIC, NUMERIC);
-        put(Carriers.USER, USER);
-        put(Carriers.PASSWORD, PASSWORD);
-        put(Carriers.AUTH_TYPE, AUTH_TYPE);
-        put(Carriers.TYPE, TYPE);
-        put(Carriers.PROTOCOL, PROTOCOL);
-        put(Carriers.ROAMING_PROTOCOL, ROAMING_PROTOCOL);
-        put(Carriers.CARRIER_ENABLED, CARRIER_ENABLED);
-        put(Carriers.NETWORK_TYPE_BITMASK, NETWORK_TYPE_BITMASK);
-        put(Carriers.BEARER, BEARER);
-    }};
+    private static final Map<String, String> APN_MAP =
+            new HashMap<String, String>() {
+                {
+                    put(Carriers.NAME, NAME);
+                    put(Carriers.APN, APN);
+                    put(Carriers.PROXY, PROXY);
+                    put(Carriers.PORT, PORT);
+                    put(Carriers.MMSC, MMSC);
+                    put(Carriers.MMSPROXY, MMSPROXY);
+                    put(Carriers.MMSPORT, MMSPORT);
+                    put(Carriers.NUMERIC, NUMERIC);
+                    put(Carriers.USER, USER);
+                    put(Carriers.PASSWORD, PASSWORD);
+                    put(Carriers.AUTH_TYPE, AUTH_TYPE);
+                    put(Carriers.TYPE, TYPE);
+                    put(Carriers.PROTOCOL, PROTOCOL);
+                    put(Carriers.ROAMING_PROTOCOL, ROAMING_PROTOCOL);
+                    put(Carriers.CARRIER_ENABLED, CARRIER_ENABLED);
+                    put(Carriers.NETWORK_TYPE_BITMASK, NETWORK_TYPE_BITMASK);
+                    put(Carriers.BEARER, BEARER);
+                }
+            };
 
     // Faked network type bitmask and its compatible bearer bitmask.
     private static final int NETWORK_TYPE_BITMASK_NUMBER = 1 << (13 - 1);
@@ -98,29 +97,16 @@
 
     @Before
     public void setUp() throws Exception {
-        mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
-        mPackageManager = InstrumentationRegistry.getContext().getPackageManager();
-        // Checks whether the cellular stack should be running on this device.
-        mHasCellular = mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
-        if (!mHasCellular) {
-            Log.e(TAG, "No cellular support, all tests will be skipped.");
-        }
-    }
-
-    private void failMessage() {
-        fail("This test requires a SIM card with carrier privilege rule on it.\n" +
-                "Visit https://source.android.com/devices/tech/config/uicc.html");
+        mContentResolver = getContext().getContentResolver();
     }
 
     /**
-     * Test inserting, querying, updating and deleting values in carriers table.
-     * Verify that the inserted values match the result of the query and are deleted.
+     * Test inserting, querying, updating and deleting values in carriers table. Verify that the
+     * inserted values match the result of the query and are deleted.
      */
     @Test
     public void testValidCase() {
-        if (!mHasCellular) return;
         Uri uri = Carriers.CONTENT_URI;
-        // CONTENT_URI = Uri.parse("content://telephony/carriers");
         // Create A set of column_name/value pairs to add to the database.
         ContentValues contentValues = makeDefaultContentValues();
 
@@ -128,69 +114,84 @@
             // Insert the value into database.
             Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues.toString());
             Uri newUri = mContentResolver.insert(uri, contentValues);
-            assertNotNull("Failed to insert to table", newUri);
+            assertWithMessage("Failed to insert to table").that(newUri).isNotNull();
 
             // Get the values in table.
             final String selection = Carriers.NUMERIC + "=?";
-            String[] selectionArgs = { NUMERIC };
+            String[] selectionArgs = {NUMERIC};
             String[] apnProjection = APN_MAP.keySet().toArray(new String[APN_MAP.size()]);
-            Log.d(TAG, "testInsertCarriers query projection: " + Arrays.toString(apnProjection)
-                    + "\ntestInsertCarriers selection: " + selection
-                    + "\ntestInsertCarriers selectionArgs: " + Arrays.toString(selectionArgs));
-            Cursor cursor = mContentResolver.query(
-                    uri, apnProjection, selection, selectionArgs, null);
+            Log.d(
+                    TAG,
+                    "testInsertCarriers query projection: "
+                            + Arrays.toString(apnProjection)
+                            + "\ntestInsertCarriers selection: "
+                            + selection
+                            + "\ntestInsertCarriers selectionArgs: "
+                            + Arrays.toString(selectionArgs));
+            Cursor cursor =
+                    mContentResolver.query(uri, apnProjection, selection, selectionArgs, null);
 
             // Verify that the inserted value match the results of the query
-            assertNotNull("Failed to query the table", cursor);
-            assertEquals("Unexpected number of APNs returned by cursor",
-                    1, cursor.getCount());
+            assertWithMessage("Failed to query the table").that(cursor).isNotNull();
+            assertWithMessage("Unexpected number of APNs returned by cursor")
+                    .that(cursor.getCount())
+                    .isEqualTo(1);
             cursor.moveToFirst();
-            for (Map.Entry<String, String> entry: APN_MAP.entrySet()) {
-                assertEquals(
-                        "Unexpected value returned by cursor",
-                        cursor.getString(cursor.getColumnIndex(entry.getKey())), entry.getValue());
+            for (Map.Entry<String, String> entry : APN_MAP.entrySet()) {
+                assertWithMessage("Unexpected value returned by cursor")
+                        .that(cursor.getString(cursor.getColumnIndex(entry.getKey())))
+                        .isEqualTo(entry.getValue());
             }
 
             // update the apn
             final String newApn = "newapn";
             Log.d(TAG, "Update the APN field to: " + newApn);
             contentValues.put(Carriers.APN, newApn);
-            final int updateCount = mContentResolver.update(uri, contentValues, selection,
-                    selectionArgs);
-            assertEquals("Unexpected number of rows updated", 1, updateCount);
+            final int updateCount =
+                    mContentResolver.update(uri, contentValues, selection, selectionArgs);
+            assertWithMessage("Unexpected number of rows updated").that(updateCount).isEqualTo(1);
 
             // Verify the updated value
             cursor = mContentResolver.query(uri, apnProjection, selection, selectionArgs, null);
-            assertNotNull("Failed to query the table", cursor);
-            assertEquals("Unexpected number of APNs returned by cursor", 1, cursor.getCount());
+            assertWithMessage("Failed to query the table").that(cursor).isNotNull();
+            assertWithMessage("Unexpected number of APNs returned by cursor")
+                    .that(cursor.getCount())
+                    .isEqualTo(1);
             cursor.moveToFirst();
-            assertEquals("Unexpected value returned by cursor",
-                    cursor.getString(cursor.getColumnIndex(Carriers.APN)), newApn);
+            assertWithMessage("Unexpected value returned by cursor")
+                    .that(cursor.getString(cursor.getColumnIndex(Carriers.APN)))
+                    .isEqualTo(newApn);
 
             // delete test content
             final String selectionToDelete = Carriers.NUMERIC + "=?";
-            String[] selectionArgsToDelete = { NUMERIC };
-            Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
-                    + "testInsertCarriers selectionArgs: " + Arrays.toString(selectionArgs));
-            int numRowsDeleted = mContentResolver.delete(
-                    uri, selectionToDelete, selectionArgsToDelete);
-            assertEquals("Unexpected number of rows deleted",1, numRowsDeleted);
+            String[] selectionArgsToDelete = {NUMERIC};
+            Log.d(
+                    TAG,
+                    "testInsertCarriers deleting selection: "
+                            + selectionToDelete
+                            + "testInsertCarriers selectionArgs: "
+                            + Arrays.toString(selectionArgs));
+            int numRowsDeleted =
+                    mContentResolver.delete(uri, selectionToDelete, selectionArgsToDelete);
+            assertWithMessage("Unexpected number of rows deleted")
+                    .that(numRowsDeleted)
+                    .isEqualTo(1);
 
             // verify that deleted values are gone
             cursor = mContentResolver.query(uri, apnProjection, selection, selectionArgs, null);
-            assertEquals("Unexpected number of rows deleted", 0, cursor.getCount());
+            assertWithMessage("Unexpected number of rows deleted")
+                    .that(cursor.getCount())
+                    .isEqualTo(0);
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
     @Test
     public void testQueryConflictCase() {
-        if (!mHasCellular) return;
         String invalidColumn = "random";
         Uri uri = Carriers.CONTENT_URI;
-        // CONTENT_URI = Uri.parse("content://telephony/carriers");
-        // Create A set of column_name/value pairs to add to the database.
+        // Create a set of column_name/value pairs to add to the database.
         ContentValues contentValues = new ContentValues();
         contentValues.put(Carriers.NAME, NAME);
         contentValues.put(Carriers.APN, APN);
@@ -202,50 +203,57 @@
             // Insert the value into database.
             Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues.toString());
             Uri newUri = mContentResolver.insert(uri, contentValues);
-            assertNotNull("Failed to insert to table", newUri);
+            assertWithMessage("Failed to insert to table").that(newUri).isNotNull();
 
             // Try to get the value with invalid selection
-            final String[] testProjection =
-                    {
-                            Carriers.NAME,
-                            Carriers.APN,
-                            Carriers.PORT,
-                            Carriers.PROTOCOL,
-                            Carriers.NUMERIC,
-                    };
+            final String[] testProjection = {
+                Carriers.NAME, Carriers.APN, Carriers.PORT, Carriers.PROTOCOL, Carriers.NUMERIC,
+            };
             final String selection = invalidColumn + "=?";
-            String[] selectionArgs = { invalidColumn };
-            Log.d(TAG, "testInsertCarriers query projection: " + Arrays.toString(testProjection)
-                    + "\ntestInsertCarriers selection: " + selection
-                    + "\ntestInsertCarriers selectionArgs: " + Arrays.toString(selectionArgs));
-            Cursor cursor = mContentResolver.query(
-                    uri, testProjection, selection, selectionArgs, null);
-            assertNull("Failed to query the table",cursor);
+            String[] selectionArgs = {invalidColumn};
+            Log.d(
+                    TAG,
+                    "testInsertCarriers query projection: "
+                            + Arrays.toString(testProjection)
+                            + "\ntestInsertCarriers selection: "
+                            + selection
+                            + "\ntestInsertCarriers selectionArgs: "
+                            + Arrays.toString(selectionArgs));
+            Cursor cursor =
+                    mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
+            assertWithMessage("Failed to query the table").that(cursor).isNull();
 
             // delete test content
             final String selectionToDelete = Carriers.NAME + "=?";
-            String[] selectionArgsToDelete = { NAME };
-            Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
-                    + "testInsertCarriers selectionArgs: " + Arrays.toString(selectionArgs));
-            int numRowsDeleted = mContentResolver.delete(
-                    uri, selectionToDelete, selectionArgsToDelete);
-            assertEquals("Unexpected number of rows deleted", 1, numRowsDeleted);
+            String[] selectionArgsToDelete = {NAME};
+            Log.d(
+                    TAG,
+                    "testInsertCarriers deleting selection: "
+                            + selectionToDelete
+                            + "testInsertCarriers selectionArgs: "
+                            + Arrays.toString(selectionArgs));
+            int numRowsDeleted =
+                    mContentResolver.delete(uri, selectionToDelete, selectionArgsToDelete);
+            assertWithMessage("Unexpected number of rows deleted")
+                    .that(numRowsDeleted)
+                    .isEqualTo(1);
 
             // verify that deleted values are gone
-            cursor = mContentResolver.query(
-                    uri, testProjection, selectionToDelete, selectionArgsToDelete, null);
-            assertEquals("Unexpected number of rows deleted", 0, cursor.getCount());
+            cursor =
+                    mContentResolver.query(
+                            uri, testProjection, selectionToDelete, selectionArgsToDelete, null);
+            assertWithMessage("Unexpected number of rows deleted")
+                    .that(cursor.getCount())
+                    .isEqualTo(0);
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
     @Test
     public void testUpdateConflictCase() {
-        if (!mHasCellular) return;
         Uri uri = Carriers.CONTENT_URI;
-        // CONTENT_URI = Uri.parse("content://telephony/carriers");
-        // Create A set of column_name/value pairs to add to the database.
+        // Create a set of column_name/value pairs to add to the database.
         ContentValues contentValues = new ContentValues();
         contentValues.put(Carriers.NAME, NAME);
         contentValues.put(Carriers.APN, APN);
@@ -257,63 +265,69 @@
             // Insert the value into database.
             Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues.toString());
             Uri newUri = mContentResolver.insert(uri, contentValues);
-            assertNotNull("Failed to insert to table", newUri);
+            assertWithMessage("Failed to insert to table").that(newUri).isNotNull();
 
             // Try to get the value with invalid selection
-            final String[] testProjection =
-                    {
-                            Carriers.NAME,
-                            Carriers.APN,
-                            Carriers.PORT,
-                            Carriers.PROTOCOL,
-                            Carriers.NUMERIC,
-                    };
+            final String[] testProjection = {
+                Carriers.NAME, Carriers.APN, Carriers.PORT, Carriers.PROTOCOL, Carriers.NUMERIC,
+            };
             String selection = Carriers.NAME + "=?";
-            String[] selectionArgs = { NAME };
-            Log.d(TAG, "testInsertCarriers query projection: " + Arrays.toString(testProjection)
-                    + "\ntestInsertCarriers selection: " + selection
-                    + "\ntestInsertCarriers selectionArgs: " + Arrays.toString(selectionArgs));
-            Cursor cursor = mContentResolver.query(
-                    uri, testProjection, selection, selectionArgs, null);
-            assertEquals("Unexpected number of APNs returned by cursor",
-                    1, cursor.getCount());
+            String[] selectionArgs = {NAME};
+            Log.d(
+                    TAG,
+                    "testInsertCarriers query projection: "
+                            + Arrays.toString(testProjection)
+                            + "\ntestInsertCarriers selection: "
+                            + selection
+                            + "\ntestInsertCarriers selectionArgs: "
+                            + Arrays.toString(selectionArgs));
+            Cursor cursor =
+                    mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
+            assertWithMessage("Unexpected number of APNs returned by cursor")
+                    .that(cursor.getCount())
+                    .isEqualTo(1);
 
             // Update the table with invalid column
             String invalidColumn = "random";
             contentValues.put(invalidColumn, invalidColumn);
-            try {
-                mContentResolver.update(uri, contentValues, selection, selectionArgs);
-                fail();
-            } catch (SQLiteException e) {
-                // Expected: If there's no such a column, an exception will be thrown and the
-                // Activity Manager will kill this process shortly.
-            }
+            // Expected: If there's no such a column, an exception will be thrown and
+            // ActivityManager will kill this process shortly.
+            assertThrows(
+                    SQLiteException.class,
+                    () -> mContentResolver.update(uri, contentValues, selection, selectionArgs));
 
             // delete test content
             final String selectionToDelete = Carriers.NAME + "=?";
-            String[] selectionArgsToDelete = { NAME };
-            Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
-                    + "testInsertCarriers selectionArgs: " + Arrays.toString(selectionArgs));
-            int numRowsDeleted = mContentResolver.delete(
-                    uri, selectionToDelete, selectionArgsToDelete);
-            assertEquals("Unexpected number of rows deleted", 1, numRowsDeleted);
+            String[] selectionArgsToDelete = {NAME};
+            Log.d(
+                    TAG,
+                    "testInsertCarriers deleting selection: "
+                            + selectionToDelete
+                            + "testInsertCarriers selectionArgs: "
+                            + Arrays.toString(selectionArgs));
+            int numRowsDeleted =
+                    mContentResolver.delete(uri, selectionToDelete, selectionArgsToDelete);
+            assertWithMessage("Unexpected number of rows deleted")
+                    .that(numRowsDeleted)
+                    .isEqualTo(1);
 
             // verify that deleted values are gone
-            cursor = mContentResolver.query(
-                    uri, testProjection, selectionToDelete, selectionArgsToDelete, null);
-            assertEquals("Unexpected number of rows deleted", 0, cursor.getCount());
+            cursor =
+                    mContentResolver.query(
+                            uri, testProjection, selectionToDelete, selectionArgsToDelete, null);
+            assertWithMessage("Unexpected number of rows deleted")
+                    .that(cursor.getCount())
+                    .isEqualTo(0);
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
     @Test
     public void testDeleteConflictCase() {
-        if (!mHasCellular) return;
         String invalidColumn = "random";
         Uri uri = Carriers.CONTENT_URI;
-        // CONTENT_URI = Uri.parse("content://telephony/carriers");
-        // Create A set of column_name/value pairs to add to the database.
+        // Create a set of column_name/value pairs to add to the database.
         ContentValues contentValues = new ContentValues();
         contentValues.put(Carriers.NAME, NAME);
         contentValues.put(Carriers.APN, APN);
@@ -325,68 +339,84 @@
             // Insert the value into database.
             Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues.toString());
             Uri newUri = mContentResolver.insert(uri, contentValues);
-            assertNotNull("Failed to insert to table", newUri);
+            assertWithMessage("Failed to insert to table").that(newUri).isNotNull();
 
             // Get the values in table.
-            final String[] testProjection =
-                    {
-                            Carriers.NAME,
-                            Carriers.APN,
-                            Carriers.PORT,
-                            Carriers.PROTOCOL,
-                            Carriers.NUMERIC,
-                    };
+            final String[] testProjection = {
+                Carriers.NAME, Carriers.APN, Carriers.PORT, Carriers.PROTOCOL, Carriers.NUMERIC,
+            };
             String selection = Carriers.NAME + "=?";
-            String[] selectionArgs = { NAME };
-            Log.d(TAG, "testInsertCarriers query projection: " + Arrays.toString(testProjection)
-                    + "\ntestInsertCarriers selection: " + selection
-                    + "\ntestInsertCarriers selectionArgs: " + Arrays.toString(selectionArgs));
-            Cursor cursor = mContentResolver.query(
-                    uri, testProjection, selection, selectionArgs, null);
-            assertEquals("Unexpected number of APNs returned by cursor", 1, cursor.getCount());
+            String[] selectionArgs = {NAME};
+            Log.d(
+                    TAG,
+                    "testInsertCarriers query projection: "
+                            + Arrays.toString(testProjection)
+                            + "\ntestInsertCarriers selection: "
+                            + selection
+                            + "\ntestInsertCarriers selectionArgs: "
+                            + Arrays.toString(selectionArgs));
+            Cursor cursor =
+                    mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
+            assertWithMessage("Unexpected number of APNs returned by cursor")
+                    .that(cursor.getCount())
+                    .isEqualTo(1);
 
             // try to delete with invalid selection
-            String selectionToDelete = invalidColumn + "=?";
-            String[] selectionArgsToDelete = { invalidColumn };
-            Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
-                    + "testInsertCarriers selectionArgs: " + Arrays.toString(selectionArgs));
+            String invalidSelectionToDelete = invalidColumn + "=?";
+            String[] invalidSelectionArgsToDelete = {invalidColumn};
+            Log.d(
+                    TAG,
+                    "testInsertCarriers deleting selection: "
+                            + invalidSelectionToDelete
+                            + "testInsertCarriers selectionArgs: "
+                            + Arrays.toString(selectionArgs));
 
-            try {
-                mContentResolver.delete(uri, selectionToDelete, selectionArgsToDelete);
-                fail();
-            } catch (SQLiteException e) {
-                // Expected: If there's no such a column, an exception will be thrown and the
-                // Activity Manager will kill this process shortly.
-            }
+            // Expected: If there's no such a column, an exception will be thrown and
+            // ActivityManager will kill this process shortly.
+            assertThrows(
+                    SQLiteException.class,
+                    () ->
+                            mContentResolver.delete(
+                                    uri, invalidSelectionToDelete, invalidSelectionArgsToDelete));
 
             // verify that deleted value is still there
             selection = Carriers.NAME + "=?";
             selectionArgs[0] = NAME;
             cursor = mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
-            assertEquals("Unexpected number of APNs returned by cursor", 1, cursor.getCount());
+            assertWithMessage("Unexpected number of APNs returned by cursor")
+                    .that(cursor.getCount())
+                    .isEqualTo(1);
 
             // delete test content
-            selectionToDelete = Carriers.NAME + "=?";
-            selectionArgsToDelete[0] = NAME;
-            Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
-                    + "testInsertCarriers selectionArgs: " + Arrays.toString(selectionArgs));
-            int numRowsDeleted = mContentResolver.delete(
-                    uri, selectionToDelete, selectionArgsToDelete);
-            assertEquals("Unexpected number of rows deleted", 1, numRowsDeleted);
+            String selectionToDelete = Carriers.NAME + "=?";
+            String[] selectionArgsToDelete = {NAME};
+            Log.d(
+                    TAG,
+                    "testInsertCarriers deleting selection: "
+                            + selectionToDelete
+                            + "testInsertCarriers selectionArgs: "
+                            + Arrays.toString(selectionArgs));
+            int numRowsDeleted =
+                    mContentResolver.delete(uri, selectionToDelete, selectionArgsToDelete);
+            assertWithMessage("Unexpected number of rows deleted")
+                    .that(numRowsDeleted)
+                    .isEqualTo(1);
 
             // verify that deleted values are gone
             cursor = mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
-            assertEquals("Unexpected number of rows deleted", 0, cursor.getCount());
+            assertWithMessage("Unexpected number of rows deleted")
+                    .that(cursor.getCount())
+                    .isEqualTo(0);
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
     private ContentValues makeDefaultContentValues() {
         ContentValues contentValues = new ContentValues();
-        for (Map.Entry<String, String> entry: APN_MAP.entrySet()) {
+        for (Map.Entry<String, String> entry : APN_MAP.entrySet()) {
             contentValues.put(entry.getKey(), entry.getValue());
         }
         return contentValues;
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/BaseCarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/BaseCarrierApiTest.java
new file mode 100644
index 0000000..b0b6504
--- /dev/null
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/BaseCarrierApiTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2021 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.carrierapi.cts;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.telephony.TelephonyManager;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.FeatureUtil;
+
+import org.junit.Before;
+
+/**
+ * Common test base to ensure uniform preconditions checking. This class will check for:
+ *
+ * <ol>
+ *   <li>{@link android.content.pm.PackageManager#FEATURE_TELEPHONY}
+ *   <li>A SIM that grants us carrier privileges is currently active in the device
+ * </ol>
+ *
+ * Just inherit from this class when writing your test, then you are able to assume in the subclass
+ * {@code Before} method that preconditions have all passed. The setup and test methods will not be
+ * executed if preconditions are not met.
+ */
+public abstract class BaseCarrierApiTest {
+    protected static final String NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE =
+            "This test requires a SIM card with carrier privilege rules on it.\n"
+                    + "Visit https://source.android.com/devices/tech/config/uicc.html";
+
+    protected Context getContext() {
+        return InstrumentationRegistry.getInstrumentation().getTargetContext();
+    }
+
+    private boolean mPreconditionsSatisfied = false;
+
+    protected boolean werePreconditionsSatisfied() {
+        return mPreconditionsSatisfied;
+    }
+
+    /**
+     * Subclasses do NOT need to explicitly call or override this method. Per the JUnit docs, a
+     * superclass {@code Before} method always executes before a subclass {@code Before} method.
+     *
+     * <p>If preconditions fail, neither the subclass {@code Before} method(s) nor the actual {@code
+     * Test} method will execute, but {@code After} methods will still execute. If a subclass does
+     * work in an {@code After} method, then it should first check {@link
+     * #werePreconditionsSatisfied} and return early without doing any work if it's {@code false}.
+     */
+    @Before
+    public void ensurePreconditionsMet() {
+        mPreconditionsSatisfied = false;
+        // Bail out if no cellular support.
+        assumeTrue(
+                "No cellular support, CarrierAPI."
+                        + getClass().getSimpleName()
+                        + " cases will be skipped",
+                FeatureUtil.hasTelephony());
+        // We must run with carrier privileges.
+        assertWithMessage(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE)
+                .that(getContext().getSystemService(TelephonyManager.class).hasCarrierPrivileges())
+                .isTrue();
+        mPreconditionsSatisfied = true;
+    }
+}
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/BugreportManagerTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/BugreportManagerTest.java
index b154865..4e5f4fa 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/BugreportManagerTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/BugreportManagerTest.java
@@ -22,17 +22,13 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
-import android.content.Context;
-import android.content.pm.PackageManager;
 import android.os.BugreportManager;
 import android.os.BugreportManager.BugreportCallback;
 import android.os.BugreportParams;
 import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.platform.test.annotations.SystemUserOnly;
-import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -68,7 +64,7 @@
  */
 @SystemUserOnly(reason = "BugreportManager requires calls to originate from the primary user")
 @RunWith(AndroidJUnit4.class)
-public class BugreportManagerTest {
+public class BugreportManagerTest extends BaseCarrierApiTest {
     private static final String TAG = "BugreportManagerTest";
 
     // See BugreportManagerServiceImpl#BUGREPORT_SERVICE.
@@ -86,7 +82,6 @@
 
     @Rule public TestName name = new TestName();
 
-    private TelephonyManager mTelephonyManager;
     private BugreportManager mBugreportManager;
     private File mBugreportFile;
     private ParcelFileDescriptor mBugreportFd;
@@ -95,19 +90,7 @@
 
     @Before
     public void setUp() throws Exception {
-        Context context = InstrumentationRegistry.getContext();
-        // Bail out if no cellular support.
-        assumeTrue(
-                "No cellular support, CarrierAPI.BugreportManagerTest cases will be skipped",
-                context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
-        // Fail the test if we don't have carrier privileges.
-        mTelephonyManager = context.getSystemService(TelephonyManager.class);
-        assertWithMessage(
-                        "This test requires a SIM card with carrier privilege rules on it.\n"
-                                + "Visit https://source.android.com/devices/tech/config/uicc.html")
-                .that(mTelephonyManager.hasCarrierPrivileges())
-                .isTrue();
-        mBugreportManager = context.getSystemService(BugreportManager.class);
+        mBugreportManager = getContext().getSystemService(BugreportManager.class);
 
         killCurrentBugreportIfRunning();
         mBugreportFile = createTempFile("bugreport_" + name.getMethodName(), ".zip");
@@ -120,6 +103,8 @@
 
     @After
     public void tearDown() throws Exception {
+        if (!werePreconditionsSatisfied()) return;
+
         FileUtils.closeQuietly(mBugreportFd);
         FileUtils.closeQuietly(mScreenshotFd);
         killCurrentBugreportIfRunning();
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
index 4b67d90..baae880 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
@@ -22,9 +22,10 @@
 import static android.telephony.IccOpenLogicalChannelResponse.INVALID_CHANNEL;
 import static android.telephony.IccOpenLogicalChannelResponse.STATUS_NO_ERROR;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.fail;
 
 import android.content.BroadcastReceiver;
 import android.content.ContentProviderClient;
@@ -32,8 +33,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -55,15 +54,21 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.Suppress;
 import android.util.Base64;
 import android.util.Log;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.compatibility.common.util.ShellIdentityUtils;
 
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
+import com.google.common.collect.Range;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -78,23 +83,27 @@
 
 import javax.annotation.Nonnull;
 
+/**
+ * Unit tests for various carrier-related APIs.
+ *
+ * <p>Test using `atest CtsCarrierApiTestCases:CarrierApiTest` or `make cts -j64 && cts-tradefed run
+ * cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.CarrierApiTest`
+ */
 // TODO(b/130187425): Split CarrierApiTest apart to have separate test classes for functionality
-public class CarrierApiTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class CarrierApiTest extends BaseCarrierApiTest {
     private static final String TAG = "CarrierApiTest";
+
     private TelephonyManager mTelephonyManager;
     private CarrierConfigManager mCarrierConfigManager;
-    private PackageManager mPackageManager;
     private SubscriptionManager mSubscriptionManager;
     private ContentProviderClient mVoicemailProvider;
     private ContentProviderClient mStatusProvider;
     private Uri mVoicemailContentUri;
     private Uri mStatusContentUri;
-    private boolean hasCellular;
     private String selfPackageName;
-    private String selfCertHash;
     private HandlerThread mListenerThread;
 
-    private static final String FiDevCert = "24EB92CBB156B280FA4E1429A6ECEEB6E5C1BFE4";
     // The minimum allocatable logical channel number, per TS 102 221 Section 11.1.17.1
     private static final int MIN_LOGICAL_CHANNEL = 1;
     // The maximum allocatable logical channel number in the standard range, per TS 102 221 Section
@@ -163,37 +172,26 @@
 
     private static final int DSDS_PHONE_COUNT = 2;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mPackageManager = getContext().getPackageManager();
-        mTelephonyManager = (TelephonyManager)
-                getContext().getSystemService(Context.TELEPHONY_SERVICE);
-        hasCellular = hasCellular();
-        if (!hasCellular) {
-            Log.e(TAG, "No cellular support, all tests will be skipped.");
-            return;
-        }
-
-        mCarrierConfigManager = (CarrierConfigManager)
-                getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        mSubscriptionManager = (SubscriptionManager)
-                getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
-        selfPackageName = getContext().getPackageName();
-        selfCertHash = getCertHash(selfPackageName);
+    @Before
+    public void setUp() throws Exception {
+        Context context = getContext();
+        mTelephonyManager = context.getSystemService(TelephonyManager.class);
+        mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
+        mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
+        selfPackageName = context.getPackageName();
         mVoicemailContentUri = VoicemailContract.Voicemails.buildSourceUri(selfPackageName);
-        mVoicemailProvider = getContext().getContentResolver()
-                .acquireContentProviderClient(mVoicemailContentUri);
+        mVoicemailProvider =
+                context.getContentResolver().acquireContentProviderClient(mVoicemailContentUri);
         mStatusContentUri = VoicemailContract.Status.buildSourceUri(selfPackageName);
-        mStatusProvider = getContext().getContentResolver()
-                .acquireContentProviderClient(mStatusContentUri);
+        mStatusProvider =
+                context.getContentResolver().acquireContentProviderClient(mStatusContentUri);
         mListenerThread = new HandlerThread("CarrierApiTest");
         mListenerThread.start();
     }
 
-    @Override
+    @After
     public void tearDown() throws Exception {
-        if (!hasCellular) return;
+        if (!werePreconditionsSatisfied()) return;
 
         mListenerThread.quit();
         try {
@@ -202,68 +200,34 @@
         } catch (Exception e) {
             Log.w(TAG, "Failed to clean up voicemail tables in tearDown", e);
         }
-        super.tearDown();
     }
 
-    /**
-     * Checks whether the cellular stack should be running on this device.
-     */
-    private boolean hasCellular() {
-        return mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) &&
-                mTelephonyManager.getPhoneCount() > 0;
-    }
-
-    private boolean isSimCardPresent() {
-        return mTelephonyManager.getSimState() != TelephonyManager.SIM_STATE_ABSENT;
-    }
-
-    private String getCertHash(String pkgName) {
-        try {
-            PackageInfo pInfo = mPackageManager.getPackageInfo(pkgName,
-                    PackageManager.GET_SIGNATURES | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
-            MessageDigest md = MessageDigest.getInstance("SHA-1");
-            return bytesToHexString(md.digest(pInfo.signatures[0].toByteArray()));
-        } catch (PackageManager.NameNotFoundException ex) {
-            Log.e(TAG, pkgName + " not found", ex);
-        } catch (NoSuchAlgorithmException ex) {
-            Log.e(TAG, "Algorithm SHA1 is not found.");
-        }
-        return "";
-    }
-
-    private void failMessage() {
-        if (FiDevCert.equalsIgnoreCase(selfCertHash)) {
-            fail("This test requires a Project Fi SIM card.");
-        } else {
-            fail("This test requires a SIM card with carrier privilege rule on it.\n" +
-                 "Cert hash: " + selfCertHash + "\n" +
-                 "Visit https://source.android.com/devices/tech/config/uicc.html");
-        }
-    }
-
+    @Test
     public void testSimCardPresent() {
-        if (!hasCellular) return;
-        assertTrue("This test requires SIM card.", isSimCardPresent());
+        assertWithMessage("This test requires a SIM card")
+                .that(mTelephonyManager.getSimState())
+                .isNotEqualTo(TelephonyManager.SIM_STATE_ABSENT);
     }
 
+    @Test
     public void testHasCarrierPrivileges() {
-        if (!hasCellular) return;
-        if (!mTelephonyManager.hasCarrierPrivileges()) {
-            failMessage();
-        }
+        assertWithMessage(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE)
+                .that(mTelephonyManager.hasCarrierPrivileges())
+                .isTrue();
     }
 
     private static void assertUpdateAvailableNetworkSuccess(int value) {
-        assertEquals(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS, value);
+        assertThat(value).isEqualTo(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SUCCESS);
     }
 
     private static void assertUpdateAvailableNetworkNoOpportunisticSubAvailable(int value) {
-        assertEquals(
-                TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE, value);
+        assertThat(value)
+                .isEqualTo(
+                        TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE);
     }
 
     private static void assertSetOpportunisticSubSuccess(int value) {
-        assertEquals(TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS, value);
+        assertThat(value).isEqualTo(TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS);
     }
 
     private int getFirstActivateCarrierPrivilegedSubscriptionId() {
@@ -272,8 +236,8 @@
                 mSubscriptionManager.getActiveSubscriptionInfoList();
         if (subscriptionInfos != null) {
             for (SubscriptionInfo info : subscriptionInfos) {
-                TelephonyManager telephonyManager = mTelephonyManager.createForSubscriptionId(
-                        info.getSubscriptionId());
+                TelephonyManager telephonyManager =
+                        mTelephonyManager.createForSubscriptionId(info.getSubscriptionId());
                 if (telephonyManager.hasCarrierPrivileges()) {
                     subId = info.getSubscriptionId();
                     return subId;
@@ -283,15 +247,12 @@
         return subId;
     }
 
+    @Test
     public void testUpdateAvailableNetworksWithCarrierPrivilege() {
-        if (!hasCellular) return;
-
         int subIdWithCarrierPrivilege = getFirstActivateCarrierPrivilegedSubscriptionId();
-        int activeSubscriptionInfoCount = ShellIdentityUtils.invokeMethodWithShellPermissions(
-                mSubscriptionManager, (tm) -> tm.getActiveSubscriptionInfoCount());
-        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
-            return;
-        }
+        int activeSubscriptionInfoCount =
+                ShellIdentityUtils.invokeMethodWithShellPermissions(
+                        mSubscriptionManager, (tm) -> tm.getActiveSubscriptionInfoCount());
         if (mTelephonyManager.getPhoneCount() == 1) {
             return;
         }
@@ -311,42 +272,52 @@
         List<String> mccMncs = new ArrayList<String>();
         List<Integer> bands = new ArrayList<Integer>();
         List<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<AvailableNetworkInfo>();
-        Consumer<Integer> callbackSuccess =
-                CarrierApiTest::assertUpdateAvailableNetworkSuccess;
+        Consumer<Integer> callbackSuccess = CarrierApiTest::assertUpdateAvailableNetworkSuccess;
         Consumer<Integer> callbackNoOpportunisticSubAvailable =
                 CarrierApiTest::assertUpdateAvailableNetworkNoOpportunisticSubAvailable;
         Consumer<Integer> setOpCallbackSuccess = CarrierApiTest::assertSetOpportunisticSubSuccess;
-        if (subscriptionInfoList == null || subscriptionInfoList.size() == 0
+        if (subscriptionInfoList == null
+                || subscriptionInfoList.size() == 0
                 || !mSubscriptionManager.isActiveSubscriptionId(
                         subscriptionInfoList.get(0).getSubscriptionId())) {
             try {
-                AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(
-                        subIdWithCarrierPrivilege, AvailableNetworkInfo.PRIORITY_HIGH, mccMncs,
-                        bands);
+                AvailableNetworkInfo availableNetworkInfo =
+                        new AvailableNetworkInfo(
+                                subIdWithCarrierPrivilege,
+                                AvailableNetworkInfo.PRIORITY_HIGH,
+                                mccMncs,
+                                bands);
                 availableNetworkInfos.add(availableNetworkInfo);
                 // Call updateAvailableNetworks without opportunistic subscription.
                 // callbackNoOpportunisticSubAvailable is expected to be triggered
                 // and the return value will be checked against
                 // UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE
-                mTelephonyManager.updateAvailableNetworks(availableNetworkInfos,
-                        AsyncTask.SERIAL_EXECUTOR, callbackNoOpportunisticSubAvailable);
+                mTelephonyManager.updateAvailableNetworks(
+                        availableNetworkInfos,
+                        AsyncTask.SERIAL_EXECUTOR,
+                        callbackNoOpportunisticSubAvailable);
             } finally {
                 // clear all the operations at the end of test.
                 availableNetworkInfos.clear();
-                mTelephonyManager.updateAvailableNetworks(availableNetworkInfos,
-                        AsyncTask.SERIAL_EXECUTOR, callbackNoOpportunisticSubAvailable);
+                mTelephonyManager.updateAvailableNetworks(
+                        availableNetworkInfos,
+                        AsyncTask.SERIAL_EXECUTOR,
+                        callbackNoOpportunisticSubAvailable);
             }
         } else {
             // This is case of DSDS phone, one active opportunistic subscription and one
             // active primary subscription.
             int resultSubId;
             try {
-                AvailableNetworkInfo availableNetworkInfo = new AvailableNetworkInfo(
-                        subscriptionInfoList.get(0).getSubscriptionId(),
-                        AvailableNetworkInfo.PRIORITY_HIGH, mccMncs, bands);
+                AvailableNetworkInfo availableNetworkInfo =
+                        new AvailableNetworkInfo(
+                                subscriptionInfoList.get(0).getSubscriptionId(),
+                                AvailableNetworkInfo.PRIORITY_HIGH,
+                                mccMncs,
+                                bands);
                 availableNetworkInfos.add(availableNetworkInfo);
-                mTelephonyManager.updateAvailableNetworks(availableNetworkInfos,
-                        AsyncTask.SERIAL_EXECUTOR, callbackSuccess);
+                mTelephonyManager.updateAvailableNetworks(
+                        availableNetworkInfos, AsyncTask.SERIAL_EXECUTOR, callbackSuccess);
                 // wait for the data change to take effect
                 waitForMs(500);
                 // Call setPreferredData and reconfirm with getPreferred data
@@ -357,19 +328,21 @@
                 // wait for the data change to take effect
                 waitForMs(500);
                 resultSubId = mTelephonyManager.getPreferredOpportunisticDataSubscription();
-                assertEquals(preferSubId, resultSubId);
+                assertThat(resultSubId).isEqualTo(preferSubId);
             } finally {
                 // clear all the operations at the end of test.
                 availableNetworkInfos.clear();
-                mTelephonyManager.updateAvailableNetworks(availableNetworkInfos,
-                        AsyncTask.SERIAL_EXECUTOR, callbackSuccess);
+                mTelephonyManager.updateAvailableNetworks(
+                        availableNetworkInfos, AsyncTask.SERIAL_EXECUTOR, callbackSuccess);
                 waitForMs(500);
                 mTelephonyManager.setPreferredOpportunisticDataSubscription(
-                        SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false,
-                        AsyncTask.SERIAL_EXECUTOR, callbackSuccess);
+                        SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+                        false,
+                        AsyncTask.SERIAL_EXECUTOR,
+                        callbackSuccess);
                 waitForMs(500);
                 resultSubId = mTelephonyManager.getPreferredOpportunisticDataSubscription();
-                assertEquals(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, resultSubId);
+                assertThat(resultSubId).isEqualTo(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
             }
         }
     }
@@ -382,107 +355,145 @@
         }
     }
 
+    @Test
     public void testGetIccAuthentication() {
         // EAP-SIM rand is 16 bytes.
         String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
         String base64Challenge2 = "EMNxjsFrPCpm+KcgCmQGnwQ=";
-        if (!hasCellular) return;
+
         try {
-            assertNull("getIccAuthentication should return null for empty data.",
-                    mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
-                    TelephonyManager.AUTHTYPE_EAP_AKA, ""));
-            String response = mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
-                    TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge);
-            assertTrue("Response to EAP-SIM Challenge must not be Null.", response != null);
+            assertWithMessage("getIccAuthentication should return null for empty data.")
+                    .that(
+                            mTelephonyManager.getIccAuthentication(
+                                    TelephonyManager.APPTYPE_USIM,
+                                    TelephonyManager.AUTHTYPE_EAP_AKA,
+                                    ""))
+                    .isNull();
+            String response =
+                    mTelephonyManager.getIccAuthentication(
+                            TelephonyManager.APPTYPE_USIM,
+                            TelephonyManager.AUTHTYPE_EAP_SIM,
+                            base64Challenge);
+            assertWithMessage("Response to EAP-SIM Challenge must not be Null.")
+                    .that(response)
+                    .isNotNull();
             // response is base64 encoded. After decoding, the value should be:
             // 1 length byte + SRES(4 bytes) + 1 length byte + Kc(8 bytes)
             byte[] result = android.util.Base64.decode(response, android.util.Base64.DEFAULT);
-            assertTrue("Result length must be 14 bytes.", 14 == result.length);
-            String response2 = mTelephonyManager.getIccAuthentication(TelephonyManager.APPTYPE_USIM,
-                    TelephonyManager.AUTHTYPE_EAP_SIM, base64Challenge2);
-            assertTrue("Two responses must be different.", !response.equals(response2));
+            assertThat(result).hasLength(14);
+            String response2 =
+                    mTelephonyManager.getIccAuthentication(
+                            TelephonyManager.APPTYPE_USIM,
+                            TelephonyManager.AUTHTYPE_EAP_SIM,
+                            base64Challenge2);
+            assertWithMessage("Two responses must be different")
+                    .that(response)
+                    .isNotEqualTo(response2);
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
+    @Test
     @SystemUserOnly(reason = "b/177921545, broadcast sent only to primary user")
     public void testSendDialerSpecialCode() {
-        if (!hasCellular) return;
-        try {
-            IntentReceiver intentReceiver = new IntentReceiver();
-            final IntentFilter intentFilter = new IntentFilter();
-            intentFilter.addAction(Telephony.Sms.Intents.SECRET_CODE_ACTION);
-            intentFilter.addDataScheme("android_secret_code");
-            getContext().registerReceiver(intentReceiver, intentFilter);
+        IntentReceiver intentReceiver = new IntentReceiver();
+        final IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Telephony.Sms.Intents.SECRET_CODE_ACTION);
+        intentFilter.addDataScheme("android_secret_code");
 
+        Context context = getContext();
+        context.registerReceiver(intentReceiver, intentFilter);
+        try {
             mTelephonyManager.sendDialerSpecialCode("4636");
-            assertTrue("Did not receive expected Intent: " +
-                    Telephony.Sms.Intents.SECRET_CODE_ACTION,
-                    intentReceiver.waitForReceive());
+            assertWithMessage(
+                            "Did not receive expected Intent: "
+                                    + Telephony.Sms.Intents.SECRET_CODE_ACTION)
+                    .that(intentReceiver.waitForReceive())
+                    .isTrue();
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         } catch (InterruptedException e) {
             Log.d(TAG, "Broadcast receiver wait was interrupted.");
+        } finally {
+            context.unregisterReceiver(intentReceiver);
         }
     }
 
+    @Test
     public void testSubscriptionInfoListing() {
-        if (!hasCellular) return;
         try {
-            assertTrue("getActiveSubscriptionInfoCount() should be non-zero",
-                    mSubscriptionManager.getActiveSubscriptionInfoCount() > 0);
+            assertThat(mSubscriptionManager.getActiveSubscriptionInfoCount()).isGreaterThan(0);
             List<SubscriptionInfo> subInfoList =
                     mSubscriptionManager.getActiveSubscriptionInfoList();
-            assertNotNull("getActiveSubscriptionInfoList() returned null", subInfoList);
-            assertFalse("getActiveSubscriptionInfoList() returned an empty list",
-                    subInfoList.isEmpty());
+            assertWithMessage("getActiveSubscriptionInfoList() returned null")
+                    .that(subInfoList)
+                    .isNotNull();
+            assertWithMessage("getActiveSubscriptionInfoList() returned an empty list")
+                    .that(subInfoList)
+                    .isNotEmpty();
             for (SubscriptionInfo info : subInfoList) {
                 TelephonyManager tm =
                         mTelephonyManager.createForSubscriptionId(info.getSubscriptionId());
-                assertTrue("getActiveSubscriptionInfoList() returned an inaccessible subscription",
-                        tm.hasCarrierPrivileges());
+                assertWithMessage(
+                                "getActiveSubscriptionInfoList() returned an inaccessible"
+                                        + " subscription")
+                        .that(tm.hasCarrierPrivileges())
+                        .isTrue();
 
                 // Check other APIs to make sure they are accessible and return consistent info.
                 SubscriptionInfo infoForSlot =
                         mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(
                                 info.getSimSlotIndex());
-                assertNotNull("getActiveSubscriptionInfoForSimSlotIndex() returned null",
-                        infoForSlot);
-                assertEquals(
-                        "getActiveSubscriptionInfoForSimSlotIndex() returned inconsistent info",
-                        info.getSubscriptionId(), infoForSlot.getSubscriptionId());
+                assertWithMessage("getActiveSubscriptionInfoForSimSlotIndex() returned null")
+                        .that(infoForSlot)
+                        .isNotNull();
+                assertWithMessage(
+                                "getActiveSubscriptionInfoForSimSlotIndex() returned inconsistent"
+                                        + " info")
+                        .that(infoForSlot.getSubscriptionId())
+                        .isEqualTo(info.getSubscriptionId());
 
                 SubscriptionInfo infoForSubId =
                         mSubscriptionManager.getActiveSubscriptionInfo(info.getSubscriptionId());
-                assertNotNull("getActiveSubscriptionInfo() returned null", infoForSubId);
-                assertEquals("getActiveSubscriptionInfo() returned inconsistent info",
-                        info.getSubscriptionId(), infoForSubId.getSubscriptionId());
+                assertWithMessage("getActiveSubscriptionInfo() returned null")
+                        .that(infoForSubId)
+                        .isNotNull();
+                assertWithMessage("getActiveSubscriptionInfo() returned inconsistent info")
+                        .that(infoForSubId.getSubscriptionId())
+                        .isEqualTo(info.getSubscriptionId());
             }
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
+    @Test
     public void testCarrierConfigIsAccessible() {
-        if (!hasCellular) return;
         try {
             PersistableBundle bundle = mCarrierConfigManager.getConfig();
-            assertNotNull("CarrierConfigManager#getConfig() returned null", bundle);
-            assertFalse("CarrierConfigManager#getConfig() returned empty bundle", bundle.isEmpty());
+            assertWithMessage("CarrierConfigManager#getConfig() returned null")
+                    .that(bundle)
+                    .isNotNull();
+            assertWithMessage("CarrierConfigManager#getConfig() returned empty bundle")
+                    .that(bundle.isEmpty())
+                    .isFalse();
 
             int subId = SubscriptionManager.getDefaultSubscriptionId();
             bundle = mCarrierConfigManager.getConfigForSubId(subId);
-            assertNotNull("CarrierConfigManager#getConfigForSubId() returned null", bundle);
-            assertFalse("CarrierConfigManager#getConfigForSubId() returned empty bundle",
-                    bundle.isEmpty());
+            assertWithMessage("CarrierConfigManager#getConfigForSubId() returned null")
+                    .that(bundle)
+                    .isNotNull();
+            assertWithMessage("CarrierConfigManager#getConfigForSubId() returned empty bundle")
+                    .that(bundle.isEmpty())
+                    .isFalse();
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
+    @Test
     public void testTelephonyApisAreAccessible() {
-        if (!hasCellular) return;
         // The following methods may return any value depending on the state of the device. Simply
         // call them to make sure they do not throw any exceptions. Methods that return a device
         // identifier will be accessible to apps with carrier privileges in Q, but this may change
@@ -507,54 +518,65 @@
             mTelephonyManager.getManualNetworkSelectionPlmn();
             mTelephonyManager.setForbiddenPlmns(new ArrayList<String>());
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
+    @Test
     public void testVoicemailTableIsAccessible() throws Exception {
-        if (!hasCellular) return;
         ContentValues value = new ContentValues();
         value.put(VoicemailContract.Voicemails.NUMBER, "0123456789");
         value.put(VoicemailContract.Voicemails.SOURCE_PACKAGE, selfPackageName);
         try {
             Uri uri = mVoicemailProvider.insert(mVoicemailContentUri, value);
-            assertNotNull(uri);
-            Cursor cursor = mVoicemailProvider.query(uri,
-                    new String[] {
-                            VoicemailContract.Voicemails.NUMBER,
-                            VoicemailContract.Voicemails.SOURCE_PACKAGE
-                    }, null, null, null);
-            assertNotNull(cursor);
-            assertTrue(cursor.moveToFirst());
-            assertEquals("0123456789", cursor.getString(0));
-            assertEquals(selfPackageName, cursor.getString(1));
-            assertFalse(cursor.moveToNext());
+            assertThat(uri).isNotNull();
+            Cursor cursor =
+                    mVoicemailProvider.query(
+                            uri,
+                            new String[] {
+                                VoicemailContract.Voicemails.NUMBER,
+                                VoicemailContract.Voicemails.SOURCE_PACKAGE
+                            },
+                            null,
+                            null,
+                            null);
+            assertThat(cursor).isNotNull();
+            assertThat(cursor.moveToFirst()).isTrue();
+            assertThat(cursor.getString(0)).isEqualTo("0123456789");
+            assertThat(cursor.getString(1)).isEqualTo(selfPackageName);
+            assertThat(cursor.moveToNext()).isFalse();
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
+    @Test
     public void testVoicemailStatusTableIsAccessible() throws Exception {
-        if (!hasCellular) return;
         ContentValues value = new ContentValues();
-        value.put(VoicemailContract.Status.CONFIGURATION_STATE,
+        value.put(
+                VoicemailContract.Status.CONFIGURATION_STATE,
                 VoicemailContract.Status.CONFIGURATION_STATE_OK);
         value.put(VoicemailContract.Status.SOURCE_PACKAGE, selfPackageName);
         try {
             Uri uri = mStatusProvider.insert(mStatusContentUri, value);
-            assertNotNull(uri);
-            Cursor cursor = mVoicemailProvider.query(uri,
-                    new String[] {
-                            VoicemailContract.Status.CONFIGURATION_STATE,
-                            VoicemailContract.Status.SOURCE_PACKAGE
-                    }, null, null, null);
-            assertNotNull(cursor);
-            assertTrue(cursor.moveToFirst());
-            assertEquals(VoicemailContract.Status.CONFIGURATION_STATE_OK, cursor.getInt(0));
-            assertEquals(selfPackageName, cursor.getString(1));
-            assertFalse(cursor.moveToNext());
+            assertThat(uri).isNotNull();
+            Cursor cursor =
+                    mVoicemailProvider.query(
+                            uri,
+                            new String[] {
+                                VoicemailContract.Status.CONFIGURATION_STATE,
+                                VoicemailContract.Status.SOURCE_PACKAGE
+                            },
+                            null,
+                            null,
+                            null);
+            assertThat(cursor).isNotNull();
+            assertThat(cursor.moveToFirst()).isTrue();
+            assertThat(cursor.getInt(0)).isEqualTo(VoicemailContract.Status.CONFIGURATION_STATE_OK);
+            assertThat(cursor.getString(1)).isEqualTo(selfPackageName);
+            assertThat(cursor.moveToNext()).isFalse();
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
@@ -573,23 +595,23 @@
     static final int CARRIER_PRIVILEGE_LISTENERS =
             READ_PHONE_STATE_LISTENERS | READ_PRECISE_PHONE_STATE_LISTENERS;
 
+    @Test
     public void testGetManualNetworkSelectionPlmnPersisted() throws Exception {
-        if (!hasCellular) return;
         if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_GSM) return;
 
         try {
             mTelephonyManager.setNetworkSelectionModeManual(
-                     TESTING_PLMN/* operatorNumeric */, true /* persistSelection */);
+                    TESTING_PLMN /* operatorNumeric */, true /* persistSelection */);
             String plmn = mTelephonyManager.getManualNetworkSelectionPlmn();
-            assertEquals(TESTING_PLMN, plmn);
+            assertThat(plmn).isEqualTo(TESTING_PLMN);
         } finally {
             mTelephonyManager.setNetworkSelectionModeAutomatic();
         }
     }
 
+    @Test
     public void testPhoneStateListener() throws Exception {
-        if (!hasCellular) return;
-        PhoneStateListener psl = new PhoneStateListener((Runnable r) -> { });
+        PhoneStateListener psl = new PhoneStateListener((Runnable r) -> {});
         try {
             mTelephonyManager.listen(psl, CARRIER_PRIVILEGE_LISTENERS);
         } finally {
@@ -597,60 +619,59 @@
         }
     }
 
+    @Test
     public void testIsManualNetworkSelectionAllowed() throws Exception {
-        if (!hasCellular) return;
         if (mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_GSM) return;
 
         try {
-            assertTrue(mTelephonyManager.isManualNetworkSelectionAllowed());
+            assertThat(mTelephonyManager.isManualNetworkSelectionAllowed()).isTrue();
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
+    @Test
     public void testGetNetworkSelectionMode() throws Exception {
-        if (!hasCellular) return;
-
         try {
-            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
-                    (tm) -> tm.setNetworkSelectionModeAutomatic());
+            ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(
+                    mTelephonyManager, (tm) -> tm.setNetworkSelectionModeAutomatic());
             int networkMode = mTelephonyManager.getNetworkSelectionMode();
-            assertEquals(TelephonyManager.NETWORK_SELECTION_MODE_AUTO, networkMode);
+            assertThat(networkMode).isEqualTo(TelephonyManager.NETWORK_SELECTION_MODE_AUTO);
         } catch (SecurityException e) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
     }
 
+    @Test
     public void testSubscriptionInfoChangeListener() throws Exception {
-        if (!hasCellular) return;
         final AtomicReference<SecurityException> error = new AtomicReference<>();
         final CountDownLatch latch = new CountDownLatch(1);
-        new Handler(mListenerThread.getLooper()).post(() -> {
-            SubscriptionManager.OnSubscriptionsChangedListener listener =
-                    new SubscriptionManager.OnSubscriptionsChangedListener();
-            try {
-                mSubscriptionManager.addOnSubscriptionsChangedListener(listener);
-            } catch (SecurityException e) {
-                error.set(e);
-            } finally {
-                mSubscriptionManager.removeOnSubscriptionsChangedListener(listener);
-                latch.countDown();
-            }
-        });
-        assertTrue("Test timed out", latch.await(30L, TimeUnit.SECONDS));
+        new Handler(mListenerThread.getLooper())
+                .post(
+                        () -> {
+                            SubscriptionManager.OnSubscriptionsChangedListener listener =
+                                    new SubscriptionManager.OnSubscriptionsChangedListener();
+                            try {
+                                mSubscriptionManager.addOnSubscriptionsChangedListener(listener);
+                            } catch (SecurityException e) {
+                                error.set(e);
+                            } finally {
+                                mSubscriptionManager.removeOnSubscriptionsChangedListener(listener);
+                                latch.countDown();
+                            }
+                        });
+        assertWithMessage("Test timed out").that(latch.await(30L, TimeUnit.SECONDS)).isTrue();
         if (error.get() != null) {
-            failMessage();
+            fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE);
         }
-
     }
 
     /**
      * Test that it's possible to open logical channels to the ICC. This mirrors the Manage Channel
      * command described in TS 102 221 Section 11.1.17.
      */
+    @Test
     public void testIccOpenLogicalChannel() {
-        if (!hasCellular) return;
-
         // The AID here doesn't matter - we just need to open a valid connection. In this case, the
         // specified AID ("") opens a channel and selects the MF.
         IccOpenLogicalChannelResponse response = mTelephonyManager.iccOpenLogicalChannel("");
@@ -662,9 +683,8 @@
         }
     }
 
+    @Test
     public void testIccOpenLogicalChannelWithValidP2() {
-        if (!hasCellular) return;
-
         // {@link TelephonyManager#iccOpenLogicalChannel} sends a Manage Channel (open) APDU
         // followed by a Select APDU with the given AID and p2 values. See Open Mobile API
         // Specification v3.2 Section 6.2.7.h and TS 102 221 for details.
@@ -678,9 +698,8 @@
         }
     }
 
+    @Test
     public void testIccOpenLogicalChannelWithInvalidP2() {
-        if (!hasCellular) return;
-
         // Valid p2 values are defined in TS 102 221 Table 11.2. Per Table 11.2, 0xF0 should be
         // invalid. Any p2 values that produce non '9000'/'62xx'/'63xx' status words are treated as
         // an error and the channel is not opened. Due to compatibility issues with older devices,
@@ -690,8 +709,8 @@
             IccOpenLogicalChannelResponse response =
                     mTelephonyManager.iccOpenLogicalChannel("", p2);
             final int logicalChannel = response.getChannel();
-            assertEquals(INVALID_CHANNEL, logicalChannel);
-            assertNotEquals(STATUS_NO_ERROR, response.getStatus());
+            assertThat(logicalChannel).isEqualTo(INVALID_CHANNEL);
+            assertThat(response.getStatus()).isNotEqualTo(STATUS_NO_ERROR);
         }
     }
 
@@ -699,36 +718,32 @@
      * Test that it's possible to close logical channels to the ICC. This follows the Manage Channel
      * command described in TS 102 221 Section 11.1.17.
      */
+    @Test
     public void testIccCloseLogicalChannel() {
-        if (!hasCellular) return;
-
         // The directory here doesn't matter - we just need to open a valid connection that can
         // later be closed. In this case, the specified AID ("") opens a channel and selects the MF.
         IccOpenLogicalChannelResponse response = mTelephonyManager.iccOpenLogicalChannel("");
 
         // Check that the select command succeeded. This ensures that the logical channel is indeed
         // open.
-        assertArrayEquals(STATUS_NORMAL, response.getSelectResponse());
-        assertTrue(mTelephonyManager.iccCloseLogicalChannel(response.getChannel()));
+        assertThat(response.getSelectResponse()).isEqualTo(STATUS_NORMAL);
+        assertThat(mTelephonyManager.iccCloseLogicalChannel(response.getChannel())).isTrue();
 
         // Close opened channel twice.
-        assertFalse(mTelephonyManager.iccCloseLogicalChannel(response.getChannel()));
+        assertThat(mTelephonyManager.iccCloseLogicalChannel(response.getChannel())).isFalse();
 
         // Channel 0 is guaranteed to be always available and cannot be closed, per TS 102 221
         // Section 11.1.17
-        assertFalse(mTelephonyManager.iccCloseLogicalChannel(0));
+        assertThat(mTelephonyManager.iccCloseLogicalChannel(0)).isFalse();
     }
 
     /**
      * This test ensures that valid APDU instructions can be sent and processed by the ICC. To do
-     * so, APDUs are sent to:
-     * - get the status of the MF
-     * - select the Access Rule Reference (ARR) for the MF
-     * - get the FCP template response for the select
+     * so, APDUs are sent to: - get the status of the MF - select the Access Rule Reference (ARR)
+     * for the MF - get the FCP template response for the select
      */
+    @Test
     public void testIccTransmitApduLogicalChannel() {
-        if (!hasCellular) return;
-
         // An open LC is required for transmitting APDU commands. This opens an LC to the MF.
         IccOpenLogicalChannelResponse iccOpenLogicalChannelResponse =
                 mTelephonyManager.iccOpenLogicalChannel("");
@@ -741,7 +756,7 @@
             int cla = CLA_STATUS;
             int p1 = 0; // no indication of application status
             int p2 = 0; // same response parameters as the SELECT in the iccOpenLogicalChannel()
-                        // above
+            // above
             int p3 = 0; // length of 'data' payload
             String data = "";
             String response =
@@ -749,8 +764,8 @@
                             logicalChannel, cla, COMMAND_STATUS, p1, p2, p3, data);
             FcpTemplate fcpTemplate = FcpTemplate.parseFcpTemplate(response);
             // Check that the FCP Template's file ID matches the MF
-            assertTrue(containsFileId(fcpTemplate, MF_FILE_ID));
-            assertEquals(STATUS_NORMAL_STRING, fcpTemplate.getStatus());
+            assertThat(containsFileId(fcpTemplate, MF_FILE_ID)).isTrue();
+            assertThat(fcpTemplate.getStatus()).isEqualTo(STATUS_NORMAL_STRING);
 
             // Select the Access Rule Reference for the MF. Similar to the MF, this will exist
             // across all SIM cards. TS 102 221 Section 11.1.1
@@ -785,8 +800,8 @@
 
             fcpTemplate = FcpTemplate.parseFcpTemplate(response);
             // Check that the FCP Template's file ID matches the selected ARR
-            assertTrue(containsFileId(fcpTemplate, MF_ARR_FILE_ID));
-            assertEquals(STATUS_NORMAL_STRING, fcpTemplate.getStatus());
+            assertThat(containsFileId(fcpTemplate, MF_ARR_FILE_ID)).isTrue();
+            assertThat(fcpTemplate.getStatus()).isEqualTo(STATUS_NORMAL_STRING);
         } finally {
             mTelephonyManager.iccCloseLogicalChannel(logicalChannel);
         }
@@ -796,9 +811,8 @@
      * Tests several invalid APDU instructions over a logical channel and makes sure appropriate
      * errors are returned from the UICC.
      */
+    @Test
     public void testIccTransmitApduLogicalChannelWithInvalidInputs() {
-        if (!hasCellular) return;
-
         // An open LC is required for transmitting apdu commands. This opens an LC to the MF.
         IccOpenLogicalChannelResponse iccOpenLogicalChannelResponse =
                 mTelephonyManager.iccOpenLogicalChannel("");
@@ -810,13 +824,13 @@
             int cla = CLA_STATUS | logicalChannel;
             int p1 = 0xFF; // only '00', '01', and '02' are allowed
             int p2 = 0; // same response parameters as the SELECT in the iccOpenLogicalChannel()
-                        // above
+            // above
             int p3 = 0; // length of 'data' payload
             String data = "";
             String response =
                     mTelephonyManager.iccTransmitApduLogicalChannel(
                             logicalChannel, cla, COMMAND_STATUS, p1, p2, p3, data);
-            assertTrue(INVALID_PARAMETERS_STATUSES.contains(response));
+            assertThat(INVALID_PARAMETERS_STATUSES.contains(response)).isTrue();
 
             // Select a file that doesn't exist
             cla = CLA_SELECT;
@@ -827,7 +841,7 @@
             response =
                     mTelephonyManager.iccTransmitApduLogicalChannel(
                             logicalChannel, cla, COMMAND_SELECT, p1, p2, p3, data);
-            assertEquals(STATUS_FILE_NOT_FOUND, response);
+            assertThat(response).isEqualTo(STATUS_FILE_NOT_FOUND);
 
             // Manage channel with incorrect p1 parameter
             cla = CLA_MANAGE_CHANNEL | logicalChannel;
@@ -838,7 +852,7 @@
             response =
                     mTelephonyManager.iccTransmitApduLogicalChannel(
                             logicalChannel, cla, COMMAND_MANAGE_CHANNEL, p1, p2, p3, data);
-            assertTrue(isErrorResponse(response));
+            assertThat(isErrorResponse(response)).isTrue();
 
             // Use an incorrect class byte for Status apdu
             cla = 0xFF;
@@ -849,7 +863,7 @@
             response =
                     mTelephonyManager.iccTransmitApduLogicalChannel(
                             logicalChannel, cla, COMMAND_STATUS, p1, p2, p3, data);
-            assertEquals(STATUS_WRONG_CLASS, response);
+            assertThat(response).isEqualTo(STATUS_WRONG_CLASS);
 
             // Provide a data field that is longer than described for Select apdu
             cla = CLA_SELECT | logicalChannel;
@@ -860,7 +874,7 @@
             response =
                     mTelephonyManager.iccTransmitApduLogicalChannel(
                             logicalChannel, cla, COMMAND_SELECT, p1, p2, p3, data);
-            assertTrue(isErrorResponse(response));
+            assertThat(isErrorResponse(response)).isTrue();
 
             // Use an invalid instruction
             cla = 0;
@@ -872,7 +886,7 @@
             response =
                     mTelephonyManager.iccTransmitApduLogicalChannel(
                             logicalChannel, cla, invalidInstruction, p1, p2, p3, data);
-            assertTrue(isErrorResponse(response));
+            assertThat(isErrorResponse(response)).isTrue();
         } finally {
             mTelephonyManager.iccCloseLogicalChannel(logicalChannel);
         }
@@ -882,9 +896,8 @@
      * This test ensures that files can be read off the UICC. This helps to test the SIM booting
      * process, as it process involves several file-reads. The ICCID is one of the first files read.
      */
+    @Test
     public void testApduFileRead() {
-        if (!hasCellular) return;
-
         // Open a logical channel and select the MF.
         IccOpenLogicalChannelResponse iccOpenLogicalChannel =
                 mTelephonyManager.iccOpenLogicalChannel("");
@@ -898,7 +911,7 @@
             String response =
                     mTelephonyManager.iccTransmitApduLogicalChannel(
                             logicalChannel, CLA_SELECT, COMMAND_SELECT, p1, p2, p3, ICCID_FILE_ID);
-            assertEquals(STATUS_NORMAL_STRING, response);
+            assertThat(response).isEqualTo(STATUS_NORMAL_STRING);
 
             // Read the contents of the ICCID.
             p1 = 0; // 0-byte offset
@@ -907,27 +920,25 @@
             response =
                     mTelephonyManager.iccTransmitApduLogicalChannel(
                             logicalChannel, CLA_READ_BINARY, COMMAND_READ_BINARY, p1, p2, p3, "");
-            assertTrue(response.endsWith(STATUS_NORMAL_STRING));
+            assertThat(response).endsWith(STATUS_NORMAL_STRING);
         } finally {
             mTelephonyManager.iccCloseLogicalChannel(logicalChannel);
         }
     }
 
-    /**
-     * This test sends several valid APDU commands over the basic channel (channel 0).
-     */
+    /** This test sends several valid APDU commands over the basic channel (channel 0). */
+    @Test
     public void testIccTransmitApduBasicChannel() {
-        if (!hasCellular) return;
-
         // select the MF
         int cla = CLA_SELECT;
         int p1 = 0; // select EF by FID
         int p2 = 0x0C; // requesting FCP template
         int p3 = 2; // length of 'data' payload
         String data = MF_FILE_ID;
-        String response = mTelephonyManager
-            .iccTransmitApduBasicChannel(cla, COMMAND_SELECT, p1, p2, p3, data);
-        assertEquals(STATUS_NORMAL_STRING, response);
+        String response =
+                mTelephonyManager.iccTransmitApduBasicChannel(
+                        cla, COMMAND_SELECT, p1, p2, p3, data);
+        assertThat(response).isEqualTo(STATUS_NORMAL_STRING);
 
         // get the Status of the current file/directory
         cla = CLA_STATUS;
@@ -935,10 +946,11 @@
         p2 = 0; // same response parameters as the SELECT in the iccOpenLogicalChannel() above
         p3 = 0; // length of 'data' payload
         data = "";
-        response = mTelephonyManager
-            .iccTransmitApduBasicChannel(cla, COMMAND_STATUS, p1, p2, p3, data);
+        response =
+                mTelephonyManager.iccTransmitApduBasicChannel(
+                        cla, COMMAND_STATUS, p1, p2, p3, data);
         FcpTemplate fcpTemplate = FcpTemplate.parseFcpTemplate(response);
-        assertTrue(containsFileId(fcpTemplate, MF_FILE_ID));
+        assertThat(containsFileId(fcpTemplate, MF_FILE_ID)).isTrue();
 
         // Manually open a logical channel
         cla = CLA_MANAGE_CHANNEL;
@@ -946,11 +958,12 @@
         p2 = 0; // '00' for open command
         p3 = 0; // length of data payload
         data = "";
-        response = mTelephonyManager
-            .iccTransmitApduBasicChannel(cla, COMMAND_MANAGE_CHANNEL, p1, p2, p3, data);
+        response =
+                mTelephonyManager.iccTransmitApduBasicChannel(
+                        cla, COMMAND_MANAGE_CHANNEL, p1, p2, p3, data);
         // response is in the format | 1 byte: channel number | 2 bytes: status word |
         String responseStatus = response.substring(2);
-        assertEquals(STATUS_NORMAL_STRING, responseStatus);
+        assertThat(responseStatus).isEqualTo(STATUS_NORMAL_STRING);
 
         // Close the open channel
         byte[] responseBytes = hexStringToBytes(response);
@@ -960,18 +973,18 @@
         p2 = channel; // the channel to be closed
         p3 = 0; // length of data payload
         data = "";
-        response = mTelephonyManager
-            .iccTransmitApduBasicChannel(cla, COMMAND_MANAGE_CHANNEL, p1, p2, p3, data);
-        assertEquals(STATUS_NORMAL_STRING, response);
+        response =
+                mTelephonyManager.iccTransmitApduBasicChannel(
+                        cla, COMMAND_MANAGE_CHANNEL, p1, p2, p3, data);
+        assertThat(response).isEqualTo(STATUS_NORMAL_STRING);
     }
 
     /**
      * This test verifies that {@link TelephonyManager#setLine1NumberForDisplay(String, String)}
      * correctly sets the Line 1 alpha tag and number when called.
      */
+    @Test
     public void testLine1NumberForDisplay() {
-        if (!hasCellular) return;
-
         // Cache original alpha tag and number values.
         String originalAlphaTag = mTelephonyManager.getLine1AlphaTag();
         String originalNumber = mTelephonyManager.getLine1Number();
@@ -982,18 +995,18 @@
             String defaultAlphaTag = mTelephonyManager.getLine1AlphaTag();
             String defaultNumber = mTelephonyManager.getLine1Number();
 
-            assertTrue(mTelephonyManager.setLine1NumberForDisplay(ALPHA_TAG_A, NUMBER_A));
-            assertEquals(ALPHA_TAG_A, mTelephonyManager.getLine1AlphaTag());
-            assertEquals(NUMBER_A, mTelephonyManager.getLine1Number());
+            assertThat(mTelephonyManager.setLine1NumberForDisplay(ALPHA_TAG_A, NUMBER_A)).isTrue();
+            assertThat(mTelephonyManager.getLine1AlphaTag()).isEqualTo(ALPHA_TAG_A);
+            assertThat(mTelephonyManager.getLine1Number()).isEqualTo(NUMBER_A);
 
-            assertTrue(mTelephonyManager.setLine1NumberForDisplay(ALPHA_TAG_B, NUMBER_B));
-            assertEquals(ALPHA_TAG_B, mTelephonyManager.getLine1AlphaTag());
-            assertEquals(NUMBER_B, mTelephonyManager.getLine1Number());
+            assertThat(mTelephonyManager.setLine1NumberForDisplay(ALPHA_TAG_B, NUMBER_B)).isTrue();
+            assertThat(mTelephonyManager.getLine1AlphaTag()).isEqualTo(ALPHA_TAG_B);
+            assertThat(mTelephonyManager.getLine1Number()).isEqualTo(NUMBER_B);
 
             // null is used to clear the Line 1 alpha tag and number values.
-            assertTrue(mTelephonyManager.setLine1NumberForDisplay(null, null));
-            assertEquals(defaultAlphaTag, mTelephonyManager.getLine1AlphaTag());
-            assertEquals(defaultNumber, mTelephonyManager.getLine1Number());
+            assertThat(mTelephonyManager.setLine1NumberForDisplay(null, null)).isTrue();
+            assertThat(mTelephonyManager.getLine1AlphaTag()).isEqualTo(defaultAlphaTag);
+            assertThat(mTelephonyManager.getLine1Number()).isEqualTo(defaultNumber);
         } finally {
             // Reset original alpha tag and number values.
             mTelephonyManager.setLine1NumberForDisplay(originalAlphaTag, originalNumber);
@@ -1004,21 +1017,20 @@
      * This test verifies that {@link TelephonyManager#setVoiceMailNumber(String, String)} correctly
      * sets the VoiceMail alpha tag and number when called.
      */
+    @Test
     public void testVoiceMailNumber() {
-        if (!hasCellular) return;
-
         // Cache original alpha tag and number values.
         String originalAlphaTag = mTelephonyManager.getVoiceMailAlphaTag();
         String originalNumber = mTelephonyManager.getVoiceMailNumber();
 
         try {
-            assertTrue(mTelephonyManager.setVoiceMailNumber(ALPHA_TAG_A, NUMBER_A));
-            assertEquals(ALPHA_TAG_A, mTelephonyManager.getVoiceMailAlphaTag());
-            assertEquals(NUMBER_A, mTelephonyManager.getVoiceMailNumber());
+            assertThat(mTelephonyManager.setVoiceMailNumber(ALPHA_TAG_A, NUMBER_A)).isTrue();
+            assertThat(mTelephonyManager.getVoiceMailAlphaTag()).isEqualTo(ALPHA_TAG_A);
+            assertThat(mTelephonyManager.getVoiceMailNumber()).isEqualTo(NUMBER_A);
 
-            assertTrue(mTelephonyManager.setVoiceMailNumber(ALPHA_TAG_B, NUMBER_B));
-            assertEquals(ALPHA_TAG_B, mTelephonyManager.getVoiceMailAlphaTag());
-            assertEquals(NUMBER_B, mTelephonyManager.getVoiceMailNumber());
+            assertThat(mTelephonyManager.setVoiceMailNumber(ALPHA_TAG_B, NUMBER_B)).isTrue();
+            assertThat(mTelephonyManager.getVoiceMailAlphaTag()).isEqualTo(ALPHA_TAG_B);
+            assertThat(mTelephonyManager.getVoiceMailNumber()).isEqualTo(NUMBER_B);
         } finally {
             // Reset original alpha tag and number values.
             mTelephonyManager.setVoiceMailNumber(originalAlphaTag, originalNumber);
@@ -1029,12 +1041,11 @@
      * This test verifies that {@link SubscriptionManager#createSubscriptionGroup(List)} correctly
      * create a group with the given subscription id.
      *
-     * This also verifies that
-     * {@link SubscriptionManager#removeSubscriptionsFromGroup(List, ParcelUuid)} correctly remove
-     * the given subscription group.
+     * <p>This also verifies that {@link SubscriptionManager#removeSubscriptionsFromGroup(List,
+     * ParcelUuid)} correctly remove the given subscription group.
      */
+    @Test
     public void testCreateAndRemoveSubscriptionGroup() {
-        if (!hasCellular) return;
         // Set subscription group with current sub Id.
         int subId = SubscriptionManager.getDefaultSubscriptionId();
         List<Integer> subGroup = Arrays.asList(subId);
@@ -1044,19 +1055,20 @@
         List<SubscriptionInfo> infoList = mSubscriptionManager.getSubscriptionsInGroup(uuid);
 
         try {
-            assertEquals(1, infoList.size());
-            assertEquals(uuid, infoList.get(0).getGroupUuid());
-            assertEquals(subId, infoList.get(0).getSubscriptionId());
+            assertThat(infoList).hasSize(1);
+            assertThat(infoList.get(0).getGroupUuid()).isEqualTo(uuid);
+            assertThat(infoList.get(0).getSubscriptionId()).isEqualTo(subId);
         } finally {
             // Verify that the given subGroup has been removed.
             mSubscriptionManager.removeSubscriptionsFromGroup(subGroup, uuid);
             infoList = mSubscriptionManager.getSubscriptionsInGroup(uuid);
-            assertTrue(infoList.isEmpty());
+            assertThat(infoList).isEmpty();
         }
     }
 
+    @Test
     public void testAddSubscriptionToExistingGroupForMultipleSims() {
-        if (!hasCellular || mTelephonyManager.getPhoneCount() < DSDS_PHONE_COUNT) return;
+        if (mTelephonyManager.getPhoneCount() < DSDS_PHONE_COUNT) return;
 
         // Set subscription group with current sub Id.
         int subId = SubscriptionManager.getDefaultDataSubscriptionId();
@@ -1069,7 +1081,7 @@
                     mSubscriptionManager.getActiveSubscriptionInfoList();
 
             // Verify that the device has at least two active subscriptions.
-            assertTrue(activeSubInfos.size() >= DSDS_PHONE_COUNT);
+            assertThat(activeSubInfos.size()).isAtLeast(DSDS_PHONE_COUNT);
 
             List<Integer> activeSubGroup = getSubscriptionIdList(activeSubInfos);
             activeSubGroup.removeIf(id -> id == subId);
@@ -1079,23 +1091,21 @@
             List<Integer> infoList =
                     getSubscriptionIdList(mSubscriptionManager.getSubscriptionsInGroup(uuid));
             activeSubGroup.add(subId);
-            assertEquals(activeSubGroup.size(), infoList.size());
-            assertTrue(activeSubGroup.containsAll(infoList));
+            assertThat(infoList).hasSize(activeSubGroup.size());
+            assertThat(infoList).containsExactly(activeSubGroup);
         } finally {
             removeSubscriptionsFromGroup(uuid);
         }
     }
 
     /**
-     * This test verifies that
-     * {@link SubscriptionManager#addSubscriptionsIntoGroup(List, ParcelUuid)}} correctly add some
-     * additional subscriptions to the existing group.
+     * This test verifies that {@link SubscriptionManager#addSubscriptionsIntoGroup(List,
+     * ParcelUuid)}} correctly add some additional subscriptions to the existing group.
      *
-     * This test required the device has more than one subscription.
+     * <p>This test required the device has more than one subscription.
      */
+    @Test
     public void testAddSubscriptionToExistingGroupForEsim() {
-        if (!hasCellular) return;
-
         // Set subscription group with current sub Id.
         int subId = SubscriptionManager.getDefaultDataSubscriptionId();
         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return;
@@ -1114,8 +1124,8 @@
                 List<Integer> infoList =
                         getSubscriptionIdList(mSubscriptionManager.getSubscriptionsInGroup(uuid));
                 accessibleSubGroup.add(subId);
-                assertEquals(accessibleSubGroup.size(), infoList.size());
-                assertTrue(accessibleSubGroup.containsAll(infoList));
+                assertThat(infoList).hasSize(accessibleSubGroup.size());
+                assertThat(infoList).containsExactly(accessibleSubGroup);
             }
         } finally {
             removeSubscriptionsFromGroup(uuid);
@@ -1126,9 +1136,8 @@
      * This test verifies that {@link SubscriptionManager#setOpportunistic(boolean, int)} correctly
      * set the opportunistic property of the given subscription.
      */
+    @Test
     public void testOpportunistic() {
-        if (!hasCellular) return;
-
         int subId = SubscriptionManager.getDefaultDataSubscriptionId();
         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return;
         SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
@@ -1137,17 +1146,16 @@
 
         try {
             // Mark the given subscription as opportunistic subscription.
-            boolean successed = mSubscriptionManager.setOpportunistic(newOpportunistic, subId);
-            assertTrue(successed);
+            assertThat(mSubscriptionManager.setOpportunistic(newOpportunistic, subId)).isTrue();
 
             // Verify that the given subscription is opportunistic subscription.
             info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
-            assertEquals(newOpportunistic, info.isOpportunistic());
+            assertThat(info.isOpportunistic()).isEqualTo(newOpportunistic);
         } finally {
             // Set back to original opportunistic property.
             mSubscriptionManager.setOpportunistic(oldOpportunistic, subId);
             info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
-            assertEquals(oldOpportunistic, info.isOpportunistic());
+            assertThat(info.isOpportunistic()).isEqualTo(oldOpportunistic);
         }
     }
 
@@ -1156,9 +1164,8 @@
      * String)} correctly transmits iccIO commands to the UICC card. First, the MF is selected via a
      * SELECT apdu via the basic channel, then a STATUS AT-command is sent.
      */
+    @Test
     public void testIccExchangeSimIO() {
-        if (!hasCellular) return;
-
         // select the MF first. This makes sure the next STATUS AT-command returns a FCP template
         // for the right file.
         int cla = CLA_SELECT;
@@ -1166,65 +1173,71 @@
         int p2 = 0x0C; // requesting FCP template
         int p3 = 2; // length of 'data' payload
         String data = MF_FILE_ID;
-        String response = mTelephonyManager
-                .iccTransmitApduBasicChannel(cla, COMMAND_SELECT, p1, p2, p3, data);
-        assertEquals(STATUS_NORMAL_STRING, response);
+        String response =
+                mTelephonyManager.iccTransmitApduBasicChannel(
+                        cla, COMMAND_SELECT, p1, p2, p3, data);
+        assertThat(response).isEqualTo(STATUS_NORMAL_STRING);
 
         // The iccExchangeSimIO command implements the +CRSM command defined in TS 27.007 section
         // 8.18. A STATUS command is sent and the returned value will be an FCP template.
-        byte[] result = mTelephonyManager.iccExchangeSimIO(
-                0, // fileId: not required for STATUS
-                COMMAND_STATUS,  // command: STATUS
-                0, // p1: not required for STATUS
-                0, // p2: not required for STATUS
-                0, // p3: not required for STATUS
-                ""); // filePath: not required for STATUS
+        byte[] result =
+                mTelephonyManager.iccExchangeSimIO(
+                        0, // fileId: not required for STATUS
+                        COMMAND_STATUS, // command: STATUS
+                        0, // p1: not required for STATUS
+                        0, // p2: not required for STATUS
+                        0, // p3: not required for STATUS
+                        ""); // filePath: not required for STATUS
         String resultString = bytesToHexString(result);
         FcpTemplate fcpTemplate = FcpTemplate.parseFcpTemplate(resultString);
-        assertTrue(containsFileId(fcpTemplate, MF_FILE_ID));
-        assertEquals("iccExchangeSimIO returned non-normal Status byte: " + resultString,
-                STATUS_NORMAL_STRING, fcpTemplate.getStatus());
+        assertThat(containsFileId(fcpTemplate, MF_FILE_ID)).isTrue();
+        assertWithMessage("iccExchangeSimIO returned non-normal Status byte: %s", resultString)
+                .that(fcpTemplate.getStatus())
+                .isEqualTo(STATUS_NORMAL_STRING);
     }
 
     /**
      * This test checks that a STATUS apdu can be sent as an encapsulated envelope to the UICC via
      * {@link TelephonyManager#sendEnvelopeWithStatus(String)}.
      */
+    @Test
     public void testSendEnvelopeWithStatus() {
-        if (!hasCellular) return;
-
         // STATUS apdu as hex String
         String envelope =
                 CLA_STATUS_STRING
-                + COMMAND_STATUS_STRING
-                + "00" // p1: no indication of application status
-                + "00"; // p2: identical parameters to
+                        + COMMAND_STATUS_STRING
+                        + "00" // p1: no indication of application status
+                        + "00"; // p2: identical parameters to
         String response = mTelephonyManager.sendEnvelopeWithStatus(envelope);
 
         // TODO(b/137963715): add more specific assertions on response from TelMan#sendEnvelope
-        assertNotNull("sendEnvelopeWithStatus is null for envelope=" + envelope, response);
+        assertWithMessage("sendEnvelopeWithStatus is null for envelope=%s", envelope)
+                .that(response)
+                .isNotNull();
     }
 
     /**
      * This test checks that applications with carrier privilege can set/clear signal strength
-     * update request via
-     * {@link TelephonyManager#setSignalStrengthUpdateRequest(SignalStrengthUpdateRequest)} and
-     * {@link TelephonyManager#clearSignalStrengthUpdateRequest} without
-     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     * update request via {@link
+     * TelephonyManager#setSignalStrengthUpdateRequest(SignalStrengthUpdateRequest)} and {@link
+     * TelephonyManager#clearSignalStrengthUpdateRequest} without {@link
+     * android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
      */
+    @Test
     public void testSetClearSignalStrengthUpdateRequest() {
-        if (!hasCellular) return;
-
         final SignalStrengthUpdateRequest request =
                 new SignalStrengthUpdateRequest.Builder()
-                        .setSignalThresholdInfos(List.of(
-                                new SignalThresholdInfo.Builder()
-                                        .setRadioAccessNetworkType(
-                                                AccessNetworkConstants.AccessNetworkType.GERAN)
-                                        .setSignalMeasurementType(
-                                                SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI)
-                                        .setThresholds(new int[]{-113, -103, -97, -51})
-                                        .build()))
+                        .setSignalThresholdInfos(
+                                List.of(
+                                        new SignalThresholdInfo.Builder()
+                                                .setRadioAccessNetworkType(
+                                                        AccessNetworkConstants.AccessNetworkType
+                                                                .GERAN)
+                                                .setSignalMeasurementType(
+                                                        SignalThresholdInfo
+                                                                .SIGNAL_MEASUREMENT_TYPE_RSSI)
+                                                .setThresholds(new int[] {-113, -103, -97, -51})
+                                                .build()))
                         .setReportingRequestedWhileIdle(true)
                         .build();
         try {
@@ -1237,20 +1250,19 @@
     private void verifyValidIccOpenLogicalChannelResponse(IccOpenLogicalChannelResponse response) {
         // The assigned channel should be between the min and max allowed channel numbers
         int channel = response.getChannel();
-        assertTrue(MIN_LOGICAL_CHANNEL <= channel && channel <= MAX_LOGICAL_CHANNEL);
-        assertEquals(STATUS_NO_ERROR, response.getStatus());
-        assertArrayEquals(STATUS_NORMAL, response.getSelectResponse());
+        assertThat(channel).isIn(Range.closed(MIN_LOGICAL_CHANNEL, MAX_LOGICAL_CHANNEL));
+        assertThat(response.getStatus()).isEqualTo(STATUS_NO_ERROR);
+        assertThat(response.getSelectResponse()).isEqualTo(STATUS_NORMAL);
     }
 
     private void removeSubscriptionsFromGroup(ParcelUuid uuid) {
         List<SubscriptionInfo> infoList = mSubscriptionManager.getSubscriptionsInGroup(uuid);
         if (!infoList.isEmpty()) {
             mSubscriptionManager.removeSubscriptionsFromGroup(
-                    getSubscriptionIdList(infoList),
-                    uuid);
+                    getSubscriptionIdList(infoList), uuid);
         }
         infoList = mSubscriptionManager.getSubscriptionsInGroup(uuid);
-        assertTrue(infoList.isEmpty());
+        assertThat(infoList).isEmpty();
     }
 
     private List<Integer> getSubscriptionIdList(List<SubscriptionInfo> subInfoList) {
@@ -1265,26 +1277,24 @@
      *
      * @param fcpTemplate The FCP Template to be checked.
      * @param fileId The file ID that is being searched for
-     *
      * @return true iff fcpTemplate contains fileId.
      */
     private boolean containsFileId(FcpTemplate fcpTemplate, String fileId) {
-        return fcpTemplate.getTlvs().stream().anyMatch(tlv ->
-                tlv.getTag() == FILE_IDENTIFIER && tlv.getValue().equals(fileId));
+        return fcpTemplate.getTlvs().stream()
+                .anyMatch(tlv -> tlv.getTag() == FILE_IDENTIFIER && tlv.getValue().equals(fileId));
     }
 
     /**
      * Returns true iff {@code response} indicates an error with the previous APDU.
      *
      * @param response The APDU response to be checked.
-     *
      * @return true iff the given response indicates an error occurred
      */
     private boolean isErrorResponse(@Nonnull String response) {
-        return !(STATUS_NORMAL_STRING.equals(response) ||
-            response.startsWith(STATUS_WARNING_A) ||
-            response.startsWith(STATUS_WARNING_B) ||
-            response.startsWith(STATUS_BYTES_REMAINING));
+        return !(STATUS_NORMAL_STRING.equals(response)
+                || response.startsWith(STATUS_WARNING_A)
+                || response.startsWith(STATUS_WARNING_B)
+                || response.startsWith(STATUS_BYTES_REMAINING));
     }
 
     private static class IntentReceiver extends BroadcastReceiver {
@@ -1300,7 +1310,8 @@
         }
     }
 
-    @Suppress
+    @Test
+    @Ignore
     public void testEapSimAuthentication() {
         // K: '000102030405060708090A0B0C0D0E0F', defined by TS 134 108#8.2
         // n: 128 (Bits to use for RES value)
@@ -1313,13 +1324,13 @@
                         TelephonyManager.AUTHTYPE_EAP_SIM,
                         base64Challenge);
         byte[] response = Base64.decode(base64Response, Base64.DEFAULT);
-        assertArrayEquals(
-                "Results for AUTHTYPE_EAP_SIM failed",
-                hexStringToBytes(EXPECTED_EAP_SIM_RESULT),
-                response);
+        assertWithMessage("Results for AUTHTYPE_EAP_SIM failed")
+                .that(response)
+                .isEqualTo(hexStringToBytes(EXPECTED_EAP_SIM_RESULT));
     }
 
-    @Suppress
+    @Test
+    @Ignore
     public void testEapAkaAuthentication() {
         // K: '000102030405060708090A0B0C0D0E0F', defined by TS 134 108#8.2
         // n: 128 (Bits to use for RES value)
@@ -1332,14 +1343,13 @@
                         TelephonyManager.AUTHTYPE_EAP_AKA,
                         base64Challenge);
 
-        assertNotNull("UICC returned null for EAP-AKA auth", base64Response);
+        assertWithMessage("UICC returned null for EAP-AKA auth").that(base64Response).isNotNull();
         byte[] response = Base64.decode(base64Response, Base64.NO_WRAP);
 
         // response may be formatted as: [DB][Length][RES][Length][CK][Length][IK][Length][Kc]
         byte[] akaResponse = Arrays.copyOfRange(response, 0, EAP_AKA_RESPONSE_LENGTH);
-        assertArrayEquals(
-                "Results for AUTHTYPE_EAP_AKA failed",
-                hexStringToBytes(EXPECTED_EAP_AKA_RESULT),
-                akaResponse);
+        assertWithMessage("Results for AUTHTYPE_EAP_AKA failed")
+                .that(akaResponse)
+                .isEqualTo(hexStringToBytes(EXPECTED_EAP_AKA_RESULT));
     }
 }
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/FcpTemplate.java b/tests/tests/carrierapi/src/android/carrierapi/cts/FcpTemplate.java
index a90c756..252b874 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/FcpTemplate.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/FcpTemplate.java
@@ -21,13 +21,14 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+
 import javax.annotation.Nonnull;
 
 /**
  * Class for representing a File Control Parameters (FCP) Template object. TS 101 220
  *
- * A correctly formatted FCP Template will be in the format:
- * | 1 byte: BER tag (0x62) | 1 byte: length of TLVs |...TLV objects...| 2 bytes: status |
+ * <p>A correctly formatted FCP Template will be in the format: | 1 byte: BER tag (0x62) | 1 byte:
+ * length of TLVs |...TLV objects...| 2 bytes: status |
  */
 public class FcpTemplate {
 
@@ -69,12 +70,11 @@
      * Parses and returns a FcpTemplate for the given {@code fcpResponse}
      *
      * @param fcpResponse The Hex String response for a given Status APDU command. Expected to be in
-     * the format: | 1 byte: BER tag | 1 byte: length of TLVs |...TLV objects...| 2 bytes: status |
-     *
+     *     the format: | 1 byte: BER tag | 1 byte: length of TLVs |...TLV objects...| 2 bytes:
+     *     status |
      * @return a FcpTemplate for the given hex String
-     *
      * @throws FcpTemplateParseException for non-FCP inputs or inputs of the wrong length (encoded
-     *                                   length does not match actual length)
+     *     length does not match actual length)
      */
     public static FcpTemplate parseFcpTemplate(@Nonnull String fcpResponse) {
         final List<Tlv> tlvObjects = new ArrayList<>();
@@ -98,17 +98,15 @@
             int tag = data[index++] & 0xFF;
             int length = data[index++] & 0xFF; // assumes that length is < 128 bytes.
             String value = fcpResponse.substring(index * 2, (index + length) * 2);
-            tlvObjects .add(new Tlv(tag, length, value));
+            tlvObjects.add(new Tlv(tag, length, value));
             index += length;
         }
 
         String status = fcpResponse.substring(fcpResponse.length() - 4);
-        return new FcpTemplate(tlvObjects , status);
+        return new FcpTemplate(tlvObjects, status);
     }
 
-    /**
-     * Represents a Tag-Length-Value object. TS 101 220 Section 2
-     */
+    /** Represents a Tag-Length-Value object. TS 101 220 Section 2 */
     public static class Tlv {
 
         private final int tag;
@@ -142,9 +140,7 @@
                 return false;
             }
             Tlv tlv = (Tlv) o;
-            return tag == tlv.tag &&
-                    length == tlv.length &&
-                    value.equals(tlv.value);
+            return tag == tlv.tag && length == tlv.length && value.equals(tlv.value);
         }
 
         @Override
@@ -159,7 +155,6 @@
     }
 
     private static final class FcpTemplateParseException extends RuntimeException {
-
         public FcpTemplateParseException(String message) {
             super(message);
         }
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/IccUtils.java b/tests/tests/carrierapi/src/android/carrierapi/cts/IccUtils.java
index 3409fe5..d36ca03 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/IccUtils.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/IccUtils.java
@@ -18,20 +18,18 @@
 
 import javax.annotation.Nonnull;
 
-/**
- * Utility class for converting between hex Strings and bitwise representations.
- */
+/** Utility class for converting between hex Strings and bitwise representations. */
 public class IccUtils {
 
     // A table mapping from a number to a hex character for fast encoding hex strings.
     private static final char[] HEX_CHARS = {
-            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
     };
 
     @Nonnull
     public static String bytesToHexString(byte[] bytes) {
         StringBuilder ret = new StringBuilder(2 * bytes.length);
-        for (int i = 0 ; i < bytes.length ; i++) {
+        for (int i = 0; i < bytes.length; i++) {
             int b;
             b = 0x0f & (bytes[i] >> 4);
             ret.append(HEX_CHARS[b]);
@@ -44,11 +42,8 @@
     /**
      * Converts a hex String to a byte array.
      *
-     * @param s A string of hexadecimal characters, must be an even number of
-     *          chars long
-     *
+     * @param s A string of hexadecimal characters, must be an even number of chars long
      * @return byte array representation
-     *
      * @throws RuntimeException on invalid format
      */
     public static byte[] hexStringToBytes(String s) {
@@ -58,10 +53,10 @@
 
         int sz = s.length();
 
-        ret = new byte[sz/2];
+        ret = new byte[sz / 2];
 
-        for (int i=0 ; i <sz ; i+=2) {
-            ret[i/2] = (byte) ((hexCharToInt(s.charAt(i)) << 4) | hexCharToInt(s.charAt(i+1)));
+        for (int i = 0; i < sz; i += 2) {
+            ret[i / 2] = (byte) ((hexCharToInt(s.charAt(i)) << 4) | hexCharToInt(s.charAt(i + 1)));
         }
 
         return ret;
@@ -71,12 +66,13 @@
      * Converts a hex char to its integer value
      *
      * @param c A single hexadecimal character. Must be in one of these ranges:
-     *          - '0' to '9', or
-     *          - 'a' to 'f', or
-     *          - 'A' to 'F'
+     *     <ul>
+     *       <li>'0' to '9'
+     *       <li>'a' to 'f'
+     *       <li>'A' to 'F'
+     *     </ul>
      *
      * @return the integer representation of {@code c}
-     *
      * @throws RuntimeException on invalid character
      */
     public static int hexCharToInt(char c) {
@@ -84,6 +80,6 @@
         if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
         if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
 
-        throw new RuntimeException ("invalid hex char '" + c + "'");
+        throw new RuntimeException("invalid hex char '" + c + "'");
     }
 }
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
index 017d7fa..82655e9 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/NetworkScanApiTest.java
@@ -18,13 +18,12 @@
 import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.junit.Assert.fail;
 
-import android.content.Context;
+import android.content.ContentResolver;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
@@ -64,15 +63,16 @@
 import java.util.stream.Collectors;
 
 /**
- * Build, install and run the tests by running the commands below:
- *  make cts -j64
- *  cts-tradefed run cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.NetworkScanApiTest
+ * Unit tests for {@link TelephonyManager}'s network scan APIs.
+ *
+ * <p>Test using `atest CtsCarrierApiTestCases:NetworkScanApiTest` or `make cts -j64 && cts-tradefed
+ * run cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.NetworkScanApiTest`
  */
 @RunWith(AndroidJUnit4.class)
-public class NetworkScanApiTest {
-    private TelephonyManager mTelephonyManager;
-    private PackageManager mPackageManager;
+public class NetworkScanApiTest extends BaseCarrierApiTest {
     private static final String TAG = "NetworkScanApiTest";
+
+    private TelephonyManager mTelephonyManager;
     private int mNetworkScanStatus;
     private static final int EVENT_NETWORK_SCAN_START = 100;
     private static final int EVENT_NETWORK_SCAN_RESULTS = 200;
@@ -103,18 +103,18 @@
     private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
     private static final ArrayList<String> MCC_MNC = new ArrayList<>();
     private static final RadioAccessSpecifier[] RADIO_ACCESS_SPECIFIERS = {
-            new RadioAccessSpecifier(
-                    AccessNetworkConstants.AccessNetworkType.GERAN,
-                    null /* bands */,
-                    null /* channels */),
-            new RadioAccessSpecifier(
-                    AccessNetworkConstants.AccessNetworkType.EUTRAN,
-                    null /* bands */,
-                    null /* channels */),
-            new RadioAccessSpecifier(
-                    AccessNetworkConstants.AccessNetworkType.UTRAN,
-                    null /* bands */,
-                    null /* channels */)
+        new RadioAccessSpecifier(
+                AccessNetworkConstants.AccessNetworkType.GERAN,
+                null /* bands */,
+                null /* channels */),
+        new RadioAccessSpecifier(
+                AccessNetworkConstants.AccessNetworkType.EUTRAN,
+                null /* bands */,
+                null /* channels */),
+        new RadioAccessSpecifier(
+                AccessNetworkConstants.AccessNetworkType.UTRAN,
+                null /* bands */,
+                null /* channels */)
     };
 
     // Needed because NETWORK_SCAN_PERMISSION is a systemapi
@@ -122,20 +122,25 @@
 
     @Before
     public void setUp() throws Exception {
-        Context context = InstrumentationRegistry.getContext();
-        mTelephonyManager = (TelephonyManager)
-                context.getSystemService(Context.TELEPHONY_SERVICE);
-        mPackageManager = context.getPackageManager();
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
-                context.getPackageName(), ACCESS_FINE_LOCATION);
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
-                context.getPackageName(), ACCESS_BACKGROUND_LOCATION);
+        mTelephonyManager = getContext().getSystemService(TelephonyManager.class);
+        String selfPackageName = getContext().getPackageName();
+        InstrumentationRegistry.getInstrumentation()
+                .getUiAutomation()
+                .grantRuntimePermission(selfPackageName, ACCESS_FINE_LOCATION);
+        InstrumentationRegistry.getInstrumentation()
+                .getUiAutomation()
+                .grantRuntimePermission(selfPackageName, ACCESS_BACKGROUND_LOCATION);
         mTestHandlerThread = new NetworkScanHandlerThread(TAG);
         mTestHandlerThread.start();
     }
 
     @After
     public void tearDown() throws Exception {
+        if (!werePreconditionsSatisfied()) return;
+
+        // Revoking runtime permissions makes ActivityManager kill our process, so we don't do it,
+        // as the test harness will eventually uninstall this APK after testing completes anyway, so
+        // we aren't really leaking anything long-term.
         mTestHandlerThread.quit();
     }
 
@@ -146,9 +151,7 @@
             } catch (InterruptedException ie) {
             }
 
-            if (!mReady) {
-                fail("NetworkScanApiTest failed to initialize");
-            }
+            assertWithMessage("NetworkScanApiTest failed to initialize").that(mReady).isTrue();
         }
     }
 
@@ -168,41 +171,45 @@
         @Override
         public void onLooperPrepared() {
             /* create a custom handler for the Handler Thread */
-            mHandler = new Handler(mTestHandlerThread.getLooper()) {
-                @Override
-                public void handleMessage(Message msg) {
-                    switch (msg.what) {
-                        case EVENT_NETWORK_SCAN_START:
-                            Log.d(TAG, "request network scan");
-                            boolean useShellIdentity = (Boolean) msg.obj;
-                            if (useShellIdentity) {
-                                InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                                        .adoptShellPermissionIdentity();
+            mHandler =
+                    new Handler(mTestHandlerThread.getLooper()) {
+                        @Override
+                        public void handleMessage(Message msg) {
+                            switch (msg.what) {
+                                case EVENT_NETWORK_SCAN_START:
+                                    Log.d(TAG, "request network scan");
+                                    boolean useShellIdentity = (Boolean) msg.obj;
+                                    if (useShellIdentity) {
+                                        InstrumentationRegistry.getInstrumentation()
+                                                .getUiAutomation()
+                                                .adoptShellPermissionIdentity();
+                                    }
+                                    try {
+                                        mNetworkScan =
+                                                mTelephonyManager.requestNetworkScan(
+                                                        mNetworkScanRequest,
+                                                        AsyncTask.SERIAL_EXECUTOR,
+                                                        mNetworkScanCallback);
+                                        if (mNetworkScan == null) {
+                                            mNetworkScanStatus = EVENT_SCAN_DENIED;
+                                            setReady(true);
+                                        }
+                                    } catch (SecurityException e) {
+                                        mNetworkScanStatus = EVENT_SCAN_DENIED;
+                                        setReady(true);
+                                    } finally {
+                                        if (useShellIdentity) {
+                                            InstrumentationRegistry.getInstrumentation()
+                                                    .getUiAutomation()
+                                                    .dropShellPermissionIdentity();
+                                        }
+                                    }
+                                    break;
+                                default:
+                                    Log.d(TAG, "Unknown Event " + msg.what);
                             }
-                            try {
-                                mNetworkScan = mTelephonyManager.requestNetworkScan(
-                                        mNetworkScanRequest,
-                                        AsyncTask.SERIAL_EXECUTOR,
-                                        mNetworkScanCallback);
-                                if (mNetworkScan == null) {
-                                    mNetworkScanStatus = EVENT_SCAN_DENIED;
-                                    setReady(true);
-                                }
-                            } catch (SecurityException e) {
-                                mNetworkScanStatus = EVENT_SCAN_DENIED;
-                                setReady(true);
-                            } finally {
-                                if (useShellIdentity) {
-                                    InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                                            .dropShellPermissionIdentity();
-                                }
-                            }
-                            break;
-                        default:
-                            Log.d(TAG, "Unknown Event " + msg.what);
-                    }
-                }
-            };
+                        }
+                    };
         }
     }
 
@@ -265,39 +272,35 @@
             Log.d(TAG, "lte channels" + lteChannels.toString());
             int ranLte = AccessNetworkConstants.AccessNetworkType.EUTRAN;
             radioAccessSpecifier.add(
-                    new RadioAccessSpecifier(ranLte, null /* bands */,
-                            lteChannels.stream().mapToInt(i->i).toArray()));
+                    new RadioAccessSpecifier(
+                            ranLte,
+                            null /* bands */,
+                            lteChannels.stream().mapToInt(i -> i).toArray()));
         }
         if (!wcdmaChannels.isEmpty()) {
             Log.d(TAG, "wcdma channels" + wcdmaChannels.toString());
             int ranWcdma = AccessNetworkConstants.AccessNetworkType.UTRAN;
             radioAccessSpecifier.add(
-                    new RadioAccessSpecifier(ranWcdma, null /* bands */,
-                            wcdmaChannels.stream().mapToInt(i->i).toArray()));
+                    new RadioAccessSpecifier(
+                            ranWcdma,
+                            null /* bands */,
+                            wcdmaChannels.stream().mapToInt(i -> i).toArray()));
         }
         if (!gsmChannels.isEmpty()) {
             Log.d(TAG, "gsm channels" + gsmChannels.toString());
             int ranGsm = AccessNetworkConstants.AccessNetworkType.GERAN;
             radioAccessSpecifier.add(
-                    new RadioAccessSpecifier(ranGsm, null /* bands */,
-                            gsmChannels.stream().mapToInt(i->i).toArray()));
+                    new RadioAccessSpecifier(
+                            ranGsm,
+                            null /* bands */,
+                            gsmChannels.stream().mapToInt(i -> i).toArray()));
         }
         return radioAccessSpecifier;
     }
 
-    /**
-     * Tests that the device properly requests a network scan.
-     */
+    /** Tests that the device properly requests a network scan. */
     @Test
     public void testRequestNetworkScan() {
-        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
-            // Checks whether the cellular stack should be running on this device.
-            Log.e(TAG, "No cellular support, the test will be skipped.");
-            return;
-        }
-        if (!mTelephonyManager.hasCarrierPrivileges()) {
-            fail("This test requires a SIM card with carrier privilege rule on it.");
-        }
         boolean isLocationSwitchOn = getAndSetLocationSwitch(true);
         try {
             mNetworkScanRequest = buildNetworkScanRequest(true);
@@ -308,11 +311,16 @@
             waitUntilReady();
 
             Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus);
-            assertTrue("The final scan status is " + mNetworkScanStatus + " with error code "
-                            + mErrorCode + ", not ScanCompleted"
-                            + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or"
-                            + " ERROR_UNSUPPORTED",
-                    isScanStatusValid());
+            assertWithMessage(
+                            "The final scan status is "
+                                    + mNetworkScanStatus
+                                    + " with error code "
+                                    + mErrorCode
+                                    + ", not ScanCompleted"
+                                    + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or"
+                                    + " ERROR_UNSUPPORTED")
+                    .that(isScanStatusValid())
+                    .isTrue();
         } finally {
             getAndSetLocationSwitch(isLocationSwitchOn);
         }
@@ -328,40 +336,36 @@
         requestNetworkScanLocationOffHelper(true, true);
     }
 
-    public void requestNetworkScanLocationOffHelper(boolean includeBandsAndChannels,
-            boolean useSpecialScanPermission) {
-        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
-            // Checks whether the cellular stack should be running on this device.
-            Log.e(TAG, "No cellular support, the test will be skipped.");
-            return;
-        }
-        if (!mTelephonyManager.hasCarrierPrivileges()) {
-            fail("This test requires a SIM card with carrier privilege rule on it.");
-        }
-
+    public void requestNetworkScanLocationOffHelper(
+            boolean includeBandsAndChannels, boolean useSpecialScanPermission) {
         mNetworkScanRequest = buildNetworkScanRequest(includeBandsAndChannels);
 
         boolean isLocationSwitchOn = getAndSetLocationSwitch(false);
         try {
             mNetworkScanCallback = new NetworkScanCallbackImpl();
-            Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_START,
-                    useSpecialScanPermission);
+            Message startNetworkScan =
+                    mHandler.obtainMessage(EVENT_NETWORK_SCAN_START, useSpecialScanPermission);
             setReady(false);
             startNetworkScan.sendToTarget();
             waitUntilReady();
             if (includeBandsAndChannels) {
                 // If we included the bands when location is off, expect a security error and
                 // nothing else.
-                assertEquals(EVENT_SCAN_DENIED, mNetworkScanStatus);
+                assertThat(mNetworkScanStatus).isEqualTo(EVENT_SCAN_DENIED);
                 return;
             }
 
             Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus);
-            assertTrue("The final scan status is " + mNetworkScanStatus + " with error code "
-                            + mErrorCode + ", not ScanCompleted"
-                            + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or"
-                            + " ERROR_UNSUPPORTED",
-                    isScanStatusValid());
+            assertWithMessage(
+                            "The final scan status is "
+                                    + mNetworkScanStatus
+                                    + " with error code "
+                                    + mErrorCode
+                                    + ", not ScanCompleted"
+                                    + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or"
+                                    + " ERROR_UNSUPPORTED")
+                    .that(isScanStatusValid())
+                    .isTrue();
         } finally {
             getAndSetLocationSwitch(isLocationSwitchOn);
         }
@@ -376,32 +380,40 @@
             // Construct a NetworkScanRequest
             radioAccessSpecifier = getRadioAccessSpecifier(allCellInfo);
             if (!includeBandsAndChannels) {
-                radioAccessSpecifier = radioAccessSpecifier.stream().map(spec ->
-                    new RadioAccessSpecifier(spec.getRadioAccessNetwork(), null, null))
-                    .collect(Collectors.toList());
+                radioAccessSpecifier =
+                        radioAccessSpecifier.stream()
+                                .map(
+                                        spec ->
+                                                new RadioAccessSpecifier(
+                                                        spec.getRadioAccessNetwork(), null, null))
+                                .collect(Collectors.toList());
             }
         }
 
         Log.d(TAG, "number of radioAccessSpecifier: " + radioAccessSpecifier.size());
         if (radioAccessSpecifier.isEmpty()) {
             // Put in some arbitrary bands and channels so that we trip the location check if needed
-            int[] fakeBands = includeBandsAndChannels
-                    ? new int[] { AccessNetworkConstants.EutranBand.BAND_5 }
-                    : null;
-            int[] fakeChannels = includeBandsAndChannels ? new int[] { 2400 } : null;
+            int[] fakeBands =
+                    includeBandsAndChannels
+                            ? new int[] {AccessNetworkConstants.EutranBand.BAND_5}
+                            : null;
+            int[] fakeChannels = includeBandsAndChannels ? new int[] {2400} : null;
 
-            RadioAccessSpecifier gsm = new RadioAccessSpecifier(
-                    AccessNetworkConstants.AccessNetworkType.GERAN,
-                    null /* bands */,
-                    null /* channels */);
-            RadioAccessSpecifier lte = new RadioAccessSpecifier(
-                    AccessNetworkConstants.AccessNetworkType.EUTRAN,
-                    fakeBands /* bands */,
-                    fakeChannels /* channels */);
-            RadioAccessSpecifier wcdma = new RadioAccessSpecifier(
-                    AccessNetworkConstants.AccessNetworkType.UTRAN,
-                    null /* bands */,
-                    null /* channels */);
+            RadioAccessSpecifier gsm =
+                    new RadioAccessSpecifier(
+                            AccessNetworkConstants.AccessNetworkType.GERAN,
+                            null /* bands */,
+                            null /* channels */);
+            RadioAccessSpecifier lte =
+                    new RadioAccessSpecifier(
+                            AccessNetworkConstants.AccessNetworkType.EUTRAN,
+                            fakeBands /* bands */,
+                            fakeChannels /* channels */);
+            RadioAccessSpecifier wcdma =
+                    new RadioAccessSpecifier(
+                            AccessNetworkConstants.AccessNetworkType.UTRAN,
+                            null /* bands */,
+                            null /* channels */);
             radioAccessSpecifier.add(gsm);
             radioAccessSpecifier.add(lte);
             radioAccessSpecifier.add(wcdma);
@@ -416,7 +428,6 @@
                 true /*enable incremental results*/,
                 5 /* incremental results periodicity */,
                 null /* List of PLMN ids (MCC-MNC) */);
-
     }
 
     private List<CellInfo> getCellInfo() {
@@ -432,71 +443,87 @@
 
     @Test
     public void testNetworkScanPermission() {
-        PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+        PackageManager pm = getContext().getPackageManager();
 
-        List<Integer> specialUids = Arrays.asList(Process.SYSTEM_UID,
-                Process.PHONE_UID, Process.SHELL_UID);
+        List<Integer> specialUids =
+                Arrays.asList(Process.SYSTEM_UID, Process.PHONE_UID, Process.SHELL_UID);
 
-        List<PackageInfo> holding = pm.getPackagesHoldingPermissions(
-                new String[] { NETWORK_SCAN_PERMISSION },
-                PackageManager.MATCH_DISABLED_COMPONENTS);
+        List<PackageInfo> holding =
+                pm.getPackagesHoldingPermissions(
+                        new String[] {NETWORK_SCAN_PERMISSION},
+                        PackageManager.MATCH_DISABLED_COMPONENTS);
 
-        List<Integer> nonSpecialPackages = holding.stream()
-                .map(pi -> {
-                    try {
-                        return pm.getPackageUid(pi.packageName, 0);
-                    } catch (PackageManager.NameNotFoundException e) {
-                        return Process.INVALID_UID;
-                    }
-                })
-                .filter(uid -> !specialUids.contains(UserHandle.getAppId(uid)))
-                .collect(Collectors.toList());
+        List<Integer> nonSpecialPackages =
+                holding.stream()
+                        .map(
+                                pi -> {
+                                    try {
+                                        return pm.getPackageUid(pi.packageName, 0);
+                                    } catch (PackageManager.NameNotFoundException e) {
+                                        return Process.INVALID_UID;
+                                    }
+                                })
+                        .filter(uid -> !specialUids.contains(UserHandle.getAppId(uid)))
+                        .collect(Collectors.toList());
 
-        if (nonSpecialPackages.size() > 1) {
-            fail("Only one app on the device is allowed to hold the NETWORK_SCAN permission.");
-        }
+        assertWithMessage(
+                        "Only one app on the device is allowed to hold the NETWORK_SCAN"
+                                + " permission.")
+                .that(nonSpecialPackages.size())
+                .isAtMost(1);
     }
 
     private boolean getAndSetLocationSwitch(boolean enabled) {
         CountDownLatch locationChangeLatch = new CountDownLatch(1);
-        ContentObserver settingsObserver = new ContentObserver(mHandler) {
-            @Override
-            public void onChange(boolean selfChange) {
-                locationChangeLatch.countDown();
-                super.onChange(selfChange);
-            }
-        };
+        ContentObserver settingsObserver =
+                new ContentObserver(mHandler) {
+                    @Override
+                    public void onChange(boolean selfChange) {
+                        locationChangeLatch.countDown();
+                        super.onChange(selfChange);
+                    }
+                };
 
-        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+        InstrumentationRegistry.getInstrumentation()
+                .getUiAutomation()
                 .adoptShellPermissionIdentity();
+        ContentResolver contentResolver = getContext().getContentResolver();
         try {
-            int oldLocationMode = Settings.Secure.getInt(
-                    InstrumentationRegistry.getContext().getContentResolver(),
-                    Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
+            int oldLocationMode =
+                    Settings.Secure.getInt(
+                            contentResolver,
+                            Settings.Secure.LOCATION_MODE,
+                            Settings.Secure.LOCATION_MODE_OFF);
 
-            int locationMode = enabled ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
-                    : Settings.Secure.LOCATION_MODE_OFF;
+            int locationMode =
+                    enabled
+                            ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY
+                            : Settings.Secure.LOCATION_MODE_OFF;
             if (locationMode != oldLocationMode) {
-                InstrumentationRegistry.getContext().getContentResolver().registerContentObserver(
+                contentResolver.registerContentObserver(
                         Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE),
-                        false, settingsObserver);
-                Settings.Secure.putInt(InstrumentationRegistry.getContext().getContentResolver(),
-                        Settings.Secure.LOCATION_MODE, locationMode);
+                        false,
+                        settingsObserver);
+                Settings.Secure.putInt(
+                        contentResolver, Settings.Secure.LOCATION_MODE, locationMode);
                 try {
-                    assertTrue(locationChangeLatch.await(LOCATION_SETTING_CHANGE_WAIT_MS,
-                            TimeUnit.MILLISECONDS));
+                    assertThat(
+                                    locationChangeLatch.await(
+                                            LOCATION_SETTING_CHANGE_WAIT_MS, TimeUnit.MILLISECONDS))
+                            .isTrue();
                 } catch (InterruptedException e) {
-                    Log.w(NetworkScanApiTest.class.getSimpleName(),
+                    Log.w(
+                            NetworkScanApiTest.class.getSimpleName(),
                             "Interrupted while waiting for location settings change. Test results"
-                            + " may not be accurate.");
+                                    + " may not be accurate.");
                 } finally {
-                    InstrumentationRegistry.getContext().getContentResolver()
-                            .unregisterContentObserver(settingsObserver);
+                    contentResolver.unregisterContentObserver(settingsObserver);
                 }
             }
             return oldLocationMode == Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
         } finally {
-            InstrumentationRegistry.getInstrumentation().getUiAutomation()
+            InstrumentationRegistry.getInstrumentation()
+                    .getUiAutomation()
                     .dropShellPermissionIdentity();
         }
     }
@@ -509,7 +536,7 @@
         }
         if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_ERROR)
                 && ((mErrorCode == NetworkScan.ERROR_MODEM_UNAVAILABLE)
-                || (mErrorCode == NetworkScan.ERROR_UNSUPPORTED))) {
+                        || (mErrorCode == NetworkScan.ERROR_UNSUPPORTED))) {
             // Scan error but the error type is allowed.
             return true;
         }
@@ -523,130 +550,140 @@
         return mccMncs;
     }
 
-    /**
-     * To test its constructor and getters.
-     */
+    /** To test its constructor and getters. */
     @Test
-    public void testNetworkScanRequest_ConstructorAndGetters() {
-        NetworkScanRequest networkScanRequest = new NetworkScanRequest(
-                SCAN_TYPE,
-                RADIO_ACCESS_SPECIFIERS,
-                SEARCH_PERIODICITY_SEC,
-                MAX_SEARCH_TIME_SEC,
-                INCREMENTAL_RESULTS,
-                INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                getPlmns());
+    public void testNetworkScanRequest_constructorAndGetters() {
+        NetworkScanRequest networkScanRequest =
+                new NetworkScanRequest(
+                        SCAN_TYPE,
+                        RADIO_ACCESS_SPECIFIERS,
+                        SEARCH_PERIODICITY_SEC,
+                        MAX_SEARCH_TIME_SEC,
+                        INCREMENTAL_RESULTS,
+                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
+                        getPlmns());
 
-        assertEquals("getScanType() returns wrong value",
-                SCAN_TYPE, networkScanRequest.getScanType());
-        assertEquals("getSpecifiers() returns wrong value",
-                RADIO_ACCESS_SPECIFIERS, networkScanRequest.getSpecifiers());
-        assertEquals("getSearchPeriodicity() returns wrong value",
-                SEARCH_PERIODICITY_SEC, networkScanRequest.getSearchPeriodicity());
-        assertEquals("getMaxSearchTime() returns wrong value",
-                MAX_SEARCH_TIME_SEC, networkScanRequest.getMaxSearchTime());
-        assertEquals("getIncrementalResults() returns wrong value",
-                INCREMENTAL_RESULTS, networkScanRequest.getIncrementalResults());
-        assertEquals("getIncrementalResultsPeriodicity() returns wrong value",
-                INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                networkScanRequest.getIncrementalResultsPeriodicity());
-        assertEquals("getPlmns() returns wrong value", getPlmns(), networkScanRequest.getPlmns());
-        assertEquals("describeContents() returns wrong value",
-                0, networkScanRequest.describeContents());
+        assertWithMessage("getScanType() returns wrong value")
+                .that(networkScanRequest.getScanType())
+                .isEqualTo(SCAN_TYPE);
+        assertWithMessage("getSpecifiers() returns wrong value")
+                .that(networkScanRequest.getSpecifiers())
+                .isEqualTo(RADIO_ACCESS_SPECIFIERS);
+        assertWithMessage("getSearchPeriodicity() returns wrong value")
+                .that(networkScanRequest.getSearchPeriodicity())
+                .isEqualTo(SEARCH_PERIODICITY_SEC);
+        assertWithMessage("getMaxSearchTime() returns wrong value")
+                .that(networkScanRequest.getMaxSearchTime())
+                .isEqualTo(MAX_SEARCH_TIME_SEC);
+        assertWithMessage("getIncrementalResults() returns wrong value")
+                .that(networkScanRequest.getIncrementalResults())
+                .isEqualTo(INCREMENTAL_RESULTS);
+        assertWithMessage("getIncrementalResultsPeriodicity() returns wrong value")
+                .that(networkScanRequest.getIncrementalResultsPeriodicity())
+                .isEqualTo(INCREMENTAL_RESULTS_PERIODICITY_SEC);
+        assertWithMessage("getPlmns() returns wrong value")
+                .that(networkScanRequest.getPlmns())
+                .isEqualTo(getPlmns());
+        assertWithMessage("describeContents() returns wrong value")
+                .that(networkScanRequest.describeContents())
+                .isEqualTo(0);
     }
 
-    /**
-     * To test its hashCode method.
-     */
+    /** To test its hashCode method. */
     @Test
-    public void testNetworkScanRequestParcel_Hashcode() {
-        NetworkScanRequest networkScanRequest1 = new NetworkScanRequest(
-                SCAN_TYPE,
-                RADIO_ACCESS_SPECIFIERS,
-                SEARCH_PERIODICITY_SEC,
-                MAX_SEARCH_TIME_SEC,
-                INCREMENTAL_RESULTS,
-                INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                getPlmns());
+    public void testNetworkScanRequestParcel_hashCode() {
+        NetworkScanRequest networkScanRequest1 =
+                new NetworkScanRequest(
+                        SCAN_TYPE,
+                        RADIO_ACCESS_SPECIFIERS,
+                        SEARCH_PERIODICITY_SEC,
+                        MAX_SEARCH_TIME_SEC,
+                        INCREMENTAL_RESULTS,
+                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
+                        getPlmns());
 
-        NetworkScanRequest networkScanRequest2 = new NetworkScanRequest(
-                SCAN_TYPE,
-                RADIO_ACCESS_SPECIFIERS,
-                SEARCH_PERIODICITY_SEC,
-                MAX_SEARCH_TIME_SEC,
-                INCREMENTAL_RESULTS,
-                INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                getPlmns());
+        NetworkScanRequest networkScanRequest2 =
+                new NetworkScanRequest(
+                        SCAN_TYPE,
+                        RADIO_ACCESS_SPECIFIERS,
+                        SEARCH_PERIODICITY_SEC,
+                        MAX_SEARCH_TIME_SEC,
+                        INCREMENTAL_RESULTS,
+                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
+                        getPlmns());
 
-        NetworkScanRequest networkScanRequest3 = new NetworkScanRequest(
-                SCAN_TYPE,
-                null,
-                SEARCH_PERIODICITY_SEC,
-                MAX_SEARCH_TIME_SEC,
-                false,
-                0,
-                getPlmns());
+        NetworkScanRequest networkScanRequest3 =
+                new NetworkScanRequest(
+                        SCAN_TYPE,
+                        null,
+                        SEARCH_PERIODICITY_SEC,
+                        MAX_SEARCH_TIME_SEC,
+                        false,
+                        0,
+                        getPlmns());
 
-        assertEquals("hashCode() returns different hash code for same objects",
-                networkScanRequest1.hashCode(), networkScanRequest2.hashCode());
-        assertNotSame("hashCode() returns same hash code for different objects",
-                networkScanRequest1.hashCode(), networkScanRequest3.hashCode());
+        assertWithMessage("hashCode() returns different hash code for same objects")
+                .that(networkScanRequest1.hashCode())
+                .isEqualTo(networkScanRequest2.hashCode());
+        assertWithMessage("hashCode() returns same hash code for different objects")
+                .that(networkScanRequest1.hashCode())
+                .isNotEqualTo(networkScanRequest3.hashCode());
     }
 
-    /**
-     * To test its comparision method.
-     */
+    /** To test its comparison method. */
     @Test
-    public void testNetworkScanRequestParcel_Equals() {
-        NetworkScanRequest networkScanRequest1 = new NetworkScanRequest(
-                SCAN_TYPE,
-                RADIO_ACCESS_SPECIFIERS,
-                SEARCH_PERIODICITY_SEC,
-                MAX_SEARCH_TIME_SEC,
-                INCREMENTAL_RESULTS,
-                INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                getPlmns());
+    public void testNetworkScanRequestParcel_equals() {
+        NetworkScanRequest networkScanRequest1 =
+                new NetworkScanRequest(
+                        SCAN_TYPE,
+                        RADIO_ACCESS_SPECIFIERS,
+                        SEARCH_PERIODICITY_SEC,
+                        MAX_SEARCH_TIME_SEC,
+                        INCREMENTAL_RESULTS,
+                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
+                        getPlmns());
 
-        NetworkScanRequest networkScanRequest2 = new NetworkScanRequest(
-                SCAN_TYPE,
-                RADIO_ACCESS_SPECIFIERS,
-                SEARCH_PERIODICITY_SEC,
-                MAX_SEARCH_TIME_SEC,
-                INCREMENTAL_RESULTS,
-                INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                getPlmns());
+        NetworkScanRequest networkScanRequest2 =
+                new NetworkScanRequest(
+                        SCAN_TYPE,
+                        RADIO_ACCESS_SPECIFIERS,
+                        SEARCH_PERIODICITY_SEC,
+                        MAX_SEARCH_TIME_SEC,
+                        INCREMENTAL_RESULTS,
+                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
+                        getPlmns());
 
-        assertTrue(networkScanRequest1.equals(networkScanRequest2));
+        assertThat(networkScanRequest1).isEqualTo(networkScanRequest2);
 
-        networkScanRequest2 = new NetworkScanRequest(
-                SCAN_TYPE,
-                RADIO_ACCESS_SPECIFIERS,
-                SEARCH_PERIODICITY_SEC,
-                MAX_SEARCH_TIME_SEC,
-                INCREMENTAL_RESULTS,
-                INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                null /* List of PLMN ids (MCC-MNC) */);
-        assertFalse(networkScanRequest1.equals(networkScanRequest2));
+        networkScanRequest2 =
+                new NetworkScanRequest(
+                        SCAN_TYPE,
+                        RADIO_ACCESS_SPECIFIERS,
+                        SEARCH_PERIODICITY_SEC,
+                        MAX_SEARCH_TIME_SEC,
+                        INCREMENTAL_RESULTS,
+                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
+                        null /* List of PLMN ids (MCC-MNC) */);
+        assertThat(networkScanRequest1).isNotEqualTo(networkScanRequest2);
     }
 
-    /**
-     * To test its writeToParcel and createFromParcel methods.
-     */
+    /** To test its writeToParcel and createFromParcel methods. */
     @Test
-    public void testNetworkScanRequestParcel_Parcel() {
-        NetworkScanRequest networkScanRequest = new NetworkScanRequest(
-                SCAN_TYPE,
-                null /* Radio Access Specifier */,
-                SEARCH_PERIODICITY_SEC,
-                MAX_SEARCH_TIME_SEC,
-                INCREMENTAL_RESULTS,
-                INCREMENTAL_RESULTS_PERIODICITY_SEC,
-                getPlmns());
+    public void testNetworkScanRequestParcel_parcel() {
+        NetworkScanRequest networkScanRequest =
+                new NetworkScanRequest(
+                        SCAN_TYPE,
+                        null /* Radio Access Specifier */,
+                        SEARCH_PERIODICITY_SEC,
+                        MAX_SEARCH_TIME_SEC,
+                        INCREMENTAL_RESULTS,
+                        INCREMENTAL_RESULTS_PERIODICITY_SEC,
+                        getPlmns());
 
         Parcel p = Parcel.obtain();
         networkScanRequest.writeToParcel(p, 0);
         p.setDataPosition(0);
         NetworkScanRequest newnsr = NetworkScanRequest.CREATOR.createFromParcel(p);
-        assertTrue(networkScanRequest.equals(newnsr));
+        assertThat(networkScanRequest).isEqualTo(newnsr);
     }
 }
diff --git a/tests/tests/display/src/android/display/cts/DisplayTest.java b/tests/tests/display/src/android/display/cts/DisplayTest.java
index d72a56b..1ac4507 100644
--- a/tests/tests/display/src/android/display/cts/DisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayTest.java
@@ -807,7 +807,6 @@
         }
     }
 
-
     @Test
     public void testGetDeviceProductInfo() {
         DeviceProductInfo deviceProductInfo = mDefaultDisplay.getDeviceProductInfo();
@@ -839,6 +838,23 @@
     }
 
     @Test
+    public void testDeviceProductInfo() {
+        DeviceProductInfo deviceProductInfo = new DeviceProductInfo(
+                "DeviceName" /* name */,
+                "TTL" /* manufacturePnpId */,
+                "ProductId1" /* productId */,
+                2000 /* modelYear */,
+                DeviceProductInfo.CONNECTION_TO_SINK_DIRECT);
+
+        assertEquals("DeviceName", deviceProductInfo.getName());
+        assertEquals("TTL", deviceProductInfo.getManufacturerPnpId());
+        assertEquals("ProductId1", deviceProductInfo.getProductId());
+        assertEquals(2000, deviceProductInfo.getModelYear());
+        assertEquals(DeviceProductInfo.CONNECTION_TO_SINK_DIRECT,
+                deviceProductInfo.getConnectionToSinkType());
+    }
+
+    @Test
     public void testFailBrightnessChangeWithoutPermission() throws Exception {
         final DisplayTestActivity activity = launchActivity(mDisplayTestActivity);
         final int originalValue = Settings.System.getInt(mContext.getContentResolver(),
diff --git a/tests/tests/media/src/android/media/cts/PlaybackStateTest.java b/tests/tests/media/src/android/media/cts/PlaybackStateTest.java
index c68f208..54ae88b 100644
--- a/tests/tests/media/src/android/media/cts/PlaybackStateTest.java
+++ b/tests/tests/media/src/android/media/cts/PlaybackStateTest.java
@@ -283,37 +283,6 @@
         }
     }
 
-    public void testIsActive() {
-        int[] activeStates = new int[] {
-                PlaybackState.STATE_FAST_FORWARDING,
-                PlaybackState.STATE_REWINDING,
-                PlaybackState.STATE_SKIPPING_TO_PREVIOUS,
-                PlaybackState.STATE_SKIPPING_TO_NEXT,
-                PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM,
-                PlaybackState.STATE_BUFFERING,
-                PlaybackState.STATE_CONNECTING,
-                PlaybackState.STATE_PLAYING};
-
-        int[] nonActiveStates = new int[] {
-                PlaybackState.STATE_NONE,
-                PlaybackState.STATE_STOPPED,
-                PlaybackState.STATE_PAUSED,
-                PlaybackState.STATE_ERROR};
-
-        for (int i = 0; i < activeStates.length; i++) {
-            PlaybackState activePlaybackState = new PlaybackState.Builder()
-                    .setState(activeStates[i], 0, 1.0f)
-                    .build();
-            assertTrue(activePlaybackState.isActive());
-        }
-        for (int i = 0; i < nonActiveStates.length; i++) {
-            PlaybackState nonActivePlaybackState = new PlaybackState.Builder()
-                    .setState(nonActiveStates[i], 0, 1.0f)
-                    .build();
-            assertFalse(nonActivePlaybackState.isActive());
-        }
-    }
-
     private void assertCustomActionEquals(PlaybackState.CustomAction action1,
             PlaybackState.CustomAction action2) {
         assertEquals(action1.getAction(), action2.getAction());
diff --git a/tests/tests/media/src/android/media/cts/RoutingTest.java b/tests/tests/media/src/android/media/cts/RoutingTest.java
index f3972a8..cd70a51 100644
--- a/tests/tests/media/src/android/media/cts/RoutingTest.java
+++ b/tests/tests/media/src/android/media/cts/RoutingTest.java
@@ -456,7 +456,7 @@
         }
     }
 
-    public void test_audioTrack_getRoutedDevice() {
+    public void test_audioTrack_getRoutedDevice() throws Exception {
         if (!DeviceUtils.hasOutputDevice(mAudioManager)) {
             Log.i(TAG, "No output devices. Test skipped");
             return; // nothing to test here
@@ -484,17 +484,25 @@
         Thread fillerThread = new Thread(filler);
         fillerThread.start();
 
-        try { Thread.sleep(1000); } catch (InterruptedException ex) {}
-
-        // No explicit route
-        AudioDeviceInfo routedDevice = audioTrack.getRoutedDevice();
-        assertNotNull(routedDevice); // we probably can't say anything more than this
+        assertHasNonNullRoutedDevice(audioTrack);
 
         filler.stop();
         audioTrack.stop();
         audioTrack.release();
     }
 
+    private void assertHasNonNullRoutedDevice(AudioRouting router) throws Exception {
+        AudioDeviceInfo routedDevice = null;
+        // Give a chance for playback or recording to start so routing can be established
+        final long timeouts[] = { 100, 200, 500, 500, 1000};
+        int attempt = 0;
+        do {
+            try { Thread.sleep(timeouts[attempt++]); } catch (InterruptedException ex) {}
+            routedDevice = router.getRoutedDevice();
+        } while (routedDevice == null && attempt < timeouts.length);
+        assertNotNull(routedDevice); // we probably can't say anything more than this
+    }
+
     private class AudioRecordPuller implements Runnable {
         AudioRecord mAudioRecord;
         int mBufferSize;
@@ -520,7 +528,7 @@
         }
     }
 
-    public void test_audioRecord_getRoutedDevice() {
+    public void test_audioRecord_getRoutedDevice() throws Exception {
         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
             return;
         }
@@ -550,11 +558,7 @@
         Thread pullerThread = new Thread(puller);
         pullerThread.start();
 
-        try { Thread.sleep(1000); } catch (InterruptedException ex) {}
-
-        // No explicit route
-        AudioDeviceInfo routedDevice = audioRecord.getRoutedDevice();
-        assertNotNull(routedDevice); // we probably can't say anything more than this
+        assertHasNonNullRoutedDevice(audioRecord);
 
         puller.stop();
         audioRecord.stop();
@@ -645,7 +649,7 @@
         mediaPlayer.release();
     }
 
-    public void test_mediaPlayer_getRoutedDevice() {
+    public void test_mediaPlayer_getRoutedDevice() throws Exception {
         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
             // Can't do it so skip this test
             return;
@@ -654,12 +658,7 @@
         MediaPlayer mediaPlayer = allocMediaPlayer();
         assertTrue(mediaPlayer.isPlaying());
 
-        // Sleep for 1s to ensure the output device open
-        SystemClock.sleep(1000);
-
-        // No explicit route
-        AudioDeviceInfo routedDevice = mediaPlayer.getRoutedDevice();
-        assertNotNull(routedDevice);
+        assertHasNonNullRoutedDevice(mediaPlayer);
 
         mediaPlayer.stop();
         mediaPlayer.release();
diff --git a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodeManagerTest.java b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodeManagerTest.java
index 14d0cb6..805086f 100644
--- a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodeManagerTest.java
+++ b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodeManagerTest.java
@@ -466,14 +466,16 @@
                         .setClientPid(pid)
                         .setClientUid(uid);
 
+        AssetFileDescriptor srcFd = null;
+        AssetFileDescriptor dstFd = null;
         if (testFileDescriptor) {
             // Open source Uri.
-            AssetFileDescriptor afd = mContentResolver.openAssetFileDescriptor(fileUri,
+            srcFd = mContentResolver.openAssetFileDescriptor(fileUri,
                     "r");
-            builder.setSourceFileDescriptor(afd.getParcelFileDescriptor());
+            builder.setSourceFileDescriptor(srcFd.getParcelFileDescriptor());
             // Open destination Uri
-            afd = mContentResolver.openAssetFileDescriptor(destinationUri, "rw");
-            builder.setDestinationFileDescriptor(afd.getParcelFileDescriptor());
+            dstFd = mContentResolver.openAssetFileDescriptor(destinationUri, "rw");
+            builder.setDestinationFileDescriptor(dstFd.getParcelFileDescriptor());
         }
         VideoTranscodingRequest request = builder.build();
         Executor listenerExecutor = Executors.newSingleThreadExecutor();
@@ -493,6 +495,12 @@
                 });
         assertNotNull(session);
         assertTrue(compareFormat(videoTrackFormat, request.getVideoTrackFormat()));
+        assertEquals(fileUri, request.getSourceUri());
+        assertEquals(destinationUri, request.getDestinationUri());
+        if (testFileDescriptor) {
+            assertEquals(srcFd.getParcelFileDescriptor(), request.getSourceFileDescriptor());
+            assertEquals(dstFd.getParcelFileDescriptor(), request.getDestinationFileDescriptor());
+        }
 
         if (session != null) {
             Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
diff --git a/tests/tests/neuralnetworks/Android.mk b/tests/tests/neuralnetworks/Android.mk
index abd6818..01cf38f 100644
--- a/tests/tests/neuralnetworks/Android.mk
+++ b/tests/tests/neuralnetworks/Android.mk
@@ -38,6 +38,7 @@
 
 LOCAL_SDK_VERSION := current
 LOCAL_NDK_STL_VARIANT := c++_static
+LOCAL_MIN_SDK_VERSION := 30
 
 include $(BUILD_CTS_EXECUTABLE)
 
diff --git a/tests/tests/neuralnetworks/AndroidManifest.xml b/tests/tests/neuralnetworks/AndroidManifest.xml
new file mode 100644
index 0000000..de2efbd
--- /dev/null
+++ b/tests/tests/neuralnetworks/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.neuralnetworks">
+    <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="31" />
+</manifest>
+
diff --git a/tests/tests/neuralnetworks/benchmark/Android.mk b/tests/tests/neuralnetworks/benchmark/Android.mk
index 7f67499..5e57c06 100644
--- a/tests/tests/neuralnetworks/benchmark/Android.mk
+++ b/tests/tests/neuralnetworks/benchmark/Android.mk
@@ -36,6 +36,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_ASSET_DIR := test/mlts/models/assets
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 30
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/permission/src/android/permission/cts/NfcPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NfcPermissionTest.java
index 45dddb2..975414f 100644
--- a/tests/tests/permission/src/android/permission/cts/NfcPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NfcPermissionTest.java
@@ -23,7 +23,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.nfc.NfcAdapter;
-import android.nfc.NfcAdapter.ControllerAlwaysOnStateCallback;
+import android.nfc.NfcAdapter.ControllerAlwaysOnListener;
 import android.os.Process;
 
 import androidx.test.InstrumentationRegistry;
@@ -143,16 +143,16 @@
     }
 
     /**
-     * Verifies that registerControllerAlwaysOnStateCallback() requires Permission.
+     * Verifies that registerControllerAlwaysOnListener() requires Permission.
      * <p>
      * Requires Permission: {@link android.Manifest.permission#NFC_SET_CONTROLLER_ALWAYS_ON}.
      */
     @Test
-    public void testRegisterControllerAlwaysOnStateCallback() {
+    public void testRegisterControllerAlwaysOnListener() {
         try {
-            mNfcAdapter.registerControllerAlwaysOnStateCallback(
+            mNfcAdapter.registerControllerAlwaysOnListener(
                     new SynchronousExecutor(), new AlwaysOnStateListener());
-            fail("mNfcAdapter.registerControllerAlwaysOnStateCallback did not throw"
+            fail("mNfcAdapter.registerControllerAlwaysOnListener did not throw"
                     + "SecurityException as expected");
         } catch (SecurityException se) {
             // Expected Exception
@@ -165,9 +165,9 @@
         }
     }
 
-    private class AlwaysOnStateListener implements ControllerAlwaysOnStateCallback {
+    private class AlwaysOnStateListener implements ControllerAlwaysOnListener {
         @Override
-        public void onStateChanged(boolean isEnabled) {
+        public void onControllerAlwaysOnChanged(boolean isEnabled) {
             // Do nothing
         }
     }
diff --git a/tests/tests/preference/AndroidTest.xml b/tests/tests/preference/AndroidTest.xml
index 625ff4d..09741b9 100644
--- a/tests/tests/preference/AndroidTest.xml
+++ b/tests/tests/preference/AndroidTest.xml
@@ -34,10 +34,4 @@
         <option name="collect-on-run-ended-only" value="true" />
         <option name="clean-up" value="false" />
     </metrics_collector>
-    <!-- Automotive tests run on user 10 -->
-    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
-        <option name="directory-keys" value="/storage/emulated/10/CtsPreferenceTestCases" />
-        <option name="collect-on-run-ended-only" value="true" />
-        <option name="clean-up" value="false" />
-    </metrics_collector>
 </configuration>
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java b/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java
index 1de465e..b836871 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/CallLogTest.java
@@ -168,7 +168,8 @@
         Pair<Uri, CallLog.CallComposerLoggingException> result;
         try (InputStream inputStream =
                      context.getResources().openRawResource(R.drawable.testimage)) {
-            CallLog.storeCallComposerPictureAsUser(context, android.os.Process.myUserHandle(),
+            CallLog.storeCallComposerPicture(
+                    context.createContextAsUser(android.os.Process.myUserHandle(), 0),
                     inputStream,
                     Executors.newSingleThreadExecutor(),
                     new OutcomeReceiver<Uri, CallLog.CallComposerLoggingException>() {
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerConfigActivityTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerConfigActivityTest.java
index cc8df51..5947c39 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerConfigActivityTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerConfigActivityTest.java
@@ -17,8 +17,12 @@
 
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
 import android.app.Activity;
 import android.app.Instrumentation;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.LauncherActivityInfo;
@@ -58,6 +62,22 @@
         });
     }
 
+    public void testIntentSenderNotCreatedForWrongActivity() throws Throwable {
+        setDefaultLauncher(getInstrumentation(), mLauncherContext1);
+        runWithCallerWithStrictMode(mLauncherContext1, () -> {
+            LauncherActivityInfo originalLai = getConfigActivity();
+            assertNotNull(originalLai);
+
+            LauncherActivityInfo lai = spy(originalLai);
+            assertNotNull(lai);
+            doReturn(new ComponentName(getTestContext(), MyActivity.class))
+                    .when(lai).getComponentName();
+            doReturn(originalLai.getUser()).when(lai).getUser();
+
+            assertNull(getLauncherApps().getShortcutConfigActivityIntent(lai));
+        });
+    }
+
     public void testCorrectIntentSenderCreated() throws Throwable {
         setDefaultLauncher(getInstrumentation(), mLauncherContext1);
         final AtomicReference<IntentSender> sender = new AtomicReference<>();
diff --git a/tests/tests/telecom/AndroidManifest.xml b/tests/tests/telecom/AndroidManifest.xml
index e88a5ca..ad9f709 100644
--- a/tests/tests/telecom/AndroidManifest.xml
+++ b/tests/tests/telecom/AndroidManifest.xml
@@ -40,6 +40,8 @@
     <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
     <uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
 
     <application>
         <uses-library android:name="android.test.runner"/>
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
index 9f936f9..8c8cd05 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -26,6 +26,7 @@
 import static org.junit.Assert.assertThat;
 
 import android.app.AppOpsManager;
+import android.app.UiAutomation;
 import android.app.UiModeManager;
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +41,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.Process;
+import android.os.UserHandle;
 import android.provider.CallLog;
 import android.telecom.Call;
 import android.telecom.CallAudioState;
@@ -62,6 +64,8 @@
 import android.util.Log;
 import android.util.Pair;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.compatibility.common.util.ShellIdentityUtils;
 
 import java.util.ArrayList;
@@ -90,6 +94,9 @@
 
     public static final String TEST_EMERGENCY_NUMBER = "5553637";
     public static final Uri TEST_EMERGENCY_URI = Uri.fromParts("tel", TEST_EMERGENCY_NUMBER, null);
+    public static final String PKG_NAME = "android.telecom.cts";
+    public static final String PERMISSION_PROCESS_OUTGOING_CALLS =
+            "android.permission.PROCESS_OUTGOING_CALLS";
 
     Context mContext;
     TelecomManager mTelecomManager;
@@ -295,6 +302,10 @@
                 (tm) -> tm.registerTelephonyCallback(
                         mTelephonyCallbackHandler::post,
                         mTelephonyCallback));
+        UiAutomation uiAutomation =
+                InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        uiAutomation.grantRuntimePermissionAsUser(PKG_NAME, PERMISSION_PROCESS_OUTGOING_CALLS,
+                UserHandle.CURRENT);
     }
 
     @Override
@@ -324,6 +335,10 @@
             TestUtils.executeShellCommand(getInstrumentation(), "telecom cleanup-stuck-calls");
             throw t;
         }
+        UiAutomation uiAutomation =
+                InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        uiAutomation.revokeRuntimePermissionAsUser(PKG_NAME, PERMISSION_PROCESS_OUTGOING_CALLS,
+                UserHandle.CURRENT);
     }
 
     protected PhoneAccount setupConnectionService(MockConnectionService connectionService,
diff --git a/tests/tests/telecom/src/android/telecom/cts/carmodetestapp/CtsCarModeInCallService.java b/tests/tests/telecom/src/android/telecom/cts/carmodetestapp/CtsCarModeInCallService.java
index 0635754..13d34ba 100644
--- a/tests/tests/telecom/src/android/telecom/cts/carmodetestapp/CtsCarModeInCallService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/carmodetestapp/CtsCarModeInCallService.java
@@ -36,8 +36,8 @@
     private static boolean sIsServiceUnbound = false;
     private static CtsCarModeInCallService sInstance = null;
     private int mCallCount = 0;
-    private static CountDownLatch sBoundLatch = new CountDownLatch(1);;
-    private static CountDownLatch sUnboundLatch = new CountDownLatch(1);;
+    private static CountDownLatch sBoundLatch = new CountDownLatch(1);
+    private static CountDownLatch sUnboundLatch = new CountDownLatch(1);
     private List<Call> mCalls = new ArrayList<>();
 
     @Override
diff --git a/tests/tests/telephony/current/EmbmsMiddlewareTestApp/src/android/telephony/cts/embmstestapp/CtsDownloadService.java b/tests/tests/telephony/current/EmbmsMiddlewareTestApp/src/android/telephony/cts/embmstestapp/CtsDownloadService.java
index e74c315..3d968b4 100644
--- a/tests/tests/telephony/current/EmbmsMiddlewareTestApp/src/android/telephony/cts/embmstestapp/CtsDownloadService.java
+++ b/tests/tests/telephony/current/EmbmsMiddlewareTestApp/src/android/telephony/cts/embmstestapp/CtsDownloadService.java
@@ -148,7 +148,9 @@
 
     private final MbmsDownloadServiceBase mDownloadServiceImpl = new MbmsDownloadServiceBase() {
         @Override
-        public int initialize(int subscriptionId, MbmsDownloadSessionCallback callback) {
+        public int initialize(int subscriptionId, MbmsDownloadSessionCallback callback)
+                throws RemoteException {
+            super.initialize(subscriptionId, callback); // noop to placate the coverage tool
             Bundle b = new Bundle();
             b.putString(METHOD_NAME, METHOD_INITIALIZE);
             b.putInt(ARGUMENT_SUBSCRIPTION_ID, subscriptionId);
@@ -182,7 +184,11 @@
         }
 
         @Override
-        public int requestUpdateFileServices(int subscriptionId, List<String> serviceClasses) {
+        public int requestUpdateFileServices(int subscriptionId, List<String> serviceClasses)
+                throws RemoteException {
+            // noop to placate the coverage tool
+            super.requestUpdateFileServices(subscriptionId, serviceClasses);
+
             Bundle b = new Bundle();
             b.putString(METHOD_NAME, METHOD_REQUEST_UPDATE_FILE_SERVICES);
             b.putInt(ARGUMENT_SUBSCRIPTION_ID, subscriptionId);
@@ -205,13 +211,17 @@
         }
 
         @Override
-        public int download(DownloadRequest downloadRequest) {
+        public int download(DownloadRequest downloadRequest) throws RemoteException {
+            super.download(downloadRequest); // noop to placate the coverage tool
             mReceivedRequests.add(downloadRequest);
             return MbmsErrors.SUCCESS;
         }
 
         @Override
-        public int setTempFileRootDirectory(int subscriptionId, String rootDirectoryPath) {
+        public int setTempFileRootDirectory(int subscriptionId, String rootDirectoryPath)
+                throws RemoteException {
+            // noop to placate the coverage tool
+            super.setTempFileRootDirectory(subscriptionId, rootDirectoryPath);
             if (mErrorCodeOverride != MbmsErrors.SUCCESS) {
                 return mErrorCodeOverride;
             }
@@ -228,6 +238,8 @@
         @Override
         public int addProgressListener(DownloadRequest downloadRequest,
                 DownloadProgressListener listener) throws RemoteException {
+            // noop to placate the coverage tool
+            super.addProgressListener(downloadRequest, listener);
             mDownloadProgressListener = listener;
             return MbmsErrors.SUCCESS;
         }
@@ -235,12 +247,16 @@
         @Override
         public int addStatusListener(DownloadRequest downloadRequest,
                 DownloadStatusListener listener) throws RemoteException {
+            // noop to placate the coverage tool
+            super.addStatusListener(downloadRequest, listener);
             mDownloadStatusListener = listener;
             return MbmsErrors.SUCCESS;
         }
 
         @Override
-        public void dispose(int subscriptionId) {
+        public void dispose(int subscriptionId) throws RemoteException {
+            // noop to placate the coverage tool
+            super.dispose(subscriptionId);
             Bundle b = new Bundle();
             b.putString(METHOD_NAME, METHOD_CLOSE);
             b.putInt(ARGUMENT_SUBSCRIPTION_ID, subscriptionId);
@@ -248,7 +264,10 @@
         }
 
         @Override
-        public int requestDownloadState(DownloadRequest downloadRequest, FileInfo fileInfo) {
+        public int requestDownloadState(DownloadRequest downloadRequest, FileInfo fileInfo)
+                throws RemoteException {
+            // noop to placate the coverage tool
+            super.requestDownloadState(downloadRequest, fileInfo);
             Bundle b = new Bundle();
             b.putString(METHOD_NAME, METHOD_GET_DOWNLOAD_STATUS);
             b.putParcelable(ARGUMENT_DOWNLOAD_REQUEST, downloadRequest);
@@ -259,6 +278,12 @@
 
         @Override
         public int addServiceAnnouncement(int subscriptionId, byte[] announcementFile) {
+            try {
+                // noop to placate the coverage tool
+                super.addServiceAnnouncement(subscriptionId, announcementFile);
+            } catch (UnsupportedOperationException e) {
+                // expected
+            }
             Bundle b = new Bundle();
             b.putString(METHOD_NAME, METHOD_ADD_SERVICE_ANNOUNCEMENT);
             b.putInt(ARGUMENT_SUBSCRIPTION_ID, subscriptionId);
@@ -268,7 +293,9 @@
         }
 
         @Override
-        public int cancelDownload(DownloadRequest request) {
+        public int cancelDownload(DownloadRequest request) throws RemoteException {
+            // noop to placate the coverage tool
+            super.cancelDownload(request);
             Bundle b = new Bundle();
             b.putString(METHOD_NAME, METHOD_CANCEL_DOWNLOAD);
             b.putParcelable(ARGUMENT_DOWNLOAD_REQUEST, request);
@@ -278,19 +305,26 @@
         }
 
         @Override
-        public List<DownloadRequest> listPendingDownloads(int subscriptionId) {
+        public List<DownloadRequest> listPendingDownloads(int subscriptionId)
+                throws RemoteException {
+            // noop to placate the coverage tool
+            super.listPendingDownloads(subscriptionId);
             return mReceivedRequests;
         }
 
         @Override
         public int removeStatusListener(DownloadRequest downloadRequest,
-                DownloadStatusListener callback) {
+                DownloadStatusListener callback) throws RemoteException {
+            // noop to placate the coverage tool
+            super.removeStatusListener(downloadRequest, callback);
             mDownloadStatusListener = null;
             return MbmsErrors.SUCCESS;
         }
 
         @Override
-        public int resetDownloadKnowledge(DownloadRequest downloadRequest) {
+        public int resetDownloadKnowledge(DownloadRequest downloadRequest) throws RemoteException {
+            // noop to placate the coverage tool
+            super.resetDownloadKnowledge(downloadRequest);
             Bundle b = new Bundle();
             b.putString(METHOD_NAME, METHOD_RESET_DOWNLOAD_KNOWLEDGE);
             b.putParcelable(ARGUMENT_DOWNLOAD_REQUEST, downloadRequest);
@@ -300,6 +334,8 @@
 
         @Override
         public void onAppCallbackDied(int uid, int subscriptionId) {
+            // noop to placate the coverage tool
+            super.onAppCallbackDied(uid, subscriptionId);
             mAppCallback = null;
         }
     };
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java b/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
index 3ec048b..60b9106 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
@@ -29,7 +29,10 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
+import android.content.Context;
+import android.os.Build;
 import android.os.Parcel;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.LteVopsSupportInfo;
@@ -37,10 +40,14 @@
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 
+import androidx.test.InstrumentationRegistry;
+
 import org.junit.Before;
 import org.junit.Test;
 
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public class ServiceStateTest {
     private static final String OPERATOR_ALPHA_LONG = "CtsOperatorLong";
@@ -150,12 +157,38 @@
         assertEquals(DUPLEX_MODE_TDD, serviceState.getDuplexMode());
     }
 
+    private static Context getContext() {
+        return InstrumentationRegistry.getContext();
+    }
+
     @Test
     public void testToString() {
         assertNotNull(serviceState.toString());
     }
 
     @Test
+    public void testNrStateRedacted() {
+        final TelephonyManager tm = getContext().getSystemService(TelephonyManager.class);
+
+        // Verify that NR State is not leaked in user builds.
+        if (!Build.IS_DEBUGGABLE) {
+            final String sss = tm.getServiceState().toString();
+            // The string leaked in previous releases is "nrState=<val>"; test that there is
+            // no matching or highly similar string leak, such as:
+            // nrState=NONE
+            // nrState=0
+            // mNrState=RESTRICTED
+            // NRSTATE=NOT_RESTRICTED
+            // nrState = CONNECTED
+            // etc.
+            Pattern p = Pattern.compile("nrState\\s*=\\s*[a-zA-Z0-9_]+", Pattern.CASE_INSENSITIVE);
+            Matcher m = p.matcher(sss);
+            // Need to use if (find) fail to ensure that the start and end are populated
+            if (m.find()) fail("Found nrState reported as: " + sss.substring(m.start(), m.end()));
+        }
+    }
+
+    @Test
     public void testCopyConstructor() {
         ServiceState serviceState = getServiceStateWithOperatorName("name", "numeric");
         assertEquals(serviceState, new ServiceState(serviceState));
diff --git a/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java b/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
index 64a1538..c5baf84 100644
--- a/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/gba/cts/GbaServiceTest.java
@@ -134,6 +134,7 @@
                       TelephonyManager.BootstrapAuthenticationCallback() {
                 @Override
                 public void onKeysAvailable(byte[] gbaKey, String btId) {
+                    super.onKeysAvailable(gbaKey, btId);
                     assertNotNull(gbaKey);
                     assertNotNull(btId);
                     assertArrayEquals(key, gbaKey);
@@ -146,6 +147,7 @@
 
                 @Override
                 public void onAuthenticationFailure(int reason) {
+                    super.onAuthenticationFailure(reason);
                     synchronized (isSuccess) {
                         isFail.set(true);
                         isSuccess.notify();
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
index 689ab97..62fa719 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
@@ -1204,13 +1204,19 @@
             public void onSignalTypeReported(int signalType) {}
 
             @Override
-            public void onModulationReported(int modulation) {}
+            public void onModulationReported(int modulation) {
+                ScanCallback.super.onModulationReported(modulation);
+            }
 
             @Override
-            public void onPriorityReported(boolean isHighPriority) {}
+            public void onPriorityReported(boolean isHighPriority) {
+                ScanCallback.super.onPriorityReported(isHighPriority);
+            }
 
             @Override
-            public void onDvbcAnnexReported(int dvbcAnnext) {}
+            public void onDvbcAnnexReported(int dvbcAnnext) {
+                ScanCallback.super.onDvbcAnnexReported(dvbcAnnext);
+            }
         };
     }
 }
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
index e9c050a..95de736 100755
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
@@ -104,13 +104,13 @@
 
         // Access APIs guarded by a platform defined signature permissions
         try {
+            assertSame(packageManager.checkPermission(Manifest.permission.ANSWER_PHONE_CALLS,
+                    context.getPackageName()), PackageManager.PERMISSION_DENIED);
             getInstrumentation().getUiAutomation().adoptShellPermissionIdentity();
             // Access APIs guarded by a platform defined signature permission
             activityManager.getPackageImportance("foo.bar.baz");
 
             // Grant ourselves a runtime permission (was granted at install)
-            assertSame(packageManager.checkPermission(Manifest.permission.ANSWER_PHONE_CALLS,
-                    context.getPackageName()), PackageManager.PERMISSION_DENIED);
             packageManager.grantRuntimePermission(context.getPackageName(),
                     Manifest.permission.ANSWER_PHONE_CALLS, Process.myUserHandle());
         } catch (SecurityException e) {
diff --git a/tests/tests/view/res/layout-round/gesture_exclusion_basic.xml b/tests/tests/view/res/layout-round/gesture_exclusion_basic.xml
new file mode 100644
index 0000000..71754b6
--- /dev/null
+++ b/tests/tests/view/res/layout-round/gesture_exclusion_basic.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/abslistview_root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+    <View android:id="@+id/animating_view"
+          android:layout_width="5px"
+          android:layout_height="5px"
+          android:layout_gravity="center|left"
+          android:background="#ff00ff00" />
+</FrameLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 5fbd5c0..08b9067 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -932,10 +932,12 @@
     }
 
     @Test
-    public void testRateLimitingToasts() throws Throwable {
+    public void testRateLimitingToastsWhenInBackground() throws Throwable {
         // enable rate limiting to test it
         SystemUtil.runWithShellPermissionIdentity(() -> mNotificationManager
                 .setToastRateLimitingEnabled(true));
+        // move to background
+        mActivityRule.finishActivity();
 
         long totalTimeSpentMs = 0;
         int shownToastsNum = 0;
@@ -966,6 +968,18 @@
     }
 
     @Test
+    public void testDontRateLimitToastsWhenInForeground() throws Throwable {
+        // enable rate limiting to test it
+        SystemUtil.runWithShellPermissionIdentity(() -> mNotificationManager
+                .setToastRateLimitingEnabled(true));
+
+        List<TextToastInfo> toasts =
+                createTextToasts(TOAST_RATE_LIMITS[0] + 1, "Text", Toast.LENGTH_SHORT);
+        showToasts(toasts);
+        assertTextToastsShownAndHidden(toasts);
+    }
+
+    @Test
     public void testCustomToastPostedWhileInForeground_notShownWhenAppGoesToBackground()
             throws Throwable {
         List<CustomToastInfo> toasts = createCustomToasts(2, "Custom", Toast.LENGTH_SHORT);
@@ -984,6 +998,8 @@
         // enable rate limiting to test it
         SystemUtil.runWithShellPermissionIdentity(() -> mNotificationManager
                 .setToastRateLimitingEnabled(true));
+        // move to background
+        mActivityRule.finishActivity();
 
         int highestToastRateLimit = TOAST_RATE_LIMITS[TOAST_RATE_LIMITS.length - 1];
         List<TextToastInfo> toasts = createTextToasts(highestToastRateLimit + 1, "Text",
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
index 3b979cc..c82d51c 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
@@ -299,7 +299,7 @@
                                 .isAtLeast(0);
                         assertThat(statsEntry.getRateStats().get(0).getRateMcsIdx()).isAtLeast(0);
                         assertThat(statsEntry.getRateStats().get(0).getBitRateInKbps())
-                                .isGreaterThan(0);
+                                .isAtLeast(0);
                         assertThat(statsEntry.getRateStats().get(0).getTxMpdu()).isAtLeast(0);
                         assertThat(statsEntry.getRateStats().get(0).getRxMpdu()).isAtLeast(0);
                         assertThat(statsEntry.getRateStats().get(0).getMpduLost()).isAtLeast(0);
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
index 218276c..ec7f740 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
@@ -1026,7 +1026,7 @@
         }
         WifiEnterpriseConfig config = new WifiEnterpriseConfig();
 
-        assertEquals("", config.getDecoratedIdentityPrefix());
+        assertNull(config.getDecoratedIdentityPrefix());
         config.setDecoratedIdentityPrefix(TEST_DECORATED_IDENTITY_PREFIX);
         assertEquals(TEST_DECORATED_IDENTITY_PREFIX, config.getDecoratedIdentityPrefix());
     }