Merge "Enabled CtsScopedStorageHostTest for secondary users." into sc-dev
diff --git a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
index 1016687..f6adec0 100644
--- a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
+++ b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
@@ -311,12 +311,18 @@
 
   if pose_reference == REFERENCE_GYRO:
     logging.debug('pose_reference is GYRO')
-    i_ref = list(cam_reference.keys())[0]  # pick first camera as ref
-    i_2nd = list(cam_reference.keys())[1]
+    keys = list(cam_reference.keys())
+    i_ref = keys[0]  # pick first camera as ref
+    i_2nd = keys[1]
   else:
     logging.debug('pose_reference is CAMERA')
-    i_ref = next(k for (k, v) in cam_reference.items() if v)
-    i_2nd = next(k for (k, v) in cam_reference.items() if not v)
+    i_refs = [k for (k, v) in cam_reference.items() if v]
+    if len(i_refs) > 1:
+      raise AssertionError('More than 1 reference camera. Check translation '
+                           f'matrices. cam_reference: {cam_reference}')
+    else:
+      i_ref = i_refs[0]
+      i_2nd = next(k for (k, v) in cam_reference.items() if not v)
   return i_ref, i_2nd
 
 
diff --git a/apps/CameraITS/utils/opencv_processing_utils.py b/apps/CameraITS/utils/opencv_processing_utils.py
index ac0daa0..b6c0521 100644
--- a/apps/CameraITS/utils/opencv_processing_utils.py
+++ b/apps/CameraITS/utils/opencv_processing_utils.py
@@ -364,7 +364,7 @@
       colour = img_bw[shape['cty']][shape['ctx']]
       circlish = (math.pi * radius**2) / area
       aspect_ratio = shape['width'] / shape['height']
-      logging.debug('Potential circle found. radius: %.2f, color: %d,'
+      logging.debug('Potential circle found. radius: %.2f, color: %d, '
                     'circlish: %.3f, ar: %.3f, pts: %d', radius, colour,
                     circlish, aspect_ratio, num_pts)
       if (colour == color and
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 1d7e8d6..a7a29bb 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -179,7 +179,7 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_other" />
-            <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive" />
+            <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive:android.hardware.type.watch" />
             <meta-data android:name="display_mode"
                        android:value="multi_display_mode" />
         </activity>
@@ -2975,6 +2975,18 @@
                        android:value="multi_display_mode" />
         </activity>
 
+        <activity android:name=".notifications.ToastVerifierActivity"
+                  android:exported="true"
+                  android:label="@string/toast_title">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_notifications" />
+            <meta-data android:name="display_mode"
+                       android:value="multi_display_mode" />
+        </activity>
+
         <activity android:name=".notifications.BubblesVerifierActivity"
                   android:exported="true"
                   android:label="@string/bubbles_notification_title">
@@ -3142,6 +3154,8 @@
             <meta-data android:name="test_excluded_features"
                     android:value="android.hardware.type.watch:android.hardware.type.television:android.software.leanback" />
             <meta-data android:name="test_required_features" android:value="android.software.device_admin" />
+            <meta-data android:name="test_required_actions"
+                       android:value="com.android.settings.TRUSTED_CREDENTIALS_USER" />
             <meta-data android:name="display_mode"
                        android:value="single_display_mode" />
         </activity>
@@ -3156,6 +3170,8 @@
             <meta-data android:name="test_excluded_features"
                     android:value="android.hardware.type.watch:android.hardware.type.television:android.software.leanback" />
             <meta-data android:name="test_required_features" android:value="android.software.device_admin" />
+            <meta-data android:name="test_required_actions"
+                       android:value="com.android.settings.TRUSTED_CREDENTIALS_USER" />
             <meta-data android:name="display_mode"
                        android:value="single_display_mode" />
         </activity>
@@ -4819,6 +4835,32 @@
             <meta-data android:name="display_mode" android:value="multi_display_mode" />
         </activity>
 
+        <activity android:name=".audio.AudioOutColdStartLatencyActivity"
+            android:exported="true"
+            android:label="@string/audio_coldstart_out_latency_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_audio" />
+            <meta-data android:name="test_excluded_features"
+                android:value="android.hardware.type.watch:android.hardware.type.television" />
+            <meta-data android:name="display_mode" android:value="multi_display_mode" />
+        </activity>
+
+        <activity android:name=".audio.AudioInColdStartLatencyActivity"
+            android:exported="true"
+            android:label="@string/audio_coldstart_in_latency_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_audio" />
+            <meta-data android:name="test_excluded_features"
+                android:value="android.hardware.type.watch:android.hardware.type.television" />
+            <meta-data android:name="display_mode" android:value="multi_display_mode" />
+        </activity>
+
         <activity android:name=".audio.MidiActivity"
                 android:exported="true"
                   android:label="@string/midi_test">
diff --git a/apps/CtsVerifier/jni/megaaudio/Android.bp b/apps/CtsVerifier/jni/megaaudio/Android.bp
index 8ebff9f..6683787 100644
--- a/apps/CtsVerifier/jni/megaaudio/Android.bp
+++ b/apps/CtsVerifier/jni/megaaudio/Android.bp
@@ -29,6 +29,7 @@
         "player/NoiseAudioSource.cpp",
         "player/OboePlayer.cpp",
         "player/SinAudioSource.cpp",
+        "player/SilenceAudioSource.cpp",
         "player/WaveTableSource.cpp",
         "recorder/AppCallbackAudioSink.cpp",
         "recorder/DefaultAudioSink.cpp",
diff --git a/apps/CtsVerifier/jni/megaaudio/common/OboeStream.cpp b/apps/CtsVerifier/jni/megaaudio/common/OboeStream.cpp
index 7c51eec..26e2531 100644
--- a/apps/CtsVerifier/jni/megaaudio/common/OboeStream.cpp
+++ b/apps/CtsVerifier/jni/megaaudio/common/OboeStream.cpp
@@ -109,3 +109,20 @@
     mStreamStarted = false;
     return errCode;
 }
+
+StreamBase::Result OboeStream::getTimeStamp(oboe::FrameTimestamp* timeStamp) {
+    __android_log_print(ANDROID_LOG_INFO, TAG, "getTimeStamp()");
+    Result errCode = ERROR_UNKNOWN;
+    if (mAudioStream == nullptr) {
+        __android_log_print(ANDROID_LOG_INFO, TAG, "ERROR_INVALID_STATE");
+        errCode = ERROR_INVALID_STATE;
+    } else {
+        ResultWithValue<oboe::FrameTimestamp> result = mAudioStream->getTimestamp(CLOCK_MONOTONIC);
+
+        *timeStamp = result.value();
+
+        errCode = OK;
+    }
+
+    return errCode;
+}
diff --git a/apps/CtsVerifier/jni/megaaudio/common/OboeStream.h b/apps/CtsVerifier/jni/megaaudio/common/OboeStream.h
index a622ddd..cd2e89a 100644
--- a/apps/CtsVerifier/jni/megaaudio/common/OboeStream.h
+++ b/apps/CtsVerifier/jni/megaaudio/common/OboeStream.h
@@ -31,6 +31,8 @@
     virtual Result startStream() override;
     virtual Result stopStream() override;
 
+    StreamBase::Result getTimeStamp(oboe::FrameTimestamp* timeStamp);
+
 protected:
     OboeStream(int32_t subtype) : mSubtype(subtype), mStreamStarted(false) {}
 
diff --git a/apps/CtsVerifier/jni/megaaudio/player/OboePlayer.cpp b/apps/CtsVerifier/jni/megaaudio/player/OboePlayer.cpp
index 31da138..e6f5235 100644
--- a/apps/CtsVerifier/jni/megaaudio/player/OboePlayer.cpp
+++ b/apps/CtsVerifier/jni/megaaudio/player/OboePlayer.cpp
@@ -26,9 +26,16 @@
 
 constexpr int32_t kBufferSizeInBursts = 2; // Use 2 bursts as the buffer size (double buffer)
 
-OboePlayer::OboePlayer(AudioSource* source, int subtype)
+OboePlayer::OboePlayer(JNIEnv *env, AudioSource* source, int subtype)
  : Player(source, subtype)
-{}
+{
+    env->GetJavaVM(&mJvm);
+
+    jclass clsAudioTimestamp = env->FindClass("android/media/AudioTimestamp");
+
+    mFidFramePosition = env->GetFieldID(clsAudioTimestamp, "framePosition", "J");
+    mFidNanoTime = env->GetFieldID(clsAudioTimestamp, "nanoTime", "J");
+}
 
 DataCallbackResult OboePlayer::onAudioReady(AudioStream *oboeStream, void *audioData,
                                             int32_t numFrames) {
@@ -60,7 +67,6 @@
 }
 
 StreamBase::Result OboePlayer::setupStream(int32_t channelCount, int32_t sampleRate, int32_t routeDeviceId) {
-    __android_log_print(ANDROID_LOG_INFO, TAG, "setupStream()");
 
     oboe::Result result = oboe::Result::ErrorInternal;
     if (mAudioStream != nullptr) {
@@ -89,9 +95,6 @@
         case SUB_TYPE_OBOE_OPENSL_ES:
             builder.setAudioApi(AudioApi::OpenSLES);
             break;
-
-        default:
-           return ERROR_INVALID_STATE;
         }
 
         if (mRouteDeviceId != ROUTING_DEVICE_NONE) {
@@ -125,6 +128,20 @@
     return result;
 }
 
+bool OboePlayer::getJavaTimestamp(jobject timestampObj) {
+    oboe::FrameTimestamp nativeStamp;
+    StreamBase::Result result = Player::getTimeStamp(&nativeStamp);
+    if (result == OK) {
+        JNIEnv* env;
+        mJvm->AttachCurrentThread(&env, NULL);
+
+        env->SetLongField(timestampObj, mFidFramePosition, nativeStamp.position);
+        env->SetLongField(timestampObj, mFidNanoTime, nativeStamp.timestamp);
+    }
+
+    return result == OK;
+}
+
 //
 // JNI functions
 //
@@ -137,7 +154,7 @@
 Java_org_hyphonate_megaaudio_player_OboePlayer_allocNativePlayer(
     JNIEnv *env, jobject thiz, jlong native_audio_source, jint playerSubtype) {
 
-    return (jlong)new OboePlayer((AudioSource*)native_audio_source, playerSubtype);
+    return (jlong)new OboePlayer(env, (AudioSource*)native_audio_source, playerSubtype);
 }
 
 JNIEXPORT jint JNICALL Java_org_hyphonate_megaaudio_player_OboePlayer_setupStreamN(
@@ -176,4 +193,8 @@
     return ((OboePlayer*)(native_player))->getRoutedDeviceId();
 }
 
+JNIEXPORT jboolean JNICALL Java_org_hyphonate_megaaudio_player_OboePlayer_getTimestampN(JNIEnv *env, jobject thiz, jlong native_player, jobject timestamp) {
+    return ((OboePlayer*)native_player)->getJavaTimestamp(timestamp);
+}
+
 } // extern "C"
diff --git a/apps/CtsVerifier/jni/megaaudio/player/OboePlayer.h b/apps/CtsVerifier/jni/megaaudio/player/OboePlayer.h
index 963cdb2..73686ab 100644
--- a/apps/CtsVerifier/jni/megaaudio/player/OboePlayer.h
+++ b/apps/CtsVerifier/jni/megaaudio/player/OboePlayer.h
@@ -17,13 +17,15 @@
 #ifndef MEGA_PLAYER_OBOEPLAYER_H
 #define MEGA_PLAYER_OBOEPLAYER_H
 
+#include <jni.h>
+
 #include <oboe/Oboe.h>
 
 #include "Player.h"
 
 class OboePlayer : public Player, oboe::AudioStreamCallback {
 public:
-    OboePlayer(AudioSource* source, int playerSubtype);
+    OboePlayer(JNIEnv *env, AudioSource* source, int playerSubtype);
     virtual ~OboePlayer() {}
 
     // Inherited from oboe::AudioStreamCallback
@@ -34,6 +36,15 @@
 
     virtual Result setupStream(int32_t channelCount, int32_t sampleRate, int32_t routeDeviceId) override;
     virtual Result startStream() override;
+
+    bool getJavaTimestamp(jobject timestampObj);
+
+private:
+    // AudioTimestamp Field IDs
+    JavaVM* mJvm;
+
+    jfieldID    mFidFramePosition;
+    jfieldID    mFidNanoTime;
 };
 
 #endif // MEGA_PLAYER_OBOEPLAYER_H
diff --git a/apps/CtsVerifier/jni/megaaudio/player/SilenceAudioSource.cpp b/apps/CtsVerifier/jni/megaaudio/player/SilenceAudioSource.cpp
new file mode 100644
index 0000000..f5e46344
--- /dev/null
+++ b/apps/CtsVerifier/jni/megaaudio/player/SilenceAudioSource.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+#include <cstring>
+
+#include "SilenceAudioSource.h"
+
+int SilenceAudioSource::pull(float* buffer, int numFrames, int numChans) {
+    memset(buffer, 0, sizeof(float) * numFrames * numChans);
+    return numFrames;
+}
+
+//
+// JNI functions
+//
+#include <jni.h>
+
+#include <android/log.h>
+
+extern "C" {
+JNIEXPORT JNICALL jlong Java_org_hyphonate_megaaudio_player_sources_SilenceAudioSourceProvider_allocNativeSource(
+        JNIEnv *env, jobject thiz) {
+    return (jlong)new SilenceAudioSource();
+}
+
+} // extern "C"
+
+#include "SilenceAudioSource.h"
diff --git a/apps/CtsVerifier/jni/megaaudio/player/SilenceAudioSource.h b/apps/CtsVerifier/jni/megaaudio/player/SilenceAudioSource.h
new file mode 100644
index 0000000..9278269
--- /dev/null
+++ b/apps/CtsVerifier/jni/megaaudio/player/SilenceAudioSource.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef MEGA_PLAYER_SILENCEAUDIOSOURCE_H
+#define MEGA_PLAYER_SILENCEAUDIOSOURCE_H
+
+#include "AudioSource.h"
+
+class SilenceAudioSource: public AudioSource {
+public:
+    SilenceAudioSource() {}
+    virtual ~SilenceAudioSource() {}
+
+    /**
+     * Fills the specified buffer with silence.
+     *
+     * @param buffer The buffer to be filled.
+     * @param numFrames The number of frames of audio to provide.
+     * @param numChans The number of channels (in the buffer) required by the player.
+     * @return  The number of samples generated.This will always be <code>numFrames</code>.
+     */
+    virtual int pull(float* buffer, int numFrames, int numChans) override;
+};
+
+#endif // MEGA_PLAYER_SILENCEAUDIOSOURCE_H
diff --git a/apps/CtsVerifier/jni/megaaudio/recorder/OboeRecorder.cpp b/apps/CtsVerifier/jni/megaaudio/recorder/OboeRecorder.cpp
index 8d249f1..32d7035 100644
--- a/apps/CtsVerifier/jni/megaaudio/recorder/OboeRecorder.cpp
+++ b/apps/CtsVerifier/jni/megaaudio/recorder/OboeRecorder.cpp
@@ -66,8 +66,6 @@
             builder.setDeviceId(mRouteDeviceId);
         }
 
-        mAudioSink->init(mBufferSizeInFrames, mChannelCount);
-
         if (mSubtype == SUB_TYPE_OBOE_AAUDIO) {
             builder.setAudioApi(AudioApi::AAudio);
         } else if (mSubtype == SUB_TYPE_OBOE_OPENSL_ES) {
@@ -82,6 +80,7 @@
                     "openStream failed. Error: %s", convertToText(result));
         } else {
             mBufferSizeInFrames = mAudioStream->getFramesPerBurst();
+            mAudioSink->init(mBufferSizeInFrames, mChannelCount);
         }
     }
 
diff --git a/apps/CtsVerifier/res/layout-small/sensor_test.xml b/apps/CtsVerifier/res/layout-small/sensor_test.xml
index 96cf30a..348e321 100644
--- a/apps/CtsVerifier/res/layout-small/sensor_test.xml
+++ b/apps/CtsVerifier/res/layout-small/sensor_test.xml
@@ -16,7 +16,10 @@
 <com.android.cts.verifier.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:paddingTop="20dp"
+    android:paddingLeft="15dp"
+    android:paddingRight="15dp">
     <ScrollView android:id="@+id/log_scroll_view"
             app:ctsv_layout_box="all"
             android:fillViewport="true"
diff --git a/apps/CtsVerifier/res/layout-watch/requesting_bugreport_device_owner.xml b/apps/CtsVerifier/res/layout-watch/requesting_bugreport_device_owner.xml
index 8aebbe6..ae7111a 100644
--- a/apps/CtsVerifier/res/layout-watch/requesting_bugreport_device_owner.xml
+++ b/apps/CtsVerifier/res/layout-watch/requesting_bugreport_device_owner.xml
@@ -39,7 +39,7 @@
         <ListView
             android:id="@+id/android:list"
             android:layout_width="match_parent"
-            android:layout_height="500dp"/>
+            android:layout_height="560dp"/>
 
         <include layout="@layout/pass_fail_buttons"/>
     </LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_coldstart_common.xml b/apps/CtsVerifier/res/layout/audio_coldstart_common.xml
new file mode 100644
index 0000000..3eaa55d
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/audio_coldstart_common.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:soundEffectsEnabled="false"
+            android:text="@string/audio_general_start"
+            android:id="@+id/coldstart_start_btn" />
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:soundEffectsEnabled="false"
+            android:text="@string/audio_general_stop"
+            android:id="@+id/coldstart_stop_btn" />
+    </LinearLayout>
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/coldstart_attributesTxt" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/coldstart_openTimeTxt" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/coldstart_startTimeTxt" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/coldstart_coldLatencyTxt" />
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_coldstart_in_activity.xml b/apps/CtsVerifier/res/layout/audio_coldstart_in_activity.xml
new file mode 100644
index 0000000..a5a41ef
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/audio_coldstart_in_activity.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/audio_coldstart_inputlbl"
+        android:textSize="20sp"
+        android:textStyle="bold" />
+
+    <include layout="@layout/audio_java_native_api_buttons" />
+
+    <include layout="@layout/audio_coldstart_common" />
+
+    <include layout="@layout/pass_fail_buttons" />
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_coldstart_out_activity.xml b/apps/CtsVerifier/res/layout/audio_coldstart_out_activity.xml
new file mode 100644
index 0000000..819aa25
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/audio_coldstart_out_activity.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/audio_coldstart_outputlbl"
+        android:textSize="20sp"
+        android:textStyle="bold" />
+
+    <include layout="@layout/audio_java_native_api_buttons" />
+
+    <include layout="@layout/audio_coldstart_common" />
+
+    <include layout="@layout/pass_fail_buttons" />
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_java_native_api_buttons.xml b/apps/CtsVerifier/res/layout/audio_java_native_api_buttons.xml
new file mode 100644
index 0000000..29509a8
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/audio_java_native_api_buttons.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal">
+
+    <RadioGroup
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <RadioButton
+            android:id="@+id/audioJavaApiBtn"
+            android:text="@string/audio_general_JavaApi"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+        <RadioButton
+            android:id="@+id/audioNativeApiBtn"
+            android:text="@string/audio_general_NativeApi"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+    </RadioGroup>
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_tap2tone_activity.xml b/apps/CtsVerifier/res/layout/audio_tap2tone_activity.xml
index baa4519..65994c0 100644
--- a/apps/CtsVerifier/res/layout/audio_tap2tone_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_tap2tone_activity.xml
@@ -25,21 +25,7 @@
         android:layout_height="wrap_content"
         android:orientation="vertical">
 
-        <RadioGroup
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-            <RadioButton
-                android:id="@+id/tap2toneJavaApiBtn"
-                android:text="@string/audio_general_JavaApi"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-            <RadioButton
-                android:id="@+id/tap2toneNativeApiBtn"
-                android:text="@string/audio_general_NativeApi"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-        </RadioGroup>
+        <include layout="@layout/audio_java_native_api_buttons" />
 
         <LinearLayout
             android:layout_width="match_parent"
@@ -83,6 +69,13 @@
             android:textSize="20sp"
             android:textStyle="bold"/>
 
+        <TextView
+            android:id="@+id/tap2tone_phaseInfo"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textSize="20sp"
+            android:textStyle="bold"/>
+
         <Button
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/toast_main.xml b/apps/CtsVerifier/res/layout/toast_main.xml
new file mode 100644
index 0000000..5f8313d
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/toast_main.xml
@@ -0,0 +1,65 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical"
+              android:gravity="center_horizontal"
+              style="@style/RootLayoutPadding">
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_horizontal"
+            android:orientation="vertical" >
+
+            <TextView
+                android:id="@+id/toast_description_pre_s"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/toast_instructions_pre_s"
+                style="@style/InstructionsSmallFont"/>
+            <TextView
+                android:id="@+id/toast_description_s"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:padding="10dp"
+                android:text="@string/toast_instructions_s"
+                style="@style/InstructionsSmallFont"/>
+
+            <Button
+                android:id="@+id/toast_post_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/toast_post_button_label"
+                android:layout_margin="24dp"/>
+        </LinearLayout>
+    </ScrollView>
+
+    <include
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0"
+        layout="@layout/pass_fail_buttons" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 545df9d..0ddd8d5 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -882,7 +882,7 @@
         Remove the test app from the ignore battery optimizations list to begin the test. (Try going
         to the App Info page and make sure the system is optimizing battery for the app.)
     </string>
-    <string name="ibo_exempt_app">
+    <string name="ibo_exempt_app_request">
         Click Next to have the test request the exemption. Grant the exemption when prompted.
     </string>
     <string name="ibo_next_to_confirm">Press next to confirm.</string>
@@ -892,6 +892,14 @@
         to the App Info page and make sure the system is optimizing battery for the app.)
     </string>
     <string name="ibo_app_is_exempted">The app is exempted from battery optimizations.</string>
+    <string name="ibo_exempt_app_list">
+        Click Next to have the test open the list of apps and their exemption statuses. Find the
+        test app in the list and exempt it.
+    </string>
+    <string name="ibo_unexempt_app_list">
+        Click Next to have the test open the list of apps and their exemption statuses. Find the
+        test app in the list and remove the app\'s exemption.
+    </string>
 
     <!-- Strings for Location tests -->
     <string name="location_gps_test">GPS Test</string>
@@ -3489,9 +3497,10 @@
     <string name="set_device_owner_button_label">Set up device owner</string>
     <string name="set_device_owner_dialog_title">Set up device owner</string>
     <string name="grant_headless_system_user_permissions">
-            For this test you need to grant INTERACT_ACROSS_USERS to CtsVerifier by running\n
+            For this test you need to grant some permissions to CtsVerifier by running\n
             adb shell pm grant --user current com.android.cts.verifier android.permission.INTERACT_ACROSS_USERS\n
-            adb shell pm grant --user 0 com.android.cts.verifier android.permission.INTERACT_ACROSS_USERS\n\n
+            adb shell pm grant --user 0 com.android.cts.verifier android.permission.INTERACT_ACROSS_USERS\n
+            adb shell am compat enable ALLOW_TEST_API_ACCESS com.android.cts.verifier\n\n
     </string>
     <string name="set_device_owner_dialog_text">
             For this test you need to install CtsEmptyDeviceOwner.apk by running\n
@@ -5037,7 +5046,7 @@
 
     <!-- Audio Loopback Latency Test -->
     <string name="audio_loopback_latency_test">Audio Loopback Latency Test</string>
-     <string name="audio_loopback_info">
+    <string name="audio_loopback_info">
           This test requires some form of audio loopback. This can be either:\n
           - a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a>  connected to a 3.5mm headset jack.\n
           - a <a href="https://source.android.com/devices/audio/latency/loopback">Loopback Plug</a>  connected to a USB audio adapter.\n
@@ -5061,7 +5070,16 @@
     <string name="audio_loopback_test_btn">Test</string>
     <string name="audio_loopback_results_text">Results...</string>
 
-   <!-- Audio Frequency Line Test -->
+    <!-- Audio Loopback Latency Test -->
+    <string name="audio_coldstart_out_latency_test">Audio Cold Start Output Latency Test</string>
+    <string name="audio_coldstart_in_latency_test">Audio Cold Start Input Latency Test</string>
+
+    <string name="audio_coldstart_output_info">Info Here</string>
+    <string name="audio_coldstart_input_info">Info Here</string>
+    <string name="audio_coldstart_outputlbl">Output Cold Start Latency</string>
+    <string name="audio_coldstart_inputlbl">Input Cold Start Latency</string>
+
+    <!-- Audio Frequency Line Test -->
     <string name="audio_frequency_line_test">Audio Frequency Line Test</string>
     <string name="audio_frequency_line_info">
         The system will measure the frequency response of the left and right line outputs,
@@ -5219,12 +5237,17 @@
     <!-- AudioTap2Tone test -->
     <string name="audio_tap2tone">Audio Tap To Tone Test</string>
     <string name="audio_tap2tone_info">This tests the latency from a screen interaction to a
-        resulting tone. This time is a combination of touch screen latency and audio latency\nSelect
+        resulting tone. This time is a combination of touch screen latency and audio latency.\nThis
+        test is best conducted in a quiet room with the device laying on a table. Select
         the Audio API to test and press the \"Start\" button. Use your fingernail to tap on the
-        field below to trigger the test tone. Results will be displayed in the field.</string>
-    <string name="audio_tap2tone_spec">80ms average is required to pass.</string>
+        field below to trigger the test tone. Results will be displayed in the field above the
+        waveform display.\nFive successful tests runs are required to determine if the test
+        as a whole succeeds.
+    </string>
+    <string name="audio_tap2tone_spec">80ms or less average latency is STRONGLY RECOMMENDED to pass.</string>
     <string name="audio_tap2tone_too_few">Not enough edges. Use fingernail.</string>
-    <string name="audio_tap2tone_too_many">Too many edges. Use fingernail.</string>
+    <string name="audio_tap2tone_too_many">Too many edges. Use fingernail. Ensure there is
+    no background noise.</string>
 
     <!-- Strings for 6DoF test -->
     <string name="six_dof_test">6DoF Test</string>
@@ -5727,6 +5750,30 @@
     <string name="bubbles_test_summary">%1$d out of %2$d tests passed</string>
     <string name="bubble_activity_title">Bubble Activity</string>
 
+    <!-- Toast test -->
+    <string name="toast_title">Toast test (may auto pass if CtsVerifier isn\'t targeting
+        S+)</string>
+    <string name="toast_info">This test checks the behavior for toasts for apps targeting
+        sdk S+ (31). Toasts are short messages that appear as popups for a limited amount of time.
+    </string>
+    <string name="toast_instructions_pre_s">No cts requirement for toasts for apps targeting
+        pre-s. Auto pass this test.</string>
+    <string name="toast_instructions_s">Press the button below to post a toast. Pass this
+        test if a toast appears and has:\n
+        \n\t1. a maximum of two lines
+        \n\t2. an application icon
+    </string>
+    <string name="toast_post_button_label">Post toast</string>
+    <string name="toast_long_text">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+        Nam luctus eros ac interdum tincidunt. Vestibulum dignissim, metus nec tempor mollis,
+        tortor leo aliquam est, eget rutrum mi nisi ut ligula. Quisque enim justo, tempus at
+        ligula ac, porta posuere odio. Proin et tortor tincidunt, tempus ligula id,
+        vestibulum mauris. Vivamus blandit tristique tempus. Integer dignissim purus eu nibh
+        faucibus, eget dignissim eros gravida. Sed sit amet erat quis leo pharetra euismod vel at
+        purus. Duis blandit, diam eu imperdiet pulvinar, erat odio eleifend augue, nec luctus
+        lectus erat ac nibh. Nullam id enim metus.
+    </string>
+
     <!-- Strings for Instant Apps -->
     <string name="ia_instruction_heading_label">Instructions:</string>
     <string name="ia_instruction_text_photo_label">READ BEFORE STARTING TEST</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
index 75a9adc..eaeb5f3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
@@ -103,6 +103,13 @@
  *             <meta-data android:name="test_applicable_features" android:value="android.hardware.sensor.compass" />
  *         </pre>
  *     </li>
+ *     <li>OPTIONAL: Add a meta data attribute to indicate which intent actions are required to run
+ *         the test. If the device does not have activities that handle all those actions, then it
+ *         will not appear in the test list. Use a colon (:) to specify multiple required intent actions.
+ *         <pre>
+ *             <meta-data android:name="test_required_actions" android:value="android.app.action.ADD_DEVICE_ADMIN" />
+ *         </pre>
+ *     </li>
  *
  * </ol>
  */
@@ -121,6 +128,8 @@
 
     private static final String TEST_REQUIRED_CONFIG_META_DATA = "test_required_configs";
 
+    private static final String TEST_REQUIRED_ACTIONS_META_DATA = "test_required_actions";
+
     private static final String TEST_DISPLAY_MODE_META_DATA = "display_mode";
 
     private static final String CONFIG_NO_EMULATOR = "config_no_emulator";
@@ -252,11 +261,14 @@
             Intent intent = getActivityIntent(info.activityInfo);
             String[] requiredFeatures = getRequiredFeatures(info.activityInfo.metaData);
             String[] requiredConfigs = getRequiredConfigs(info.activityInfo.metaData);
+            String[] requiredActions = getRequiredActions(info.activityInfo.metaData);
             String[] excludedFeatures = getExcludedFeatures(info.activityInfo.metaData);
             String[] applicableFeatures = getApplicableFeatures(info.activityInfo.metaData);
             String displayMode = getDisplayMode(info.activityInfo.metaData);
+
             TestListItem item = TestListItem.newTest(title, testName, intent, requiredFeatures,
-                     requiredConfigs, excludedFeatures, applicableFeatures, displayMode);
+                     requiredConfigs, requiredActions, excludedFeatures, applicableFeatures,
+                     displayMode);
 
             String testCategory = getTestCategory(mContext, info.activityInfo.metaData);
             addTestToCategory(testsByCategory, testCategory, item);
@@ -294,6 +306,19 @@
         }
     }
 
+    static String[] getRequiredActions(Bundle metaData) {
+        if (metaData == null) {
+            return null;
+        } else {
+            String value = metaData.getString(TEST_REQUIRED_ACTIONS_META_DATA);
+            if (value == null) {
+                return null;
+            } else {
+                return value.split(":");
+            }
+        }
+    }
+
     static String[] getRequiredConfigs(Bundle metaData) {
         if (metaData == null) {
             return null;
@@ -381,6 +406,7 @@
                     return true;
                 }
             }
+            Log.v(LOG_TAG, "Missing features " + Arrays.toString(features));
         }
         return false;
     }
@@ -390,6 +416,21 @@
             PackageManager packageManager = mContext.getPackageManager();
             for (String feature : features) {
                 if (!packageManager.hasSystemFeature(feature)) {
+                    Log.v(LOG_TAG, "Missing feature " + feature);
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean hasAllActions(String[] actions) {
+        if (actions != null) {
+            PackageManager packageManager = mContext.getPackageManager();
+            for (String action : actions) {
+                Intent intent = new Intent(action);
+                if (packageManager.queryIntentActivities(intent, /* flags= */ 0).isEmpty()) {
+                    Log.v(LOG_TAG, "Missing action " + action);
                     return false;
                 }
             }
@@ -505,13 +546,18 @@
         List<TestListItem> filteredTests = new ArrayList<>();
         for (TestListItem test : tests) {
             if (!hasAnyFeature(test.excludedFeatures) && hasAllFeatures(test.requiredFeatures)
-                && matchAllConfigs(test.requiredConfigs)
-                && matchDisplayMode(test.displayMode, mode)) {
+                    && hasAllActions(test.requiredActions)
+                    && matchAllConfigs(test.requiredConfigs)
+                    && matchDisplayMode(test.displayMode, mode)) {
                 if (test.applicableFeatures == null || hasAnyFeature(test.applicableFeatures)) {
                     // Add suffix in test name if the test is in the folded mode.
                     test.testName = setTestNameSuffix(mode, test.testName);
                     filteredTests.add(test);
+                } else {
+                    Log.d(LOG_TAG, "Skipping " + test.testName + " due to metadata filtering");
                 }
+            } else {
+                Log.d(LOG_TAG, "Skipping " + test.testName + " due to metadata filtering");
             }
         }
         return filteredTests;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
index 0ec8ff1..b729a2d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
@@ -19,10 +19,6 @@
 import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
 import static com.android.cts.verifier.TestListActivity.sInitialLaunch;
 
-import com.android.compatibility.common.util.ReportLog;
-import com.android.compatibility.common.util.TestResultHistory;
-import com.android.cts.verifier.TestListActivity.DisplayMode;
-
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -37,6 +33,9 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.compatibility.common.util.ReportLog;
+import com.android.cts.verifier.TestListActivity.DisplayMode;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -117,6 +116,9 @@
         /** Configs necessary to run this test. */
         final String[] requiredConfigs;
 
+        /** Intent actions necessary to run this test. */
+        final String[] requiredActions;
+
         /** Features such that, if any present, the test gets excluded from being shown. */
         final String[] excludedFeatures;
 
@@ -126,6 +128,8 @@
         /** Configs display mode to run this test. */
         final String displayMode;
 
+        // TODO: refactor to use a Builder approach instead
+
         public static TestListItem newTest(Context context, int titleResId, String testName,
             Intent intent, String[] requiredFeatures, String[] excludedFeatures,
             String[] applicableFeatures) {
@@ -136,45 +140,50 @@
         public static TestListItem newTest(Context context, int titleResId, String testName,
                 Intent intent, String[] requiredFeatures, String[] excludedFeatures) {
             return newTest(context.getString(titleResId), testName, intent, requiredFeatures,
-                    excludedFeatures, null);
+                    excludedFeatures, /* applicableFeatures= */ null);
         }
 
         public static TestListItem newTest(Context context, int titleResId, String testName,
                 Intent intent, String[] requiredFeatures) {
-            return newTest(context.getString(titleResId), testName, intent, requiredFeatures, null,
-                    null);
+            return newTest(context.getString(titleResId), testName, intent, requiredFeatures,
+                    /* excludedFeatures= */ null, /* applicableFeatures= */ null);
         }
 
         public static TestListItem newTest(String title, String testName, Intent intent,
-                String[] requiredFeatures, String[] requiredConfigs, String[] excludedFeatures,
-                String[] applicableFeatures, String displayMode) {
+                String[] requiredFeatures, String[] requiredConfigs, String[] requiredActions,
+                String[] excludedFeatures, String[] applicableFeatures, String displayMode) {
             return new TestListItem(title, testName, intent, requiredFeatures, requiredConfigs,
-                    excludedFeatures, applicableFeatures, displayMode);
+                    requiredActions, excludedFeatures, applicableFeatures, displayMode);
         }
 
         public static TestListItem newTest(String title, String testName, Intent intent,
             String[] requiredFeatures, String[] requiredConfigs, String[] excludedFeatures,
             String[] applicableFeatures) {
             return new TestListItem(title, testName, intent, requiredFeatures, requiredConfigs,
-                excludedFeatures, applicableFeatures, null);
+                    /* requiredActions = */ null, excludedFeatures, applicableFeatures,
+                    /* displayMode= */ null);
         }
 
         public static TestListItem newTest(String title, String testName, Intent intent,
                 String[] requiredFeatures, String[] excludedFeatures, String[] applicableFeatures) {
-            return new TestListItem(title, testName, intent, requiredFeatures, null,
-                    excludedFeatures, applicableFeatures, null);
+            return new TestListItem(title, testName, intent, requiredFeatures,
+                    /* requiredConfigs= */ null, /* requiredActions = */ null, excludedFeatures,
+                    applicableFeatures, /* displayMode= */ null);
         }
 
         public static TestListItem newTest(String title, String testName, Intent intent,
                 String[] requiredFeatures, String[] excludedFeatures) {
-            return new TestListItem(title, testName, intent, requiredFeatures, null,
-                    excludedFeatures, null, null);
+            return new TestListItem(title, testName, intent, requiredFeatures,
+                    /* requiredConfigs= */ null, /* requiredActions = */ null, excludedFeatures,
+                    /* applicableFeatures= */ null, /* displayMode= */ null);
         }
 
         public static TestListItem newTest(String title, String testName, Intent intent,
                 String[] requiredFeatures) {
-            return new TestListItem(title, testName, intent, requiredFeatures, null, null, null,
-                    null);
+            return new TestListItem(title, testName, intent, requiredFeatures,
+                    /* requiredConfigs= */ null, /* requiredActions = */ null,
+                    /* excludedFeatures= */ null, /* applicableFeatures= */ null,
+                    /* displayMode= */ null);
         }
 
         public static TestListItem newCategory(Context context, int titleResId) {
@@ -182,24 +191,29 @@
         }
 
         public static TestListItem newCategory(String title) {
-            return new TestListItem(title, null, null, null, null, null, null, null);
+            return new TestListItem(title, /* testName= */ null, /* intent= */ null,
+                    /* requiredFeatures= */ null,  /* requiredConfigs= */ null,
+                    /* requiredActions = */ null, /* excludedFeatures= */ null,
+                    /* applicableFeatures= */ null, /* displayMode= */ null);
         }
 
         protected TestListItem(String title, String testName, Intent intent,
                 String[] requiredFeatures, String[] excludedFeatures, String[] applicableFeatures) {
-            this(title, testName, intent, requiredFeatures, null, excludedFeatures,
-                    applicableFeatures, null);
+            this(title, testName, intent, requiredFeatures, /* requiredConfigs= */ null,
+                    /* requiredActions = */ null, excludedFeatures, applicableFeatures,
+                    /* displayMode= */ null);
         }
 
         protected TestListItem(String title, String testName, Intent intent,
-                String[] requiredFeatures, String[] requiredConfigs, String[] excludedFeatures,
-                String[] applicableFeatures, String displayMode) {
+                String[] requiredFeatures, String[] requiredConfigs, String[] requiredActions,
+                String[] excludedFeatures, String[] applicableFeatures, String displayMode) {
             this.title = title;
             if (!sInitialLaunch) {
                 testName = setTestNameSuffix(sCurrentDisplayMode, testName);
             }
             this.testName = testName;
             this.intent = intent;
+            this.requiredActions = requiredActions;
             this.requiredFeatures = requiredFeatures;
             this.requiredConfigs = requiredConfigs;
             this.excludedFeatures = excludedFeatures;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java
new file mode 100644
index 0000000..71448df
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java
@@ -0,0 +1,188 @@
+/*
+ * 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.verifier.audio;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.RadioButton;
+import android.widget.TextView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import org.hyphonate.megaaudio.common.BuilderBase;
+
+public abstract class AudioColdStartBaseActivity
+        extends PassFailButtons.Activity
+        implements View.OnClickListener {
+    private static final String TAG = "AudioColdStartBaseActivity";
+
+    // JNI load
+    static {
+        try {
+            System.loadLibrary("megaaudio_jni");
+        } catch (UnsatisfiedLinkError e) {
+            Log.e(TAG, "Error loading MegaAudio JNI library");
+            Log.e(TAG, "e: " + e);
+            e.printStackTrace();
+        }
+
+        /* TODO: gracefully fail/notify if the library can't be loaded */
+    }
+
+    // Test State
+    protected boolean mIsTestRunning;
+
+    // Audio Attributes
+    protected static final int NUM_CHANNELS = 2;
+    protected int mSampleRate;
+    protected int mNumBufferFrames;
+
+    protected int mAudioApi = BuilderBase.TYPE_OBOE;
+
+    // (all times in nanoseconds)
+    protected long mPreOpenTime;
+    protected long mPostOpenTime;
+    protected long mPreStartTime;
+    protected long mPostStartTime;
+
+    protected double mColdStartlatencyMS;
+
+    // Widgets
+    Button mStartBtn;
+    Button mStopBtn;
+
+    TextView mAttributesTxt;
+    TextView mOpenTimeTxt;
+    TextView mStartTimeTxt;
+    TextView mResultsTxt;
+
+    // Time-base conversions
+    protected double nanosToMs(double nanos) {
+        return nanos / 1000000.0;
+    }
+
+    protected long msToNanos(double ms) {
+        return (long) (ms * 1000000.0);
+    }
+
+    //
+    // UI Helpers
+    //
+    private final String msFormat = "%.2f ms";
+
+    protected String makeMSString(double ms) {
+        return String.format(msFormat, ms);
+    }
+
+    //
+    // UI
+    //
+    void showAttributes() {
+        mAttributesTxt.setText("" + mSampleRate + " Hz " + mNumBufferFrames + " Frames");
+    }
+
+    void showOpenTime() {
+        double timeMs = nanosToMs(mPostOpenTime - mPreOpenTime);
+        mOpenTimeTxt.setText("Open: " + makeMSString(timeMs));
+    }
+
+    void showStartTime() {
+        double timeMs = nanosToMs(mPostStartTime - mPreStartTime);
+        mStartTimeTxt.setText("Start: " + makeMSString(timeMs));
+    }
+
+    void showColdStartLatency() {
+        mResultsTxt.setText("latency: " + mColdStartlatencyMS);
+    }
+
+    protected void clearResults() {
+        mAttributesTxt.setText("");
+        mOpenTimeTxt.setText("");
+        mStartTimeTxt.setText("");
+        mResultsTxt.setText("");
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        ((RadioButton) findViewById(R.id.audioJavaApiBtn)).setOnClickListener(this);
+        RadioButton nativeApiRB = findViewById(R.id.audioNativeApiBtn);
+        nativeApiRB.setChecked(true);
+        nativeApiRB.setOnClickListener(this);
+
+        mStartBtn = (Button) findViewById(R.id.coldstart_start_btn);
+        mStartBtn.setOnClickListener(this);
+        mStopBtn = (Button) findViewById(R.id.coldstart_stop_btn);
+        mStopBtn.setOnClickListener(this);
+        mStopBtn.setEnabled(false);
+
+        mAttributesTxt = ((TextView) findViewById(R.id.coldstart_attributesTxt));
+        mOpenTimeTxt = ((TextView) findViewById(R.id.coldstart_openTimeTxt));
+        mStartTimeTxt = ((TextView) findViewById(R.id.coldstart_startTimeTxt));
+        mResultsTxt = (TextView) findViewById(R.id.coldstart_coldLatencyTxt);
+    }
+
+    abstract boolean startAudioTest();
+    abstract void stopAudioTest();
+
+    protected void updateTestStateButtons() {
+        mStartBtn.setEnabled(!mIsTestRunning);
+        mStopBtn.setEnabled(mIsTestRunning);
+    }
+
+    //
+    // View.OnClickListener overrides
+    //
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            case R.id.audioJavaApiBtn:
+                stopAudioTest();
+                updateTestStateButtons();
+                clearResults();
+                mAudioApi = BuilderBase.TYPE_JAVA;
+                break;
+
+            case R.id.audioNativeApiBtn:
+                stopAudioTest();
+                updateTestStateButtons();
+                clearResults();
+                mAudioApi = BuilderBase.TYPE_OBOE;
+                break;
+
+            case R.id.coldstart_start_btn:
+                startAudioTest();
+
+                showAttributes();
+                showOpenTime();
+                showStartTime();
+
+                updateTestStateButtons();
+                break;
+
+            case R.id.coldstart_stop_btn:
+                stopAudioTest();
+
+                updateTestStateButtons();
+                break;
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java
new file mode 100644
index 0000000..9af7e14
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInColdStartLatencyActivity.java
@@ -0,0 +1,200 @@
+/*
+ * 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.verifier.audio;
+
+import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
+import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.audio.audiolib.AudioSystemParams;
+
+import org.hyphonate.megaaudio.recorder.AudioSinkProvider;
+import org.hyphonate.megaaudio.recorder.Recorder;
+import org.hyphonate.megaaudio.recorder.RecorderBuilder;
+import org.hyphonate.megaaudio.recorder.sinks.AppCallback;
+import org.hyphonate.megaaudio.recorder.sinks.AppCallbackAudioSink;
+import org.hyphonate.megaaudio.recorder.sinks.AppCallbackAudioSinkProvider;
+
+/**
+ * CTS-Test for cold-start latency measurements
+ */
+public class AudioInColdStartLatencyActivity
+        extends AudioColdStartBaseActivity {
+    private static final String TAG = "AudioInColdStartLatencyActivity";
+    private static final boolean DEBUG = false;
+
+    private static final int LATENCY_MS_MUST     = 500; // CDD C-3-2
+    private static final int LATENCY_MS_RECOMMEND = 100; // CDD C-SR
+
+    // MegaAudio
+    private Recorder mRecorder;
+
+    private TextView mCallbackDeltaTxt;
+
+    private long mPreviousCallbackTime;
+    private long mCallbackDeltaTime;
+
+    private long mNominalCallbackDelta;
+    private long mCallbackThresholdTime;
+    private long mAccumulatedTime;
+    private long mNumCallbacks;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        setContentView(R.layout.audio_coldstart_in_activity);
+        super.onCreate(savedInstanceState);
+
+//        mCallbackDeltaTxt = (TextView) findViewById(R.id.coldstart_inCallbackDeltaTxt);
+
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        setInfoResources(
+                R.string.audio_coldstart_inputlbl, R.string.audio_coldstart_input_info, -1);
+    }
+
+    @Override
+    public String getTestId() {
+        return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
+    }
+
+    boolean calcTestResult() {
+        boolean pass = mColdStartlatencyMS <= LATENCY_MS_MUST;
+        getPassButton().setEnabled(pass);
+        return pass;
+    }
+
+    double calcColdStartLatency() {
+        mColdStartlatencyMS = nanosToMs(mPreviousCallbackTime - mPreOpenTime);
+        return mColdStartlatencyMS;
+    }
+
+    void showInResults() {
+        showColdStartLatency();
+
+        calcTestResult();
+    }
+
+    protected void stopAudio() {
+        stopAudioTest();
+    }
+
+    //
+    // Audio Streaming
+    //
+    @Override
+    boolean startAudioTest() {
+        AudioSystemParams audioSystemParams = new AudioSystemParams();
+        audioSystemParams.init(this);
+
+        mSampleRate = audioSystemParams.getSystemSampleRate();
+        mNumBufferFrames = audioSystemParams.getSystemBurstFrames();
+
+        mAccumulatedTime = 0;
+        mNumCallbacks = 0;
+
+        AudioSinkProvider sinkProvider =
+                new AppCallbackAudioSinkProvider(new ColdStartAppCallback());
+        try {
+            mPreOpenTime = System.nanoTime();
+            mRecorder = (new RecorderBuilder())
+                    .setRecorderType(mAudioApi)
+                    .setAudioSinkProvider(sinkProvider)
+                    .build();
+            mRecorder.setupStream(NUM_CHANNELS, mSampleRate, mNumBufferFrames);
+            mPostOpenTime = System.nanoTime();
+
+            mIsTestRunning = true;
+        } catch (RecorderBuilder.BadStateException badStateException) {
+            mResultsTxt.setText("Can't Start Recorder.");
+            Log.e(TAG, "BadStateException: " + badStateException);
+            mIsTestRunning = false;
+        }
+
+        mPreStartTime = System.nanoTime();
+        mRecorder.startStream();
+        mPostStartTime = System.nanoTime();
+
+        showOpenTime();
+        showStartTime();
+
+        if (mIsTestRunning) {
+            mStartBtn.setEnabled(false);
+            mStopBtn.setEnabled(true);
+        }
+        return mIsTestRunning;
+    }
+
+    @Override
+    void stopAudioTest() {
+        if (!mIsTestRunning) {
+            return;
+        }
+
+        mRecorder.stopStream();
+
+        mIsTestRunning = false;
+
+        mStartBtn.setEnabled(true);
+        mStopBtn.setEnabled(false);
+
+        calcColdStartLatency();
+
+        showInResults();
+    }
+
+    // Callback for Recorder
+    /*
+     * Monitor callbacks until they become consistent (i.e. delta between callbacks is below
+     * some threshold like 1/8 the "nominal" callback time. This is defined as the "cold start
+     * latency". Calculate that time and display the results.
+     */
+    class ColdStartAppCallback implements AppCallback {
+        public void onDataReady(float[] audioData, int numFrames) {
+            mNumCallbacks++;
+
+            long time = System.nanoTime();
+            if (mPreviousCallbackTime == 0) {
+                mNumBufferFrames = numFrames;
+                mNominalCallbackDelta
+                        = (long)((1000000000.0 * (double) mNumBufferFrames) / (double) mSampleRate);
+                mCallbackThresholdTime = mNominalCallbackDelta + (mNominalCallbackDelta / 8);
+                // update attributes with actual buffer size
+                // showAttributes();
+                mPreviousCallbackTime = time;
+            } else {
+                mCallbackDeltaTime = time - mPreviousCallbackTime;
+
+                mPreviousCallbackTime = time;
+                mAccumulatedTime += mCallbackDeltaTime;
+
+                if (mCallbackDeltaTime < mCallbackThresholdTime) {
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            stopAudioTest();
+                        }
+                    });
+                }
+            }
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
new file mode 100644
index 0000000..a605edf
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutColdStartLatencyActivity.java
@@ -0,0 +1,181 @@
+/*
+ * 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.verifier.audio;
+
+import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
+import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
+
+import android.media.AudioTimestamp;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.audio.audiolib.AudioSystemParams;
+
+import org.hyphonate.megaaudio.player.AudioSourceProvider;
+import org.hyphonate.megaaudio.player.Player;
+import org.hyphonate.megaaudio.player.PlayerBuilder;
+import org.hyphonate.megaaudio.player.sources.SilenceAudioSourceProvider;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * CTS-Test for cold-start latency measurements
+ */
+public class AudioOutColdStartLatencyActivity
+        extends AudioColdStartBaseActivity {
+    private static final String TAG = "AudioOutColdStartLatencyActivity";
+    private static final boolean DEBUG = false;
+
+    private static final int LATENCY_MS_MUST      = 500; // CDD C-1-2
+    private static final int LATENCY_MS_RECOMMEND = 100; // CDD C-SR
+
+    // MegaAudio
+    private Player mPlayer;
+
+    // Time Stamps
+    Timer mTimer;
+    private AudioTimestamp mPullTimestamp = new AudioTimestamp();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        setContentView(R.layout.audio_coldstart_out_activity);
+        super.onCreate(savedInstanceState);
+
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        setInfoResources(
+                R.string.audio_coldstart_outputlbl, R.string.audio_coldstart_output_info, -1);
+    }
+
+    @Override
+    public String getTestId() {
+        return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
+    }
+
+    boolean calcTestResult() {
+        boolean pass = mColdStartlatencyMS <= LATENCY_MS_MUST;
+        getPassButton().setEnabled(pass);
+        return pass;
+    }
+
+    double calcColdStartLatency(AudioTimestamp timestamp) {
+        // how long ago was frame 0?
+        long frame0Delta
+                = msToNanos((1000.0 * (double)timestamp.framePosition) / (double) mSampleRate);
+        long frame0Time = timestamp.nanoTime - frame0Delta;
+        double coldStartLatency = frame0Time - mPreOpenTime;
+
+        mColdStartlatencyMS = nanosToMs(coldStartLatency);
+
+        return mColdStartlatencyMS;
+    }
+
+    protected void stopAudio() {
+        stopAudioTest();
+    }
+
+    void startOutTimer() {
+        TimerTask task = new TimerTask() {
+            public void run() {
+                boolean gotTimestamp = mPlayer.getTimestamp(mPullTimestamp);
+                if (gotTimestamp) {
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            calcColdStartLatency(mPullTimestamp);
+                            showColdStartLatency();
+                            stopAudioTest();
+                            updateTestStateButtons();
+                            calcTestResult();
+                        }
+                    });
+
+                } else {
+                    Log.e(TAG, "NO TIME STAMP");
+                    mResultsTxt.setText("NO TIME STAMP");
+                }
+
+                mTimer = null;
+            }
+        };
+
+        mTimer = new Timer();
+        mTimer.schedule(task, 500L /*delay*/);
+    }
+
+    void stopOutTimer() {
+        if (mTimer != null) {
+            mTimer.cancel();
+            mTimer = null;
+        }
+    }
+
+    //
+    // Audio Streaming
+    //
+    @Override
+    boolean startAudioTest() {
+        AudioSystemParams audioSystemParams = new AudioSystemParams();
+        audioSystemParams.init(this);
+
+        mSampleRate = audioSystemParams.getSystemSampleRate();
+        // mNumBufferFrames = audioSystemParams.getSystemBufferFrames();
+        mNumBufferFrames = audioSystemParams.getSystemBurstFrames();
+
+        AudioSourceProvider sourceProvider = new SilenceAudioSourceProvider();
+        try {
+            mPreOpenTime = System.nanoTime();
+            mPlayer = (new PlayerBuilder())
+                    .setPlayerType(mAudioApi)
+                    .setSourceProvider(sourceProvider)
+                    .build();
+            mPlayer.setupStream(NUM_CHANNELS, mSampleRate, mNumBufferFrames);
+            mPostOpenTime = System.nanoTime();
+
+            mIsTestRunning = true;
+        } catch (PlayerBuilder.BadStateException badStateException) {
+            Log.e(TAG, "BadStateException: " + badStateException);
+            mResultsTxt.setText("Can't Start Player.");
+            mIsTestRunning = false;
+        }
+
+        mPreStartTime = System.nanoTime();
+        mPlayer.startStream();
+        mPostStartTime = System.nanoTime();
+
+        if (mIsTestRunning) {
+            startOutTimer();
+        }
+        return mIsTestRunning;
+    }
+
+    @Override
+    void stopAudioTest() {
+        if (!mIsTestRunning) {
+            return;
+        }
+
+        mPlayer.stopStream();
+        mIsTestRunning = false;
+
+        stopOutTimer();
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
index bfc501c..04cfa7c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
@@ -78,6 +78,7 @@
     private TextView mSpecView;
     private TextView mResultsView;
     private TextView mStatsView;
+    private TextView mPhaseView;
 
     private WaveformView mWaveformView;
 
@@ -140,8 +141,8 @@
         mStopBtn = (Button) findViewById(R.id.tap2tone_stopBtn);
         mStopBtn.setOnClickListener(this);
 
-        ((RadioButton) findViewById(R.id.tap2toneJavaApiBtn)).setOnClickListener(this);
-        RadioButton nativeApiRB = findViewById(R.id.tap2toneNativeApiBtn);
+        ((RadioButton) findViewById(R.id.audioJavaApiBtn)).setOnClickListener(this);
+        RadioButton nativeApiRB = findViewById(R.id.audioNativeApiBtn);
         nativeApiRB.setChecked(true);
         nativeApiRB.setOnClickListener(this);
 
@@ -150,6 +151,7 @@
         mSpecView = (TextView) findViewById(R.id.tap2tone_specTxt);
         mResultsView = (TextView) findViewById(R.id.tap2tone_resultTxt);
         mStatsView = (TextView) findViewById(R.id.tap2tone_statsTxt);
+        mPhaseView = (TextView) findViewById(R.id.tap2tone_phaseInfo);
 
         mWaveformView = (WaveformView) findViewById(R.id.tap2tone_waveView);
         // Start a blip test when the waveform view is tapped.
@@ -190,7 +192,6 @@
     }
 
     private void startAudio() {
-        Log.i(TAG, "---- startAudio() mIsRecording:" + mIsRecording);
         if (mIsRecording) {
             return;
         }
@@ -206,7 +207,6 @@
         mDuplexAudioManager.start();
 
         mBlipSource = (AudioSource) mDuplexAudioManager.getAudioSource();
-        Log.i(TAG, "---- smBlipSource:" + mBlipSource);
 
         mIsRecording = true;
         enableAudioButtons();
@@ -246,15 +246,21 @@
     }
 
     private void calculateTestPass() {
+        // 80ms is currently STRONGLY RECOMMENDED, so pass the test as long as they have run it.
+        boolean testCompleted = mTestPhase >= NUM_TEST_PHASES;
         boolean pass = mLatencyAve[mActiveTestAPI] != 0
-                && mTestPhase >= NUM_TEST_PHASES
                 && mLatencyAve[mActiveTestAPI] <= MAX_TAP_2_TONE_LATENCY;
 
-        if (pass) {
-            mSpecView.setText("Ave: " + mLatencyAve[mActiveTestAPI] + " ms <= "
-                    + MAX_TAP_2_TONE_LATENCY + " ms -- PASS");
+        if (testCompleted) {
+            if (pass) {
+                mSpecView.setText("Ave: " + mLatencyAve[mActiveTestAPI] + " ms <= "
+                        + MAX_TAP_2_TONE_LATENCY + " ms -- PASS");
+            } else {
+                mSpecView.setText("Ave: " + mLatencyAve[mActiveTestAPI] + " ms > "
+                        + MAX_TAP_2_TONE_LATENCY + " ms -- DOES NOT MEET STRONGLY RECOMMENDED");
+            }
         }
-        getPassButton().setEnabled(pass);
+        getPassButton().setEnabled(testCompleted);
     }
 
     private void recordTestStatus() {
@@ -352,6 +358,8 @@
         mResultsView.setText("Phase: " + mTestPhase + " : " + latencyMillis
                 + " ms, Ave: " + mLatencyAve[mActiveTestAPI] + " ms");
         mStatsView.setText("Deviation: " + String.format("%.2f",meanAbsoluteDeviation));
+
+        mPhaseView.setText("" + mTestPhase + " of " + NUM_TEST_PHASES + " completed.");
     }
 
     private void analyzeCapturedAudio() {
@@ -407,14 +415,14 @@
                 stopAudio();
                 break;
 
-            case R.id.tap2toneJavaApiBtn:
+            case R.id.audioJavaApiBtn:
                 stopAudio();
                 clearResults();
                 mPlayerType = BuilderBase.TYPE_JAVA;
                 mActiveTestAPI = TEST_API_JAVA;
                 break;
 
-            case R.id.tap2toneNativeApiBtn:
+            case R.id.audioNativeApiBtn:
                 stopAudio();
                 clearResults();
                 mPlayerType = BuilderBase.TYPE_OBOE | BuilderBase.SUB_TYPE_OBOE_AAUDIO;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/RingerModeActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/RingerModeActivity.java
index 3d2639b..74e92f1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/RingerModeActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/RingerModeActivity.java
@@ -76,6 +76,8 @@
     private boolean mIsTelevision;
     private boolean mIsSingleVolume;
     private boolean mSkipRingerTests;
+    private boolean mIsWatch;
+    private boolean mSkipTouchSoundTests;
 
     @Override
     protected int getTitleResource() {
@@ -101,6 +103,8 @@
         mIsSingleVolume = mContext.getResources().getBoolean(
                 Resources.getSystem().getIdentifier("config_single_volume", "bool", "android"));
         mSkipRingerTests = mUseFixedVolume || mIsTelevision || mIsSingleVolume;
+        mIsWatch = packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH);
+        mSkipTouchSoundTests = mIsWatch;
     }
 
     // Test Setup
@@ -246,6 +250,10 @@
 
         @Override
         protected void test() {
+            if (mSkipTouchSoundTests) {
+                status = PASS;
+                return;
+            }
             boolean touchSoundEnabled =
                 Settings.System.getInt(mContext.getContentResolver(),
                     Settings.System.SOUND_EFFECTS_ENABLED, 1) == 1;
@@ -276,6 +284,10 @@
 
         @Override
         protected void test() {
+            if (mSkipTouchSoundTests) {
+                status = PASS;
+                return;
+            }
             // should hear sound after loadSoundEffects() called.
             mAudioManager.loadSoundEffects();
             try {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java
index 5f41fa7..29e23c7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/battery/IgnoreBatteryOptimizationsTestActivity.java
@@ -51,13 +51,41 @@
                 mConfirmIsExempted,
                 mRemoveExemption,
                 mIntermediate,
+                mConfirmIsNotExempted,
+                mOpenAppExemptionListToExempt,
+                mIntermediate,
+                mConfirmIsExempted,
+                mOpenAppExemptionListToUnexempt,
+                mIntermediate,
                 mConfirmIsNotExempted
         };
     }
 
     private boolean isExempted() {
-        return mUsageStatsManager.getAppStandbyBucket() == UsageStatsManager.STANDBY_BUCKET_EXEMPTED
-                && mPowerManager.isIgnoringBatteryOptimizations(getPackageName());
+        return mPowerManager.isIgnoringBatteryOptimizations(getPackageName())
+                && mUsageStatsManager.getAppStandbyBucket()
+                == UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
+    }
+
+    private boolean isFullyNotExempted() {
+        // Use an OR so we check both values to make sure neither of them say the app is exempted.
+        if (mPowerManager.isIgnoringBatteryOptimizations(getPackageName())
+                || mUsageStatsManager.getAppStandbyBucket()
+                == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) {
+            return false;
+        }
+        return true;
+    }
+
+    private void openAppInfoPage() {
+        Intent appInfoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+        appInfoIntent.setData(Uri.parse("package:" + getPackageName()));
+        startActivity(appInfoIntent);
+    }
+
+    private void openIgnoreBatteryOptimizationsAppList() {
+        Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
+        startActivity(intent);
     }
 
     private final Test mConfirmNotExemptedAtStart = new Test(R.string.ibo_test_start_unexempt_app) {
@@ -65,7 +93,7 @@
         protected void run() {
             super.run();
 
-            if (!isExempted()) {
+            if (isFullyNotExempted()) {
                 succeed();
             }
         }
@@ -73,16 +101,14 @@
         @Override
         protected void onNextClick() {
             if (isExempted()) {
-                Intent appInfoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
-                appInfoIntent.setData(Uri.parse("package:" + getPackageName()));
-                startActivity(appInfoIntent);
+                openAppInfoPage();
             } else {
                 succeed();
             }
         }
     };
 
-    private final Test mRequestExemption = new Test(R.string.ibo_exempt_app) {
+    private final Test mRequestExemption = new Test(R.string.ibo_exempt_app_request) {
         @Override
         protected void onNextClick() {
             Intent request = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
@@ -106,6 +132,8 @@
 
             if (isExempted()) {
                 succeed();
+            } else {
+                findViewById(R.id.btn_next).setVisibility(View.GONE);
             }
         }
     };
@@ -115,7 +143,7 @@
         protected void run() {
             super.run();
 
-            if (!isExempted()) {
+            if (isFullyNotExempted()) {
                 succeed();
             }
         }
@@ -123,9 +151,7 @@
         @Override
         protected void onNextClick() {
             if (isExempted()) {
-                Intent appInfoIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
-                appInfoIntent.setData(Uri.parse("package:" + getPackageName()));
-                startActivity(appInfoIntent);
+                openAppInfoPage();
             } else {
                 succeed();
             }
@@ -137,11 +163,27 @@
         protected void run() {
             super.run();
 
-            if (!isExempted()) {
+            if (isFullyNotExempted()) {
                 succeed();
             } else {
                 findViewById(R.id.btn_next).setVisibility(View.GONE);
             }
         }
     };
+
+    private final Test mOpenAppExemptionListToExempt = new Test(R.string.ibo_exempt_app_list) {
+        @Override
+        protected void onNextClick() {
+            openIgnoreBatteryOptimizationsAppList();
+            succeed();
+        }
+    };
+
+    private final Test mOpenAppExemptionListToUnexempt = new Test(R.string.ibo_unexempt_app_list) {
+        @Override
+        protected void onNextClick() {
+            openIgnoreBatteryOptimizationsAppList();
+            succeed();
+        }
+    };
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestActivity.java
index 690bd6b..690bf58 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/PolicyTransparencyTestActivity.java
@@ -138,6 +138,7 @@
         R.string.password_quality_complex
     };
 
+    private boolean mForceCurrentUserDpm;
     private String mSettingsIntentAction;
     private String mTestId;
     private String mTitle;
@@ -149,6 +150,9 @@
         setContentView(R.layout.policy_transparency_test);
         setPassFailButtonClickListeners();
 
+        mForceCurrentUserDpm =
+                getIntent().getBooleanExtra(
+                        CommandReceiverActivity.EXTRA_USE_CURRENT_USER_DPM, false);
         mTitle = getIntent().getStringExtra(EXTRA_TITLE);
         mTestId = getIntent().getStringExtra(EXTRA_TEST_ID);
         mSettingsIntentAction = getIntent().getStringExtra(EXTRA_SETTINGS_INTENT_ACTION);
@@ -238,8 +242,11 @@
         if (TEST_CHECK_USER_RESTRICTION.equals(mTest)) {
             final String userRestriction = getIntent().getStringExtra(
                     CommandReceiverActivity.EXTRA_USER_RESTRICTION);
-            intent = CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
-                    userRestriction, isChecked);
+            intent = mForceCurrentUserDpm
+                    ? CommandReceiverActivity.createSetCurrentUserRestrictionIntent(
+                            userRestriction, isChecked)
+                    : CommandReceiverActivity.createSetDeviceOwnerUserRestrictionIntent(
+                            userRestriction, isChecked);
         } else {
             intent = new Intent(CommandReceiverActivity.ACTION_EXECUTE_COMMAND);
             final PolicyTestItem testItem = POLICY_TEST_ITEMS.get(mTest);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
index 233e1bd..ac54bac 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
@@ -221,13 +221,20 @@
 
     public static Intent getUserRestrictionTestIntent(Context context, String restriction) {
         final UserRestrictionItem item = USER_RESTRICTION_ITEMS.get(restriction);
-        return new Intent(PolicyTransparencyTestActivity.ACTION_SHOW_POLICY_TRANSPARENCY_TEST)
-                .putExtra(PolicyTransparencyTestActivity.EXTRA_TEST,
-                        PolicyTransparencyTestActivity.TEST_CHECK_USER_RESTRICTION)
-                .putExtra(CommandReceiverActivity.EXTRA_USER_RESTRICTION, restriction)
-                .putExtra(PolicyTransparencyTestActivity.EXTRA_TITLE, context.getString(item.label))
-                .putExtra(PolicyTransparencyTestActivity.EXTRA_SETTINGS_INTENT_ACTION,
-                        item.intentAction);
+        final Intent intent =
+                new Intent(PolicyTransparencyTestActivity.ACTION_SHOW_POLICY_TRANSPARENCY_TEST)
+                        .putExtra(PolicyTransparencyTestActivity.EXTRA_TEST,
+                                PolicyTransparencyTestActivity.TEST_CHECK_USER_RESTRICTION)
+                        .putExtra(CommandReceiverActivity.EXTRA_USER_RESTRICTION, restriction)
+                        .putExtra(PolicyTransparencyTestActivity.EXTRA_TITLE,
+                                context.getString(item.label))
+                        .putExtra(PolicyTransparencyTestActivity.EXTRA_SETTINGS_INTENT_ACTION,
+                                item.intentAction);
+        // For DISALLOW_FACTORY_RESET, set on the device owner, not on the current user.
+        if (!UserManager.DISALLOW_FACTORY_RESET.equals(restriction)) {
+            intent.putExtra(CommandReceiverActivity.EXTRA_USE_CURRENT_USER_DPM, true);
+        }
+        return intent;
     }
 
     public static boolean isRestrictionValid(Context context, String restriction) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ToastVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ToastVerifierActivity.java
new file mode 100644
index 0000000..693bcb0
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ToastVerifierActivity.java
@@ -0,0 +1,66 @@
+/*
+ * 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.verifier.notifications;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Toast;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+/**
+ * Tests visual requirements for toasts.
+ *   - max 2 lines
+ *   - show app icon
+ */
+public class ToastVerifierActivity extends PassFailButtons.Activity {
+
+    @Override
+    protected void onCreate(Bundle savedState) {
+        super.onCreate(savedState);
+        setContentView(getLayoutInflater().inflate(R.layout.toast_main, null));
+        setPassFailButtonClickListeners();
+
+        // Sets the text in the dialog
+        setInfoResources(R.string.toast_title,
+                R.string.toast_info, -1);
+
+        if (getApplicationContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.S) {
+            // don't run the test, auto-pass
+            findViewById(R.id.toast_description_s).setVisibility(View.GONE);
+            findViewById(R.id.toast_post_button).setVisibility(View.GONE);
+            getPassButton().callOnClick();
+        } else {
+            // only enable pass after tester has pressed button to post a toast
+            getPassButton().setEnabled(false);
+            findViewById(R.id.toast_description_pre_s).setVisibility(View.GONE);
+        }
+
+        // Post toast
+        findViewById(R.id.toast_post_button).setOnClickListener(v -> {
+            postToast();
+            getPassButton().setEnabled(true);
+        });
+    }
+
+    private void postToast() {
+        Toast.makeText(getApplicationContext(), R.string.toast_long_text, Toast.LENGTH_LONG)
+                .show();
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/OWNERS
index a778d54..48b0246 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/OWNERS
@@ -1,4 +1,2 @@
 # Bug component: 109606
-dysu@google.com
-etancohen@google.com
-satk@google.com
+include platform/packages/modules/Wifi:/WIFI_OWNERS
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/speech/tts/TtsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/speech/tts/TtsTestActivity.java
index f95162d..0bffd91 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/speech/tts/TtsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/speech/tts/TtsTestActivity.java
@@ -2,10 +2,12 @@
 
 import android.content.ActivityNotFoundException;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.view.View;
 import android.widget.Button;
+
 import androidx.annotation.Nullable;
 
 import com.android.cts.verifier.PassFailButtons;
@@ -16,24 +18,36 @@
  */
 public class TtsTestActivity extends PassFailButtons.Activity {
 
-  private Button mAccessibilitySettingsButton;
+    private static final String TTS_INTENT = "com.android.settings.TTS_SETTINGS";
 
-  @Override
-  protected void onCreate(@Nullable Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
+    private Button mAccessibilitySettingsButton;
 
-    setContentView(R.layout.tts_main);
-    setInfoResources(R.string.tts_test, R.string.tts_test_info, -1);
-    setPassFailButtonClickListeners();
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
 
-    mAccessibilitySettingsButton = findViewById(R.id.accessibility_settings_button);
-    mAccessibilitySettingsButton.setOnClickListener(new View.OnClickListener() {
-        public void onClick(View v) {
-            try {
-                startActivityForResult(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0);
-            } catch (ActivityNotFoundException e) {}
-        }
-    });
-  }
+        setContentView(R.layout.tts_main);
+        setInfoResources(R.string.tts_test, R.string.tts_test_info, -1);
+        setPassFailButtonClickListeners();
 
+        mAccessibilitySettingsButton = findViewById(R.id.accessibility_settings_button);
+        mAccessibilitySettingsButton.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                Intent intent;
+                if (isAutomotive()) {
+                    // Automotive doesn't have accessibility settings - open TTS settings directly
+                    intent = new Intent(TTS_INTENT);
+                } else {
+                    intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
+                }
+                try {
+                    startActivityForResult(intent, 0);
+                } catch (ActivityNotFoundException e) { }
+            }
+        });
+    }
+
+    private boolean isAutomotive() {
+        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifi/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/wifi/OWNERS
index 7d9d0f9..a0ab9e6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/wifi/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifi/OWNERS
@@ -1,4 +1,2 @@
 # Bug component: 33618
-dysu@google.com
-etancohen@google.com
-satk@google.com
+include platform/packages/modules/Wifi:/WIFI_OWNERS
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/OWNERS
index 0132857..1cd283c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifiaware/OWNERS
@@ -1,4 +1,2 @@
 # Bug component: 109581
-dysu@google.com
-etancohen@google.com
-satk@google.com
+include platform/packages/modules/Wifi:/WIFI_OWNERS
diff --git a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/JavaPlayer.java b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/JavaPlayer.java
index c9f9f06..8e1bc18 100644
--- a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/JavaPlayer.java
+++ b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/JavaPlayer.java
@@ -17,6 +17,7 @@
 
 import android.media.AudioDeviceInfo;
 import android.media.AudioFormat;
+import android.media.AudioTimestamp;
 import android.media.AudioTrack;
 import android.util.Log;
 
@@ -196,6 +197,15 @@
         return OK;
     }
 
+    /**
+     * Gets a timestamp from the audio stream
+     * @param timestamp
+     * @return
+     */
+    public boolean getTimestamp(AudioTimestamp timestamp) {
+        return mPlaying ? mAudioTrack.getTimestamp(timestamp) : false;
+    }
+
     //
     // StreamPlayerRunnable
     //
@@ -213,6 +223,8 @@
             while (mPlaying) {
                 mAudioSource.pull(mAudioBuffer, mNumBufferFrames, mChannelCount);
 
+                onPull();
+
                 int numSamplesWritten = mAudioTrack.write(
                         mAudioBuffer,0, numBufferSamples, AudioTrack.WRITE_BLOCKING);
                 if (numSamplesWritten < 0) {
diff --git a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/OboePlayer.java b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/OboePlayer.java
index 9f2ed4e..86f507e 100644
--- a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/OboePlayer.java
+++ b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/OboePlayer.java
@@ -15,6 +15,8 @@
  */
 package org.hyphonate.megaaudio.player;
 
+import android.media.AudioTimestamp;
+
 public class OboePlayer extends Player {
     boolean mPlaying;
 
@@ -87,6 +89,15 @@
         return stopN(mNativePlayer);
     }
 
+    /**
+     * Gets a timestamp from the audio stream
+     * @param timestamp
+     * @return
+     */
+    public boolean getTimestamp(AudioTimestamp timestamp) {
+        return getTimestampN(mNativePlayer, timestamp);
+    }
+
     private native long allocNativePlayer(long nativeSource, int playerSubtype);
 
     private native int setupStreamN(long nativePlayer, int channelCount, int sampleRate, int routeDeviceId);
@@ -98,4 +109,6 @@
     private native int getBufferFrameCountN(long mNativePlayer);
 
     private native int getRoutedDeviceIdN(long nativePlayer);
+
+    private native boolean getTimestampN(long nativePlayer, AudioTimestamp timestamp);
 }
diff --git a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/Player.java b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/Player.java
index c078c6a..a6b6532 100644
--- a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/Player.java
+++ b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/Player.java
@@ -16,15 +16,20 @@
 package org.hyphonate.megaaudio.player;
 
 import android.media.AudioFormat;
+import android.media.AudioTimestamp;
 import android.media.AudioTrack;
 
 import org.hyphonate.megaaudio.common.StreamBase;
 
+import java.util.ArrayList;
+
 /**
  * An abstract class defining the common operations and attributes for all
  * player (concrete) sub-classes.
  */
 public abstract class Player extends StreamBase {
+    private ArrayList<BufferCallback> mCallbacks = new ArrayList<BufferCallback>();
+
     public Player(AudioSourceProvider sourceProvider) {
         mSourceProvider = sourceProvider;
     }
@@ -96,4 +101,52 @@
         }
     }
 
+    //
+    // TimeStamp
+    //
+    /**
+     * Gets a timestamp from the audio stream
+     * @param timestamp
+     * @return
+     */
+    public abstract boolean getTimestamp(AudioTimestamp timestamp);
+
+    //
+    // BufferCallback Stuff
+    //
+
+    /**
+     * Defines an interface for buffer callback objects
+     */
+    public interface BufferCallback {
+        /**
+         * Called when player executes a pull() on the associated AudioSource
+         */
+        void onPull();
+    }
+
+    /**
+     * Adds a callback object
+     * @param callback
+     */
+    public void addBufferCallback(BufferCallback callback) {
+        mCallbacks.add(callback);
+    }
+
+    /**
+     * Removes a previously added callback object
+     * @param callback
+     */
+    public void removeBufferCallback(BufferCallback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    /**
+     * Iterates through callback objects and calls their onPull() method.
+     */
+    public void onPull() {
+        for (BufferCallback callback : mCallbacks) {
+            callback.onPull();
+        }
+    }
 }
diff --git a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/SilenceAudioSource.java b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/SilenceAudioSource.java
new file mode 100644
index 0000000..be67326
--- /dev/null
+++ b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/SilenceAudioSource.java
@@ -0,0 +1,36 @@
+/*
+ * 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 org.hyphonate.megaaudio.player.sources;
+
+import org.hyphonate.megaaudio.player.AudioSource;
+
+public class SilenceAudioSource extends AudioSource {
+    /**
+     * Fills the specified buffer with zeros (silence).
+     *
+     * @param buffer The buffer to be filled.
+     * @param numFrames The number of frames of audio to provide.
+     * @param numChans The number of channels (in the buffer) required by the player.
+     * @return  The number of samples generated. Since we are generating a continuous periodic
+     * signal, this will always be <code>numFrames</code>.
+     */
+    @Override
+    public int pull(float[] buffer, int numFrames, int numChans) {
+        java.util.Arrays.fill(buffer, 0);
+
+        return numFrames;
+    }
+}
diff --git a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/SilenceAudioSourceProvider.java b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/SilenceAudioSourceProvider.java
new file mode 100644
index 0000000..16be178
--- /dev/null
+++ b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/SilenceAudioSourceProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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 org.hyphonate.megaaudio.player.sources;
+
+import org.hyphonate.megaaudio.player.AudioSource;
+import org.hyphonate.megaaudio.player.AudioSourceProvider;
+import org.hyphonate.megaaudio.player.NativeAudioSource;
+
+public class SilenceAudioSourceProvider implements AudioSourceProvider {
+    @Override
+    public AudioSource getJavaSource() {
+        return new SilenceAudioSource();
+    }
+
+    @Override
+    public NativeAudioSource getNativeSource() {
+        return new NativeAudioSource(allocNativeSource());
+    }
+
+    private native long allocNativeSource();
+}
diff --git a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/WaveTableSource.java b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/WaveTableSource.java
index 6cb8333b..30545b1 100644
--- a/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/WaveTableSource.java
+++ b/apps/CtsVerifier/src/org/hyphonate/megaaudio/player/sources/WaveTableSource.java
@@ -126,6 +126,7 @@
             float value = ((mWaveTbl[srcIndex] * delta0) + (mWaveTbl[srcIndex + 1] * delta1));
 
             // Put the same value in all channels.
+            // This is inefficient and should be pulled out of this loop
             for (int chanIndex = 0; chanIndex < numChans; chanIndex++) {
                 buffer[outIndex++] = value;
             }
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DevicePolicyManagerWrapper.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DevicePolicyManagerWrapper.java
index 0b273dd..3444eeb 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DevicePolicyManagerWrapper.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/DevicePolicyManagerWrapper.java
@@ -247,6 +247,12 @@
             doAnswer(answer).when(spy).setPasswordHistoryLength(any(), anyInt());
             doAnswer(answer).when(spy).setMaximumFailedPasswordsForWipe(any(), anyInt());
 
+            // Used by AccessibilityServicesTest
+            doAnswer(answer).when(spy).getPermittedAccessibilityServices(any());
+
+            // Used by InputMethodsTest
+            doAnswer(answer).when(spy).getPermittedInputMethods(any());
+
             // TODO(b/176993670): add more methods below as tests are converted
         } catch (Exception e) {
             // Should never happen, but needs to be catch as some methods declare checked exceptions
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
index c48456d..9aafad1 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
@@ -185,7 +185,11 @@
 
         Answer<?> answer = (inv) -> {
             Object[] args = inv.getArguments();
-            Log.d(TAG, "spying " + inv + " method: " + inv.getMethod());
+            if (VERBOSE) {
+                Log.v(TAG, "spying " + inv + " method: " + inv.getMethod());
+            } else {
+                Log.i(TAG, "spying " + inv.getMethod());
+            }
             String methodName = inv.getMethod().getName();
             Intent intent = new Intent(ACTION_WRAPPED_MANAGER_CALL)
                     .setClassName(context, receiverClassName)
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 847a8a8..32e2047 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
@@ -69,6 +69,7 @@
 import com.android.bedstead.nene.users.User;
 import com.android.bedstead.nene.users.UserBuilder;
 import com.android.bedstead.nene.users.UserReference;
+import com.android.bedstead.nene.users.UserType;
 import com.android.bedstead.nene.utils.ShellCommand;
 import com.android.bedstead.nene.utils.Versions;
 import com.android.bedstead.remotedpc.RemoteDpc;
@@ -155,193 +156,9 @@
 
                 assumeFalse(mSkipTestsReason, mSkipTests);
 
-                PermissionContextImpl permissionContext = null;
+                Collection<Annotation> annotations = getAnnotations(description);
+                PermissionContextImpl permissionContext = applyAnnotations(annotations);
 
-                for (Annotation annotation : getAnnotations(description)) {
-                    Class<? extends Annotation> annotationType = annotation.annotationType();
-
-                    EnsureHasNoProfileAnnotation ensureHasNoProfileAnnotation =
-                            annotationType.getAnnotation(EnsureHasNoProfileAnnotation.class);
-                    if (ensureHasNoProfileAnnotation != null) {
-                        UserType userType = (UserType) annotation.annotationType()
-                                .getMethod("forUser").invoke(annotation);
-                        ensureHasNoProfile(ensureHasNoProfileAnnotation.value(), userType);
-                        continue;
-                    }
-
-                    EnsureHasProfileAnnotation ensureHasProfileAnnotation =
-                            annotationType.getAnnotation(EnsureHasProfileAnnotation.class);
-                    if (ensureHasProfileAnnotation != null) {
-                        UserType forUser = (UserType) annotation.annotationType()
-                                .getMethod("forUser").invoke(annotation);
-                        OptionalBoolean installInstrumentedApp = (OptionalBoolean)
-                                annotation.annotationType()
-                                .getMethod("installInstrumentedApp").invoke(annotation);
-                            ensureHasProfile(
-                                    ensureHasProfileAnnotation.value(), installInstrumentedApp,
-                                    forUser);
-                            continue;
-                    }
-
-                    EnsureHasNoUserAnnotation ensureHasNoUserAnnotation =
-                            annotationType.getAnnotation(EnsureHasNoUserAnnotation.class);
-                    if (ensureHasNoUserAnnotation != null) {
-                        ensureHasNoUser(ensureHasNoUserAnnotation.value());
-                        continue;
-                    }
-
-                    EnsureHasUserAnnotation ensureHasUserAnnotation =
-                            annotationType.getAnnotation(EnsureHasUserAnnotation.class);
-                    if (ensureHasUserAnnotation != null) {
-                        OptionalBoolean installInstrumentedApp = (OptionalBoolean)
-                                annotation.getClass()
-                                .getMethod("installInstrumentedApp").invoke(annotation);
-                        ensureHasUser(ensureHasUserAnnotation.value(), installInstrumentedApp);
-                        continue;
-                    }
-
-                    RequireRunOnUserAnnotation requireRunOnUserAnnotation =
-                            annotationType.getAnnotation(RequireRunOnUserAnnotation.class);
-                    if (requireRunOnUserAnnotation != null) {
-                        requireRunOnUser(requireRunOnUserAnnotation.value());
-                        continue;
-                    }
-
-                    RequireRunOnProfileAnnotation requireRunOnProfileAnnotation =
-                            annotationType.getAnnotation(RequireRunOnProfileAnnotation.class);
-                    if (requireRunOnProfileAnnotation != null) {
-                        OptionalBoolean installInstrumentedAppInParent = (OptionalBoolean)
-                                annotation.getClass()
-                                        .getMethod("installInstrumentedAppInParent")
-                                        .invoke(annotation);
-                        requireRunOnProfile(requireRunOnProfileAnnotation.value(),
-                                installInstrumentedAppInParent);
-                    }
-
-                    if (annotation instanceof EnsureHasDeviceOwner) {
-                        EnsureHasDeviceOwner ensureHasDeviceOwnerAnnotation =
-                                (EnsureHasDeviceOwner) annotation;
-                        ensureHasDeviceOwner(ensureHasDeviceOwnerAnnotation.onUser(),
-                                ensureHasDeviceOwnerAnnotation.failureMode(),
-                                ensureHasDeviceOwnerAnnotation.isPrimary());
-                    }
-
-                    if (annotation instanceof EnsureHasNoDeviceOwner) {
-                        ensureHasNoDeviceOwner();
-                    }
-
-                    if (annotation instanceof RequireFeature) {
-                        RequireFeature requireFeatureAnnotation = (RequireFeature) annotation;
-                        requireFeature(
-                                requireFeatureAnnotation.value(),
-                                requireFeatureAnnotation.failureMode());
-                        continue;
-                    }
-
-                    if (annotation instanceof RequireDoesNotHaveFeature) {
-                        RequireDoesNotHaveFeature requireDoesNotHaveFeatureAnnotation =
-                                (RequireDoesNotHaveFeature) annotation;
-                        requireDoesNotHaveFeature(
-                                requireDoesNotHaveFeatureAnnotation.value(),
-                                requireDoesNotHaveFeatureAnnotation.failureMode());
-                        continue;
-                    }
-
-                    if (annotation instanceof EnsureHasProfileOwner) {
-                        EnsureHasProfileOwner ensureHasProfileOwnerAnnotation =
-                                (EnsureHasProfileOwner) annotation;
-                        ensureHasProfileOwner(ensureHasProfileOwnerAnnotation.onUser(),
-                                ensureHasProfileOwnerAnnotation.isPrimary());
-                    }
-
-                    if (annotationType.equals(EnsureHasNoProfileOwner.class)) {
-                        EnsureHasNoProfileOwner ensureHasNoProfileOwnerAnnotation =
-                                (EnsureHasNoProfileOwner) annotation;
-                        ensureHasNoProfileOwner(ensureHasNoProfileOwnerAnnotation.onUser());
-                    }
-                       
-                    if (annotation instanceof RequireUserSupported) {
-                        RequireUserSupported requireUserSupportedAnnotation =
-                                (RequireUserSupported) annotation;
-                        requireUserSupported(
-                                requireUserSupportedAnnotation.value(),
-                                requireUserSupportedAnnotation.failureMode());
-                        continue;
-                    }
-
-                    if (annotation instanceof RequireSdkVersion) {
-                        RequireSdkVersion requireSdkVersionAnnotation =
-                                (RequireSdkVersion) annotation;
-
-                        requireSdkVersion(
-                                requireSdkVersionAnnotation.min(),
-                                requireSdkVersionAnnotation.max(),
-                                requireSdkVersionAnnotation.failureMode());
-                        continue;
-                    }
-
-                    if (annotation instanceof RequirePackageInstalled) {
-                        RequirePackageInstalled requirePackageInstalledAnnotation =
-                                (RequirePackageInstalled) annotation;
-                        requirePackageInstalled(
-                                requirePackageInstalledAnnotation.value(),
-                                requirePackageInstalledAnnotation.onUser(),
-                                requirePackageInstalledAnnotation.failureMode());
-                        continue;
-                    }
-
-                    if (annotation instanceof RequirePackageNotInstalled) {
-                        RequirePackageNotInstalled requirePackageNotInstalledAnnotation =
-                                (RequirePackageNotInstalled) annotation;
-                        requirePackageNotInstalled(
-                                requirePackageNotInstalledAnnotation.value(),
-                                requirePackageNotInstalledAnnotation.onUser(),
-                                requirePackageNotInstalledAnnotation.failureMode()
-                        );
-                        continue;
-                    }
-
-                    if (annotation instanceof EnsurePackageNotInstalled) {
-                        EnsurePackageNotInstalled ensurePackageNotInstalledAnnotation =
-                                (EnsurePackageNotInstalled) annotation;
-                        ensurePackageNotInstalled(
-                                ensurePackageNotInstalledAnnotation.value(),
-                                ensurePackageNotInstalledAnnotation.onUser()
-                        );
-                        continue;
-                    }
-
-                    if (annotation instanceof EnsureHasPermission) {
-                        EnsureHasPermission ensureHasPermissionAnnotation =
-                                (EnsureHasPermission) annotation;
-                        try {
-                            permissionContext = sTestApis.permissions().withPermission(
-                                    ensureHasPermissionAnnotation.value());
-                        } catch (NeneException e) {
-                            failOrSkip("Error getting permission: " + e,
-                                    ensureHasPermissionAnnotation.failureMode());
-                        }
-                    }
-
-                    if (annotation instanceof EnsureDoesNotHavePermission) {
-                        EnsureDoesNotHavePermission ensureDoesNotHavePermission =
-                                (EnsureDoesNotHavePermission) annotation;
-
-                        try {
-                            if (permissionContext == null) {
-                                permissionContext = sTestApis.permissions().withoutPermission(
-                                        ensureDoesNotHavePermission.value());
-                            } else {
-                                permissionContext = permissionContext.withoutPermission(
-                                        ensureDoesNotHavePermission.value());
-                            }
-                        } catch (NeneException e) {
-                            failOrSkip("Error denying permission: " + e,
-                                    ensureDoesNotHavePermission.failureMode());
-                        }
-                    }
-
-                }
                 Log.d(LOG_TAG,
                         "Finished preparing state for test " + description.getMethodName());
 
@@ -366,16 +183,231 @@
             }};
     }
 
+    private PermissionContextImpl applyAnnotations(Collection<Annotation> annotations)
+            throws Throwable {
+        PermissionContextImpl permissionContext = null;
+        for (Annotation annotation : annotations) {
+            Class<? extends Annotation> annotationType = annotation.annotationType();
+
+            EnsureHasNoProfileAnnotation ensureHasNoProfileAnnotation =
+                    annotationType.getAnnotation(EnsureHasNoProfileAnnotation.class);
+            if (ensureHasNoProfileAnnotation != null) {
+                UserType userType = (UserType) annotation.annotationType()
+                        .getMethod("forUser").invoke(annotation);
+                ensureHasNoProfile(ensureHasNoProfileAnnotation.value(), userType);
+                continue;
+            }
+
+            EnsureHasProfileAnnotation ensureHasProfileAnnotation =
+                    annotationType.getAnnotation(EnsureHasProfileAnnotation.class);
+            if (ensureHasProfileAnnotation != null) {
+                UserType forUser = (UserType) annotation.annotationType()
+                        .getMethod("forUser").invoke(annotation);
+                OptionalBoolean installInstrumentedApp = (OptionalBoolean)
+                        annotation.annotationType()
+                                .getMethod("installInstrumentedApp").invoke(annotation);
+
+                boolean dpcIsPrimary = false;
+                if (ensureHasProfileAnnotation.hasProfileOwner()) {
+                    dpcIsPrimary = (boolean)
+                            annotation.annotationType()
+                                    .getMethod("dpcIsPrimary").invoke(annotation);
+                }
+
+                ensureHasProfile(
+                        ensureHasProfileAnnotation.value(), installInstrumentedApp,
+                        forUser, ensureHasProfileAnnotation.hasProfileOwner(),
+                        dpcIsPrimary);
+                continue;
+            }
+
+            EnsureHasNoUserAnnotation ensureHasNoUserAnnotation =
+                    annotationType.getAnnotation(EnsureHasNoUserAnnotation.class);
+            if (ensureHasNoUserAnnotation != null) {
+                ensureHasNoUser(ensureHasNoUserAnnotation.value());
+                continue;
+            }
+
+            EnsureHasUserAnnotation ensureHasUserAnnotation =
+                    annotationType.getAnnotation(EnsureHasUserAnnotation.class);
+            if (ensureHasUserAnnotation != null) {
+                OptionalBoolean installInstrumentedApp = (OptionalBoolean)
+                        annotation.getClass()
+                                .getMethod("installInstrumentedApp").invoke(annotation);
+                ensureHasUser(ensureHasUserAnnotation.value(), installInstrumentedApp);
+                continue;
+            }
+
+            RequireRunOnUserAnnotation requireRunOnUserAnnotation =
+                    annotationType.getAnnotation(RequireRunOnUserAnnotation.class);
+            if (requireRunOnUserAnnotation != null) {
+                requireRunOnUser(requireRunOnUserAnnotation.value());
+                continue;
+            }
+
+            RequireRunOnProfileAnnotation requireRunOnProfileAnnotation =
+                    annotationType.getAnnotation(RequireRunOnProfileAnnotation.class);
+            if (requireRunOnProfileAnnotation != null) {
+                OptionalBoolean installInstrumentedAppInParent = (OptionalBoolean)
+                        annotation.getClass()
+                                .getMethod("installInstrumentedAppInParent")
+                                .invoke(annotation);
+                requireRunOnProfile(requireRunOnProfileAnnotation.value(),
+                        installInstrumentedAppInParent);
+                continue;
+            }
+
+            if (annotation instanceof EnsureHasDeviceOwner) {
+                EnsureHasDeviceOwner ensureHasDeviceOwnerAnnotation =
+                        (EnsureHasDeviceOwner) annotation;
+                ensureHasDeviceOwner(ensureHasDeviceOwnerAnnotation.onUser(),
+                        ensureHasDeviceOwnerAnnotation.failureMode(),
+                        ensureHasDeviceOwnerAnnotation.isPrimary());
+            }
+
+            if (annotation instanceof EnsureHasNoDeviceOwner) {
+                ensureHasNoDeviceOwner();
+            }
+
+            if (annotation instanceof RequireFeature) {
+                RequireFeature requireFeatureAnnotation = (RequireFeature) annotation;
+                requireFeature(
+                        requireFeatureAnnotation.value(),
+                        requireFeatureAnnotation.failureMode());
+                continue;
+            }
+
+            if (annotation instanceof RequireDoesNotHaveFeature) {
+                RequireDoesNotHaveFeature requireDoesNotHaveFeatureAnnotation =
+                        (RequireDoesNotHaveFeature) annotation;
+                requireDoesNotHaveFeature(
+                        requireDoesNotHaveFeatureAnnotation.value(),
+                        requireDoesNotHaveFeatureAnnotation.failureMode());
+                continue;
+            }
+
+            if (annotation instanceof EnsureHasProfileOwner) {
+                EnsureHasProfileOwner ensureHasProfileOwnerAnnotation =
+                        (EnsureHasProfileOwner) annotation;
+                ensureHasProfileOwner(ensureHasProfileOwnerAnnotation.onUser(),
+                        ensureHasProfileOwnerAnnotation.isPrimary());
+                continue;
+            }
+
+            if (annotationType.equals(EnsureHasNoProfileOwner.class)) {
+                EnsureHasNoProfileOwner ensureHasNoProfileOwnerAnnotation =
+                        (EnsureHasNoProfileOwner) annotation;
+                ensureHasNoProfileOwner(ensureHasNoProfileOwnerAnnotation.onUser());
+                continue;
+            }
+
+            if (annotation instanceof RequireUserSupported) {
+                RequireUserSupported requireUserSupportedAnnotation =
+                        (RequireUserSupported) annotation;
+                requireUserSupported(
+                        requireUserSupportedAnnotation.value(),
+                        requireUserSupportedAnnotation.failureMode());
+                continue;
+            }
+
+            if (annotation instanceof RequireSdkVersion) {
+                RequireSdkVersion requireSdkVersionAnnotation =
+                        (RequireSdkVersion) annotation;
+
+                requireSdkVersion(
+                        requireSdkVersionAnnotation.min(),
+                        requireSdkVersionAnnotation.max(),
+                        requireSdkVersionAnnotation.failureMode());
+                continue;
+            }
+
+            if (annotation instanceof RequirePackageInstalled) {
+                RequirePackageInstalled requirePackageInstalledAnnotation =
+                        (RequirePackageInstalled) annotation;
+                requirePackageInstalled(
+                        requirePackageInstalledAnnotation.value(),
+                        requirePackageInstalledAnnotation.onUser(),
+                        requirePackageInstalledAnnotation.failureMode());
+                continue;
+            }
+
+            if (annotation instanceof RequirePackageNotInstalled) {
+                RequirePackageNotInstalled requirePackageNotInstalledAnnotation =
+                        (RequirePackageNotInstalled) annotation;
+                requirePackageNotInstalled(
+                        requirePackageNotInstalledAnnotation.value(),
+                        requirePackageNotInstalledAnnotation.onUser(),
+                        requirePackageNotInstalledAnnotation.failureMode()
+                );
+                continue;
+            }
+
+            if (annotation instanceof EnsurePackageNotInstalled) {
+                EnsurePackageNotInstalled ensurePackageNotInstalledAnnotation =
+                        (EnsurePackageNotInstalled) annotation;
+                ensurePackageNotInstalled(
+                        ensurePackageNotInstalledAnnotation.value(),
+                        ensurePackageNotInstalledAnnotation.onUser()
+                );
+                continue;
+            }
+
+            if (annotation instanceof EnsureHasPermission) {
+                EnsureHasPermission ensureHasPermissionAnnotation =
+                        (EnsureHasPermission) annotation;
+                try {
+                    if (permissionContext == null) {
+                        permissionContext = sTestApis.permissions().withPermission(
+                                ensureHasPermissionAnnotation.value());
+                    } else {
+                        permissionContext = permissionContext.withPermission(
+                                ensureHasPermissionAnnotation.value());
+                    }
+                } catch (NeneException e) {
+                    failOrSkip("Error getting permission: " + e,
+                            ensureHasPermissionAnnotation.failureMode());
+                }
+                continue;
+            }
+
+            if (annotation instanceof EnsureDoesNotHavePermission) {
+                EnsureDoesNotHavePermission ensureDoesNotHavePermission =
+                        (EnsureDoesNotHavePermission) annotation;
+
+                try {
+                    if (permissionContext == null) {
+                        permissionContext = sTestApis.permissions().withoutPermission(
+                                ensureDoesNotHavePermission.value());
+                    } else {
+                        permissionContext = permissionContext.withoutPermission(
+                                ensureDoesNotHavePermission.value());
+                    }
+                } catch (NeneException e) {
+                    failOrSkip("Error denying permission: " + e,
+                            ensureDoesNotHavePermission.failureMode());
+                }
+                continue;
+            }
+        }
+
+        return permissionContext;
+    }
+
     private Collection<Annotation> getAnnotations(Description description) {
-        if (mUsingBedsteadJUnit4) {
+        if (mUsingBedsteadJUnit4 && description.isTest()) {
             // The annotations are already exploded
             return description.getAnnotations();
         }
 
         // Otherwise we should build a new collection by recursively gathering annotations
         // if we find any which don't work without the runner we should error and fail the test
-        List<Annotation> annotations =
-                new ArrayList<>(Arrays.asList(description.getTestClass().getAnnotations()));
+        List<Annotation> annotations = new ArrayList<>();
+
+        if (description.isTest()) {
+            annotations =
+                    new ArrayList<>(Arrays.asList(description.getTestClass().getAnnotations()));
+        }
+
         annotations.addAll(description.getAnnotations());
 
         checkAnnotations(annotations);
@@ -404,8 +436,20 @@
         return new Statement() {
             @Override
             public void evaluate() throws Throwable {
+                Log.d(LOG_TAG, "Preparing state for suite " + description.getMethodName());
+
+                Collection<Annotation> annotations = getAnnotations(description);
+                PermissionContextImpl permissionContext = applyAnnotations(annotations);
+
+                Log.d(LOG_TAG,
+                        "Finished preparing state for suite " + description.getMethodName());
+
                 base.evaluate();
 
+                if (permissionContext != null) {
+                    permissionContext.close();
+                }
+
                 if (!mSkipClassTeardown) {
                     teardownShareableState();
                 }
@@ -414,21 +458,33 @@
     }
 
     private void requireRunOnUser(String userType) {
+        User instrumentedUser = sTestApis.users().instrumented().resolve();
+
         assumeTrue("This test only runs on users of type " + userType,
-                isRunningOnUser(userType));
+                instrumentedUser.type().name().equals(userType));
+
+        mUsers.put(instrumentedUser.type(), instrumentedUser);
     }
 
     private void requireRunOnProfile(String userType,
             OptionalBoolean installInstrumentedAppInParent) {
+        User instrumentedUser = sTestApis.users().instrumented().resolve();
+
         assumeTrue("This test only runs on users of type " + userType,
-                isRunningOnUser(userType));
+                instrumentedUser.type().name().equals(userType));
+
+        if (!mProfiles.containsKey(instrumentedUser.type())) {
+            mProfiles.put(instrumentedUser.type(), new HashMap<>());
+        }
+
+        mProfiles.get(instrumentedUser.type()).put(instrumentedUser.parent(), instrumentedUser);
 
         if (installInstrumentedAppInParent.equals(OptionalBoolean.TRUE)) {
             sTestApis.packages().find(sContext.getPackageName()).install(
-                    sTestApis.users().instrumented().resolve().parent());
+                    instrumentedUser.parent());
         } else if (installInstrumentedAppInParent.equals(OptionalBoolean.FALSE)) {
             sTestApis.packages().find(sContext.getPackageName()).uninstall(
-                    sTestApis.users().instrumented().resolve().parent());
+                    instrumentedUser.parent());
         }
     }
 
@@ -514,7 +570,9 @@
     private Map<UserReference, DevicePolicyController> mChangedProfileOwners = new HashMap<>();
 
     /**
-     * Get the {@link UserReference} of the work profile for the current user
+     * Get the {@link UserReference} of the work profile for the current user.
+     *
+     * <p>If the current user is a work profile, then the current user will be returned.
      *
      * <p>This should only be used to get work profiles managed by Harrier (using either the
      * annotations or calls to the {@link DeviceState} class.
@@ -549,7 +607,42 @@
         return profile(MANAGED_PROFILE_TYPE_NAME, forUser);
     }
 
-    private UserReference profile(String profileType, UserReference forUser) {
+    /**
+     * Get the {@link UserReference} of the profile of the given type for the given user.
+     *
+     * <p>This should only be used to get profiles managed by Harrier (using either the
+     * annotations or calls to the {@link DeviceState} class.
+     *
+     * @throws IllegalStateException if there is no harrier-managed profile for the given user
+     */
+    public UserReference profile(String profileType, UserType forUser) {
+        return profile(profileType, resolveUserTypeToUser(forUser));
+    }
+
+    /**
+     * Get the {@link UserReference} of the profile for the current user.
+     *
+     * <p>If the current user is a profile of the correct type, then the current user will be
+     * returned.
+     *
+     * <p>This should only be used to get profiles managed by Harrier (using either the
+     * annotations or calls to the {@link DeviceState} class.
+     *
+     * @throws IllegalStateException if there is no harrier-managed profile
+     */
+    public UserReference profile(String profileType) {
+        return profile(profileType, /* forUser= */ UserType.CURRENT_USER);
+    }
+
+    /**
+     * Get the {@link UserReference} of the profile of the given type for the given user.
+     *
+     * <p>This should only be used to get profiles managed by Harrier (using either the
+     * annotations or calls to the {@link DeviceState} class.
+     *
+     * @throws IllegalStateException if there is no harrier-managed profile for the given user
+     */
+    public UserReference profile(String profileType, UserReference forUser) {
         com.android.bedstead.nene.users.UserType resolvedUserType =
                 sTestApis.users().supportedType(profileType);
 
@@ -561,13 +654,30 @@
         return profile(resolvedUserType, forUser);
     }
 
-    private UserReference profile(
+    /**
+     * Get the {@link UserReference} of the profile of the given type for the given user.
+     *
+     * <p>This should only be used to get profiles managed by Harrier (using either the
+     * annotations or calls to the {@link DeviceState} class.
+     *
+     * @throws IllegalStateException if there is no harrier-managed profile for the given user
+     */
+    public UserReference profile(
             com.android.bedstead.nene.users.UserType userType, UserReference forUser) {
         if (userType == null || forUser == null) {
             throw new NullPointerException();
         }
 
         if (!mProfiles.containsKey(userType) || !mProfiles.get(userType).containsKey(forUser)) {
+            UserReference parentUser = sTestApis.users().instrumented().resolve().parent();
+
+            if (parentUser != null) {
+                if (mProfiles.containsKey(userType)
+                        && mProfiles.get(userType).containsKey(parentUser)) {
+                    return mProfiles.get(userType).get(parentUser);
+                }
+            }
+
             throw new IllegalStateException(
                     "No harrier-managed profile of type " + userType + ". This method should only"
                             + " be used when Harrier has been used to create the profile.");
@@ -576,11 +686,6 @@
         return mProfiles.get(userType).get(forUser);
     }
 
-    private boolean isRunningOnUser(String userType) {
-        return sTestApis.users().instrumented()
-                .resolve().type().name().equals(userType);
-    }
-
     /**
      * Get the {@link UserReference} of the tv profile for the current user
      *
@@ -636,12 +741,19 @@
      *
      * @throws IllegalStateException if there is no harrier-managed secondary user
      */
-    @Nullable
     public UserReference secondaryUser() {
         return user(SECONDARY_USER_TYPE_NAME);
     }
 
-    private UserReference user(String userType) {
+    /**
+     * Get a user of the given type.
+     *
+     * <p>This should only be used to get users managed by Harrier (using either the
+     * annotations or calls to the {@link DeviceState} class.
+     *
+     * @throws IllegalStateException if there is no harrier-managed user of the correct type
+     */
+    public UserReference user(String userType) {
         com.android.bedstead.nene.users.UserType resolvedUserType =
                 sTestApis.users().supportedType(userType);
 
@@ -653,22 +765,34 @@
         return user(resolvedUserType);
     }
 
-    private UserReference user(com.android.bedstead.nene.users.UserType userType) {
+    /**
+     * Get a user of the given type.
+     *
+     * <p>This should only be used to get users managed by Harrier (using either the
+     * annotations or calls to the {@link DeviceState} class.
+     *
+     * @throws IllegalStateException if there is no harrier-managed user of the correct type
+     */
+    public UserReference user(com.android.bedstead.nene.users.UserType userType) {
         if (userType == null) {
             throw new NullPointerException();
         }
 
         if (!mUsers.containsKey(userType)) {
             throw new IllegalStateException(
-                    "No harrier-managed secondary user. This method should only be used when "
-                            + "Harrier has been used to create the secondary user.");
+                    "No harrier-managed user of type " + userType + ". This method should only be"
+                            + "used when Harrier has been used to create the user.");
         }
 
         return mUsers.get(userType);
     }
 
     private UserReference ensureHasProfile(
-            String profileType, OptionalBoolean installInstrumentedApp, UserType forUser) {
+            String profileType,
+            OptionalBoolean installInstrumentedApp,
+            UserType forUser,
+            boolean hasProfileOwner,
+            boolean profileOwnerIsPrimary) {
         requireFeature("android.software.managed_users", FailureMode.SKIP);
         com.android.bedstead.nene.users.UserType resolvedUserType =
                 requireUserSupported(profileType, FailureMode.SKIP);
@@ -695,6 +819,9 @@
 
         mProfiles.get(resolvedUserType).put(forUserReference, profile);
 
+        if (hasProfileOwner) {
+            ensureHasProfileOwner(profile, profileOwnerIsPrimary);
+        }
         return profile;
     }
 
@@ -975,11 +1102,15 @@
 
     private void ensureHasProfileOwner(UserType onUser, boolean isPrimary) {
         // TODO(scottjonathan): Should support non-remotedpc profile owner (default to remotedpc)
+        UserReference user = resolveUserTypeToUser(onUser);
+        ensureHasProfileOwner(user, isPrimary);
+    }
+
+    private void ensureHasProfileOwner(UserReference user, boolean isPrimary) {
         if (isPrimary && mPrimaryDpc != null) {
             throw new IllegalStateException("Only one DPC can be marked as primary per test");
         }
 
-        UserReference user = resolveUserTypeToUser(onUser);
         ProfileOwner currentProfileOwner = sTestApis.devicePolicy().getProfileOwner(user);
         DeviceOwner currentDeviceOwner = sTestApis.devicePolicy().getDeviceOwner();
 
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasWorkProfile.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasWorkProfile.java
index 309056c..144dffe 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasWorkProfile.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/EnsureHasWorkProfile.java
@@ -41,7 +41,7 @@
  */
 @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
-@EnsureHasProfileAnnotation("android.os.usertype.profile.MANAGED")
+@EnsureHasProfileAnnotation(value = "android.os.usertype.profile.MANAGED", hasProfileOwner = true)
 @RequireFeature("android.software.managed_users")
 @EnsureHasNoDeviceOwner // TODO: This should only apply on Android R+
 public @interface EnsureHasWorkProfile {
@@ -56,6 +56,5 @@
      *
      * <p>Only one device policy controller per test should be marked as primary.
      */
-    // TODO(scottjonathan): Enforce dpcIsPrimary
     boolean dpcIsPrimary() default false;
 }
\ No newline at end of file
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/EnsureHasProfileAnnotation.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/EnsureHasProfileAnnotation.java
index 9b405d8..4976d35 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/EnsureHasProfileAnnotation.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/annotations/meta/EnsureHasProfileAnnotation.java
@@ -33,4 +33,7 @@
 public @interface EnsureHasProfileAnnotation {
     /** The name of the profile type which should be present. */
     String value();
+
+    /** Whether a profile owner should be set for the profile. */
+    boolean hasProfileOwner() default false;
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTaskPackages.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/DisallowNetworkReset.java
similarity index 82%
rename from common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTaskPackages.java
rename to common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/DisallowNetworkReset.java
index 3f6d18c..7e9a56f 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTaskPackages.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/DisallowNetworkReset.java
@@ -21,6 +21,9 @@
 
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
 
+/** Policy for network reset test. */
+// TODO(b/189195534):  Update the profileOwner flag once support is added for the way this policy
+//  can be set by a Profile Owner
 @EnterprisePolicy(deviceOwner = USER, profileOwner = NO)
-public class LockTaskPackages {
+public final class DisallowNetworkReset {
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTaskPackages.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/DisallowPrivateDnsConfig.java
similarity index 82%
copy from common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTaskPackages.java
copy to common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/DisallowPrivateDnsConfig.java
index 3f6d18c..cf8feb6 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTaskPackages.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/DisallowPrivateDnsConfig.java
@@ -21,6 +21,9 @@
 
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
 
+/** Policy for configuring private dns test. */
+// TODO(b/189195534):  Update the profileOwner flag once support is added for the way this policy
+//  can be set by a Profile Owner
 @EnterprisePolicy(deviceOwner = USER, profileOwner = NO)
-public class LockTaskPackages {
+public class DisallowPrivateDnsConfig {
 }
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTaskPackages.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java
similarity index 70%
copy from common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTaskPackages.java
copy to common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java
index 3f6d18c..992138d 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTaskPackages.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/policies/LockTask.java
@@ -19,8 +19,19 @@
 import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.DeviceOwnerControl.USER;
 import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.ProfileOwnerControl.NO;
 
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+
 import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy;
 
+/**
+ * Policies around Lock Task mode
+ * (https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode).
+ *
+ * <p>This is used by methods such as
+ * {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)} and
+ * {@link DevicePolicyManager#setLockTaskPackages(ComponentName, String[])}.
+ */
 @EnterprisePolicy(deviceOwner = USER, profileOwner = NO)
-public class LockTaskPackages {
+public final class LockTask {
 }
diff --git a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateClassAnnotationTest.java b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateClassAnnotationTest.java
index b2b0cc4..287eb4a 100644
--- a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateClassAnnotationTest.java
+++ b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateClassAnnotationTest.java
@@ -17,12 +17,18 @@
 package com.android.bedstead.harrier;
 
 import static com.android.bedstead.nene.users.UserType.MANAGED_PROFILE_TYPE_NAME;
+import static com.android.bedstead.nene.users.UserType.SECONDARY_USER_TYPE_NAME;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.android.bedstead.harrier.annotations.EnsureHasNoSecondaryUser;
+import com.android.bedstead.harrier.annotations.EnsureHasNoWorkProfile;
+import com.android.bedstead.harrier.annotations.EnsureHasSecondaryUser;
 import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile;
 import com.android.bedstead.nene.TestApis;
 
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
@@ -30,6 +36,7 @@
 
 @RunWith(BedsteadJUnit4.class)
 @EnsureHasWorkProfile
+@EnsureHasNoSecondaryUser
 public class DeviceStateClassAnnotationTest {
 
     @ClassRule
@@ -38,6 +45,25 @@
 
     private static final TestApis sTestApis = new TestApis();
 
+    @BeforeClass
+    public static void beforeClass() {
+        // We test here that ensureHasWorkProfile is processed before the test method
+        // but ensureHasSecondaryUser is not processed
+
+        assertThat(sTestApis.users().findProfileOfType(
+                sTestApis.users().supportedType(MANAGED_PROFILE_TYPE_NAME),
+                sTestApis.users().instrumented())
+        ).isNotNull();
+        assertThat(sTestApis.users().findUserOfType(
+                sTestApis.users().supportedType(SECONDARY_USER_TYPE_NAME))
+        ).isNull();
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        // State is not guaranteed afterClass as changes made by tests can propagate
+    }
+
     @Test
     public void ensureHasWorkProfileAnnotationOnClass_workProfileExists() {
         assertThat(sTestApis.users().findProfileOfType(
@@ -45,4 +71,21 @@
                 sTestApis.users().instrumented())
         ).isNotNull();
     }
+
+    @Test
+    @EnsureHasNoWorkProfile
+    public void ensureHasNoWorkProfileAnnotation_overridesClassAnnotation() {
+        assertThat(sTestApis.users().findProfileOfType(
+                sTestApis.users().supportedType(MANAGED_PROFILE_TYPE_NAME),
+                sTestApis.users().instrumented())
+        ).isNull();
+    }
+
+    @Test
+    @EnsureHasSecondaryUser
+    public void ensureHasSecondaryUserAnnotation_overridesClassAnnotation() {
+        assertThat(sTestApis.users().findUserOfType(
+                sTestApis.users().supportedType(SECONDARY_USER_TYPE_NAME))
+        ).isNotNull();
+    }
 }
diff --git a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
index 0a1f55a..9a6e88f 100644
--- a/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
+++ b/common/device-side/bedstead/harrier/src/test/java/com/android/bedstead/harrier/DeviceStateTest.java
@@ -22,6 +22,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 import static com.android.bedstead.harrier.DeviceState.UserType.ANY;
+import static com.android.bedstead.harrier.DeviceState.UserType.PRIMARY_USER;
 import static com.android.bedstead.harrier.annotations.RequireAospBuild.GMS_CORE_PACKAGE;
 import static com.android.bedstead.harrier.annotations.RequireCnGmsBuild.CHINA_GOOGLE_SERVICES_FEATURE;
 import static com.android.bedstead.nene.users.UserType.MANAGED_PROFILE_TYPE_NAME;
@@ -96,6 +97,18 @@
     }
 
     @Test
+    @EnsureHasWorkProfile
+    public void profile_profileIsProvided_returnsProfile() {
+        assertThat(sDeviceState.profile(MANAGED_PROFILE_TYPE_NAME)).isNotNull();
+    }
+
+    @Test
+    @RequireRunOnWorkProfile
+    public void workProfile_runningOnWorkProfile_returnsCurrentProfile() {
+        assertThat(sDeviceState.workProfile()).isEqualTo(sTestApis.users().instrumented());
+    }
+
+    @Test
     @EnsureHasNoWorkProfile
     public void workProfile_noWorkProfile_throwsException() {
         assertThrows(IllegalStateException.class, sDeviceState::workProfile);
@@ -141,6 +154,12 @@
     }
 
     @Test
+    @RequireRunOnTvProfile
+    public void tvProfile_runningOnTvProfile_returnsCurrentProfile() {
+        assertThat(sDeviceState.tvProfile()).isEqualTo(sTestApis.users().instrumented());
+    }
+
+    @Test
     @EnsureHasNoTvProfile
     public void tvProfile_noTvProfile_throwsException() {
         assertThrows(IllegalStateException.class, sDeviceState::tvProfile);
@@ -187,6 +206,18 @@
     }
 
     @Test
+    @EnsureHasSecondaryUser
+    public void user_userProvided_returnUser() {
+        assertThat(sDeviceState.user(SECONDARY_USER_TYPE_NAME)).isNotNull();
+    }
+
+    @Test
+    @RequireRunOnSecondaryUser
+    public void secondaryUser_runningOnSecondaryUser_returnsCurrentUser() {
+        assertThat(sDeviceState.secondaryUser()).isEqualTo(sTestApis.users().instrumented());
+    }
+
+    @Test
     @EnsureHasNoSecondaryUser
     public void secondaryUser_noSecondaryUser_throwsException() {
         assertThrows(IllegalStateException.class, sDeviceState::secondaryUser);
@@ -403,8 +434,9 @@
     public void includeRunOnSecondaryUserInDifferentProfileGroupToProfileOwnerAnnotation_isRunningOnSecondaryUserInDifferentProfileGroupToProfileOwner() {
         assertThat(sTestApis.users().instrumented().resolve().type().name())
                 .isEqualTo(SECONDARY_USER_TYPE_NAME);
-        assertThat(sDeviceState.workProfile()).isNotEqualTo(sTestApis.users().instrumented());
-        assertThat(sTestApis.devicePolicy().getProfileOwner(sDeviceState.workProfile()))
+        assertThat(sDeviceState.workProfile(PRIMARY_USER))
+                .isNotEqualTo(sTestApis.users().instrumented());
+        assertThat(sTestApis.devicePolicy().getProfileOwner(sDeviceState.workProfile(PRIMARY_USER)))
                 .isNotNull();
 
         // TODO(scottjonathan): Assert profile groups are different
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java
index 1ef0146..24d15d1 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DevicePolicy.java
@@ -35,6 +35,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.annotations.Experimental;
 import com.android.bedstead.nene.exceptions.AdbException;
 import com.android.bedstead.nene.exceptions.AdbParseException;
 import com.android.bedstead.nene.exceptions.NeneException;
@@ -340,4 +341,15 @@
             throw new RuntimeException("Error filling cache", e);
         }
     }
+
+    /** See {@link android.app.admin.DevicePolicyManager#getPolicyExemptApps()}. */
+    @Experimental
+    public Set<String> getPolicyExemptApps() {
+        try (PermissionContext p = mTestApis.permissions().withPermission(MANAGE_DEVICE_ADMINS)) {
+            return mTestApis.context()
+                    .instrumentedContext()
+                    .getSystemService(DevicePolicyManager.class)
+                    .getPolicyExemptApps();
+        }
+    }
 }
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java
index b943059..0c167e2 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/UserReference.java
@@ -85,7 +85,7 @@
                     .execute();
             mTestApis.users().waitForUserToNotExistOrMatch(this, User::isRemoving);
         } catch (AdbException e) {
-            throw new NeneException("Could not remove user + " + this, e);
+            throw new NeneException("Could not remove user " + this, e);
         }
     }
 
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java
index 894667d..78cb7b5 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/ShellCommandUtils.java
@@ -20,10 +20,12 @@
 
 import android.app.UiAutomation;
 import android.os.ParcelFileDescriptor;
+import android.provider.Settings;
 import android.util.Log;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.bedstead.nene.TestApis;
 import com.android.bedstead.nene.exceptions.AdbException;
 import com.android.compatibility.common.util.FileUtils;
 
@@ -34,6 +36,8 @@
 
 /**
  * Utilities for interacting with adb shell commands.
+ *
+ * <p>To enable command logging use the adb command `adb shell settings put global nene_log 1`.
  */
 public final class ShellCommandUtils {
 
@@ -43,6 +47,20 @@
     private static final int IN_DESCRIPTOR_INDEX = 1;
     private static final int ERR_DESCRIPTOR_INDEX = 2;
 
+    private static final TestApis sTestApis = new TestApis();
+
+    private static final boolean SHOULD_LOG = shouldLog();
+
+    private static boolean shouldLog() {
+        try {
+            return Settings.Global.getInt(
+                    sTestApis.context().instrumentedContext().getContentResolver(),
+                    "nene_log") == 1;
+        } catch (Settings.SettingNotFoundException e) {
+            return false;
+        }
+    }
+
     private ShellCommandUtils() { }
 
     /**
@@ -85,7 +103,9 @@
                 throw new AdbException("Error executing command", command, out, err);
             }
 
-            Log.d(LOG_TAG, "Command result: " + out);
+            if (SHOULD_LOG) {
+                Log.d(LOG_TAG, "Command result: " + out);
+            }
 
             return out;
         } catch (IOException e) {
@@ -94,6 +114,10 @@
     }
 
     private static void logCommand(String command, boolean allowEmptyOutput, byte[] stdInBytes) {
+        if (!SHOULD_LOG) {
+            return;
+        }
+
         StringBuilder logBuilder = new StringBuilder("Executing shell command ");
         logBuilder.append(command);
         if (allowEmptyOutput) {
@@ -169,7 +193,9 @@
                             command, out);
                 }
 
-                Log.d(LOG_TAG, "Command result: " + out);
+                if (SHOULD_LOG) {
+                    Log.d(LOG_TAG, "Command result: " + out);
+                }
 
                 return out;
             }
diff --git a/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java b/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java
index d51063a..f9c42bc 100644
--- a/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java
+++ b/common/device-side/bedstead/remotedpc/src/communication/main/java/com/android/bedstead/remotedpc/managers/RemoteDevicePolicyManager.java
@@ -62,4 +62,24 @@
     /** See {@link DevicePolicyManager#getLockTaskPackages(ComponentName)}. */
     @RemoteDpcAutomaticAdmin @NonNull String[] getLockTaskPackages();
 
+    /** See {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}. */
+    void setLockTaskFeatures(
+            @NonNull ComponentName admin, int flags);
+    /** See {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}. */
+    @RemoteDpcAutomaticAdmin void setLockTaskFeatures(int flags);
+
+    /** See {@link DevicePolicyManager#getLockTaskFeatures(Component)}. */
+    int getLockTaskFeatures(@NonNull ComponentName admin);
+    /** See {@link DevicePolicyManager#getLockTaskFeatures(Component)}. */
+    @RemoteDpcAutomaticAdmin int getLockTaskFeatures();
+
+    /** See {@link DevicePolicyManager#addUserRestriction(ComponentName, String)}. */
+    void addUserRestriction(@NonNull ComponentName admin, String key);
+    /** See {@link DevicePolicyManager#addUserRestriction(ComponentName, String)}. */
+    @RemoteDpcAutomaticAdmin void addUserRestriction(String key);
+
+    /** See {@link DevicePolicyManager#clearUserRestriction(ComponentName, String)}. */
+    void clearUserRestriction(@NonNull ComponentName admin, String key);
+    /** See {@link DevicePolicyManager#clearUserRestriction(ComponentName, String)}. */
+    @RemoteDpcAutomaticAdmin void clearUserRestriction(String key);
 }
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsTouchUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsTouchUtils.java
index 5a552ed..5b0a95b 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsTouchUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsTouchUtils.java
@@ -71,8 +71,20 @@
      */
     public static void emulateTapOnViewCenter(Instrumentation instrumentation,
             ActivityTestRule<?> activityTestRule, View view) {
+        emulateTapOnViewCenter(instrumentation, activityTestRule, view, true);
+    }
+
+    /**
+     * Emulates a tap in the center of the passed {@link View}.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param view the view to "tap"
+     * @param waitForAnimations wait for animations to complete before sending an event
+     */
+    public static void emulateTapOnViewCenter(Instrumentation instrumentation,
+            ActivityTestRule<?> activityTestRule, View view, boolean waitForAnimations) {
         emulateTapOnView(instrumentation, activityTestRule, view, view.getWidth() / 2,
-                view.getHeight() / 2);
+                view.getHeight() / 2, waitForAnimations);
     }
 
     /**
@@ -87,6 +99,22 @@
     public static void emulateTapOnView(Instrumentation instrumentation,
             ActivityTestRule<?> activityTestRule, View anchorView,
             int offsetX, int offsetY) {
+        emulateTapOnView(instrumentation, activityTestRule, anchorView, offsetX, offsetY, true);
+    }
+
+    /**
+     * Emulates a tap on a point relative to the top-left corner of the passed {@link View}. Offset
+     * parameters are used to compute the final screen coordinates of the tap point.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param anchorView the anchor view to determine the tap location on the screen
+     * @param offsetX extra X offset for the tap
+     * @param offsetY extra Y offset for the tap
+     * @param waitForAnimations wait for animations to complete before sending an event
+     */
+    public static void emulateTapOnView(Instrumentation instrumentation,
+            ActivityTestRule<?> activityTestRule, View anchorView,
+            int offsetX, int offsetY, boolean waitForAnimations) {
         final int touchSlop = ViewConfiguration.get(anchorView.getContext()).getScaledTouchSlop();
         // Get anchor coordinates on the screen
         final int[] viewOnScreenXY = new int[2];
@@ -96,9 +124,10 @@
         final UiAutomation uiAutomation = instrumentation.getUiAutomation();
         final long downTime = SystemClock.uptimeMillis();
 
-        injectDownEvent(uiAutomation, downTime, xOnScreen, yOnScreen, null);
-        injectMoveEventForTap(uiAutomation, downTime, touchSlop, xOnScreen, yOnScreen);
-        injectUpEvent(uiAutomation, downTime, false, xOnScreen, yOnScreen, null);
+        injectDownEvent(uiAutomation, downTime, xOnScreen, yOnScreen, waitForAnimations, null);
+        injectMoveEventForTap(uiAutomation, downTime, touchSlop, xOnScreen, yOnScreen, waitForAnimations);
+        injectUpEvent(uiAutomation, downTime, false, xOnScreen, yOnScreen,
+                waitForAnimations, null);
 
         // Wait for the system to process all events in the queue
         if (activityTestRule != null) {
@@ -143,10 +172,10 @@
         final long downTime = SystemClock.uptimeMillis();
 
         injectDownEvent(uiAutomation, downTime, xOnScreen, yOnScreen, null);
-        injectMoveEventForTap(uiAutomation, downTime, touchSlop, xOnScreen, yOnScreen);
+        injectMoveEventForTap(uiAutomation, downTime, touchSlop, xOnScreen, yOnScreen, true);
         injectUpEvent(uiAutomation, downTime, false, xOnScreen, yOnScreen, null);
         injectDownEvent(uiAutomation, downTime, xOnScreen, yOnScreen, null);
-        injectMoveEventForTap(uiAutomation, downTime, touchSlop, xOnScreen, yOnScreen);
+        injectMoveEventForTap(uiAutomation, downTime, touchSlop, xOnScreen, yOnScreen, true);
         injectUpEvent(uiAutomation, downTime, false, xOnScreen, yOnScreen, null);
 
         // Wait for the system to process all events in the queue
@@ -201,21 +230,44 @@
             int dragStartX, int dragStartY, int dragAmountX, int dragAmountY,
             int dragDurationMs, int moveEventCount,
             @Nullable EventInjectionListener eventInjectionListener) {
+        emulateDragGesture(instrumentation, activityTestRule, dragStartX, dragStartY, dragAmountX,
+                dragAmountY, dragDurationMs, moveEventCount, true, eventInjectionListener);
+    }
+
+    /**
+     * Emulates a linear drag gesture between 2 points across the screen.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param dragStartX Start X of the emulated drag gesture
+     * @param dragStartY Start Y of the emulated drag gesture
+     * @param dragAmountX X amount of the emulated drag gesture
+     * @param dragAmountY Y amount of the emulated drag gesture
+     * @param dragDurationMs The time in milliseconds over which the drag occurs
+     * @param moveEventCount The number of events that produce the movement
+     * @param waitForAnimations wait for animations to complete before sending an event
+     * @param eventInjectionListener Called after each down, move, and up events.
+     */
+    public static void emulateDragGesture(Instrumentation instrumentation,
+            ActivityTestRule<?> activityTestRule,
+            int dragStartX, int dragStartY, int dragAmountX, int dragAmountY,
+            int dragDurationMs, int moveEventCount,
+            boolean waitForAnimations, @Nullable EventInjectionListener eventInjectionListener) {
         // We are using the UiAutomation object to inject events so that drag works
         // across view / window boundaries (such as for the emulated drag and drop
         // sequences)
         final UiAutomation uiAutomation = instrumentation.getUiAutomation();
         final long downTime = SystemClock.uptimeMillis();
 
-        injectDownEvent(uiAutomation, downTime, dragStartX, dragStartY, eventInjectionListener);
+        injectDownEvent(uiAutomation, downTime, dragStartX, dragStartY, waitForAnimations,
+                eventInjectionListener);
 
         // Inject a sequence of MOVE events that emulate the "move" part of the gesture
         injectMoveEventsForDrag(uiAutomation, downTime, true, dragStartX, dragStartY,
                 dragStartX + dragAmountX, dragStartY + dragAmountY, moveEventCount, dragDurationMs,
-            eventInjectionListener);
+                waitForAnimations, eventInjectionListener);
 
         injectUpEvent(uiAutomation, downTime, true, dragStartX + dragAmountX,
-                dragStartY + dragAmountY, eventInjectionListener);
+                dragStartY + dragAmountY, waitForAnimations, eventInjectionListener);
 
         // Wait for the system to process all events in the queue
         if (activityTestRule != null) {
@@ -266,6 +318,7 @@
                     coordinates.get(i + 1).y,
                     moveEventCount,
                     dragDurationMs,
+                    true,
                     null);
         }
 
@@ -297,10 +350,28 @@
      */
     public static long injectDownEvent(UiAutomation uiAutomation, long downTime, int xOnScreen,
             int yOnScreen, @Nullable EventInjectionListener eventInjectionListener) {
+        return injectDownEvent(uiAutomation, downTime, xOnScreen, yOnScreen, true,
+                eventInjectionListener);
+    }
+
+    /**
+     * Injects an {@link MotionEvent#ACTION_DOWN} event at the given coordinates.
+     *
+     * @param downTime The time of the event, usually from {@link SystemClock#uptimeMillis()}
+     * @param xOnScreen The x screen coordinate to press on
+     * @param yOnScreen The y screen coordinate to press on
+     * @param waitForAnimations wait for animations to complete before sending an event
+     * @param eventInjectionListener The listener to call back immediately after the down was
+     *                               sent.
+     * @return <code>downTime</code>
+     */
+    public static long injectDownEvent(UiAutomation uiAutomation, long downTime, int xOnScreen,
+            int yOnScreen, boolean waitForAnimations,
+            @Nullable EventInjectionListener eventInjectionListener) {
         MotionEvent eventDown = MotionEvent.obtain(
                 downTime, downTime, MotionEvent.ACTION_DOWN, xOnScreen, yOnScreen, 1);
         eventDown.setSource(InputDevice.SOURCE_TOUCHSCREEN);
-        uiAutomation.injectInputEvent(eventDown, true);
+        uiAutomation.injectInputEvent(eventDown, true, waitForAnimations);
         if (eventInjectionListener != null) {
             eventInjectionListener.onDownInjected(xOnScreen, yOnScreen);
         }
@@ -309,7 +380,7 @@
     }
 
     private static void injectMoveEventForTap(UiAutomation uiAutomation, long downTime,
-            int touchSlop, int xOnScreen, int yOnScreen) {
+            int touchSlop, int xOnScreen, int yOnScreen, boolean waitForAnimations) {
         MotionEvent eventMove = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_MOVE,
                 xOnScreen + (touchSlop / 2.0f), yOnScreen + (touchSlop / 2.0f), 1);
         eventMove.setSource(InputDevice.SOURCE_TOUCHSCREEN);
@@ -319,7 +390,8 @@
 
     private static void injectMoveEventsForDrag(UiAutomation uiAutomation, long downTime,
             boolean useCurrentEventTime, int dragStartX, int dragStartY, int dragEndX, int dragEndY,
-            int moveEventCount, int dragDurationMs, EventInjectionListener eventInjectionListener) {
+            int moveEventCount, int dragDurationMs, boolean waitForAnimations,
+            EventInjectionListener eventInjectionListener) {
         final int dragAmountX = dragEndX - dragStartX;
         final int dragAmountY = dragEndY - dragStartY;
         final int sleepTime = dragDurationMs / moveEventCount;
@@ -379,7 +451,7 @@
             }
 
             eventMove.setSource(InputDevice.SOURCE_TOUCHSCREEN);
-            uiAutomation.injectInputEvent(eventMove, true);
+            uiAutomation.injectInputEvent(eventMove, true, waitForAnimations);
             if (eventInjectionListener != null) {
                 eventInjectionListener.onMoveInjected(xCoordsForListener, yCoordsForListener);
             }
@@ -405,11 +477,29 @@
     public static void injectUpEvent(UiAutomation uiAutomation, long downTime,
             boolean useCurrentEventTime, int xOnScreen, int yOnScreen,
             EventInjectionListener eventInjectionListener) {
+        injectDownEvent(uiAutomation, downTime, xOnScreen, yOnScreen, true, eventInjectionListener);
+    }
+
+    /**
+     * Injects an {@link MotionEvent#ACTION_UP} event at the given coordinates.
+     *
+     * @param downTime The time of the event, usually from {@link SystemClock#uptimeMillis()}
+     * @param useCurrentEventTime <code>true</code> if it should use the current time for the
+     *                            up event or <code>false</code> to use <code>downTime</code>.
+     * @param xOnScreen The x screen coordinate to press on
+     * @param yOnScreen The y screen coordinate to press on
+     * @param waitForAnimations wait for animations to complete before sending an event
+     * @param eventInjectionListener The listener to call back immediately after the up was
+     *                               sent.
+     */
+    public static void injectUpEvent(UiAutomation uiAutomation, long downTime,
+            boolean useCurrentEventTime, int xOnScreen, int yOnScreen,
+            boolean waitForAnimations, EventInjectionListener eventInjectionListener) {
         long eventTime = useCurrentEventTime ? SystemClock.uptimeMillis() : downTime;
         MotionEvent eventUp = MotionEvent.obtain(
                 downTime, eventTime, MotionEvent.ACTION_UP, xOnScreen, yOnScreen, 1);
         eventUp.setSource(InputDevice.SOURCE_TOUCHSCREEN);
-        uiAutomation.injectInputEvent(eventUp, true);
+        uiAutomation.injectInputEvent(eventUp, true, waitForAnimations);
         if (eventInjectionListener != null) {
             eventInjectionListener.onUpInjected(xOnScreen, yOnScreen);
         }
@@ -444,6 +534,24 @@
     public static int emulateFlingGesture(Instrumentation instrumentation,
             ActivityTestRule<?> activityTestRule, View view, boolean isDownwardsFlingGesture,
             EventInjectionListener eventInjectionListener) {
+        return emulateFlingGesture(instrumentation, activityTestRule, view, isDownwardsFlingGesture,
+                true, eventInjectionListener);
+    }
+
+    /**
+     * Emulates a fling gesture across the horizontal center of the passed view.
+     *
+     * @param instrumentation the instrumentation used to run the test
+     * @param view the view to fling
+     * @param isDownwardsFlingGesture if <code>true</code>, the emulated fling will
+     *      be a downwards gesture
+     * @param waitForAnimations wait for animations to complete before sending an event
+     * @param eventInjectionListener optional listener to notify about the injected events
+     * @return The vertical amount of emulated fling in pixels
+     */
+    public static int emulateFlingGesture(Instrumentation instrumentation,
+            ActivityTestRule<?> activityTestRule, View view, boolean isDownwardsFlingGesture,
+            boolean waitForAnimations, EventInjectionListener eventInjectionListener) {
         final ViewConfiguration configuration = ViewConfiguration.get(view.getContext());
         final int flingVelocity = (configuration.getScaledMinimumFlingVelocity() +
                 configuration.getScaledMaximumFlingVelocity()) / 2;
@@ -466,7 +574,7 @@
         // And do the same event injection sequence as our generic drag gesture
         emulateDragGesture(instrumentation, activityTestRule,
                 x, startY, 0, amountY, durationMs, durationMs / 16,
-            eventInjectionListener);
+            waitForAnimations, eventInjectionListener);
 
         return amountY;
     }
@@ -655,7 +763,7 @@
         final long downTime = SystemClock.uptimeMillis();
 
         injectDownEvent(uiAutomation, downTime, xOnScreen, yOnScreen, null);
-        injectMoveEventForTap(uiAutomation, downTime, touchSlop, xOnScreen, yOnScreen);
+        injectMoveEventForTap(uiAutomation, downTime, touchSlop, xOnScreen, yOnScreen, true);
         SystemClock.sleep((long) (ViewConfiguration.getLongPressTimeout() * 1.5f) + extraWaitMs);
         if (upGesture) {
             injectUpEvent(uiAutomation, downTime, false, xOnScreen, yOnScreen, null);
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/DisableAnimationRule.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/DisableAnimationRule.java
new file mode 100644
index 0000000..dcf0a96
--- /dev/null
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/DisableAnimationRule.java
@@ -0,0 +1,70 @@
+/*
+ * 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.compatibility.common.util;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
+import androidx.annotation.NonNull;
+
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+public class DisableAnimationRule extends BeforeAfterRule {
+    @NonNull
+    private final GlobalSetting mWindowAnimationScaleSetting = new GlobalSetting(
+            "window_animation_scale");
+    @NonNull
+    private final GlobalSetting mTransitionAnimationScaleSetting = new GlobalSetting(
+            "transition_animation_scale");
+    @NonNull
+    private final GlobalSetting mAnimatorDurationScaleSetting = new GlobalSetting(
+            "animator_duration_scale");
+
+    @Override
+    protected void onBefore(Statement base, Description description) throws Throwable {
+        mWindowAnimationScaleSetting.put("0");
+        mTransitionAnimationScaleSetting.put("0");
+        mAnimatorDurationScaleSetting.put("0");
+    }
+
+    @Override
+    protected void onAfter(Statement base, Description description) throws Throwable {
+        mWindowAnimationScaleSetting.restore();
+        mTransitionAnimationScaleSetting.restore();
+        mAnimatorDurationScaleSetting.restore();
+    }
+
+    private static class GlobalSetting {
+        @NonNull
+        private final String mName;
+
+        private String mInitialValue;
+
+        public GlobalSetting(@NonNull String name) {
+            mName = name;
+        }
+
+        public void put(@NonNull String value) {
+            mInitialValue = runShellCommand("settings get global " + mName);
+            runShellCommand("settings put global " + mName + " " + value);
+        }
+
+        public void restore() {
+            runShellCommand("settings put global " + mName + " " + mInitialValue);
+        }
+    }
+}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
index c2e4224..6bf9cf3 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
@@ -66,7 +66,9 @@
 
             if (view == null) {
                 UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true));
-                scrollable.setSwipeDeadZonePercentage(0.25);
+                if (!FeatureUtil.isWatch()) {
+                    scrollable.setSwipeDeadZonePercentage(0.25);
+                }
                 if (scrollable.exists()) {
                     if (isAtEnd) {
                         if (wasScrolledUpAlready) {
diff --git a/hostsidetests/appsecurity/OWNERS b/hostsidetests/appsecurity/OWNERS
index a81604b..e4d9d04 100644
--- a/hostsidetests/appsecurity/OWNERS
+++ b/hostsidetests/appsecurity/OWNERS
@@ -1,34 +1,35 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
 per-file AccessSerialNumberTest.java = moltmann@google.com
 per-file ApexSignatureVerificationTest.java = dariofreni@google.com
-per-file ApplicationVisibilityTest.java = toddke@google.com
+per-file ApplicationVisibilityTest.java = toddke@google.com,patb@google.com
 per-file AppDataIsolationTests.java = rickywai@google.com,alanstokes@google.com
 per-file AppOpsTest.java = moltmann@google.com
 per-file AppSecurityTests.java = cbrubaker@google.com
 per-file AuthBoundKeyTest.java = file:test-apps/AuthBoundKeyApp/OWNERS
-per-file BaseInstallMultiple.java = toddke@google.com
+per-file BaseInstallMultiple.java = toddke@google.com,patb@google.com
 per-file CorruptApkTests.java = rtmitchell@google.com
 per-file DeviceIdentifierTest.java = cbrubaker@google.com
-per-file EphemeralTest.java = toddke@google.com
+per-file EphemeralTest.java = toddke@google.com,patb@google.com
 per-file ExternalStorageHostTest.java = nandana@google.com
 per-file ExternalStorageHostTest.java = zezeozue@google.com
-per-file InstantAppUserTest.java = toddke@google.com
-per-file InstantCookieHostTest.java = toddke@google.com
+per-file InstantAppUserTest.java = toddke@google.com,patb@google.com
+per-file InstantCookieHostTest.java = toddke@google.com,patb@google.com
 per-file IsolatedSplitsTests.java = patb@google.com,toddke@google.com
 per-file KeySetHostTest.java = cbrubaker@google.com
 per-file ListeningPortsTest.java = cbrubaker@google.com
-per-file MajorVersionTest.java = toddke@google.com
+per-file MajorVersionTest.java = toddke@google.com,patb@google.com
 per-file OverlayHostTest.java = rtmitchell@google.com
 per-file Package* = chiuwinson@google.com,patb@google.com,toddke@google.com
 per-file PermissionsHostTest.java = moltmann@google.com
 per-file Pkg* = chiuwinson@google.com,patb@google.com,toddke@google.com
 per-file PkgInstallSignatureVerificationTest.java = cbrubaker@google.com
-per-file PrivilegedUpdateTests.java = toddke@google.com
+per-file PrivilegedUpdateTests.java = toddke@google.com,patb@google.com
 per-file ReviewPermissionHelper = moltmann@google.com
 per-file RequestsOnlyCalendarApp22.java = moltmann@google.com
-per-file SharedUserIdTest.java = toddke@google.com
-per-file SplitTests.java = patb@google.com,toddke@google.com
+per-file SharedUserIdTest.java = toddke@google.com,patb@google.com
+per-file SplitTests.java = patb@google.com,toddke@google.com,patb@google.com
 per-file UseEmbeddedDexTest.java = victorhsieh@google.com
 # test apps
 per-file BasePermissionsTest.java = moltmann@google.com
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java
index 4ff0976..11cde7d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApkVerityInstallTest.java
@@ -374,6 +374,47 @@
                 .run();
     }
 
+    @Test
+    public void testInstallBaseIncrementallyWithFsvSig() throws Exception {
+        assumeTrue(hasIncrementalDeliveryFeature());
+        new InstallMultiple(/*incremental=*/true)
+                .addFile(BASE_APK)
+                .addFile(BASE_APK + FSV_SIG_SUFFIX)
+                .run();
+        verifyFsverityInstall(true, BASE_APK);
+    }
+
+    @Test
+    public void testInstallBaseIncrementallyWithFsvSigAndIdSig() throws Exception {
+        assumeTrue(hasIncrementalDeliveryFeature());
+        new InstallMultiple(/*incremental=*/true)
+                .addFile(BASE_APK)
+                .pushFile(BASE_APK + ID_SIG_SUFFIX)
+                .addFile(BASE_APK + FSV_SIG_SUFFIX)
+                .run();
+        verifyFsverityInstall(true, BASE_APK);
+    }
+
+    @Test
+    public void testInstallBaseIncrementallyWithIdSigAndWrongFsvSig() throws Exception {
+        assumeTrue(hasIncrementalDeliveryFeature());
+        new InstallMultiple(/*incremental=*/true)
+                .addFile(BASE_APK)
+                .pushFile(BASE_APK + ID_SIG_SUFFIX)
+                .renameAndAddFile(BAD_BASE_APK + FSV_SIG_SUFFIX, BASE_APK + FSV_SIG_SUFFIX)
+                .runExpectingFailure();
+    }
+
+    @Test
+    public void testInstallBaseIncrementallyWithWrongIdSigAndFsvSig() throws Exception {
+        assumeTrue(hasIncrementalDeliveryFeature());
+        new InstallMultiple(/*incremental=*/true)
+                .addFile(BASE_APK)
+                .renameAndPushFile(BAD_BASE_APK + ID_SIG_SUFFIX, BASE_APK + ID_SIG_SUFFIX)
+                .addFile(BASE_APK + FSV_SIG_SUFFIX)
+                .runExpectingFailure();
+    }
+
     private void assumePreconditions(boolean requiresIncremental) throws Exception {
         if (requiresIncremental) {
             assumeTrue(hasIncrementalDeliveryFeature());
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseInstallMultiple.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseInstallMultiple.java
index 094f372..d7ded5e 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseInstallMultiple.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseInstallMultiple.java
@@ -45,8 +45,36 @@
     private final IBuildInfo mBuild;
     private final IAbi mAbi;
 
+    static class DeviceFile {
+        public final File localFile;
+        public final File remoteFile;
+        public final boolean addToInstallSession;
+
+        private DeviceFile(File localFile, File remoteFile, boolean addToInstallSession) {
+            this.localFile = localFile;
+            this.remoteFile = remoteFile;
+            this.addToInstallSession = addToInstallSession;
+        }
+
+        static DeviceFile addToSession(File file) {
+            return new DeviceFile(file, file, true);
+        }
+
+        static DeviceFile renameAndAddToSession(File localFile, File remoteFile) {
+            return new DeviceFile(localFile, remoteFile, true);
+        }
+
+        static DeviceFile pushOnly(File file) {
+            return new DeviceFile(file, file, false);
+        }
+
+        static DeviceFile renameAndPushOnly(File localFile, File remoteFile) {
+            return new DeviceFile(localFile, remoteFile, false);
+        }
+    }
+
     private final List<String> mArgs = new ArrayList<>();
-    private final List<File> mFilesToAdd = new ArrayList<>();
+    private final List<DeviceFile> mFilesToAdd = new ArrayList<>();
     private final List<String> mSplitsToRemove = new ArrayList<>();
     private boolean mUseNaturalAbi = false;
     private boolean mUseIncremental = false;
@@ -72,7 +100,27 @@
 
     T addFile(String file) throws FileNotFoundException {
         CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
-        mFilesToAdd.add(buildHelper.getTestFile(file, mAbi));
+        mFilesToAdd.add(DeviceFile.addToSession(buildHelper.getTestFile(file, mAbi)));
+        return (T) this;
+    }
+
+    T renameAndAddFile(String localFile, String remoteFile) throws FileNotFoundException {
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
+        mFilesToAdd.add(DeviceFile.renameAndAddToSession(buildHelper.getTestFile(localFile, mAbi),
+                buildHelper.getTestFile(remoteFile, mAbi)));
+        return (T) this;
+    }
+
+    T pushFile(String file) throws FileNotFoundException {
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
+        mFilesToAdd.add(DeviceFile.pushOnly(buildHelper.getTestFile(file, mAbi)));
+        return (T) this;
+    }
+
+    T renameAndPushFile(String localFile, String remoteFile) throws FileNotFoundException {
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
+        mFilesToAdd.add(DeviceFile.renameAndPushOnly(buildHelper.getTestFile(localFile, mAbi),
+                buildHelper.getTestFile(remoteFile, mAbi)));
         return (T) this;
     }
 
@@ -155,9 +203,14 @@
     private void run(boolean expectingSuccess, String failure) throws DeviceNotAvailableException {
         if (mUseIncremental) {
             runIncremental(expectingSuccess, failure);
-            return;
+        } else {
+            runNonIncremental(expectingSuccess, failure);
         }
+        cleanupDeviceFiles();
+    }
 
+    private void runNonIncremental(boolean expectingSuccess, String failure)
+            throws DeviceNotAvailableException {
         final ITestDevice device = mDevice;
 
         // Create an install session
@@ -189,11 +242,16 @@
         // Push our files into session. Ideally we'd use stdin streaming,
         // but ddmlib doesn't support it yet.
         for (int i = 0; i < mFilesToAdd.size(); i++) {
-            final File file = mFilesToAdd.get(i);
-            final String remoteName = deriveRemoteName(file.getName(), i);
+            final File localFile = mFilesToAdd.get(i).localFile;
+            final File remoteFile = mFilesToAdd.get(i).remoteFile;
+            final String remoteName = deriveRemoteName(remoteFile.getName(), i);
             final String remotePath = "/data/local/tmp/" + remoteName;
-            if (!device.pushFile(file, remotePath)) {
-                throw new IllegalStateException("Failed to push " + file);
+            if (!device.pushFile(localFile, remotePath)) {
+                throw new IllegalStateException("Failed to push " + localFile);
+            }
+
+            if (!mFilesToAdd.get(i).addToInstallSession) {
+                continue;
             }
 
             cmd.setLength(0);
@@ -255,11 +313,16 @@
         // Push our files into session. Ideally we'd use stdin streaming,
         // but ddmlib doesn't support it yet.
         for (int i = 0; i < mFilesToAdd.size(); i++) {
-            final File file = mFilesToAdd.get(i);
-            final String remoteName = deriveRemoteName(file.getName(), i);
+            final File localFile = mFilesToAdd.get(i).localFile;
+            final File remoteFile = mFilesToAdd.get(i).remoteFile;
+            final String remoteName = deriveRemoteName(remoteFile.getName(), i);
             final String remotePath = "/data/local/tmp/" + remoteName;
-            if (!device.pushFile(file, remotePath)) {
-                throw new IllegalStateException("Failed to push " + file);
+            if (!device.pushFile(localFile, remotePath)) {
+                throw new IllegalStateException("Failed to push " + localFile);
+            }
+
+            if (!mFilesToAdd.get(i).addToInstallSession) {
+                continue;
             }
 
             cmd.append(' ').append(remotePath);
@@ -277,4 +340,14 @@
             TestCase.assertTrue(result, result.contains(failure));
         }
     }
+
+    private void cleanupDeviceFiles() throws DeviceNotAvailableException {
+        final ITestDevice device = mDevice;
+        for (int i = 0; i < mFilesToAdd.size(); i++) {
+            final File remoteFile = mFilesToAdd.get(i).remoteFile;
+            final String remoteName = deriveRemoteName(remoteFile.getName(), i);
+            final String remotePath = "/data/local/tmp/" + remoteName;
+            device.deleteFile(remotePath);
+        }
+    }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ReadableSettingsFieldsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ReadableSettingsFieldsTest.java
index 67fba8ace..35740f8 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ReadableSettingsFieldsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ReadableSettingsFieldsTest.java
@@ -48,6 +48,9 @@
     private static final String TEST_CLASS = TEST_PACKAGE + ".ReadSettingsFieldsTest";
     private static final String TEST_APK = "CtsReadSettingsFieldsApp.apk";
     private static final String TEST_APK_TEST_ONLY = "CtsReadSettingsFieldsAppTestOnly.apk";
+    private static final String TEST_APK_TARGET_Q = "CtsReadSettingsFieldsAppTargetQ.apk";
+    private static final String TEST_APK_TARGET_R = "CtsReadSettingsFieldsAppTargetR.apk";
+    private static final String TEST_APK_TARGET_S = "CtsReadSettingsFieldsAppTargetS.apk";
 
     @Before
     public void setUp() throws Exception {
@@ -61,18 +64,18 @@
     }
 
     @Test
-    public void testSecurePublicSettingsKeysAreReadable() throws DeviceNotAvailableException {
-        runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testSecurePublicSettingsKeysAreReadable");
+    public void testSecureNonHiddenSettingsKeysAreReadable() throws DeviceNotAvailableException {
+        runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testSecureNonHiddenSettingsKeysAreReadable");
     }
 
     @Test
-    public void testSystemPublicSettingsKeysAreReadable() throws DeviceNotAvailableException {
-        runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testSystemPublicSettingsKeysAreReadable");
+    public void testSystemNonHiddenSettingsKeysAreReadable() throws DeviceNotAvailableException {
+        runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testSystemNonHiddenSettingsKeysAreReadable");
     }
 
     @Test
-    public void testGlobalPublicSettingsKeysAreReadable() throws DeviceNotAvailableException {
-        runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testGlobalPublicSettingsKeysAreReadable");
+    public void testGlobalNonHiddenSettingsKeysAreReadable() throws DeviceNotAvailableException {
+        runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testGlobalNonHiddenSettingsKeysAreReadable");
     }
 
     @Test
@@ -141,4 +144,23 @@
         runDeviceTests(TEST_PACKAGE, TEST_CLASS,
                 "testGlobalHiddenSettingsKeysReadableWithoutAnnotation");
     }
+
+    @Test
+    public void testSettingsKeysNotReadableForAfterR()
+            throws DeviceNotAvailableException, FileNotFoundException {
+        new InstallMultiple().addFile(TEST_APK_TARGET_S).run();
+        runDeviceTests(TEST_PACKAGE, TEST_CLASS,
+                "testSettingsKeysNotReadableForAfterR");
+    }
+
+    @Test
+    public void testSettingsKeysReadableForRMinus()
+            throws DeviceNotAvailableException, FileNotFoundException {
+        new InstallMultiple().addFile(TEST_APK_TARGET_R).run();
+        runDeviceTests(TEST_PACKAGE, TEST_CLASS,
+                "testSettingsKeysReadableForRMinus");
+        new InstallMultiple().addFile(TEST_APK_TARGET_Q).run();
+        runDeviceTests(TEST_PACKAGE, TEST_CLASS,
+                "testSettingsKeysReadableForRMinus");
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestApp/Android.bp b/hostsidetests/appsecurity/test-apps/ApkVerityTestApp/Android.bp
index 53088c9..6ca647b 100644
--- a/hostsidetests/appsecurity/test-apps/ApkVerityTestApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestApp/Android.bp
@@ -42,6 +42,7 @@
             "cts",
         ],
     },
+    v4_signature: true,
 }
 
 android_test_helper_app {
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestApp/testdata/Android.bp b/hostsidetests/appsecurity/test-apps/ApkVerityTestApp/testdata/Android.bp
index 5060c37..b26a35d 100644
--- a/hostsidetests/appsecurity/test-apps/ApkVerityTestApp/testdata/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestApp/testdata/Android.bp
@@ -33,6 +33,19 @@
     out: ["CtsApkVerityTestDebugFiles.txt"],
 }
 
+// This is a rather complicated way to keep only APKs.
+// exclude_srcs does not work because it uses paths local to Android.bp.
+genrule {
+    name: "CtsApkVerityTestAppApk",
+    srcs: [":CtsApkVerityTestApp"],
+    cmd: "for file in $(in); do " +
+         "   if [[ $$file == *.apk ]]; then " +
+         "     cp $$file $(out); " +
+         "   fi " +
+         " done",
+    out: ["CtsApkVerityTestApp.apk"],
+}
+
 filegroup {
     name: "CtsApkVerityTestAppDm",
     srcs: ["CtsApkVerityTestApp.dm"],
@@ -69,7 +82,7 @@
 genrule {
     name: "CtsApkVerityTestAppFsvSig",
     defaults: ["cts_apk_verity_sig_gen_default"],
-    srcs: [":CtsApkVerityTestApp"],
+    srcs: [":CtsApkVerityTestAppApk"],
     out: ["CtsApkVerityTestApp.apk.fsv_sig"],
 }
 
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/README.md b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/README.md
index 6e6e408..d774d92 100644
--- a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/README.md
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/README.md
@@ -68,17 +68,18 @@
 2. Extract CtsApkVerityTestApp\*.{apk,dm} and ask the key owner to sign
    (example: b/152753442).
 3. Receive the release signature .fsv\_sig.
-4. Override CtsApkVerityTestApp2 to create a bad signature.
+4. Extract CtsApkVerityTestApp\*.idsig.
+5. Override CtsApkVerityTestApp2 to create a bad signature.
 
 ```
 cp CtsApkVerityTestApp.apk CtsApkVerityTestApp2.apk
 cp CtsApkVerityTestAppSplit.apk.fsv_sig CtsApkVerityTestApp2.apk.fsv_sig
 ```
 
-5. Rename to "Prebuilt".
+6. Rename to "Prebuilt".
 
 ```
 for f in CtsApkVerityTestApp*; do echo $f | sed -E 's/([^.]+)\.(.+)/mv & \1Prebuilt.\2/'; done | sh
 ```
 
-6. Duplicate arm64 prebuilts into arm and arm64, x86\_64 into x86 and x86\_64.
+7. Duplicate arm64 prebuilts into arm and arm64, x86\_64 into x86 and x86\_64.
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm/CtsApkVerityTestApp2Prebuilt.apk.idsig b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm/CtsApkVerityTestApp2Prebuilt.apk.idsig
new file mode 100644
index 0000000..9d8f08a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm/CtsApkVerityTestApp2Prebuilt.apk.idsig
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm/CtsApkVerityTestAppPrebuilt.apk.idsig b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm/CtsApkVerityTestAppPrebuilt.apk.idsig
new file mode 100644
index 0000000..1970a0f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm/CtsApkVerityTestAppPrebuilt.apk.idsig
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm64/CtsApkVerityTestApp2Prebuilt.apk.idsig b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm64/CtsApkVerityTestApp2Prebuilt.apk.idsig
new file mode 100644
index 0000000..9d8f08a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm64/CtsApkVerityTestApp2Prebuilt.apk.idsig
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm64/CtsApkVerityTestAppPrebuilt.apk.idsig b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm64/CtsApkVerityTestAppPrebuilt.apk.idsig
new file mode 100644
index 0000000..1970a0f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/arm64/CtsApkVerityTestAppPrebuilt.apk.idsig
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86/CtsApkVerityTestApp2Prebuilt.apk.idsig b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86/CtsApkVerityTestApp2Prebuilt.apk.idsig
new file mode 100644
index 0000000..9d8f08a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86/CtsApkVerityTestApp2Prebuilt.apk.idsig
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86/CtsApkVerityTestAppPrebuilt.apk.idsig b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86/CtsApkVerityTestAppPrebuilt.apk.idsig
new file mode 100644
index 0000000..dcc40cf
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86/CtsApkVerityTestAppPrebuilt.apk.idsig
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86_64/CtsApkVerityTestApp2Prebuilt.apk.idsig b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86_64/CtsApkVerityTestApp2Prebuilt.apk.idsig
new file mode 100644
index 0000000..9d8f08a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86_64/CtsApkVerityTestApp2Prebuilt.apk.idsig
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86_64/CtsApkVerityTestAppPrebuilt.apk.idsig b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86_64/CtsApkVerityTestAppPrebuilt.apk.idsig
new file mode 100644
index 0000000..dcc40cf
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApkVerityTestAppPrebuilt/x86_64/CtsApkVerityTestAppPrebuilt.apk.idsig
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/AuthBoundKeyApp/OWNERS b/hostsidetests/appsecurity/test-apps/AuthBoundKeyApp/OWNERS
index 8fc3c4f..4e06da3 100644
--- a/hostsidetests/appsecurity/test-apps/AuthBoundKeyApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/AuthBoundKeyApp/OWNERS
@@ -4,4 +4,5 @@
 jdanis@google.com
 swillden@google.com
 toddke@google.com
+patb@google.com
 zeuthen@google.com
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/OWNERS b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/InstantCookieApp/OWNERS b/hostsidetests/appsecurity/test-apps/InstantCookieApp/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/InstantCookieApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/InstantCookieApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/InstantCookieApp2/OWNERS b/hostsidetests/appsecurity/test-apps/InstantCookieApp2/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/InstantCookieApp2/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/InstantCookieApp2/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/InstantUpgradeApp/OWNERS b/hostsidetests/appsecurity/test-apps/InstantUpgradeApp/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/InstantUpgradeApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/InstantUpgradeApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/MajorVersionApp/OWNERS b/hostsidetests/appsecurity/test-apps/MajorVersionApp/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/MajorVersionApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/MajorVersionApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
index 6578606..6ba3e78 100644
--- a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
@@ -36,6 +36,7 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.net.Uri;
@@ -743,11 +744,13 @@
             // Some dialogs may have granted access automatically, so we're willing
             // to keep rolling forward if we can't find our grant button
             final UiSelector grant = new UiSelector().textMatches("(?i)Allow");
-            UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
-            try {
-                uiScrollable.scrollIntoView(grant);
-            } catch (UiObjectNotFoundException e) {
-                // Scrolling can fail if the UI is not scrollable
+            if (isWatch()) {
+                UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
+                try {
+                    uiScrollable.scrollIntoView(grant);
+                } catch (UiObjectNotFoundException e) {
+                    // Scrolling can fail if the UI is not scrollable
+                }
             }
             final boolean grantExists = new UiObject(grant).waitForExists(timeout);
 
@@ -880,4 +883,12 @@
         }
         throw new TimeoutException("File creation failed due to slow permission update");
     }
+
+    private boolean isWatch() {
+        return hasFeature(PackageManager.FEATURE_WATCH);
+    }
+
+    private boolean hasFeature(String feature) {
+        return mContext.getPackageManager().hasSystemFeature(feature);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/OWNERS b/hostsidetests/appsecurity/test-apps/NoRestartApp/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/OrderedActivityApp/OWNERS b/hostsidetests/appsecurity/test-apps/OrderedActivityApp/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/OrderedActivityApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/OrderedActivityApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/PackageAccessApp/OWNERS b/hostsidetests/appsecurity/test-apps/PackageAccessApp/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/PackageAccessApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/PackageAccessApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/OWNERS b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/Android.bp b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/Android.bp
index 7d4da8d..f375fa5 100644
--- a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/Android.bp
@@ -57,3 +57,66 @@
     ],
     manifest: "AndroidManifestTestOnly.xml",
 }
+
+android_test_helper_app {
+    name: "CtsReadSettingsFieldsAppTargetQ",
+    defaults: ["cts_support_defaults"],
+    static_libs: [
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    // tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    manifest: "AndroidManifestTargetQ.xml",
+}
+
+android_test_helper_app {
+    name: "CtsReadSettingsFieldsAppTargetR",
+    defaults: ["cts_support_defaults"],
+    static_libs: [
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    // tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    manifest: "AndroidManifestTargetR.xml",
+}
+
+android_test_helper_app {
+    name: "CtsReadSettingsFieldsAppTargetS",
+    defaults: ["cts_support_defaults"],
+    static_libs: [
+        "androidx.test.rules",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    srcs: [
+        "src/**/*.java",
+    ],
+    // tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    manifest: "AndroidManifestTargetS.xml",
+}
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/AndroidManifestTargetQ.xml b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/AndroidManifestTargetQ.xml
new file mode 100644
index 0000000..e6273e4
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/AndroidManifestTargetQ.xml
@@ -0,0 +1,28 @@
+<?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.readsettingsfieldsapp">
+    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
+
+    <application android:label="CtsReadSettingsFieldsAppTargetS">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.readsettingsfieldsapp" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/AndroidManifestTargetR.xml b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/AndroidManifestTargetR.xml
new file mode 100644
index 0000000..749f65c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/AndroidManifestTargetR.xml
@@ -0,0 +1,28 @@
+<?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.readsettingsfieldsapp">
+    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
+
+    <application android:label="CtsReadSettingsFieldsApp">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.readsettingsfieldsapp" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/AndroidManifestTargetS.xml b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/AndroidManifestTargetS.xml
new file mode 100644
index 0000000..7da6cb0
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/AndroidManifestTargetS.xml
@@ -0,0 +1,28 @@
+<?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.readsettingsfieldsapp">
+    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
+
+    <application android:label="CtsReadSettingsFieldsAppTargetS">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.readsettingsfieldsapp" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/OWNERS b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/OWNERS
index 7d65382..619063a 100644
--- a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 856262
 svetoslavganov@google.com
 toddke@google.com
+patb@google.com
 schfan@google.com
diff --git a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/src/com/android/cts/readsettingsfieldsapp/ReadSettingsFieldsTest.java b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/src/com/android/cts/readsettingsfieldsapp/ReadSettingsFieldsTest.java
index c28032f..62e5a3b 100644
--- a/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/src/com/android/cts/readsettingsfieldsapp/ReadSettingsFieldsTest.java
+++ b/hostsidetests/appsecurity/test-apps/ReadSettingsFieldsApp/src/com/android/cts/readsettingsfieldsapp/ReadSettingsFieldsTest.java
@@ -24,25 +24,28 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Arrays;
 
 public class ReadSettingsFieldsTest extends AndroidTestCase {
 
+    private final String[] settingsKeysWithMaxTargetSdk = {"mobile_data"};
+
     /** Test public keys are readable with annotation */
-    public void testSecurePublicSettingsKeysAreReadable() {
-        testPublicSettingsKeysAreReadable(Settings.Secure.class);
+    public void testSecureNonHiddenSettingsKeysAreReadable() {
+        testNonHiddenSettingsKeysAreReadable(Settings.Secure.class);
     }
 
-    public void testSystemPublicSettingsKeysAreReadable() {
-        testPublicSettingsKeysAreReadable(Settings.System.class);
+    public void testSystemNonHiddenSettingsKeysAreReadable() {
+        testNonHiddenSettingsKeysAreReadable(Settings.System.class);
     }
 
-    public void testGlobalPublicSettingsKeysAreReadable() {
-        testPublicSettingsKeysAreReadable(Settings.Global.class);
+    public void testGlobalNonHiddenSettingsKeysAreReadable() {
+        testNonHiddenSettingsKeysAreReadable(Settings.Global.class);
     }
 
-    private <T extends Settings.NameValueTable> void testPublicSettingsKeysAreReadable(
+    private <T extends Settings.NameValueTable> void testNonHiddenSettingsKeysAreReadable(
             Class<T> settingsClass) {
-        for (String key : getPublicSettingsKeys(settingsClass)) {
+        for (String key : getNonHiddenSettingsKeys(settingsClass)) {
             try {
                 callGetStringMethod(settingsClass, key);
             } catch (SecurityException ex) {
@@ -53,6 +56,10 @@
                 if (key.equals(Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT)) {
                     continue;
                 }
+                // Skip checking for keys with maxTargetSdk because they might not be readable
+                if (Arrays.asList(settingsKeysWithMaxTargetSdk).contains(key)) {
+                    continue;
+                }
                 fail("Reading public " + settingsClass.getSimpleName() + " settings key <" + key
                         + "> should not raise exception! "
                         + "Did you forget to add @Readable annotation?\n" + ex.getMessage());
@@ -73,7 +80,7 @@
         }
     }
 
-    private <T> ArraySet<String> getPublicSettingsKeys(Class<T> settingsClass) {
+    private <T> ArraySet<String> getNonHiddenSettingsKeys(Class<T> settingsClass) {
         final ArraySet<String> publicSettingsKeys = new ArraySet<>();
         final Field[] allFields = settingsClass.getDeclaredFields();
         try {
@@ -97,7 +104,7 @@
 
     /** Test hidden keys are readable with annotation */
     public void testSecureSomeHiddenSettingsKeysAreReadable() {
-        final ArraySet<String> publicSettingsKeys = getPublicSettingsKeys(Settings.Secure.class);
+        final ArraySet<String> publicSettingsKeys = getNonHiddenSettingsKeys(Settings.Secure.class);
         final String[] hiddenSettingsKeys = {"adaptive_sleep", "bugreport_in_power_menu",
                 "input_methods_subtype_history"};
         testHiddenSettingsKeysReadable(Settings.Secure.class, publicSettingsKeys,
@@ -105,7 +112,7 @@
     }
 
     public void testSystemSomeHiddenSettingsKeysAreReadable() {
-        final ArraySet<String> publicSettingsKeys = getPublicSettingsKeys(Settings.System.class);
+        final ArraySet<String> publicSettingsKeys = getNonHiddenSettingsKeys(Settings.System.class);
         final String[] hiddenSettingsKeys = {"advanced_settings", "system_locales",
                 "display_color_mode", "min_refresh_rate"};
         testHiddenSettingsKeysReadable(Settings.System.class, publicSettingsKeys,
@@ -113,7 +120,7 @@
     }
 
     public void testGlobalSomeHiddenSettingsKeysAreReadable() {
-        final ArraySet<String> publicSettingsKeys = getPublicSettingsKeys(Settings.Secure.class);
+        final ArraySet<String> publicSettingsKeys = getNonHiddenSettingsKeys(Settings.Secure.class);
         final String[] hiddenSettingsKeys = {"add_users_when_locked",
                 "enable_accessibility_global_gesture_enabled"};
         testHiddenSettingsKeysReadable(Settings.Global.class, publicSettingsKeys,
@@ -138,7 +145,7 @@
 
     /** Test hidden keys are not readable without annotation */
     public void testSecureHiddenSettingsKeysNotReadableWithoutAnnotation() {
-        final ArraySet<String> publicSettingsKeys = getPublicSettingsKeys(Settings.Secure.class);
+        final ArraySet<String> publicSettingsKeys = getNonHiddenSettingsKeys(Settings.Secure.class);
         final String[] hiddenSettingsKeys = {"camera_autorotate",
                 "location_time_zone_detection_enabled"};
         testHiddenSettingsKeysNotReadableWithoutAnnotation(Settings.Secure.class,
@@ -146,14 +153,14 @@
     }
 
     public void testSystemHiddenSettingsKeysNotReadableWithoutAnnotation() {
-        final ArraySet<String> publicSettingsKeys = getPublicSettingsKeys(Settings.System.class);
+        final ArraySet<String> publicSettingsKeys = getNonHiddenSettingsKeys(Settings.System.class);
         final String[] hiddenSettingsKeys = {"display_color_mode_vendor_hint"};
         testHiddenSettingsKeysNotReadableWithoutAnnotation(Settings.System.class,
                 publicSettingsKeys, hiddenSettingsKeys);
     }
 
     public void testGlobalHiddenSettingsKeysNotReadableWithoutAnnotation() {
-        final ArraySet<String> publicSettingsKeys = getPublicSettingsKeys(Settings.Global.class);
+        final ArraySet<String> publicSettingsKeys = getNonHiddenSettingsKeys(Settings.Global.class);
         final String[] hiddenSettingsKeys = {"restricted_networking_mode",
                 "people_space_conversation_type"};
         testHiddenSettingsKeysNotReadableWithoutAnnotation(Settings.Global.class,
@@ -198,7 +205,7 @@
 
     /** Test hidden keys are readable if the app is test only, even without annotation */
     public void testSecureHiddenSettingsKeysReadableWithoutAnnotation() {
-        final ArraySet<String> publicSettingsKeys = getPublicSettingsKeys(Settings.Secure.class);
+        final ArraySet<String> publicSettingsKeys = getNonHiddenSettingsKeys(Settings.Secure.class);
         final String[] hiddenSettingsKeys = {"camera_autorotate",
                 "location_time_zone_detection_enabled"};
         testHiddenSettingsKeysReadable(Settings.Secure.class, publicSettingsKeys,
@@ -206,18 +213,40 @@
     }
 
     public void testSystemHiddenSettingsKeysReadableWithoutAnnotation() {
-        final ArraySet<String> publicSettingsKeys = getPublicSettingsKeys(Settings.System.class);
+        final ArraySet<String> publicSettingsKeys = getNonHiddenSettingsKeys(Settings.System.class);
         final String[] hiddenSettingsKeys = {"display_color_mode_vendor_hint"};
         testHiddenSettingsKeysReadable(Settings.System.class, publicSettingsKeys,
                 hiddenSettingsKeys);
     }
 
     public void testGlobalHiddenSettingsKeysReadableWithoutAnnotation() {
-        final ArraySet<String> publicSettingsKeys = getPublicSettingsKeys(Settings.Global.class);
+        final ArraySet<String> publicSettingsKeys = getNonHiddenSettingsKeys(Settings.Global.class);
         final String[] hiddenSettingsKeys = {"restricted_networking_mode",
                 "people_space_conversation_type"};
         testHiddenSettingsKeysReadable(Settings.Global.class, publicSettingsKeys,
                 hiddenSettingsKeys);
     }
+
+    public void testSettingsKeysNotReadableForAfterR() {
+        final String keyWithTargetSdkR = "mobile_data";
+        try {
+            // Verify that the hidden key is not readable because of maxTargetSdk restriction
+            callGetStringMethod(Settings.Global.class, keyWithTargetSdkR);
+            fail("Reading hidden global settings key <" + keyWithTargetSdkR
+                    + "> should raise!");
+        } catch (SecurityException ex) {
+            assertTrue(ex.getMessage().contains("targetSdkVersion"));
+        }
+    }
+
+    public void testSettingsKeysReadableForRMinus() {
+        final String keyWithTargetSdkR = "mobile_data";
+        try {
+            // Verify that the hidden key can still be read
+            callGetStringMethod(Settings.Global.class, keyWithTargetSdkR);
+        } catch (SecurityException ex) {
+            fail("Reading hidden settings key <" + keyWithTargetSdkR + "> should not raise!");
+        }
+    }
 }
 
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstall/OWNERS b/hostsidetests/appsecurity/test-apps/SharedUidInstall/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstall/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstall/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/OWNERS b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/OWNERS b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/OWNERS b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/OWNERS
index 87e75ec..bdc654a 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 533114
 toddke@google.com
+patb@google.com
diff --git a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
index c199b5b..46bb5a3 100644
--- a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
+++ b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
@@ -49,8 +49,8 @@
         String teststep;
         PowerPolicyTestHelper testHelper;
 
-        teststep = "reboot to forced silent";
-        rebootForcedSilent();
+        teststep = "switch to forced silent";
+        enterForcedSilentMode();
         testHelper = getTestHelper(testcase, 1, teststep);
         testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
         testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.NO_USER_INTERACTION);
@@ -59,7 +59,7 @@
         testHelper.checkCurrentPowerComponents(PowerPolicyDef.PolicySet.NO_USER_INTERACT);
 
         teststep = "restore to normal mode";
-        restoreFromForcedSilentMode();
+        leaveForcedSilentMode();
         testHelper = getTestHelper(testcase, 2, teststep);
         testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON);
         testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON);
@@ -176,12 +176,12 @@
         waitForDeviceAvailable();
     }
 
-    private void rebootForcedSilent() throws Exception {
-        executeCommand("reboot forcedsilent");
-        waitForDeviceAvailable();
+    private void enterForcedSilentMode() throws Exception {
+        executeCommand("cmd car_service silent-mode forced-silent");
     }
 
-    private void restoreFromForcedSilentMode() throws Exception {
+    private void leaveForcedSilentMode() throws Exception {
+        executeCommand("cmd car_service silent-mode forced-non-silent");
         executeCommand("cmd car_service silent-mode non-forced-silent-mode");
     }
 
diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyDef.java b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyDef.java
index 70d7354..61aaed4 100644
--- a/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyDef.java
+++ b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyDef.java
@@ -60,10 +60,10 @@
                 .toArray(String[]::new);
         StringBuilder str = new StringBuilder();
         str.append(mPolicyId);
-        if (!enables[0].equals("none")) {
+        if (enables.length > 0) {
             str.append(" --enable ").append(String.join(",", enables));
         }
-        if (!disables[0].equals("none")) {
+        if (disables.length > 0) {
             str.append(" --disable ").append(String.join(",", disables));
         }
         return str.toString();
@@ -184,8 +184,8 @@
                 return new PowerComponent[0];
             }
             normalizeComponentName(componentNames);
-            PowerComponent[] compArray = Arrays.stream(componentNames)
-                    .map(PowerComponent::valueOf).toArray(PowerComponent[]::new);
+            PowerComponent[] compArray = Arrays.stream(componentNames).map(PowerComponent::valueOf)
+                    .filter(e -> e != NONE).toArray(PowerComponent[]::new);
             Arrays.sort(compArray);
             return compArray;
         }
@@ -251,8 +251,8 @@
             PowerComponent.MICROPHONE
         };
 
-        static final PowerComponent[] DEFAULT_ALL_ON_ENABLE =  ALL_COMPONENTS;
-        static final PowerComponent[] DEFAULT_ALL_ON_DISABLE = {PowerComponent.NONE};
+        static final PowerComponent[] DEFAULT_ALL_ON_ENABLE = ALL_COMPONENTS;
+        static final PowerComponent[] DEFAULT_ALL_ON_DISABLE = {};
 
         static final PowerComponent[] NO_USER_INTERACT_ENABLE = {
             PowerComponent.WIFI,
@@ -276,9 +276,9 @@
         };
 
         static final PowerComponent[] TEST1_ENABLE =  ALL_COMPONENTS;
-        static final PowerComponent[] TEST1_DISABLE = {PowerComponent.NONE};
+        static final PowerComponent[] TEST1_DISABLE = {};
 
-        static final PowerComponent[] TEST2_ENABLE = {PowerComponent.NONE};
+        static final PowerComponent[] TEST2_ENABLE = {};
         static final PowerComponent[] TEST2_DISABLE = ALL_COMPONENTS;
 
         static final PowerComponent[] ERROR_TEST1_ENABLE = ALL_COMPONENTS;
@@ -302,10 +302,10 @@
             PowerComponent.MICROPHONE,
             PowerComponent.CPU
         };
-        static final PowerComponent[] ERROR_TEST2_DISABLE = {PowerComponent.NONE};
+        static final PowerComponent[] ERROR_TEST2_DISABLE = {};
 
         static final PowerComponent[] RUNTIME_DEFAULT_ENABLE = ALL_COMPONENTS;
-        static final PowerComponent[] RUNTIME_DEFAULT_DISABLE = {PowerComponent.NONE};
+        static final PowerComponent[] RUNTIME_DEFAULT_DISABLE = {};
 
         static final PowerComponent[] RUNTIME_SILENT_ENABLE = {
             PowerComponent.AUDIO,
@@ -325,7 +325,7 @@
             PowerComponent.MICROPHONE,
             PowerComponent.CPU
         };
-        static final PowerComponent[] RUNTIME_SILENT_DISABLE = {PowerComponent.NONE};
+        static final PowerComponent[] RUNTIME_SILENT_DISABLE = {};
     }
 
     public static final class PolicySet {
diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java b/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
index 8487ae2..7469457 100644
--- a/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
+++ b/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
@@ -21,7 +21,7 @@
 public final class SilentModeInfo {
     private static final String[] ATTR_HEADERS = {"Monitoring HW state signal",
             "Silent mode by HW state signal", "Forced silent mode"};
-    private static final boolean[] EXPECTED_WITHOUT_SILENT_MODE = {false, false, false};
+    private static final boolean[] EXPECTED_WITHOUT_SILENT_MODE = {true, false, false};
     private static final boolean[] EXPECTED_WITH_SILENT_MODE = {false, true, true};
 
     public static final String COMMAND = "cmd car_service silent-mode query";
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/DelegateTestUtils.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/DelegateTestUtils.java
index 0480566..71d6d0d 100644
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/DelegateTestUtils.java
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/DelegateTestUtils.java
@@ -15,11 +15,6 @@
  */
 package com.android.cts.delegate;
 
-import static android.app.admin.SecurityLog.TAG_KEY_DESTRUCTION;
-import static android.app.admin.SecurityLog.TAG_KEY_GENERATED;
-
-import static com.google.common.truth.Truth.assertThat;
-
 import static junit.framework.Assert.fail;
 
 import android.app.admin.DelegatedAdminReceiver;
@@ -28,17 +23,11 @@
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.content.Context;
 import android.content.Intent;
-import android.os.Process;
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyProperties;
 import android.test.MoreAsserts;
 import android.util.Log;
 
 import junit.framework.Assert;
 
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyStore;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
@@ -48,13 +37,6 @@
  * Utils class for delegation tests.
  */
 public class DelegateTestUtils {
-    // Indices of various fields in SecurityEvent payload.
-    private static final int SUCCESS_INDEX = 0;
-    private static final int ALIAS_INDEX = 1;
-    private static final int UID_INDEX = 2;
-
-    // Value that indicates success in events that have corresponding field in their payload.
-    private static final int SUCCESS_VALUE = 1;
 
     @FunctionalInterface
     public interface ExceptionRunnable {
@@ -143,72 +125,4 @@
         }
         Assert.fail("Expected " + expectedExceptionType.getName() + " was not thrown");
     }
-
-    /**
-     * Generates a key for the given key alias, asserts it was created successfully
-     */
-    public static void testGenerateKey(String keyAlias) throws Exception {
-        final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
-        generator.initialize(
-                new KeyGenParameterSpec.Builder(keyAlias, KeyProperties.PURPOSE_SIGN).build());
-        final KeyPair keyPair = generator.generateKeyPair();
-        assertThat(keyPair).isNotNull();
-    }
-
-    /**
-     * Deletes a key for the given key alias
-     */
-    public static void deleteKey(String keyAlias) throws Exception {
-        final KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
-        ks.load(null);
-        ks.deleteEntry(keyAlias);
-    }
-
-    /**
-     * Verifies that the expected keystore events generated by {@link #testGenerateKey} are
-     * present
-     */
-    public static void verifyKeystoreEventsPresent(String generatedKeyAlias,
-            List<SecurityEvent> securityEvents) {
-        int receivedKeyGenerationEvents = 0;
-        int receivedKeyDeletionEvents = 0;
-
-        for (final SecurityEvent currentEvent : securityEvents) {
-            if (currentEvent.getTag() == TAG_KEY_GENERATED) {
-                verifyKeyEvent(currentEvent, generatedKeyAlias);
-                receivedKeyGenerationEvents++;
-            }
-
-            if (currentEvent.getTag() == TAG_KEY_DESTRUCTION) {
-                verifyKeyEvent(currentEvent, generatedKeyAlias);
-                receivedKeyDeletionEvents++;
-            }
-        }
-
-        assertThat(receivedKeyGenerationEvents).isEqualTo(1);
-        assertThat(receivedKeyDeletionEvents).isEqualTo(1);
-    }
-
-    /**
-     * Verifies that a security event represents a successful key modification event for
-     * keyAlias
-     */
-    private static void verifyKeyEvent(SecurityEvent event, String keyAlias) {
-        assertThat(getInt(event, SUCCESS_INDEX)).isEqualTo(SUCCESS_VALUE);
-        assertThat(getString(event, ALIAS_INDEX)).contains(keyAlias);
-        assertThat(getInt(event, UID_INDEX)).isEqualTo(Process.myUid());
-    }
-
-    private static Object getDatum(SecurityEvent event, int index) {
-        final Object[] dataArray = (Object[]) event.getData();
-        return dataArray[index];
-    }
-
-    private static String getString(SecurityEvent event, int index) {
-        return (String) getDatum(event, index);
-    }
-
-    private static int getInt(SecurityEvent event, int index) {
-        return (Integer) getDatum(event, index);
-    }
 }
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/SecurityLoggingDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/SecurityLoggingDelegateTest.java
index 82c99ab..479a75a 100644
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/SecurityLoggingDelegateTest.java
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/SecurityLoggingDelegateTest.java
@@ -13,8 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.cts.delegate;
 
+import static android.app.admin.SecurityLog.TAG_KEY_DESTRUCTION;
+import static android.app.admin.SecurityLog.TAG_KEY_GENERATED;
+
 import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -22,11 +26,21 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.content.Context;
+import android.os.Process;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
 import android.support.test.uiautomator.UiDevice;
-import android.test.InstrumentationTestCase;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 
@@ -34,27 +48,31 @@
  * Tests that a delegate app with DELEGATION_SECURITY_LOGGING is able to control and access
  * security logging.
  */
-public class SecurityLoggingDelegateTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class SecurityLoggingDelegateTest {
+    private static final String GENERATED_KEY_ALIAS = "generated_key_alias";
 
-    private static final String TAG = "SecurityLoggingDelegateTest";
+    // Indices of various fields in SecurityEvent payload.
+    private static final int SUCCESS_INDEX = 0;
+    private static final int ALIAS_INDEX = 1;
+    private static final int UID_INDEX = 2;
+    // Value that indicates success in events that have corresponding field in their payload.
+    private static final int SUCCESS_VALUE = 1;
 
     private Context mContext;
     private DevicePolicyManager mDpm;
     private UiDevice mDevice;
 
-    private static final String GENERATED_KEY_ALIAS = "generated_key_alias";
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
+    @Before
+    public void setUp() {
         mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        mContext = getInstrumentation().getContext();
+        mContext = InstrumentationRegistry.getContext();
         mDpm = mContext.getSystemService(DevicePolicyManager.class);
         DelegateTestUtils.DelegatedLogsReceiver.sBatchCountDown = new CountDownLatch(1);
     }
 
-    public void testCannotAccessApis()throws Exception {
+    @Test
+    public void testCannotAccessApis() {
         assertExpectException(SecurityException.class, null,
                 () -> mDpm.isSecurityLoggingEnabled(null));
 
@@ -69,6 +87,7 @@
      * Test: Test enabling security logging.
      * This test has a side effect: security logging is enabled after its execution.
      */
+    @Test
     public void testEnablingSecurityLogging() {
         mDpm.setSecurityLoggingEnabled(null, true);
 
@@ -78,11 +97,20 @@
     /**
      * Generates security events related to Keystore
      */
+    @Test
     public void testGenerateLogs() throws Exception {
         try {
-            DelegateTestUtils.testGenerateKey(GENERATED_KEY_ALIAS);
+            final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
+            keyGen.initialize(new KeyGenParameterSpec.Builder(
+                    GENERATED_KEY_ALIAS, KeyProperties.PURPOSE_SIGN).build());
+            // Should emit key generation event.
+            final KeyPair keyPair = keyGen.generateKeyPair();
+            assertThat(keyPair).isNotNull();
         } finally {
-            DelegateTestUtils.deleteKey(GENERATED_KEY_ALIAS);
+            final KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
+            ks.load(null);
+            // Should emit key destruction event.
+            ks.deleteEntry(GENERATED_KEY_ALIAS);
         }
     }
 
@@ -90,19 +118,49 @@
      * Test: retrieves security logs and verifies that all events generated as a result of host
      * side actions and by {@link #testGenerateLogs()} are there.
      */
+    @Test
     public void testVerifyGeneratedLogs() throws Exception {
         mDevice.executeShellCommand("dpm force-security-logs");
         DelegateTestUtils.DelegatedLogsReceiver.waitForBroadcast();
 
         final List<SecurityEvent> events =
                 DelegateTestUtils.DelegatedLogsReceiver.getSecurityEvents();
-        DelegateTestUtils.verifyKeystoreEventsPresent(GENERATED_KEY_ALIAS, events);
+
+        int keyGenerationEvents = 0;
+        int keyDeletionEvents = 0;
+
+        final int myUid = Process.myUid();
+
+        for (final SecurityEvent event : events) {
+            if (event.getTag() == TAG_KEY_GENERATED && getInt(event, UID_INDEX) == myUid) {
+                verifyKeyEvent(event);
+                keyGenerationEvents++;
+            }
+
+            if (event.getTag() == TAG_KEY_DESTRUCTION && getInt(event, UID_INDEX) == myUid) {
+                verifyKeyEvent(event);
+                keyDeletionEvents++;
+            }
+        }
+
+        assertThat(keyGenerationEvents).isEqualTo(1);
+        assertThat(keyDeletionEvents).isEqualTo(1);
+    }
+
+    /**
+     * Verifies that a security event represents a successful key modification event for
+     * keyAlias
+     */
+    private static void verifyKeyEvent(SecurityEvent event) {
+        assertThat(getInt(event, SUCCESS_INDEX)).isEqualTo(SUCCESS_VALUE);
+        assertThat(getString(event, ALIAS_INDEX)).isEqualTo(GENERATED_KEY_ALIAS);
     }
 
     /**
      * Test: retrieving security logs should be rate limited - subsequent attempts should return
      * null.
      */
+    @Test
     public void testSecurityLoggingRetrievalRateLimited() {
         final List<SecurityEvent> logs = mDpm.retrieveSecurityLogs(null);
         // if logs is null it means that that attempt was rate limited => test PASS
@@ -113,12 +171,26 @@
     }
 
     /**
-     * Test: Test disaling security logging.
+     * Test: Test disabling security logging.
      * This test has a side effect: security logging is disabled after its execution.
      */
+    @Test
     public void testDisablingSecurityLogging() {
         mDpm.setSecurityLoggingEnabled(null, false);
 
         assertThat(mDpm.isSecurityLoggingEnabled(null)).isFalse();
     }
+
+    private static Object getDatum(SecurityEvent event, int index) {
+        final Object[] dataArray = (Object[]) event.getData();
+        return dataArray[index];
+    }
+
+    private static String getString(SecurityEvent event, int index) {
+        return (String) getDatum(event, index);
+    }
+
+    private static int getInt(SecurityEvent event, int index) {
+        return (Integer) getDatum(event, index);
+    }
 }
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/WorkProfileSecurityLoggingDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/WorkProfileSecurityLoggingDelegateTest.java
deleted file mode 100644
index 165d38c..0000000
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/WorkProfileSecurityLoggingDelegateTest.java
+++ /dev/null
@@ -1,130 +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 com.android.cts.delegate;
-
-import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.admin.DevicePolicyManager;
-import android.app.admin.SecurityLog.SecurityEvent;
-import android.content.Context;
-import android.support.test.uiautomator.UiDevice;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
-@RunWith(AndroidJUnit4.class)
-public class WorkProfileSecurityLoggingDelegateTest {
-
-    private static final String TAG = "WorkProfileSecurityLoggingDelegateTest";
-    private static final String CTS_APP_PACKAGE_NAME = "com.android.cts.delegate";
-    private static final String GENERATED_KEY_ALIAS = "generated_key_alias";
-
-    private Context mContext;
-    private DevicePolicyManager mDpm;
-    private UiDevice mDevice;
-
-    @Before
-    public void setUp() {
-        mContext = InstrumentationRegistry.getContext();
-        mDpm = mContext.getSystemService(DevicePolicyManager.class);
-        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        DelegateTestUtils.DelegatedLogsReceiver.sBatchCountDown = new CountDownLatch(1);
-    }
-
-    @Test
-    public void testCannotAccessApis() {
-        assertExpectException(SecurityException.class, null,
-                () -> mDpm.isSecurityLoggingEnabled(null));
-
-        assertExpectException(SecurityException.class, null,
-                () -> mDpm.setSecurityLoggingEnabled(null, true));
-
-        assertExpectException(SecurityException.class, null,
-                () -> mDpm.retrieveSecurityLogs(null));
-    }
-
-    /**
-     * Test: Test enabling security logging.
-     * This test has a side effect: security logging is enabled after its execution.
-     */
-    @Test
-    public void testEnablingSecurityLogging() {
-        mDpm.setSecurityLoggingEnabled(null, true);
-
-        assertThat(mDpm.isSecurityLoggingEnabled(null)).isTrue();
-    }
-
-    /**
-     * Generates security events related to Keystore
-     */
-    @Test
-    public void testGenerateLogs() throws Exception {
-        try {
-            DelegateTestUtils.testGenerateKey(GENERATED_KEY_ALIAS);
-        } finally {
-            DelegateTestUtils.deleteKey(GENERATED_KEY_ALIAS);
-        }
-    }
-
-    /**
-     * Test: retrieves security logs and verifies that all events generated as a result of host
-     * side actions and by {@link #testGenerateLogs()} are there.
-     */
-    @Test
-    public void testVerifyGeneratedLogs() throws Exception {
-        mDevice.executeShellCommand("dpm force-security-logs");
-        DelegateTestUtils.DelegatedLogsReceiver.waitForBroadcast();
-
-        final List<SecurityEvent> events =
-                DelegateTestUtils.DelegatedLogsReceiver.getSecurityEvents();
-        DelegateTestUtils.verifyKeystoreEventsPresent(GENERATED_KEY_ALIAS, events);
-    }
-
-    /**
-     * Test: retrieving security logs should be rate limited - subsequent attempts should return
-     * null.
-     */
-    @Test
-    public void testSecurityLoggingRetrievalRateLimited() {
-        final List<SecurityEvent> logs = mDpm.retrieveSecurityLogs(null);
-        // if logs is null it means that that attempt was rate limited => test PASS
-        if (logs != null) {
-            assertThat(mDpm.retrieveSecurityLogs(null)).isNull();
-            assertThat(mDpm.retrieveSecurityLogs(null)).isNull();
-        }
-    }
-
-    /**
-     * Test: Test disaling security logging.
-     * This test has a side effect: security logging is disabled after its execution.
-     */
-    @Test
-    public void testDisablingSecurityLogging() {
-        mDpm.setSecurityLoggingEnabled(null, false);
-
-        assertThat(mDpm.isSecurityLoggingEnabled(null)).isFalse();
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java
index 8306812..0fb2764 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java
@@ -28,6 +28,7 @@
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Process;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.test.InstrumentationTestCase;
@@ -215,4 +216,9 @@
     protected boolean isDeviceOwner() {
         return mDevicePolicyManager.isDeviceOwnerApp(PACKAGE_NAME);
     }
+
+    void sleep(int timeMs) {
+        Log.d(TAG, "Sleeping " + timeMs + " ms");
+        SystemClock.sleep(timeMs);
+    }
 }
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 4897559..b98bf5c 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
@@ -16,17 +16,6 @@
 package com.android.cts.deviceandprofileowner;
 
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
-import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
-
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static org.testng.Assert.assertThrows;
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
@@ -46,8 +35,6 @@
 import androidx.test.InstrumentationRegistry;
 
 import java.time.Duration;
-import java.util.HashSet;
-import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 public class LockTaskTest extends BaseDeviceAdminTest {
@@ -169,68 +156,6 @@
         mContext.unregisterReceiver(mReceiver);
     }
 
-    // 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() {
-        final int[] flags = new int[] {
-                LOCK_TASK_FEATURE_SYSTEM_INFO,
-                LOCK_TASK_FEATURE_HOME,
-                LOCK_TASK_FEATURE_NOTIFICATIONS,
-                LOCK_TASK_FEATURE_OVERVIEW,
-                LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
-                LOCK_TASK_FEATURE_KEYGUARD
-        };
-
-        int cumulative = LOCK_TASK_FEATURE_NONE;
-        for (int flag : flags) {
-            if (flag == LOCK_TASK_FEATURE_OVERVIEW || flag == LOCK_TASK_FEATURE_NOTIFICATIONS) {
-                // Those flags can only be used in combination with HOME
-                assertThrows(
-                        IllegalArgumentException.class,
-                        () -> mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, flag));
-            } else {
-                mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, flag);
-                assertEquals(flag, mDevicePolicyManager.getLockTaskFeatures(ADMIN_COMPONENT));
-            }
-
-            cumulative |= flag;
-            mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, cumulative);
-            assertEquals(cumulative, mDevicePolicyManager.getLockTaskFeatures(ADMIN_COMPONENT));
-
-            mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, LOCK_TASK_FEATURE_NONE);
-            assertEquals(LOCK_TASK_FEATURE_NONE,
-                    mDevicePolicyManager.getLockTaskFeatures(ADMIN_COMPONENT));
-        }
-    }
-
     // Start lock task, verify that ActivityManager knows thats what is going on.
     public void testStartLockTask() throws Exception {
         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PreferentialNetworkServiceStatusTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PreferentialNetworkServiceStatusTest.java
index 191704a..b2abafa 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PreferentialNetworkServiceStatusTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PreferentialNetworkServiceStatusTest.java
@@ -33,13 +33,14 @@
     }
 
     public void testGetSetPreferentialNetworkServiceStatus() throws Exception {
-        // Assert default status is true
+        // Assert default status is false
+        assertFalse(mDevicePolicyManager.isPreferentialNetworkServiceEnabled());
+
+        mDevicePolicyManager.setPreferentialNetworkServiceEnabled(true);
         assertTrue(mDevicePolicyManager.isPreferentialNetworkServiceEnabled());
 
         mDevicePolicyManager.setPreferentialNetworkServiceEnabled(false);
         assertFalse(mDevicePolicyManager.isPreferentialNetworkServiceEnabled());
 
-        mDevicePolicyManager.setPreferentialNetworkServiceEnabled(true);
-        assertTrue(mDevicePolicyManager.isPreferentialNetworkServiceEnabled());
     }
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
index ed420f1..e3afa4e 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
@@ -15,71 +15,95 @@
  */
 package com.android.cts.deviceandprofileowner;
 
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import android.app.admin.DevicePolicyManager;
+import android.graphics.Bitmap;
 import android.util.Log;
 
 /**
  * Tests for {@link DevicePolicyManager#setScreenCaptureDisabled} and
  * {@link DevicePolicyManager#getScreenCaptureDisabled} APIs.
  */
-public class ScreenCaptureDisabledTest extends BaseDeviceAdminTest {
+public final class ScreenCaptureDisabledTest extends BaseDeviceAdminTest {
     private final int MAX_ATTEMPTS_COUNT = 20;
     private final int WAIT_IN_MILLISECOND = 500;
 
-    private static final String TAG = "ScreenCaptureDisabledTest";
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
+    private static final String TAG = ScreenCaptureDisabledTest.class.getSimpleName();
 
     public void testSetScreenCaptureDisabled_false() {
         mDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, false);
-        assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
-        assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
+        assertWithMessage("dpm.getScreenCaptureDisabled(%s)",
+                ADMIN_RECEIVER_COMPONENT.flattenToShortString())
+                    .that(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT))
+                    .isFalse();
+        assertWithMessage("dpm.getScreenCaptureDisabled(null)")
+                .that(mDevicePolicyManager.getScreenCaptureDisabled(/* admin= */ null)).isFalse();
     }
 
     public void testSetScreenCaptureDisabled_true() {
         mDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, true);
-        assertTrue(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
-        assertTrue(mDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
+        assertWithMessage("dpm.getScreenCaptureDisabled(%s)",
+                ADMIN_RECEIVER_COMPONENT.flattenToShortString())
+                     .that(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT))
+                     .isTrue();
+        assertWithMessage("dpm.getScreenCaptureDisabled(null)")
+                .that(mDevicePolicyManager.getScreenCaptureDisabled(/* admin= */ null)).isTrue();
     }
 
     public void testSetScreenCaptureDisabledOnParent_false() {
         DevicePolicyManager parentDevicePolicyManager =
                 mDevicePolicyManager.getParentProfileInstance(ADMIN_RECEIVER_COMPONENT);
         parentDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, false);
-        assertFalse(parentDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
-        assertFalse(parentDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
+        assertWithMessage("parentDevicePolicyManager.getScreenCaptureDisabled(%s)",
+                ADMIN_RECEIVER_COMPONENT.flattenToShortString())
+                     .that(parentDevicePolicyManager
+                             .getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT))
+                     .isFalse();
+        assertWithMessage("parentDpm.getScreenCaptureDisabled(null)")
+                .that(parentDevicePolicyManager.getScreenCaptureDisabled(/* admin= */ null))
+                .isFalse();
     }
 
     public void testSetScreenCaptureDisabledOnParent_true() {
         DevicePolicyManager parentDevicePolicyManager =
                 mDevicePolicyManager.getParentProfileInstance(ADMIN_RECEIVER_COMPONENT);
         parentDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, true);
-        assertTrue(parentDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
-        assertTrue(parentDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
+        assertWithMessage("parentDevicePolicyManager.getScreenCaptureDisabled(%s)",
+                ADMIN_RECEIVER_COMPONENT.flattenToShortString())
+                     .that(parentDevicePolicyManager
+                             .getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT))
+                     .isTrue();
+        assertWithMessage("parentDpm.getScreenCaptureDisabled(null)")
+                .that(parentDevicePolicyManager.getScreenCaptureDisabled(/* admin= */ null))
+                .isTrue();
     }
 
     public void testScreenCaptureImpossible() throws Exception {
-        for (int i = 0; i < MAX_ATTEMPTS_COUNT; i++) {
-            Log.d(TAG, "testScreenCaptureImpossible: " + i + " trials");
-            Thread.sleep(WAIT_IN_MILLISECOND);
-            if (getInstrumentation().getUiAutomation().takeScreenshot() == null) {
-                break;
-            }
+        Bitmap screenshot = null;
+        for (int i = 1; i <= MAX_ATTEMPTS_COUNT; i++) {
+            Log.d(TAG, "testScreenCaptureImpossible(): attempt #" + i);
+            sleep(WAIT_IN_MILLISECOND);
+            screenshot = takeScreenshot();
+            if (screenshot == null) break;
         }
-        assertNull(getInstrumentation().getUiAutomation().takeScreenshot());
+        assertWithMessage("screenshot").that(screenshot).isNull();
     }
 
     public void testScreenCapturePossible() throws Exception {
-        for (int i = 0; i < MAX_ATTEMPTS_COUNT; i++) {
-            Log.d(TAG, "testScreenCapturePossible: " + i + " trials");
-            Thread.sleep(WAIT_IN_MILLISECOND);
-            if (getInstrumentation().getUiAutomation().takeScreenshot() != null) {
-                break;
-            }
+        Bitmap screenshot = null;
+        for (int i = 1; i <= MAX_ATTEMPTS_COUNT; i++) {
+            Log.d(TAG, "testScreenCapturePossible): attempt #" + i);
+            sleep(WAIT_IN_MILLISECOND);
+            screenshot = takeScreenshot();
+            if (screenshot != null) break;
         }
-        assertNotNull(getInstrumentation().getUiAutomation().takeScreenshot());
+        assertWithMessage("screenshot").that(screenshot).isNotNull();
+    }
+
+    private Bitmap takeScreenshot() {
+        Bitmap screenshot = getInstrumentation().getUiAutomation().takeScreenshot();
+        Log.d(TAG, "takeScreenshot(): got " + screenshot);
+        return screenshot;
     }
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
index d58430b..5c9c6d2 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
@@ -63,6 +63,8 @@
 import static com.google.common.collect.ImmutableList.of;
 import static com.google.common.truth.Truth.assertThat;
 
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.SecurityLog;
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -75,6 +77,7 @@
 import android.security.keystore.KeyProtection;
 import android.support.test.uiautomator.UiDevice;
 import android.text.TextUtils;
+import android.util.DebugUtils;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -106,7 +109,7 @@
     private static final int TAG_LIBLOG_DROPPED = 1006;
     private static final String DELEGATE_APP_PKG = "com.android.cts.delegate";
     private static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging";
-
+    private static final boolean VERBOSE = false;
 
     // For brevity.
     private static final Class<String> S = String.class;
@@ -221,8 +224,7 @@
      * side actions and by {@link #testGenerateLogs()} are there.
      */
     public void testVerifyGeneratedLogs() throws Exception {
-        UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
-                .executeShellCommand("dpm force-security-logs");
+        forceSecurityLogs();
 
         final List<SecurityEvent> events = getEvents();
 
@@ -236,6 +238,11 @@
         }
     }
 
+    private void forceSecurityLogs() throws Exception {
+        UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+                .executeShellCommand("dpm force-security-logs");
+    }
+
     private void verifyAutomaticEventsPresent(List<SecurityEvent> events) {
         verifyOsStartupEventPresent(events);
         verifyLoggingStartedEventPresent(events);
@@ -337,8 +344,14 @@
         // effect just yet.
         for (int i = 0; i < 2 && events == null; i++) {
             events = mDevicePolicyManager.retrieveSecurityLogs(ADMIN_RECEIVER_COMPONENT);
-            if (events == null) Thread.sleep(1000);
+            Log.v(TAG, "getEvents(), batch #" + i + ": "  + (events == null ? -1 : events.size())
+                    + " events");
+            if (events == null) sleep(1000);
         }
+
+        Log.d(TAG, "getEvents(): received " + events.size() + " events");
+        if (VERBOSE) dumpSecurityLogs(events);
+
         try {
             verifySecurityLogs(events);
         } catch (AssertionFailedError e) {
@@ -349,18 +362,12 @@
         return events;
     }
 
-    private void dumpSecurityLogs(List<SecurityEvent> events) {
-        Log.d(TAG, "Security events dump:");
-        for (SecurityEvent event : events) {
-            Log.d(TAG, event.toString());
-        }
-    }
-
     /**
      * Test: check that there are no gaps between ids in two consecutive batches. Shared preference
      * is used to store these numbers between test invocations.
      */
     public void testVerifyLogIds() throws Exception {
+        forceSecurityLogs();
         final String param = InstrumentationRegistry.getArguments().getString(ARG_BATCH_NUMBER);
         final int batchId = param == null ? 0 : Integer.parseInt(param);
         final List<SecurityEvent> events = getEvents();
@@ -636,18 +643,22 @@
     }
 
     private void generatePasswordComplexityEvents() {
-        mDevicePolicyManager.setPasswordQuality(ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_COMPLEX);
-        mDevicePolicyManager.setPasswordMinimumLength(ADMIN_RECEIVER_COMPONENT, TEST_PWD_LENGTH);
-        mDevicePolicyManager.setPasswordMinimumLetters(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumNonLetter(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumUpperCase(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumLowerCase(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumNumeric(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumSymbols(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        DevicePolicyManager dpm = getDpmToGenerateEvents();
+
+        dpm.setPasswordQuality(ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_COMPLEX);
+        dpm.setPasswordMinimumLength(ADMIN_RECEIVER_COMPONENT, TEST_PWD_LENGTH);
+        dpm.setPasswordMinimumLetters(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        dpm.setPasswordMinimumNonLetter(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        dpm.setPasswordMinimumUpperCase(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        dpm.setPasswordMinimumLowerCase(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        dpm.setPasswordMinimumNumeric(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        dpm.setPasswordMinimumSymbols(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
     }
 
     private void generateNewStylePasswordComplexityEvents() {
-        mDevicePolicyManager.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_HIGH);
+        DevicePolicyManager dpm = getDpmToGenerateEvents();
+
+        dpm.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_HIGH);
     }
 
     private void verifyPasswordComplexityEventsPresent(List<SecurityEvent> events) {
@@ -701,18 +712,17 @@
     }
 
     private void generateLockingPolicyEvents() {
+        DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+
         if (mHasSecureLockScreen) {
-            mDevicePolicyManager.setPasswordExpirationTimeout(ADMIN_RECEIVER_COMPONENT,
-                    TEST_PWD_EXPIRATION_TIMEOUT);
-            mDevicePolicyManager.setPasswordHistoryLength(ADMIN_RECEIVER_COMPONENT,
-                    TEST_PWD_HISTORY_LENGTH);
-            mDevicePolicyManager.setMaximumFailedPasswordsForWipe(ADMIN_RECEIVER_COMPONENT,
-                    TEST_PWD_MAX_ATTEMPTS);
+            dpm.setPasswordExpirationTimeout(ADMIN_RECEIVER_COMPONENT, TEST_PWD_EXPIRATION_TIMEOUT);
+            dpm.setPasswordHistoryLength(ADMIN_RECEIVER_COMPONENT, TEST_PWD_HISTORY_LENGTH);
+            dpm.setMaximumFailedPasswordsForWipe(ADMIN_RECEIVER_COMPONENT, TEST_PWD_MAX_ATTEMPTS);
         }
-        mDevicePolicyManager.setKeyguardDisabledFeatures(ADMIN_RECEIVER_COMPONENT,
+        dpm.setKeyguardDisabledFeatures(ADMIN_RECEIVER_COMPONENT,
                 KEYGUARD_DISABLE_FINGERPRINT);
-        mDevicePolicyManager.setMaximumTimeToLock(ADMIN_RECEIVER_COMPONENT, TEST_MAX_TIME_TO_LOCK);
-        mDevicePolicyManager.lockNow();
+        dpm.setMaximumTimeToLock(ADMIN_RECEIVER_COMPONENT, TEST_MAX_TIME_TO_LOCK);
+        dpm.lockNow();
     }
 
     private void verifyLockingPolicyEventsPresent(List<SecurityEvent> events) {
@@ -764,22 +774,42 @@
     private void findPasswordComplexityEvent(
             String description, List<SecurityEvent> events, Object[] expectedPayload) {
         findEvent(description, events,
-                e -> e.getTag() == TAG_PASSWORD_COMPLEXITY_SET &&
-                        Arrays.equals((Object[]) e.getData(), expectedPayload));
+                byTagAndPayload(TAG_PASSWORD_COMPLEXITY_SET, expectedPayload));
     }
 
     private void findNewStylePasswordComplexityEvent(
             String description, List<SecurityEvent> events, Object[] expectedPayload) {
         findEvent(description, events,
-                e -> e.getTag() == TAG_PASSWORD_COMPLEXITY_REQUIRED &&
-                        Arrays.equals((Object[]) e.getData(), expectedPayload));
+                byTagAndPayload(TAG_PASSWORD_COMPLEXITY_REQUIRED, expectedPayload));
+    }
+
+    private Predicate<SecurityEvent> byTagAndPayload(int expectedTag, Object[] expectedPayload) {
+        return (event) -> {
+            boolean tagMatch = event.getTag() == expectedTag;
+            if (!tagMatch) return false;
+
+            Object[] payload = (Object[]) event.getData();
+            boolean payloadMatch = Arrays.equals(payload, expectedPayload);
+
+            if (!payloadMatch) {
+                Log.w(TAG, "Found event (id=" + event.getId() + ") with tag "
+                        + eventLogtoString(event.getTag()) + ", but invalid payload: "
+                        + "expected=" + Arrays.toString(expectedPayload)
+                        + ", actual=" + Arrays.toString(payload));
+            } else if (VERBOSE) {
+                Log.v(TAG, "Found event (id=" + event.getId() + ") with tag "
+                        + eventLogtoString(event.getTag()) + ", and expected payload ("
+                        + Arrays.toString(payload) + ")");
+            }
+            return payloadMatch;
+        };
     }
 
     private void generateUserRestrictionEvents() {
-        mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT,
-                UserManager.DISALLOW_PRINTING);
-        mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
-                UserManager.DISALLOW_PRINTING);
+        DevicePolicyManager dpm = getDpmToGenerateEvents();
+
+        dpm.addUserRestriction(ADMIN_RECEIVER_COMPONENT, UserManager.DISALLOW_PRINTING);
+        dpm.clearUserRestriction(ADMIN_RECEIVER_COMPONENT, UserManager.DISALLOW_PRINTING);
     }
 
     private void verifyUserRestrictionEventsPresent(List<SecurityEvent> events) {
@@ -798,8 +828,10 @@
     }
 
     private void generateCameraPolicyEvents() {
-        mDevicePolicyManager.setCameraDisabled(ADMIN_RECEIVER_COMPONENT, true);
-        mDevicePolicyManager.setCameraDisabled(ADMIN_RECEIVER_COMPONENT, false);
+        DevicePolicyManager dpm = getDpmToGenerateEvents();
+
+        dpm.setCameraDisabled(ADMIN_RECEIVER_COMPONENT, true);
+        dpm.setCameraDisabled(ADMIN_RECEIVER_COMPONENT, false);
     }
 
     private void verifyCameraPolicyEvents(List<SecurityEvent> events) {
@@ -821,4 +853,23 @@
                         getInt(e, TARGET_USER_INDEX) == userId &&
                         getInt(e, CAMERA_DISABLED_INDEX) == 0);
     }
+
+    private DevicePolicyManager getDpmToGenerateEvents() {
+        // It must use the dpm for the current user, as mDevicePolicyManager tunnels the calls to
+        // the device owner user on headless system user, which would cause a mismatch in the events
+        return mContext.getSystemService(DevicePolicyManager.class);
+    }
+
+    private static String eventLogtoString(int log) {
+        return DebugUtils.constantToString(SecurityLog.class, "TAG_", log);
+    }
+
+    private static String toString(SecurityEvent event) {
+        return "Event[id=" + event.getId() + ",tag=" + eventLogtoString(event.getTag()) + "]";
+    }
+
+    private void dumpSecurityLogs(List<SecurityEvent> events) {
+        Log.d(TAG, "Security events dump (" + events.size() + " events):");
+        events.forEach((event) -> Log.d(TAG, toString(event)));
+    }
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java
index 61f7645..54bd5d4 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java
@@ -94,6 +94,8 @@
             UserManager.DISALLOW_CREATE_WINDOWS,
             UserManager.DISALLOW_BLUETOOTH,
             // UserManager.DISALLOW_DATA_ROAMING, // Not set during CTS
+            UserManager.DISALLOW_CAMERA_TOGGLE,
+            UserManager.DISALLOW_MICROPHONE_TOGGLE,
 
             // PO can set them too, but when DO sets them, they're global.
             UserManager.DISALLOW_ADJUST_VOLUME,
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/PrimaryProfileOwnerUserRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/PrimaryProfileOwnerUserRestrictionsTest.java
index 340fc9b..113ac7a 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/PrimaryProfileOwnerUserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/PrimaryProfileOwnerUserRestrictionsTest.java
@@ -15,16 +15,63 @@
  */
 package com.android.cts.deviceandprofileowner.userrestrictions;
 
+import android.os.UserManager;
+
 public class PrimaryProfileOwnerUserRestrictionsTest extends BaseUserRestrictionsTest {
+    public static final String[] ALLOWED = new String[] {
+            // UserManager.DISALLOW_CONFIG_WIFI, // Has unrecoverable side effects.
+            UserManager.DISALLOW_MODIFY_ACCOUNTS,
+            UserManager.DISALLOW_INSTALL_APPS,
+            UserManager.DISALLOW_UNINSTALL_APPS,
+            // UserManager.DISALLOW_SHARE_LOCATION, // Has unrecoverable side effects.
+            // UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, // Has unrecoverable side effects.
+            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+            UserManager.DISALLOW_CONFIG_BLUETOOTH,
+            UserManager.DISALLOW_USB_FILE_TRANSFER,
+            UserManager.DISALLOW_CONFIG_CREDENTIALS,
+            UserManager.DISALLOW_REMOVE_USER,
+            // UserManager.DISALLOW_DEBUGGING_FEATURES, // Need for CTS
+            UserManager.DISALLOW_CONFIG_VPN,
+            UserManager.DISALLOW_CONFIG_TETHERING,
+            UserManager.DISALLOW_NETWORK_RESET,
+            UserManager.DISALLOW_FACTORY_RESET,
+            UserManager.DISALLOW_ADD_USER,
+            // UserManager.ENSURE_VERIFY_APPS, // Has unrecoverable side effects.
+            UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
+            UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
+            UserManager.DISALLOW_APPS_CONTROL,
+            UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
+            UserManager.DISALLOW_UNMUTE_MICROPHONE,
+            UserManager.DISALLOW_ADJUST_VOLUME,
+            UserManager.DISALLOW_OUTGOING_CALLS,
+            UserManager.DISALLOW_SMS,
+            UserManager.DISALLOW_FUN,
+            UserManager.DISALLOW_CREATE_WINDOWS,
+            UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
+            UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE,
+            UserManager.DISALLOW_OUTGOING_BEAM,
+            UserManager.DISALLOW_SAFE_BOOT,
+            UserManager.ALLOW_PARENT_PROFILE_APP_LINKING,
+            // UserManager.DISALLOW_DATA_ROAMING, // Has unrecoverable side effects.
+            UserManager.DISALLOW_SET_USER_ICON,
+            UserManager.DISALLOW_BLUETOOTH,
+            UserManager.DISALLOW_AUTOFILL,
+            UserManager.DISALLOW_CONTENT_CAPTURE,
+            UserManager.DISALLOW_CONTENT_SUGGESTIONS,
+            UserManager.DISALLOW_UNIFIED_PASSWORD,
+    };
+
+    public static final String[] DISALLOWED = new String[] {
+    };
+
     @Override
     protected String[] getAllowedRestrictions() {
-        // PO on user-0 can set DO user restrictions too. (for now?)
-        return DeviceOwnerUserRestrictionsTest.ALLOWED;
+        return ALLOWED;
     }
 
     @Override
     protected String[] getDisallowedRestrictions() {
-        return DeviceOwnerUserRestrictionsTest.DISALLOWED;
+        return DISALLOWED;
     }
 
     @Override
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiNetworkConfigurationWithoutFineLocationPermissionTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiNetworkConfigurationWithoutFineLocationPermissionTest.java
index 9189e50..2aad6f5 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiNetworkConfigurationWithoutFineLocationPermissionTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiNetworkConfigurationWithoutFineLocationPermissionTest.java
@@ -70,7 +70,7 @@
 
         try {
             List<WifiConfiguration> configs = mWifiManager.getCallerConfiguredNetworks();
-            assertWithMessage("configured networks").that(configs).hasSize(1);
+            assertWithMessage("configured networks").that(configs).isNotEmpty();
             assertWithMessage("SSID of configured networks").that(configs.get(0).SSID)
                     .isEqualTo('"' + NETWORK_SSID + '"');
         } finally {
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/proxy/BaseProxyTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/proxy/BaseProxyTest.java
index cd7c98e..5507a3e 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/proxy/BaseProxyTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/proxy/BaseProxyTest.java
@@ -16,10 +16,6 @@
 
 package com.android.cts.deviceowner.proxy;
 
-import java.net.Proxy;
-import java.util.ArrayList;
-import java.util.List;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -28,8 +24,12 @@
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.Log;
+
 import com.android.cts.deviceowner.BaseDeviceOwnerTest;
 
+import java.net.Proxy;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
@@ -80,7 +80,7 @@
    * Set the global proxy.
    */
   protected boolean setProxyAndWaitForBroadcast(ProxyInfo proxy) throws Exception {
-    Log.d(TAG, "Setting Proxy to " + proxy);
+    Log.d(TAG, "setProxyAndWaitForBroadcast(), setting Proxy to " + proxy);
     mDevicePolicyManager.setRecommendedGlobalProxy(getWho(), proxy);
     return mReceiver.waitForBroadcast();
   }
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java b/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java
index b9c5a9a..d994d21 100644
--- a/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java
+++ b/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java
@@ -15,7 +15,13 @@
  */
 package com.android.cts.launchertests;
 
-import static org.junit.Assert.assertNotEquals;
+import static android.os.Process.myUserHandle;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
 
 import android.app.Instrumentation;
 import android.content.BroadcastReceiver;
@@ -37,16 +43,19 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
-import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.test.AndroidTestCase;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.SystemUtil;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.IOException;
 import java.util.List;
 import java.util.concurrent.Semaphore;
@@ -56,7 +65,8 @@
 /**
  * Tests for LauncherApps service
  */
-public class LauncherAppsTests extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+public class LauncherAppsTests {
 
     private static final String TAG = LauncherAppsTests.class.getSimpleName();
 
@@ -88,6 +98,8 @@
     public static final int RESULT_FAIL = 2;
     public static final int RESULT_TIMEOUT = 3;
 
+    private Context mContext;
+    private UserManager mUserManager;
     private LauncherApps mLauncherApps;
     private UserHandle mUser;
     private Instrumentation mInstrumentation;
@@ -96,36 +108,36 @@
     private Result mResult;
     private Messenger mResultMessenger;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
+    @Before
+    public void setUp() throws Exception {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
         Bundle arguments = InstrumentationRegistry.getArguments();
-        Context context = mInstrumentation.getContext();
-        UserManager userManager = context.getSystemService(UserManager.class);
-        mUser = getUserHandleArgument(userManager, "testUser", arguments);
+        mContext = mInstrumentation.getContext();
+        mUserManager = mContext.getSystemService(UserManager.class);
+        mUser = getUserHandleArgument("testUser", arguments);
 
-        Log.d(TAG, "Running as user " + Process.myUserHandle() + " and checking for launcher on "
+        Log.d(TAG, "Running as user " + myUserHandle() + " and checking for launcher on "
                 + "user " + mUser);
-        mLauncherApps = context.getSystemService(LauncherApps.class);
+        mLauncherApps = mContext.getSystemService(LauncherApps.class);
 
         Intent intent = new Intent();
         intent.setComponent(new ComponentName("com.android.cts.launchertests.support",
                         "com.android.cts.launchertests.support.LauncherCallbackTestsService"));
 
         mConnection = new Connection();
-        context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+        mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
         mConnection.waitForService();
         mResult = new Result(Looper.getMainLooper());
         mResultMessenger = new Messenger(mResult);
     }
 
+    @Test
     public void testGetActivitiesForUserFails() throws Exception {
         expectSecurityException(() -> mLauncherApps.getActivityList(null, mUser),
                 "getActivities for non-profile user failed to throw exception");
     }
 
+    @Test
     public void testSimpleAppInstalledForUser() throws Exception {
         List<LauncherActivityInfo> activities =
                 mLauncherApps.getActivityList(null, mUser);
@@ -135,68 +147,75 @@
             if (activity.getComponentName().getPackageName().equals(
                     SIMPLE_APP_PACKAGE)) {
                 foundSimpleApp = true;
-                assertEquals(1.0f, activity.getLoadingProgress());
+                assertThat(activity.getLoadingProgress()).isWithin(1.0e-10f).of(1.0f);
             }
-            assertTrue(activity.getUser().equals(mUser));
+            assertThat(activity.getUser()).isEqualTo(mUser);
         }
-        assertTrue(foundSimpleApp);
+        assertThat(foundSimpleApp).isTrue();
 
         // Also make sure getApplicationInfo works too.
-        final ApplicationInfo ai =
+        ApplicationInfo ai =
                 mLauncherApps.getApplicationInfo(SIMPLE_APP_PACKAGE, /* flags= */ 0, mUser);
-        assertEquals(SIMPLE_APP_PACKAGE, ai.packageName);
-        assertEquals(mUser, UserHandle.getUserHandleForUid(ai.uid));
+        assertThat(ai.packageName).isEqualTo(SIMPLE_APP_PACKAGE);
+        assertThat(UserHandle.getUserHandleForUid(ai.uid)).isEqualTo(mUser);
     }
 
+    @Test
     public void testAccessPrimaryProfileFromManagedProfile() throws Exception {
-        assertTrue(mLauncherApps.getActivityList(null, mUser).isEmpty());
+        assertThat(mLauncherApps.getActivityList(null, mUser)).isEmpty();
 
         expectNameNotFoundException(
                 () -> mLauncherApps.getApplicationInfo(SIMPLE_APP_PACKAGE, /* flags= */ 0, mUser),
                 "get applicationInfo failed to throw name not found exception");
-        assertFalse(mLauncherApps.isPackageEnabled(SIMPLE_APP_PACKAGE, mUser));
+        assertThat(mLauncherApps.isPackageEnabled(SIMPLE_APP_PACKAGE, mUser)).isFalse();
 
-        final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.android.com/"));
-        assertNull(mLauncherApps.resolveActivity(intent, mUser));
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.android.com/"));
+        assertThat(mLauncherApps.resolveActivity(intent, mUser)).isNull();
     }
 
+    @Test
     public void testGetProfiles_fromMainProfile() {
-        final List<UserHandle> profiles = mLauncherApps.getProfiles();
-        assertEquals(2, profiles.size());
-        assertTrue(profiles.contains(android.os.Process.myUserHandle()));
-        assertEquals(getContext().getSystemService(UserManager.class).getUserProfiles(),
-                profiles);
+        List<UserHandle> profiles = mLauncherApps.getProfiles();
+        assertThat(profiles).hasSize(2);
+        assertThat(profiles).contains(myUserHandle());
+        assertThat(profiles).containsExactlyElementsIn(mUserManager.getUserProfiles());
     }
 
+    @Test
     public void testGetProfiles_fromManagedProfile() {
         final List<UserHandle> profiles = mLauncherApps.getProfiles();
-        assertEquals(1, profiles.size());
-        assertEquals(android.os.Process.myUserHandle(), profiles.get(0));
+        assertThat(profiles).containsExactly(myUserHandle());
     }
 
+    @Test
     public void testPackageAddedCallbackForUser() throws Throwable {
         int result = sendMessageToCallbacksService(MSG_CHECK_PACKAGE_ADDED,
                 mUser, SIMPLE_APP_PACKAGE);
-        assertEquals(RESULT_PASS, result);
+        assertThat(result).isEqualTo(RESULT_PASS);
     }
 
+    @Test
     public void testPackageRemovedCallbackForUser() throws Throwable {
         int result = sendMessageToCallbacksService(MSG_CHECK_PACKAGE_REMOVED,
                 mUser, SIMPLE_APP_PACKAGE);
-        assertEquals(RESULT_PASS, result);
+        assertThat(result).isEqualTo(RESULT_PASS);
     }
+
+    @Test
     public void testPackageChangedCallbackForUser() throws Throwable {
         int result = sendMessageToCallbacksService(MSG_CHECK_PACKAGE_CHANGED,
                 mUser, SIMPLE_APP_PACKAGE);
-        assertEquals(RESULT_PASS, result);
+        assertThat(result).isEqualTo(RESULT_PASS);
     }
 
+    @Test
     public void testNoPackageAddedCallbackForUser() throws Throwable {
         int result = sendMessageToCallbacksService(MSG_CHECK_NO_PACKAGE_ADDED,
                 mUser, SIMPLE_APP_PACKAGE);
-        assertEquals(RESULT_PASS, result);
+        assertThat(result).isEqualTo(RESULT_PASS);
     }
 
+    @Test
     public void testLaunchNonExportActivityFails() throws Exception {
         expectSecurityException(() -> mLauncherApps.startMainActivity(new ComponentName(
                 SIMPLE_APP_PACKAGE, SIMPLE_APP_PACKAGE + ".NonExportedActivity"),
@@ -204,6 +223,7 @@
                 "starting non-exported activity failed to throw exception");
     }
 
+    @Test
     public void testLaunchNonExportLauncherFails() throws Exception {
         expectSecurityException(() -> mLauncherApps.startMainActivity(new ComponentName(
                 SIMPLE_APP_PACKAGE, SIMPLE_APP_PACKAGE + ".NonLauncherActivity"),
@@ -211,26 +231,32 @@
                 "starting non-launcher activity failed to throw exception");
     }
 
+    @Test
     public void testLaunchMainActivity() throws Exception {
         ActivityLaunchedReceiver receiver = new ActivityLaunchedReceiver();
         IntentFilter filter = new IntentFilter();
         filter.addAction(ActivityLaunchedReceiver.ACTIVITY_LAUNCHED_ACTION);
-        mInstrumentation.getContext().registerReceiver(receiver, filter);
-        mLauncherApps.startMainActivity(new ComponentName(
-                SIMPLE_APP_PACKAGE,
-                SIMPLE_APP_PACKAGE + ".SimpleActivity"),
-                mUser, null, null);
-        assertEquals(RESULT_PASS, receiver.waitForActivity());
-        mInstrumentation.getContext().unregisterReceiver(receiver);
+        mContext.registerReceiver(receiver, filter);
+        ComponentName compName = new ComponentName(SIMPLE_APP_PACKAGE, SIMPLE_APP_PACKAGE
+                + ".SimpleActivity");
+        Log.i(TAG, "Launching " + compName.flattenToShortString() + " on user " + mUser);
+        mLauncherApps.startMainActivity(compName, mUser, null, null);
+        assertWithMessage("Activity %s launched for user %s", compName.flattenToShortString(),
+                mUser).that(receiver.waitForActivity()).isEqualTo(RESULT_PASS);
+        mContext.unregisterReceiver(receiver);
     }
 
+    @Test
     public void testReverseAccessNoThrow() throws Exception {
         // Trying to access the main profile from a managed profile -> shouldn't throw but
         // should just return false.
-        assertFalse(mLauncherApps.isPackageEnabled("android", mUser));
+        assertThat(mLauncherApps.isPackageEnabled("android", mUser)).isFalse();
     }
 
+    @Test
     public void testHasLauncherActivityAppHasAppDetailsActivityInjected() throws Exception {
+        assumeNotHeadlessSystemUserMode();
+
         // HasLauncherActivityApp is installed for duration of this test - make sure
         // it's present on the activity list, has the synthetic activity generated, and it's
         // enabled and exported
@@ -238,10 +264,13 @@
         assertActivityInjected(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE);
     }
 
+    @Test
     public void testGetSetSyntheticAppDetailsActivityEnabled() throws Exception {
+        assumeNotHeadlessSystemUserMode();
+
         disableLauncherActivity();
         assertActivityInjected(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE);
-        PackageManager pm = mInstrumentation.getContext().getPackageManager();
+        PackageManager pm = mContext.getPackageManager();
         try {
             pm.setSyntheticAppDetailsActivityEnabled(mContext.getPackageName(), false);
             fail("Should not able to change current app's app details activity state");
@@ -256,17 +285,17 @@
         }
         mInstrumentation.getUiAutomation().adoptShellPermissionIdentity();
         try {
-            assertTrue(
-                    pm.getSyntheticAppDetailsActivityEnabled(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE));
+            assertThat(pm.getSyntheticAppDetailsActivityEnabled(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE))
+                    .isTrue();
             // Disable app details activity and assert if the change is applied
             pm.setSyntheticAppDetailsActivityEnabled(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE, false);
-            assertFalse(
-                    pm.getSyntheticAppDetailsActivityEnabled(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE));
+            assertThat(pm.getSyntheticAppDetailsActivityEnabled(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE))
+                    .isFalse();
             assertInjectedActivityNotFound(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE);
             // Enable app details activity and assert if the change is applied
             pm.setSyntheticAppDetailsActivityEnabled(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE, true);
-            assertTrue(
-                    pm.getSyntheticAppDetailsActivityEnabled(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE));
+            assertThat(pm.getSyntheticAppDetailsActivityEnabled(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE))
+                    .isTrue();
             assertActivityInjected(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE);
         } finally {
             mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
@@ -274,22 +303,26 @@
     }
 
 
+    @Test
     public void testProfileOwnerLauncherActivityInjected() throws Exception {
         assertActivityInjected(MANAGED_PROFILE_PKG);
     }
 
+    @Test
     public void testNoLauncherActivityAppNotInjected() throws Exception {
         // NoLauncherActivityApp is installed for duration of this test - make sure
         // it's NOT present on the activity list
         assertInjectedActivityNotFound(NO_LAUNCHER_ACTIVITY_APP_PACKAGE);
     }
 
+    @Test
     public void testNoPermissionAppNotInjected() throws Exception {
         // NoPermissionApp is installed for duration of this test - make sure
         // it's NOT present on the activity list
         assertInjectedActivityNotFound(NO_PERMISSION_APP_PACKAGE);
     }
 
+    @Test
     public void testDoPoNoTestAppInjectedActivityFound() throws Exception {
         // HasLauncherActivityApp is installed for duration of this test - make sure
         // it's NOT present on the activity list For example, DO / PO mode won't show icons.
@@ -298,12 +331,16 @@
         assertInjectedActivityNotFound(HAS_LAUNCHER_ACTIVITY_APP_PACKAGE);
     }
 
+    @Test
     public void testProfileOwnerInjectedActivityNotFound() throws Exception {
         assertInjectedActivityNotFound(MANAGED_PROFILE_PKG);
     }
 
+    @Test
     public void testNoSystemAppHasSyntheticAppDetailsActivityInjected() throws Exception {
+        Log.d(TAG, "testNoSystemAppHasSyntheticAppDetailsActivityInjected() for user " + mUser);
         List<LauncherActivityInfo> activities = mLauncherApps.getActivityList(null, mUser);
+        logActivities(activities);
         for (LauncherActivityInfo activity : activities) {
             if (!activity.getUser().equals(mUser)) {
                 continue;
@@ -313,18 +350,18 @@
                     || ((appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
             if (isSystemApp) {
                 // make sure we haven't generated a synthetic app details activity for it
-                assertNotEquals("Found a system app that had a synthetic activity generated,"
-                        + " package name: " + activity.getComponentName().getPackageName()
-                        + "; activity name: " + activity.getName(),
-                        activity.getName(),
-                        SYNTHETIC_APP_DETAILS_ACTIVITY);
+                assertWithMessage("Found a system app that had a synthetic activity generated,"
+                        + " package name: %s; activity name: %s",
+                        activity.getComponentName().getPackageName(), activity.getName())
+                                .that(activity.getName())
+                                .isNotEqualTo(SYNTHETIC_APP_DETAILS_ACTIVITY);
             }
         }
     }
 
     private void disableLauncherActivity() throws IOException {
-        SystemUtil.runShellCommand(mInstrumentation,
-                "pm disable --user " + mUser.getIdentifier() + " " + LAUNCHER_ACTIVITY_COMPONENT);
+        runShellCommand("pm disable --user %d %s", mUser.getIdentifier(),
+                LAUNCHER_ACTIVITY_COMPONENT);
     }
 
     private void expectSecurityException(ExceptionRunnable action, String failMessage)
@@ -348,29 +385,38 @@
     }
 
     private void assertActivityInjected(String targetPackage) {
+        Log.d(TAG, "Getting activities for package " + targetPackage + " on user " + mUser);
         List<LauncherActivityInfo> activities = mLauncherApps.getActivityList(null, mUser);
+        logActivities(activities);
+
         boolean noLaunchableActivityAppFound = false;
         for (LauncherActivityInfo activity : activities) {
-            if (!activity.getUser().equals(mUser)) {
+            UserHandle user = activity.getUser();
+            if (!user.equals(mUser)) {
+                Log.w(TAG, "Skipping activity " + toString(activity) + " from user " + user);
                 continue;
             }
             ComponentName compName = activity.getComponentName();
             if (compName.getPackageName().equals(targetPackage)) {
                 noLaunchableActivityAppFound = true;
                 // make sure it points to the synthetic app details activity
-                assertEquals(SYNTHETIC_APP_DETAILS_ACTIVITY, activity.getName());
+                assertWithMessage("name of synthetic app").that(activity.getName())
+                        .isEqualTo(SYNTHETIC_APP_DETAILS_ACTIVITY);
                 // make sure it's both exported and enabled
                 try {
-                    PackageManager pm = mInstrumentation.getContext().getPackageManager();
-                    ActivityInfo ai = pm.getActivityInfo(compName, /*flags=*/ 0);
-                    assertTrue("Component " + compName + " is not enabled", ai.enabled);
-                    assertTrue("Component " + compName + " is not exported", ai.exported);
+                    PackageManager pm = mContext.getPackageManager();
+                    ActivityInfo ai = pm.getActivityInfo(compName, /* flags= */ 0);
+                    assertWithMessage("component %s enabled", compName.flattenToShortString())
+                            .that(ai.enabled).isTrue();
+                    assertWithMessage("component %s exported", compName.flattenToShortString())
+                            .that(ai.exported).isTrue();
                 } catch (NameNotFoundException e) {
-                    fail("Package " + compName.getPackageName() + " not found.");
+                    fail("Package " + compName.getPackageName() + " not found: " + e);
                 }
             }
         }
-        assertTrue(noLaunchableActivityAppFound);
+        assertWithMessage("user %s has no launchable activity for app %s", mUser, targetPackage)
+                .that(noLaunchableActivityAppFound).isTrue();
     }
 
     @FunctionalInterface
@@ -378,17 +424,16 @@
         void run() throws Exception;
     }
 
-    private UserHandle getUserHandleArgument(UserManager userManager, String key,
-            Bundle arguments) throws Exception {
+    private UserHandle getUserHandleArgument(String key, Bundle arguments) throws Exception {
         String serial = arguments.getString(key);
         if (serial == null) {
             return null;
         }
         int serialNo = Integer.parseInt(serial);
-        return userManager.getUserForSerialNumber(serialNo);
+        return mUserManager.getUserForSerialNumber(serialNo);
     }
 
-    private class Connection implements ServiceConnection {
+    private final class Connection implements ServiceConnection {
         private final Semaphore mSemaphore = new Semaphore(0);
 
         @Override
@@ -413,7 +458,7 @@
         }
     };
 
-    private static class Result extends Handler {
+    private static final class Result extends Handler {
 
         private final Semaphore mSemaphore = new Semaphore(0);
         public int result = 0;
@@ -443,7 +488,7 @@
         }
     }
 
-    public class ActivityLaunchedReceiver extends BroadcastReceiver {
+    public final class ActivityLaunchedReceiver extends BroadcastReceiver {
         public static final String ACTIVITY_LAUNCHED_ACTION =
                 "com.android.cts.launchertests.LauncherAppsTests.LAUNCHED_ACTION";
 
@@ -484,9 +529,7 @@
     private void assertInjectedActivityNotFound(String targetPackage) {
         Log.d(TAG, "Searching for package " + targetPackage + " on user " + mUser);
         List<LauncherActivityInfo> activities = mLauncherApps.getActivityList(null, mUser);
-        Log.d(TAG, "Got " + activities.size() + " activities: " + activities.stream()
-                .map((info) -> info.getComponentName().flattenToShortString())
-                .collect(Collectors.toList()));
+        logActivities(activities);
         for (LauncherActivityInfo activity : activities) {
             if (!activity.getUser().equals(mUser)) {
                 continue;
@@ -497,4 +540,28 @@
             }
         }
     }
+
+    private void logActivities(List<LauncherActivityInfo> activities) {
+        Log.d(TAG, "Got " + activities.size() + " activities: " + activities.stream()
+                .map((info) -> toString(info))
+                .collect(Collectors.toList()));
+    }
+
+    private void runShellCommand(String format, Object...args) throws IOException {
+        String command = String.format(format, args);
+        Log.i(TAG, "Running command: " + command);
+        String output = SystemUtil.runShellCommand(mInstrumentation, command);
+        Log.d(TAG, "Output: " + output);
+    }
+
+    private String toString(LauncherActivityInfo info) {
+        return info == null ? null : info.getComponentName().flattenToShortString();
+    }
+
+    private void assumeNotHeadlessSystemUserMode() {
+        // On headless system user mode, the current user is a profile owner, and hence
+        // the synthetic activity is not listed by LauncherApps.getActivityList()
+        assumeFalse("test skipped on headless system user mode",
+                UserManager.isHeadlessSystemUserMode());
+    }
 }
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileTest.java
index 83f19ff..1185ac5 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileTest.java
@@ -281,10 +281,9 @@
                 MANAGE_APP_OPS_MODES_PERMISSION,
                 UPDATE_APP_OPS_STATS_PERMISSION,
                 INTERACT_ACROSS_USERS_PERMISSION);
-        mAppOpsManager.setMode(
+        mAppOpsManager.setUidMode(
                 AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES),
                 getUidForPackageName(packageName, userHandle),
-                packageName,
                 mode);
         sUiAutomation.dropShellPermissionIdentity();
     }
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/Android.bp b/hostsidetests/devicepolicy/app/SimpleApp/Android.bp
index 3a822af..b73f38a 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/Android.bp
+++ b/hostsidetests/devicepolicy/app/SimpleApp/Android.bp
@@ -26,6 +26,7 @@
         "cts",
         "general-tests",
         "mts",
+        "sts",
     ],
     sdk_version: "current",
     // V4 signature required by Incremental installs
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 7832b6d..41a0a1c8 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -586,6 +586,8 @@
             testClassName = pkgName + testClassName;
         }
 
+        CLog.i("runDeviceTestsAsUser(): user=%d, pkg=%s class=%s, test=%s", userId, pkgName,
+                testClassName, testMethodName);
         runDeviceTests(
                 getDevice(),
                 RUNNER,
@@ -1214,12 +1216,6 @@
         return "true".equalsIgnoreCase(result);
     }
 
-    protected void ignoreOnHeadlessSystemUserMode(String reason)
-            throws DeviceNotAvailableException {
-        assumeFalse("Skipping test on headless system user mode. Reason: " + reason,
-                isHeadlessSystemUserMode());
-    }
-
     protected void assumeHeadlessSystemUserMode(String reason)
             throws DeviceNotAvailableException {
         assumeTrue("Skipping test on non-headless system user mode. Reason: " + reason,
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminFeaturesCheckerRule.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminFeaturesCheckerRule.java
index b66099e..084392d 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminFeaturesCheckerRule.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminFeaturesCheckerRule.java
@@ -67,10 +67,22 @@
 
                 String testName = description.getDisplayName();
 
-                if (description.getAnnotation(TemporaryIgnoreOnHeadlessSystemUserMode.class) != null
+                TemporaryIgnoreOnHeadlessSystemUserMode temporarilyIgnoredAnnotation = description
+                        .getAnnotation(TemporaryIgnoreOnHeadlessSystemUserMode.class);
+                if (temporarilyIgnoredAnnotation != null
                         && BaseDevicePolicyTest.isHeadlessSystemUserMode(testDevice)) {
                     throw new AssumptionViolatedException(
-                            "TEMPORARILY skipping " + testName + " on headless system user mode");
+                            "TEMPORARILY skipping " + testName + " on headless system user mode "
+                                    + "(reason: " + temporarilyIgnoredAnnotation.reason() + ")");
+                }
+
+                IgnoreOnHeadlessSystemUserMode ignoredAnnotation = description
+                        .getAnnotation(IgnoreOnHeadlessSystemUserMode.class);
+                if (ignoredAnnotation != null
+                        && BaseDevicePolicyTest.isHeadlessSystemUserMode(testDevice)) {
+                    throw new AssumptionViolatedException(
+                            "Skipping " + testName + " on headless system user mode (reason: "
+                                    + ignoredAnnotation.reason() + ")");
                 }
 
                 List<String> requiredFeatures = new ArrayList<>();
@@ -199,9 +211,6 @@
     /**
      * TODO(b/132260693): STOPSHIP - temporary annotation used on tests that haven't been fixed to
      * run on headless system user yet
-     *
-     * <p><b>NOTE:</b> if a test shouldn't run on headless system user mode in the long term, we'll
-     * need a separate {@code IgnoreOnHeadlessSystemUserMode} annotation
      */
     @Retention(RetentionPolicy.RUNTIME)
     @Target({ElementType.METHOD})
@@ -209,4 +218,13 @@
         String bugId();
         String reason();
     }
+
+    /**
+     * Annotation used on tests that cannot run on devices that use headless system user mode.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.METHOD})
+    public static @interface IgnoreOnHeadlessSystemUserMode {
+        String reason();
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index b7abcf9..41189af7 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -28,6 +28,7 @@
 import android.platform.test.annotations.RequiresDevice;
 import android.stats.devicepolicy.EventId;
 
+import com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.TemporaryIgnoreOnHeadlessSystemUserMode;
 import com.android.cts.devicepolicy.annotations.LockSettingsTest;
 import com.android.cts.devicepolicy.metrics.DevicePolicyEventLogVerifier;
 import com.android.cts.devicepolicy.metrics.DevicePolicyEventWrapper;
@@ -430,19 +431,20 @@
     }
 
     @Test
-    @FlakyTest(bugId = 187862351)
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "187862351", reason = "also failing on phones")
     public void testGrantOfSensorsRelatedPermissions() throws Exception {
         installAppPermissionAppAsUser();
         executeDeviceTestMethod(".PermissionsTest", "testSensorsRelatedPermissionsCannotBeGranted");
     }
 
-    @Test public void testDenyOfSensorsRelatedPermissions() throws Exception {
+    @Test
+    public void testDenyOfSensorsRelatedPermissions() throws Exception {
         installAppPermissionAppAsUser();
         executeDeviceTestMethod(".PermissionsTest", "testSensorsRelatedPermissionsCanBeDenied");
     }
 
     @Test
-    @FlakyTest(bugId = 187862351)
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "187862351", reason = "also failing on phones")
     public void testSensorsRelatedPermissionsNotGrantedViaPolicy() throws Exception {
         installAppPermissionAppAsUser();
         executeDeviceTestMethod(".PermissionsTest",
@@ -450,7 +452,7 @@
     }
 
     @Test
-    @FlakyTest(bugId = 187862351)
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "187862351", reason = "also failing on phones")
     public void testStateOfSensorsRelatedPermissionsCannotBeRead() throws Exception {
         installAppPermissionAppAsUser();
         executeDeviceTestMethod(".PermissionsTest",
@@ -1290,6 +1292,16 @@
     }
 
     @Test
+    public void testResetPasswordWithTokenLogged() throws Exception {
+        assertMetricsLogged(getDevice(), () -> {
+            runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".ResetPasswordWithTokenTest",
+                    "testChangePasswordWithToken", mUserId);
+        }, new DevicePolicyEventWrapper.Builder(EventId.RESET_PASSWORD_WITH_TOKEN_VALUE)
+                    .setAdminPackageName(DEVICE_ADMIN_PKG)
+                    .build());
+    }
+
+    @Test
     public void testPasswordSufficientInitially() throws Exception {
         executeDeviceTestClass(".PasswordSufficientInitiallyTest");
     }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 603db30..fcf7e76 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -101,15 +101,11 @@
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "185498043",
-            reason = "automotive doesn't have IProxyService")
     public void testProxyStaticProxyTest() throws Exception {
         executeDeviceOwnerTest("proxy.StaticProxyTest");
     }
 
     @Test
-    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "185498043",
-            reason = "automotive doesn't have IProxyService")
     public void testProxyPacProxyTest() throws Exception {
         executeDeviceOwnerTest("proxy.PacProxyTest");
     }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
index 96254f2..b3c1c92 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
@@ -24,6 +24,8 @@
 import android.platform.test.annotations.LargeTest;
 import android.stats.devicepolicy.EventId;
 
+import com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.IgnoreOnHeadlessSystemUserMode;
+import com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.TemporaryIgnoreOnHeadlessSystemUserMode;
 import com.android.cts.devicepolicy.metrics.DevicePolicyEventWrapper;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.log.LogUtil.CLog;
@@ -307,7 +309,6 @@
             // Generate various types of events on device side and check that they are logged.
             executeDeviceTestMethod(".SecurityLoggingTest", "testGenerateLogs");
             getDevice().executeShellCommand("whoami"); // Generate adb command securty event
-            getDevice().executeShellCommand("dpm force-security-logs");
             executeDeviceTestMethod(".SecurityLoggingTest", "testVerifyGeneratedLogs");
 
             // Reboot the device, so the security event ids are reset.
@@ -316,7 +317,6 @@
             // Verify event ids are consistent across a consecutive batch.
             for (int batchNumber = 0; batchNumber < 3; batchNumber++) {
                 generateTestSecurityLogs();
-                getDevice().executeShellCommand("dpm force-security-logs");
                 executeDeviceTestMethod(".SecurityLoggingTest", "testVerifyLogIds",
                         Collections.singletonMap(ARG_SECURITY_LOGGING_BATCH_NUMBER,
                                 Integer.toString(batchNumber)));
@@ -381,8 +381,7 @@
             executeDeviceTestMethod(".SecurityLoggingTest",
                     "testSetDelegateScope_delegationSecurityLogging");
 
-            runSecurityLoggingTests(DELEGATE_APP_PKG,
-                    ".SecurityLoggingDelegateTest");
+            runSecurityLoggingTests(DELEGATE_APP_PKG, ".SecurityLoggingDelegateTest");
         } finally {
             // Remove security logging delegate
             executeDeviceTestMethod(".SecurityLoggingTest",
@@ -409,22 +408,17 @@
 
     private void runSecurityLoggingTests(String packageName, String testClassName)
             throws Exception {
-        // Backup stay awake setting because testGenerateLogs() will turn it off.
-        final String stayAwake = getDevice().getSetting("global", "stay_on_while_plugged_in");
         try {
             // Turn logging on.
             runDeviceTestsAsUser(packageName, testClassName,
                     "testEnablingSecurityLogging", mUserId);
-            // Reboot to ensure ro.device_owner is set to true in logd and logging is on.
+            // Reboot to ensure ro.organization_owned is set to true in logd and logging is on.
             rebootAndWaitUntilReady();
             waitForUserUnlock(mUserId);
 
             // Generate various types of events on device side and check that they are logged.
-            runDeviceTestsAsUser(packageName, testClassName,
-                    "testGenerateLogs", mUserId);
-            getDevice().executeShellCommand("whoami"); // Generate adb command securty event
-            runDeviceTestsAsUser(packageName, testClassName,
-                    "testVerifyGeneratedLogs", mUserId);
+            runDeviceTestsAsUser(packageName, testClassName, "testGenerateLogs", mUserId);
+            runDeviceTestsAsUser(packageName, testClassName, "testVerifyGeneratedLogs", mUserId);
 
             // Immediately attempting to fetch events again should fail.
             runDeviceTestsAsUser(packageName, testClassName,
@@ -433,10 +427,6 @@
             // Turn logging off.
             runDeviceTestsAsUser(packageName, testClassName,
                     "testDisablingSecurityLogging", mUserId);
-            // Restore stay awake setting.
-            if (stayAwake != null) {
-                getDevice().setSetting("global", "stay_on_while_plugged_in", stayAwake);
-            }
         }
     }
 
@@ -482,18 +472,60 @@
     }
 
     @Override
+    @Test
+    @IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't launch activities")
     public void testSuspendPackage() throws Exception {
-        ignoreOnHeadlessSystemUserMode("headless system user doesn't launch activities");
         super.testSuspendPackage();
     }
 
     @Override
+    @Test
+    @IgnoreOnHeadlessSystemUserMode(reason = "Headless system user doesn't launch activities")
     public void testSuspendPackageWithPackageManager() throws Exception {
-        ignoreOnHeadlessSystemUserMode("headless system user doesn't launch activities");
         super.testSuspendPackageWithPackageManager();
     }
 
     @Override
+    @Test
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test makes"
+            + " sense as keys generated by DO wouldn't match keys checked by PO")
+    public void testKeyManagement() throws Exception {
+        super.testKeyManagement();
+    }
+
+    @Override
+    @Test
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test makes"
+            + " sense as keys generated by DO wouldn't match keys checked by PO")
+    public void testGenerateKeyPairLogged() throws Exception {
+        super.testGenerateKeyPairLogged();
+    }
+
+    @Override
+    @Test
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test makes"
+            + " sense as keys generated by DO wouldn't match keys checked by PO")
+    public void testDelegatedCertInstallerDirectly() throws Exception {
+        super.testDelegatedCertInstallerDirectly();
+    }
+
+    @Override
+    @Test
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test makes"
+            + " sense as keys generated by DO wouldn't match keys checked by PO")
+    public void testSetKeyGrant() throws Exception {
+        super.testSetKeyGrant();
+    }
+
+    @Override
+    @Test
+    @TemporaryIgnoreOnHeadlessSystemUserMode(bugId = "184197972", reason = "Not clear if test makes"
+            + " sense as keys generated by DO wouldn't match keys checked by PO")
+    public void testSetKeyPairCertificateLogged() throws Exception {
+        super.testSetKeyPairCertificateLogged();
+    }
+
+    @Override
     public void testApplicationHidden() throws Exception {
         if (isHeadlessSystemUserMode()) {
             // Must run on user 0 because the test has a broadcast receiver that listen to packages
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
index 01d720f..4c94a5d 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
@@ -22,7 +22,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import android.platform.test.annotations.FlakyTest;
@@ -236,14 +235,14 @@
         installAppAsUser(DELEGATE_APP_APK, mUserId);
         installAppAsUser(DEVICE_ADMIN_APK, mPrimaryUserId);
         try {
-            runDeviceTestsAsUser(DELEGATE_APP_PKG, ".WorkProfileSecurityLoggingDelegateTest",
+            runDeviceTestsAsUser(DELEGATE_APP_PKG, ".SecurityLoggingDelegateTest",
                     "testCannotAccessApis", mUserId);
             // Set security logging delegate
             runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".SecurityLoggingTest",
                     "testSetDelegateScope_delegationSecurityLogging", mUserId);
 
             testSecurityLoggingOnWorkProfile(DELEGATE_APP_PKG,
-                    ".WorkProfileSecurityLoggingDelegateTest");
+                    ".SecurityLoggingDelegateTest");
         } finally {
             // Remove security logging delegate
             runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".SecurityLoggingTest",
@@ -259,16 +258,14 @@
             // Turn logging on.
             runDeviceTestsAsUser(packageName, testClassName,
                     "testEnablingSecurityLogging", mUserId);
-            // Reboot to ensure ro.device_owner is set to true in logd and logging is on.
+            // Reboot to ensure ro.organization_owned is set to true in logd and logging is on.
             rebootAndWaitUntilReady();
             waitForUserUnlock(mUserId);
 
             // Generate various types of events on device side and check that they are logged.
-            runDeviceTestsAsUser(packageName, testClassName,
-                    "testGenerateLogs", mUserId);
-            getDevice().executeShellCommand("whoami"); // Generate adb command security event
-            runDeviceTestsAsUser(packageName, testClassName,
-                    "testVerifyGeneratedLogs", mUserId);
+            runDeviceTestsAsUser(packageName, testClassName, "testGenerateLogs", mUserId);
+            getDevice().executeShellCommand("whoami"); // Generate adb command securty event
+            runDeviceTestsAsUser(packageName, testClassName, "testVerifyGeneratedLogs", mUserId);
 
             // Immediately attempting to fetch events again should fail.
             runDeviceTestsAsUser(packageName, testClassName,
@@ -284,15 +281,6 @@
         }
     }
 
-    private void failToCreateUser() throws Exception {
-        String command ="pm create-user " + "TestUser_" + System.currentTimeMillis();
-        String commandOutput = getDevice().executeShellCommand(command);
-
-        String[] tokens = commandOutput.split("\\s+");
-        assertTrue(tokens.length > 0);
-        assertEquals("Error:", tokens[0]);
-    }
-
     @Test
     public void testSetTime() throws Exception {
         runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".TimeManagementTest", "testSetTime", mUserId);
diff --git a/hostsidetests/edi/Android.bp b/hostsidetests/edi/Android.bp
index 4544e6f..80a7cc6 100644
--- a/hostsidetests/edi/Android.bp
+++ b/hostsidetests/edi/Android.bp
@@ -33,4 +33,7 @@
     static_libs: [
         "compat-classpaths-testing",
     ],
+    data: [
+        ":ClasspathDeviceInfoHelperApp",
+    ],
 }
diff --git a/hostsidetests/edi/AndroidTest.xml b/hostsidetests/edi/AndroidTest.xml
index acd6b57..c39246f 100644
--- a/hostsidetests/edi/AndroidTest.xml
+++ b/hostsidetests/edi/AndroidTest.xml
@@ -20,6 +20,10 @@
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="ClasspathDeviceInfoHelperApp.apk" />
+    </target_preparer>
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsEdiHostTestCases.jar" />
     </test>
diff --git a/hostsidetests/edi/apps/classpath/Android.bp b/hostsidetests/edi/apps/classpath/Android.bp
new file mode 100644
index 0000000..3b1626e
--- /dev/null
+++ b/hostsidetests/edi/apps/classpath/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+    name: "ClasspathDeviceInfoHelperApp",
+    defaults: ["cts_defaults"],
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.core",
+        "guava",
+    ],
+    srcs: ["src/**/*.java"],
+    sdk_version: "test_current",
+}
diff --git a/hostsidetests/edi/apps/classpath/AndroidManifest.xml b/hostsidetests/edi/apps/classpath/AndroidManifest.xml
new file mode 100644
index 0000000..88cb689
--- /dev/null
+++ b/hostsidetests/edi/apps/classpath/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?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.edi.cts.apps.classpath"
+          android:targetSandboxVersion="2">
+
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" />
+
+    <application android:requestLegacyExternalStorage="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.edi.cts.apps.classpath" />
+
+</manifest>
diff --git a/hostsidetests/edi/apps/classpath/src/android/edi/cts/apps/classpath/ClasspathDeviceTest.java b/hostsidetests/edi/apps/classpath/src/android/edi/cts/apps/classpath/ClasspathDeviceTest.java
new file mode 100644
index 0000000..93532aa
--- /dev/null
+++ b/hostsidetests/edi/apps/classpath/src/android/edi/cts/apps/classpath/ClasspathDeviceTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.edi.cts.apps.classpath;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.SharedLibraryInfo;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Device-side helper app for ClasspathDeviceInfo.
+ *
+ * <p>It is not technically a test as it simply collects information, but it simplifies the usage
+ * and communication with host-side ClasspathDeviceInfo.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ClasspathDeviceTest {
+
+    private static final String TAG = "ClasspathDeviceTest";
+
+    private final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+    private final Context context = instrumentation.getTargetContext();
+
+    @Before
+    public void before() {
+        instrumentation.getUiAutomation().adoptShellPermissionIdentity();
+    }
+
+    @After
+    public void after() {
+        instrumentation.getUiAutomation().dropShellPermissionIdentity();
+    }
+
+    /**
+     * Collects details about all shared libraries on the device and writes them to disk.
+     */
+    @Test
+    public void collectSharedLibraryPaths() throws Exception {
+        List<SharedLibraryInfo> sharedLibraries =
+                context.getPackageManager().getSharedLibraries(0);
+
+        ImmutableList.Builder<String> content = ImmutableList.builder();
+        for (SharedLibraryInfo sharedLibrary : sharedLibraries) {
+            content.add(String.format(Locale.US, "%s %d %d %s",
+                    sharedLibrary.getName(),
+                    sharedLibrary.getType(),
+                    sharedLibrary.getLongVersion(),
+                    String.join(" ", sharedLibrary.getAllCodePaths())));
+        }
+
+        Path detailsFilepath = new File("/sdcard/shared-libs.txt").toPath();
+        ImmutableList<String> lines = content.build();
+        Log.i(TAG, String.format("Writing details about %d shared libraries to %s",
+                lines.size(), detailsFilepath));
+        Files.write(detailsFilepath, lines);
+    }
+
+}
diff --git a/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java b/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java
index 202f407..8dc7b32 100644
--- a/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java
+++ b/hostsidetests/edi/src/android/edi/cts/ClasspathDeviceInfo.java
@@ -19,6 +19,9 @@
 import static android.compat.testing.Classpaths.ClasspathType.DEX2OATBOOTCLASSPATH;
 import static android.compat.testing.Classpaths.ClasspathType.SYSTEMSERVERCLASSPATH;
 
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import android.compat.testing.Classpaths;
 import android.compat.testing.Classpaths.ClasspathType;
 
@@ -30,8 +33,15 @@
 
 import org.jf.dexlib2.iface.ClassDef;
 
+/**
+ * Collects information about Java classes present in *CLASSPATH variables and Java shared libraries
+ * from the device.
+ */
 public class ClasspathDeviceInfo extends DeviceInfo {
 
+    private static final String HELPER_APP_PACKAGE = "android.edi.cts.apps.classpath";
+    private static final String HELPER_APP_CLASS = HELPER_APP_PACKAGE + ".ClasspathDeviceTest";
+
     private ITestDevice mDevice;
 
     @Override
@@ -40,16 +50,18 @@
 
         store.startArray("jars");
         collectBootclasspathJars(store);
+        collectSharedLibraryJars(store);
         store.endArray();
     }
 
     private void collectBootclasspathJars(HostInfoStore store) throws Exception {
-        collectJarInfo(store, BOOTCLASSPATH);
-        collectJarInfo(store, SYSTEMSERVERCLASSPATH);
-        collectJarInfo(store, DEX2OATBOOTCLASSPATH);
+        collectClasspathJarInfo(store, BOOTCLASSPATH);
+        collectClasspathJarInfo(store, SYSTEMSERVERCLASSPATH);
+        collectClasspathJarInfo(store, DEX2OATBOOTCLASSPATH);
     }
 
-    private void collectJarInfo(HostInfoStore store, ClasspathType classpath) throws Exception {
+    private void collectClasspathJarInfo(HostInfoStore store, ClasspathType classpath)
+            throws Exception {
         ImmutableList<String> paths = Classpaths.getJarsOnClasspath(mDevice, classpath);
         for (int i = 0; i < paths.size(); i++) {
             store.startGroup();
@@ -61,6 +73,44 @@
         }
     }
 
+    private void collectSharedLibraryJars(HostInfoStore store) throws Exception {
+        // Trigger helper app to collect and write info about shared libraries on the device.
+        assertThat(runDeviceTests(HELPER_APP_PACKAGE, HELPER_APP_CLASS)).isTrue();
+
+        String remoteFile = "/sdcard/shared-libs.txt";
+        String content;
+        try {
+            content = mDevice.pullFileContents(remoteFile);
+        } finally {
+            mDevice.deleteFile(remoteFile);
+        }
+
+        for (String line : content.split("\n")) {
+            String[] words = line.split(" ");
+            assertWithMessage(
+                    "expected each line to be in the format: <name> <type> <version> <path>...")
+                    .that(words.length)
+                    .isAtLeast(4);
+            String libraryName = words[0];
+            String libraryType = words[1];
+            String libraryVersion = words[2];
+            for (int i = 3; i < words.length; i++) {
+                String path = words[i];
+
+                store.startGroup();
+                store.startGroup("shared_library");
+                store.addResult("name", libraryName);
+                store.addResult("type", libraryType);
+                store.addResult("version", libraryVersion);
+                store.endGroup(); // shared_library
+                store.addResult("path", path);
+                store.addResult("index", i - 3); // minus <name> <type> <version>
+                collectClassInfo(store, path);
+                store.endGroup();
+            }
+        }
+    }
+
     private void collectClassInfo(HostInfoStore store, String path) throws Exception {
         store.startArray("classes");
         for (ClassDef classDef : Classpaths.getClassDefsFromJar(mDevice, path)) {
diff --git a/hostsidetests/incrementalinstall/OWNERS b/hostsidetests/incrementalinstall/OWNERS
index d16fb6c..49bed85 100644
--- a/hostsidetests/incrementalinstall/OWNERS
+++ b/hostsidetests/incrementalinstall/OWNERS
@@ -3,4 +3,5 @@
 alexbuy@google.com
 schfan@google.com
 toddke@google.com
+patb@google.com
 zyy@google.com
\ No newline at end of file
diff --git a/hostsidetests/install/app/src/android/cts/install/InstallTest.java b/hostsidetests/install/app/src/android/cts/install/InstallTest.java
index 5a5dd54..4d9d835 100644
--- a/hostsidetests/install/app/src/android/cts/install/InstallTest.java
+++ b/hostsidetests/install/app/src/android/cts/install/InstallTest.java
@@ -104,8 +104,17 @@
     @Test
     public void assert_commitFailure_phase() {
         Install install = getParameterizedInstall(VERSION_CODE_TARGET);
-        InstallUtils.commitExpectingFailure(IllegalArgumentException.class,
-                "APEX files can only be installed as part of a staged session.", install);
+        if (mEnableRollback) {
+            InstallUtils.commitExpectingFailure(IllegalArgumentException.class,
+                "Non-staged APEX session doesn't support INSTALL_ENABLE_ROLLBACK", install);
+        } else if (mInstallType.equals(INSTALL_TYPE.SINGLE_APEX)) {
+            InstallUtils.commitExpectingFailure(AssertionError.class,
+                "does not support non-staged update", install);
+        } else {
+            InstallUtils.commitExpectingFailure(AssertionError.class,
+                "Non-staged multi package install of APEX and APK packages is not supported",
+                install);
+        }
     }
 
     @Test
diff --git a/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
index 8c9ee7e..7dc17f4 100644
--- a/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
+++ b/hostsidetests/media/src/android/media/cts/MediaExtractorHostSideTest.java
@@ -17,7 +17,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.stats.mediametrics.Mediametrics;
+import android.stats.mediametrics_message.MediametricsMessage;
 
 import com.android.internal.os.StatsdConfigProto;
 import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
@@ -67,20 +67,20 @@
     public void testMediaMetricsEntryPointSdk() throws Exception {
         runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testEntryPointSdk");
         assertThat(getMediaExtractorReportedEntryPoint())
-                .isEqualTo(Mediametrics.ExtractorData.EntryPoint.SDK);
+                .isEqualTo(MediametricsMessage.ExtractorData.EntryPoint.SDK);
     }
 
     public void testMediaMetricsEntryPointNdkNoJvm() throws Exception {
         runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testEntryPointNdkNoJvm");
         assertThat(getMediaExtractorReportedEntryPoint())
-                .isEqualTo(Mediametrics.ExtractorData.EntryPoint.NDK_NO_JVM);
+                .isEqualTo(MediametricsMessage.ExtractorData.EntryPoint.NDK_NO_JVM);
     }
 
     public void testMediaMetricsEntryPointNdkWithJvm() throws Exception {
         runDeviceTests(
                 DEVICE_SIDE_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testEntryPointNdkWithJvm");
         assertThat(getMediaExtractorReportedEntryPoint())
-                .isEqualTo(Mediametrics.ExtractorData.EntryPoint.NDK_WITH_JVM);
+                .isEqualTo(MediametricsMessage.ExtractorData.EntryPoint.NDK_WITH_JVM);
     }
 
     public void testMediaMetricsLogSessionId() throws Exception {
@@ -144,7 +144,7 @@
      *
      * <p>Note: Calls {@link #getAndClearReportList()} to obtain the statsd report.
      */
-    private Mediametrics.ExtractorData.EntryPoint getMediaExtractorReportedEntryPoint()
+    private MediametricsMessage.ExtractorData.EntryPoint getMediaExtractorReportedEntryPoint()
             throws Exception {
         return getMediaExtractorReportedData().getEntryPoint();
     }
@@ -159,7 +159,7 @@
         return getMediaExtractorReportedData().getLogSessionId();
     }
 
-    private Mediametrics.ExtractorData getMediaExtractorReportedData() throws Exception {
+    private MediametricsMessage.ExtractorData getMediaExtractorReportedData() throws Exception {
         ConfigMetricsReportList reportList = getAndClearReportList();
         assertThat(reportList.getReportsCount()).isEqualTo(1);
         StatsLog.ConfigMetricsReport report = reportList.getReports(0);
diff --git a/hostsidetests/os/app/src/android/os/app/TestFgService.java b/hostsidetests/os/app/src/android/os/app/TestFgService.java
index e751d47..01d3f9d 100644
--- a/hostsidetests/os/app/src/android/os/app/TestFgService.java
+++ b/hostsidetests/os/app/src/android/os/app/TestFgService.java
@@ -42,7 +42,7 @@
                 .setContentTitle("Foreground service")
                 .setContentText("Ongoing test app foreground service is live")
                 .setSmallIcon(NOTIFICATION_ID)
-                .setShowForegroundImmediately(true)
+                .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
                 .build();
 
         Log.i(TAG, "TestFgService starting foreground: pid=" + Process.myPid());
diff --git a/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/PackageInstallerV2StatsTests.java b/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/PackageInstallerV2StatsTests.java
index bcac138..3f604fb 100644
--- a/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/PackageInstallerV2StatsTests.java
+++ b/hostsidetests/packagemanager/stats/src/com/android/cts/packagemanager/stats/host/PackageInstallerV2StatsTests.java
@@ -114,7 +114,8 @@
                 AtomsProto.Atom.PACKAGE_INSTALLER_V2_REPORTED_FIELD_NUMBER);
         Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
         installPackageUsingIncremental(apkNames, TEST_REMOTE_DIR);
-        assertTrue(getDevice().isPackageInstalled(TEST_INSTALL_PACKAGE));
+        assertTrue(getDevice().isPackageInstalled(TEST_INSTALL_PACKAGE,
+                String.valueOf(getDevice().getCurrentUser())));
         Thread.sleep(AtomTestUtils.WAIT_TIME_SHORT);
 
         List<AtomsProto.PackageInstallerV2Reported> reports = new ArrayList<>();
@@ -135,7 +136,8 @@
             remoteApkPaths[i] = pushApkToRemote(apkNames[i], remoteDirPath);
         }
         String installResult = getDevice().executeShellCommand(
-                "pm install-incremental -t -g " + String.join(" ", remoteApkPaths));
+                "pm install-incremental -t -g " + "--user " + getDevice().getCurrentUser() + " "
+                        + String.join(" ", remoteApkPaths));
         assertEquals("Success\n", installResult);
     }
 
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 8f3022b..fbbb849 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -154,7 +154,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -1239,9 +1238,11 @@
                     getExifMetadataFromRawResource(R.raw.img_with_metadata);
             try (InputStream in =
                          getContext().getResources().openRawResource(R.raw.img_with_metadata);
-                 OutputStream out = new FileOutputStream(imgFile)) {
+                FileOutputStream out = new FileOutputStream(imgFile)) {
                 // Dump the image we have to external storage
                 FileUtils.copy(in, out);
+                // Sync file to disk to ensure file is fully written to the lower fs.
+                out.getFD().sync();
             }
             HashMap<String, String> exif = getExifMetadata(imgFile);
             assertExifMetadataMatch(exif, originalExif);
@@ -1258,11 +1259,17 @@
             // Revoke A_M_L and verify sensitive data redaction
             revokePermission(
                     APP_C.getPackageName(), Manifest.permission.ACCESS_MEDIA_LOCATION);
+            // revokePermission waits for permission status to be updated, but MediaProvider still
+            // needs to get permission change callback and clear its permission cache.
+            Thread.sleep(500);
             exifFromTestApp = readExifMetadataFromTestApp(APP_C, imgFile.getPath());
             assertExifMetadataMismatch(exifFromTestApp, originalExif);
 
             // Re-grant A_M_L and verify access to sensitive data
             grantPermission(APP_C.getPackageName(), Manifest.permission.ACCESS_MEDIA_LOCATION);
+            // grantPermission waits for permission status to be updated, but MediaProvider still
+            // needs to get permission change callback and clear its permission cache.
+            Thread.sleep(500);
             exifFromTestApp = readExifMetadataFromTestApp(APP_C, imgFile.getPath());
             assertExifMetadataMatch(exifFromTestApp, originalExif);
         } finally {
@@ -1353,6 +1360,9 @@
         } else {
             denyAppOpsToUid(uid, opstr);
         }
+        // revokePermission waits for permission status to be updated, but MediaProvider still
+        // needs to get permission change callback and clear its permission cache.
+        Thread.sleep(100);
         assertThat(canOpenFileAs(app, file, forWrite)).isFalse();
 
         // Grant
@@ -1361,6 +1371,9 @@
         } else {
             allowAppOpsToUid(uid, opstr);
         }
+        // grantPermission waits for permission status to be updated, but MediaProvider still
+        // needs to get permission change callback and clear its permission cache.
+        Thread.sleep(100);
         assertThat(canOpenFileAs(app, file, forWrite)).isTrue();
 
         // Deny
@@ -1369,6 +1382,9 @@
         } else {
             denyAppOpsToUid(uid, opstr);
         }
+        // revokePermission waits for permission status to be updated, but MediaProvider still
+        // needs to get permission change callback and clear its permission cache.
+        Thread.sleep(100);
         assertThat(canOpenFileAs(app, file, forWrite)).isFalse();
     }
 
diff --git a/hostsidetests/silentupdate/testapp/src/com/android/tests/silentupdate/SilentUpdateTests.java b/hostsidetests/silentupdate/testapp/src/com/android/tests/silentupdate/SilentUpdateTests.java
index da1d5ee..80821bc 100644
--- a/hostsidetests/silentupdate/testapp/src/com/android/tests/silentupdate/SilentUpdateTests.java
+++ b/hostsidetests/silentupdate/testapp/src/com/android/tests/silentupdate/SilentUpdateTests.java
@@ -142,7 +142,8 @@
                 .putLong("lastUpdateTime", lastUpdateTime)
                 .commit();
         commit(fileSupplier(
-                "/data/local/tmp/silentupdatetest/CtsSilentUpdateTestCases.apk"), false);
+                "/data/local/tmp/silentupdatetest/CtsSilentUpdateTestCases.apk"),
+                false /* requireUserAction */, true /* dontKillApp */);
     }
 
     @Test
@@ -217,7 +218,8 @@
 
     private int install(Supplier<InputStream> apkStreamSupplier, Boolean requireUserAction)
             throws Exception {
-        InstallStatusListener isl = commit(apkStreamSupplier, requireUserAction);
+        InstallStatusListener isl = commit(apkStreamSupplier, requireUserAction,
+                false /* dontKillApp */);
         final Intent statusUpdate = isl.getResult();
         final int result =
                 statusUpdate.getIntExtra(PackageInstaller.EXTRA_STATUS, Integer.MIN_VALUE);
@@ -230,7 +232,7 @@
     }
 
     private InstallStatusListener commit(Supplier<InputStream> apkStreamSupplier,
-            Boolean requireUserAction) throws IOException {
+            Boolean requireUserAction, boolean dontKillApp) throws IOException {
         final Context context = getContext();
         final PackageInstaller installer = context.getPackageManager().getPackageInstaller();
         SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
@@ -239,6 +241,7 @@
                     ? USER_ACTION_REQUIRED
                     : USER_ACTION_NOT_REQUIRED);
         }
+        params.setDontKillApp(dontKillApp);
         int sessionId = installer.createSession(params);
         Assert.assertEquals("SessionInfo.getRequireUserAction and "
                         + "SessionParams.setRequireUserAction are not equal",
diff --git a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
index 9ba9448..1e3759e5 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
@@ -511,17 +511,14 @@
 
     @Test
     public void testsFailsNonStagedApexInstall() throws Exception {
-        PackageInstaller installer = getPackageInstaller();
-        PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
-                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
-        params.setInstallAsApex();
-        try {
-            installer.createSession(params);
-            fail("IllegalArgumentException expected");
-        } catch (IllegalArgumentException expected) {
-            assertThat(expected.getMessage()).contains(
-                    "APEX files can only be installed as part of a staged session");
-        }
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
+        TestApp apex = new TestApp(
+                "Apex2", SHIM_APEX_PACKAGE_NAME, 2, /*isApex*/true,
+                "com.android.apex.cts.shim.v2.apex");
+        InstallUtils.commitExpectingFailure(AssertionError.class,
+                "does not support non-staged update",
+                Install.single(apex));
+        assertThat(getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
     }
 
     @Test
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/incremental/OWNERS b/hostsidetests/statsdatom/src/android/cts/statsdatom/incremental/OWNERS
index 3795493..3794ba0 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/incremental/OWNERS
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/incremental/OWNERS
@@ -2,4 +2,5 @@
 alexbuy@google.com
 schfan@google.com
 toddke@google.com
+patb@google.com
 zyy@google.com
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/ProcessDmabufMemoryTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/ProcessDmabufMemoryTests.java
new file mode 100644
index 0000000..25cb2f7
--- /dev/null
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/ProcessDmabufMemoryTests.java
@@ -0,0 +1,85 @@
+/*
+ * 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.cts.statsdatom.memory;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.cts.statsdatom.lib.AtomTestUtils;
+import android.cts.statsdatom.lib.ConfigUtils;
+import android.cts.statsdatom.lib.DeviceUtils;
+import android.cts.statsdatom.lib.ReportUtils;
+
+import com.android.compatibility.common.util.PropertyUtil;
+import com.android.os.AtomsProto;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.util.Pair;
+
+import java.util.List;
+
+public class ProcessDmabufMemoryTests extends DeviceTestCase implements IBuildReceiver {
+    private IBuildInfo mCtsBuild;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        assertThat(mCtsBuild).isNotNull();
+        ConfigUtils.removeConfig(getDevice());
+        ReportUtils.clearReports(getDevice());
+        DeviceUtils.installStatsdTestApp(getDevice(), mCtsBuild);
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        ConfigUtils.removeConfig(getDevice());
+        ReportUtils.clearReports(getDevice());
+        DeviceUtils.uninstallStatsdTestApp(getDevice());
+        super.tearDown();
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = buildInfo;
+    }
+
+    public void testProcessDmabufMemoryAtom() throws Exception {
+        boolean supportsFds = DeviceUtils.isKernelGreaterEqual(getDevice(), Pair.create(5, 4))
+                && PropertyUtil.getFirstApiLevel(getDevice()) > 30;
+
+        List<AtomsProto.Atom> atoms = pullAsGaugeMetric();
+        for (AtomsProto.Atom atom : atoms) {
+            AtomsProto.ProcessDmabufMemory stats = atom.getProcessDmabufMemory();
+            assertThat(stats.getProcessName()).isNotEmpty();
+            assertThat(stats.getMappedDmabufKb()).isAtLeast(0);
+            assertThat(stats.getMappedDmabufCount()).isAtLeast(0);
+            if (supportsFds) {
+                assertThat(stats.getRetainedDmabufKb()).isAtLeast(0);
+                assertThat(stats.getRetainedDmabufCount()).isAtLeast(0);
+            }
+        }
+    }
+
+    private List<AtomsProto.Atom> pullAsGaugeMetric() throws Exception {
+        ConfigUtils.uploadConfigForPulledAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
+                AtomsProto.Atom.PROCESS_DMABUF_MEMORY_FIELD_NUMBER);
+        AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice());
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+        return ReportUtils.getGaugeMetricAtoms(getDevice());
+    }
+}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/SystemMemoryStatsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/SystemMemoryStatsTests.java
index 2bffcc1..93fd221 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/SystemMemoryStatsTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/memory/SystemMemoryStatsTests.java
@@ -23,6 +23,7 @@
 import android.cts.statsdatom.lib.DeviceUtils;
 import android.cts.statsdatom.lib.ReportUtils;
 
+import com.android.compatibility.common.util.PropertyUtil;
 import com.android.os.AtomsProto;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.testtype.DeviceTestCase;
@@ -64,6 +65,9 @@
         assertThat(systemMemory.getVmallocUsedKb()).isAtLeast(0);
         assertThat(systemMemory.getPageTablesKb()).isAtLeast(0);
         assertThat(systemMemory.getKernelStackKb()).isAtLeast(0);
+        if (PropertyUtil.getFirstApiLevel(getDevice()) >= 30) {
+            assertThat(systemMemory.getTotalIonKb()).isAtLeast(0);
+        }
     }
 
     /** Returns SystemMemory atoms pulled as a simple gauge metric while test app is running. */
@@ -71,15 +75,8 @@
         // Get SystemMemory as a simple gauge metric.
         ConfigUtils.uploadConfigForPulledAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
                 AtomsProto.Atom.SYSTEM_MEMORY_FIELD_NUMBER);
-
-        // Start test app and trigger a pull while it is running.
-        try (AutoCloseable a = DeviceUtils.withActivity(getDevice(),
-                DeviceUtils.STATSD_ATOM_TEST_PKG, "StatsdCtsForegroundActivity", "action",
-                "action.show_notification")) {
-            AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice());
-            Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
-        }
-
+        AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice());
+        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
         return ReportUtils.getGaugeMetricAtoms(getDevice());
     }
 }
diff --git a/hostsidetests/wifibroadcasts/OWNERS b/hostsidetests/wifibroadcasts/OWNERS
index 7d9d0f9..a0ab9e6 100644
--- a/hostsidetests/wifibroadcasts/OWNERS
+++ b/hostsidetests/wifibroadcasts/OWNERS
@@ -1,4 +1,2 @@
 # Bug component: 33618
-dysu@google.com
-etancohen@google.com
-satk@google.com
+include platform/packages/modules/Wifi:/WIFI_OWNERS
diff --git a/libs/deviceutillegacy/src/android/webkit/cts/WebViewSyncLoader.java b/libs/deviceutillegacy/src/android/webkit/cts/WebViewSyncLoader.java
index 2b27b52..d856480 100644
--- a/libs/deviceutillegacy/src/android/webkit/cts/WebViewSyncLoader.java
+++ b/libs/deviceutillegacy/src/android/webkit/cts/WebViewSyncLoader.java
@@ -343,18 +343,29 @@
         class ExitLoopException extends RuntimeException {
         }
 
+        // Pumping messages only makes sense if the current thread is the one we're waiting on.
+        Assert.assertEquals("Waiting for a WebView event on the wrong thread",
+                Looper.myLooper(), mWebView.getHandler().getLooper());
+
         // Force loop to exit when processing this. Loop.quit() doesn't
         // work because this is the main Loop.
-        mWebView.getHandler().post(new Runnable() {
+        Runnable exitRunnable = new Runnable() {
             @Override
             public void run() {
                 throw new ExitLoopException(); // exit loop!
             }
-        });
+        };
+        mWebView.getHandler().post(exitRunnable);
         try {
             // Pump messages until our message gets through.
             Looper.loop();
         } catch (ExitLoopException e) {
+        } finally {
+            // If we're exiting the loop due to another task throwing an unrelated exception then we
+            // need to remove the Runnable we added; leaving it in the queue will crash the regular
+            // event loop if it gets to run. This is a no-op if it's already been removed from the
+            // queue.
+            mWebView.getHandler().removeCallbacks(exitRunnable);
         }
     }
 
diff --git a/libs/input/src/com/android/cts/input/HidLightTestData.java b/libs/input/src/com/android/cts/input/HidLightTestData.java
index 8a3bfb4..88227da 100644
--- a/libs/input/src/com/android/cts/input/HidLightTestData.java
+++ b/libs/input/src/com/android/cts/input/HidLightTestData.java
@@ -25,6 +25,9 @@
     // Light type
     public int lightType;
 
+    // Light capabilities
+    public int lightCapabilities;
+
     // Light color
     public int lightColor;
 
diff --git a/libs/input/src/com/android/cts/input/InputJsonParser.java b/libs/input/src/com/android/cts/input/InputJsonParser.java
index 35a5df0..ebcfa23 100644
--- a/libs/input/src/com/android/cts/input/InputJsonParser.java
+++ b/libs/input/src/com/android/cts/input/InputJsonParser.java
@@ -361,10 +361,13 @@
             HidLightTestData testData = new HidLightTestData();
             try {
                 JSONObject testcaseEntry = json.getJSONObject(testCaseNumber);
-                testData.lightType = lightTypeFromString(testcaseEntry.getString("lightType"));
-                testData.lightName = testcaseEntry.getString("lightName");
-                testData.lightColor = testcaseEntry.getInt("lightColor");
-                testData.lightPlayerId = testcaseEntry.getInt("lightPlayerId");
+                testData.lightType = lightTypeFromString(
+                    testcaseEntry.getString("type"));
+                testData.lightCapabilities = lightCapabilityFromString(
+                        testcaseEntry.getString("capabilities"));
+                testData.lightName = testcaseEntry.getString("name");
+                testData.lightColor = testcaseEntry.getInt("color");
+                testData.lightPlayerId = testcaseEntry.getInt("playerId");
                 testData.hidEventType = uhidEventFromString(
                         testcaseEntry.getString("hidEventType"));
                 testData.report = testcaseEntry.getString("report");
@@ -718,14 +721,34 @@
 
     private static int lightTypeFromString(String typeString) {
         switch (typeString.toUpperCase()) {
-            case "INPUT_SINGLE":
-                return Light.LIGHT_TYPE_INPUT_SINGLE;
-            case "INPUT_PLAYER_ID":
-                return Light.LIGHT_TYPE_INPUT_PLAYER_ID;
-            case "INPUT_RGB":
-                return Light.LIGHT_TYPE_INPUT_RGB;
+            case "INPUT":
+                return Light.LIGHT_TYPE_INPUT;
+            case "PLAYER_ID":
+                return Light.LIGHT_TYPE_PLAYER_ID;
+            default:
+                throw new RuntimeException("Unknown light type specified: " + typeString);
         }
-        throw new RuntimeException("Unknown light type specified: " + typeString);
+    }
+
+    private static int lightCapabilityFromString(String capString) {
+        int capabilities = 0;
+        final String[] entries = capString.split("\\|");
+        for (final String entry : entries) {
+            final String trimmedEntry = entry.trim();
+            switch (trimmedEntry.toUpperCase()) {
+                case "BRIGHTNESS":
+                    capabilities |= Light.LIGHT_CAPABILITY_BRIGHTNESS;
+                    break;
+                case "RGB":
+                    capabilities |= Light.LIGHT_CAPABILITY_RGB;
+                    break;
+                case "NONE":
+                    break;
+                default:
+                    throw new RuntimeException("Unknown capability specified: " + capString);
+            }
+        }
+        return capabilities;
     }
 
     // Return the enum uhid_event_type in kernel linux/uhid.h.
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
index f0fc793..784fad4 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/ExactAlarmsTest.java
@@ -30,13 +30,16 @@
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.PowerWhitelistManager;
 import android.os.Process;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.platform.test.annotations.AppModeFull;
 import android.provider.Settings;
 import android.util.Log;
@@ -47,7 +50,9 @@
 import com.android.compatibility.common.util.AppOpsUtils;
 import com.android.compatibility.common.util.AppStandbyUtils;
 import com.android.compatibility.common.util.FeatureUtil;
+import com.android.compatibility.common.util.ShellUtils;
 import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.TestUtils;
 
 import org.junit.After;
 import org.junit.Before;
@@ -59,6 +64,8 @@
 
 import java.io.IOException;
 import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 @AppModeFull
 @RunWith(AndroidJUnit4.class)
@@ -410,4 +417,65 @@
                 + Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM, pm.resolveActivity(request, 0));
     }
 
+    /**
+     * Check if a given UID is in the "can start FGS" allowlist.
+     */
+    private boolean checkThisAppTempAllowListed(int uid) {
+        // The allowlist used internally is ActivityManagerService.mFgsStartTempAllowList. We
+        // don't use the device-idle allowlist directly.
+
+        // Run "dumpsys activity processes", and remove everything until "mFgsStartTempAllowList:".
+        String output = ShellUtils.runShellCommand("dumpsys activity processes");
+        output = output.replaceFirst("^.*? mFgsStartTempAllowList:$", "");
+
+        final String uidStr = UserHandle.formatUid(uid);
+        final String expected = "^\\s*" + uidStr
+                + ":.* reasonCode=REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED.*";
+        for (String line : output.split("\n")) {
+            if (line.matches(expected)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Test
+    public void testActionScheduleExactAlarmPermissionStateChanged() throws Exception {
+        // Revoke the permission.
+        revokeAppOp();
+
+        final int myUid = Process.myUid();
+
+        // Because prior tests may already put the app on the temp allowlist, wait until
+        // it's removed from it...
+        // TODO(b/188789296) We should use `cmd deviceidle tempwhitelist -r PACKAGE-NAME`, but
+        //  it currently doesn't work.
+        TestUtils.waitUntil("App still on temp-allowlist", 60,
+                () -> !checkThisAppTempAllowListed(myUid));
+
+        final IntentFilter filter = new IntentFilter(
+                AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED);
+        final CountDownLatch latch = new CountDownLatch(1);
+        sContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                latch.countDown();
+            }
+        }, filter);
+
+        // Grant again.
+        AppOpsUtils.setOpMode(sContext.getOpPackageName(), AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM,
+                AppOpsManager.MODE_ALLOWED);
+
+        assertTrue("Didn't receive ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED",
+                latch.await(30, TimeUnit.SECONDS));
+
+        // We really should try starting a foreground service to make sure the app is
+        // allowed to start an FGS here, but when an app is running on `am instrument`, it's always
+        // exempted anyway, so we can't do that. Instead, we just check the dumpsys output.
+        //
+        // TODO(b/188790230): Use the test app instead, and make sure the app can actually start
+        // the FGS.
+        assertTrue("App should be temp-allowlisted", checkThisAppTempAllowListed(myUid));
+    }
 }
diff --git a/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java b/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java
index ed2495d..e786076 100644
--- a/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java
+++ b/tests/MediaProviderTranscode/src/android/mediaprovidertranscode/cts/TranscodeTest.java
@@ -906,23 +906,12 @@
             // Trigger transcoding so that the transcoded file gets added to cache.
             assertTranscode(modernFile, true);
 
-            // To make the cache clearing logic easier to verify, ignore any cache reserved space.
-            executeShellCommand("settings put global sys_storage_cache_max_bytes 0");
-            // Invoke StorageManager to free maximum allocatable bytes, so that it tries to clear
-            // all available caches.
-            StorageManager storageManager = getContext().getSystemService(StorageManager.class);
-            StorageVolume vol = storageManager.getStorageVolume(modernFile);
-            UUID uuid = vol.getStorageUuid();
-            try {
-                // The storage allocation for requested bytes may succeed or fail, but we don't
-                // care as long as the cache clearing gets invoked. Hence we swallow the exception
-                // for failure case, and allow the test execution to continue.
-                storageManager.allocateBytes(uuid, storageManager.getAllocatableBytes(uuid));
-            } catch (IOException e) {}
-            finally {
-                // Assert that transcoding happens again, i.e., transcoding cache was cleared.
-                assertTranscode(modernFile, true);
-            }
+            // Invoke PackageManager to free a huge amount of storage, so that it tries to clear all
+            // available caches.
+            executeShellCommand("pm trim-caches 4096G");
+
+            // Assert that transcoding happens again, i.e., transcoding cache was cleared.
+            assertTranscode(modernFile, true);
         } finally {
             modernFile.delete();
         }
diff --git a/tests/accessibilityservice/res/values/strings.xml b/tests/accessibilityservice/res/values/strings.xml
index 747ce54..dd59c0b 100644
--- a/tests/accessibilityservice/res/values/strings.xml
+++ b/tests/accessibilityservice/res/values/strings.xml
@@ -32,7 +32,7 @@
     <string name="text_input_blah_blah">Blah blah</string>
 
     <!-- String title of the button -->
-    <string name="button_title">Click me</string>
+    <string name="button_title">Click</string>
 
     <string name="button_tooltip">Never press this button</string>
 
diff --git a/tests/app/ActivityManagerApi29Test/Android.bp b/tests/app/ActivityManagerApi29Test/Android.bp
index 5418a8c..c1cf276 100644
--- a/tests/app/ActivityManagerApi29Test/Android.bp
+++ b/tests/app/ActivityManagerApi29Test/Android.bp
@@ -24,6 +24,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     sdk_version: "current",
 }
diff --git a/tests/app/Android.bp b/tests/app/Android.bp
index b3e421b..9fb2860 100644
--- a/tests/app/Android.bp
+++ b/tests/app/Android.bp
@@ -47,6 +47,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts"
     ],
     instrumentation_for: "CtsAppTestStubs",
     sdk_version: "test_current",
diff --git a/tests/app/BadProviderStubs/Android.bp b/tests/app/BadProviderStubs/Android.bp
index 1c4fca0..6f3c010 100644
--- a/tests/app/BadProviderStubs/Android.bp
+++ b/tests/app/BadProviderStubs/Android.bp
@@ -27,6 +27,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     optimize: {
         enabled: false,
diff --git a/tests/app/CantSaveState1/Android.bp b/tests/app/CantSaveState1/Android.bp
index 9173cd9..22a3d21 100644
--- a/tests/app/CantSaveState1/Android.bp
+++ b/tests/app/CantSaveState1/Android.bp
@@ -24,6 +24,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     sdk_version: "current",
 }
diff --git a/tests/app/CantSaveState2/Android.bp b/tests/app/CantSaveState2/Android.bp
index 6e812af..4c461af 100644
--- a/tests/app/CantSaveState2/Android.bp
+++ b/tests/app/CantSaveState2/Android.bp
@@ -24,6 +24,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     sdk_version: "current",
 }
diff --git a/tests/app/NotificationDelegator/Android.bp b/tests/app/NotificationDelegator/Android.bp
index 314742c..f4fbdd3 100644
--- a/tests/app/NotificationDelegator/Android.bp
+++ b/tests/app/NotificationDelegator/Android.bp
@@ -24,6 +24,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     sdk_version: "current",
 }
diff --git a/tests/app/NotificationListener/Android.bp b/tests/app/NotificationListener/Android.bp
index 64b11f7..4c43e37 100644
--- a/tests/app/NotificationListener/Android.bp
+++ b/tests/app/NotificationListener/Android.bp
@@ -29,6 +29,7 @@
         "cts",
         "vts10",
         "general-tests",
+        "sts",
     ],
     libs: [
         "android.test.runner",
diff --git a/tests/app/NotificationProvider/Android.bp b/tests/app/NotificationProvider/Android.bp
index cb33762..4a9d084 100644
--- a/tests/app/NotificationProvider/Android.bp
+++ b/tests/app/NotificationProvider/Android.bp
@@ -25,6 +25,7 @@
         "cts",
         "vts10",
         "general-tests",
+        "sts",
     ],
     platform_apis: true,
     sdk_version: "current",
diff --git a/tests/app/NotificationTrampoline/Android.bp b/tests/app/NotificationTrampoline/Android.bp
index 0c2f481..83d7d18 100644
--- a/tests/app/NotificationTrampoline/Android.bp
+++ b/tests/app/NotificationTrampoline/Android.bp
@@ -26,6 +26,7 @@
         "cts",
         "vts10",
         "general-tests",
+        "sts",
     ],
     static_libs: [
         "NotificationTrampolineBase",
diff --git a/tests/app/NotificationTrampolineApi30/Android.bp b/tests/app/NotificationTrampolineApi30/Android.bp
index 2ef4fbe..1b64164 100644
--- a/tests/app/NotificationTrampolineApi30/Android.bp
+++ b/tests/app/NotificationTrampolineApi30/Android.bp
@@ -26,6 +26,7 @@
         "cts",
         "vts10",
         "general-tests",
+        "sts",
     ],
     static_libs: [
         "NotificationTrampolineBase",
diff --git a/tests/app/StorageDelegator/Android.bp b/tests/app/StorageDelegator/Android.bp
index 77273516..bd38958 100644
--- a/tests/app/StorageDelegator/Android.bp
+++ b/tests/app/StorageDelegator/Android.bp
@@ -30,5 +30,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
 }
diff --git a/tests/app/app/Android.bp b/tests/app/app/Android.bp
index 44c365c..d4594ed 100644
--- a/tests/app/app/Android.bp
+++ b/tests/app/app/Android.bp
@@ -45,6 +45,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     additional_manifests: ["ProviderAndroidManifest.xml"],
     platform_apis: true,
@@ -77,6 +78,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     platform_apis: true,
     aaptflags: [
@@ -111,6 +113,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     platform_apis: true,
     aaptflags: [
@@ -145,6 +148,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     platform_apis: true,
     aaptflags: [
@@ -179,6 +183,7 @@
     test_suites: [
         "cts",
         "general-tests",
+        "sts",
     ],
     platform_apis: true,
     target_sdk_version: "30",
diff --git a/tests/app/app/src/android/app/stubs/BubblesTestService.java b/tests/app/app/src/android/app/stubs/BubblesTestService.java
index a3bf4f7..98362a0 100644
--- a/tests/app/app/src/android/app/stubs/BubblesTestService.java
+++ b/tests/app/app/src/android/app/stubs/BubblesTestService.java
@@ -66,7 +66,7 @@
         Notification.Builder nb = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
                 .setContentTitle("foofoo")
                 .setContentIntent(pendingIntent)
-                .setShowForegroundImmediately(true)
+                .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
                 .setStyle(new Notification.MessagingStyle(person)
                         .setConversationTitle("Bubble Chat")
diff --git a/tests/app/app/src/android/app/stubs/CommandReceiver.java b/tests/app/app/src/android/app/stubs/CommandReceiver.java
index b618dcc..5e154f7 100644
--- a/tests/app/app/src/android/app/stubs/CommandReceiver.java
+++ b/tests/app/app/src/android/app/stubs/CommandReceiver.java
@@ -16,6 +16,7 @@
 
 package android.app.stubs;
 
+import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ForegroundServiceStartNotAllowedException;
 import android.app.PendingIntent;
@@ -59,6 +60,7 @@
     public static final int COMMAND_STOP_SERVICE = 19;
     public static final int COMMAND_START_FOREGROUND_SERVICE_STICKY = 20;
     public static final int COMMAND_STOP_FOREGROUND_SERVICE_STICKY = 21;
+    public static final int COMMAND_EMPTY = 22;
 
     public static final int RESULT_CHILD_PROCESS_STARTED = IBinder.FIRST_CALL_TRANSACTION;
     public static final int RESULT_CHILD_PROCESS_STOPPED = IBinder.FIRST_CALL_TRANSACTION + 1;
@@ -166,6 +168,8 @@
             case COMMAND_WAIT_FOR_CHILD_PROCESS_GONE:
                 doWaitForChildProcessGone(context, intent);
                 break;
+            case COMMAND_EMPTY:
+                break;
         }
     }
 
@@ -382,6 +386,15 @@
         context.sendOrderedBroadcast(intent, null);
     }
 
+    public static void sendCommandWithResultReceiver(Context context, int command,
+            String sourcePackage, String targetPackage, int flags, Bundle extras,
+            BroadcastReceiver resultReceiver) {
+        final Intent intent = makeIntent(command, sourcePackage, targetPackage, flags, extras);
+        Log.d(TAG, "Sending broadcast with result receiver " + intent);
+        context.sendOrderedBroadcast(intent, null, resultReceiver, null,
+                Activity.RESULT_OK, null, null);
+    }
+
     public static void sendCommandWithBroadcastOptions(Context context, int command,
             String sourcePackage, String targetPackage, int flags, Bundle extras,
             Bundle broadcastOptions) {
diff --git a/tests/app/app/src/android/app/stubs/LocalForegroundService.java b/tests/app/app/src/android/app/stubs/LocalForegroundService.java
index 52a9b61..f255ac6 100644
--- a/tests/app/app/src/android/app/stubs/LocalForegroundService.java
+++ b/tests/app/app/src/android/app/stubs/LocalForegroundService.java
@@ -66,7 +66,7 @@
     }
 
     /** Returns the channel id for this service */
-    protected String getNotificationChannelId() {
+    public static String getNotificationChannelId() {
         return NOTIFICATION_CHANNEL_ID;
     }
 
diff --git a/tests/app/app/src/android/app/stubs/LocalForegroundServiceLocation.java b/tests/app/app/src/android/app/stubs/LocalForegroundServiceLocation.java
index a0f140e..2ec072e 100644
--- a/tests/app/app/src/android/app/stubs/LocalForegroundServiceLocation.java
+++ b/tests/app/app/src/android/app/stubs/LocalForegroundServiceLocation.java
@@ -39,8 +39,7 @@
     private int mNotificationId = 10;
 
     /** Returns the channel id for this service */
-    @Override
-    protected String getNotificationChannelId() {
+    public static String getNotificationChannelId() {
         return NOTIFICATION_CHANNEL_ID;
     }
 
diff --git a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
index 2d02bc6..09faefe 100644
--- a/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java
@@ -57,6 +57,7 @@
 import android.os.PowerExemptionManager;
 import android.os.SystemClock;
 import android.permission.cts.PermissionUtils;
+import android.platform.test.annotations.SecurityTest;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 
@@ -447,6 +448,7 @@
      * @throws Exception
      */
     @Test
+    @SecurityTest(minPatchLevel = "2021-03")
     public void testFgsLocationStartFromBGWithBind() throws Exception {
         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                 PACKAGE_NAME_APP1, 0);
diff --git a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
index 35021cf..9c3a311 100644
--- a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
@@ -49,6 +49,7 @@
 import android.app.stubs.LocalForegroundServiceLocation;
 import android.app.stubs.LocalForegroundServiceSticky;
 import android.app.stubs.ScreenOnActivity;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -61,6 +62,7 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.permission.cts.PermissionUtils;
 import android.platform.test.annotations.Presubmit;
 import android.server.wm.WindowManagerState;
@@ -80,6 +82,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
 @RunWith(AndroidJUnit4.class)
@@ -98,6 +102,7 @@
 
     private static final int WAIT_TIME = 10000;
     private static final int WAITFOR_MSEC = 10000;
+    private static final int WAITFOR_ORDERED_BROADCAST_DRAINED = 60000;
     // A secondary test activity from another APK.
     static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp";
     static final String SIMPLE_SERVICE = ".SimpleService";
@@ -170,6 +175,7 @@
         CtsAppTestUtils.turnScreenOn(mInstrumentation, mContext);
         removeTestAppFromWhitelists();
         mAppCount = 0;
+        drainOrderedBroadcastQueue();
         // Make sure we are in Home screen before starting the test
         mInstrumentation.getUiAutomation().performGlobalAction(
                 AccessibilityService.GLOBAL_ACTION_HOME);
@@ -184,6 +190,24 @@
     }
 
     /**
+     * Drain the ordered broadcast queue, it'll be useful when the test runs in secondary user
+     * which is just created prior to the testing, the ordered broadcast queue could be clogged.
+     */
+    private void drainOrderedBroadcastQueue() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        final BroadcastReceiver receiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                latch.countDown();
+            }
+        };
+        CommandReceiver.sendCommandWithResultReceiver(mContext, CommandReceiver.COMMAND_EMPTY,
+                STUB_PACKAGE_NAME, STUB_PACKAGE_NAME, 0, null, receiver);
+        latch.await(WAITFOR_ORDERED_BROADCAST_DRAINED, TimeUnit.MILLISECONDS);
+        Log.i(TAG, "Ordered broadcast queue drained");
+    }
+
+    /**
      * Set up count app info objects and WatchUidRunners.
      */
     private void setupWatchers(int count) throws Exception {
@@ -474,6 +498,8 @@
         WatchUidRunner uidWatcher = new WatchUidRunner(mInstrumentation, appInfo.uid,
                 WAIT_TIME);
 
+        final int userId = UserHandle.getUserId(appInfo.uid);
+
         // First kill the process to start out in a stable state.
         mContext.stopService(serviceIntent);
         conn.bind();
@@ -493,7 +519,8 @@
         // And wait for the uid report to be gone.
         uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null);
 
-        String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny";
+        String cmd = "appops set --user " + userId + " "
+                + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny";
         String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         // This is a side-effect of the app op command.
@@ -501,7 +528,7 @@
         uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "NONE");
 
         // We don't want to wait for the uid to actually go idle, we can force it now.
-        cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
+        cmd = "am make-uid-idle --user " + userId + " " + SIMPLE_PACKAGE_NAME;
         result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         // Make sure app is not yet on whitelist
@@ -524,8 +551,8 @@
             }
 
             // Put app on temporary whitelist to see if this allows the service start.
-            cmd = String.format("cmd deviceidle tempwhitelist -d %d %s",
-                    TEMP_WHITELIST_DURATION_MS, SIMPLE_PACKAGE_NAME);
+            cmd = String.format("cmd deviceidle tempwhitelist -u %d -d %d %s",
+                    userId, TEMP_WHITELIST_DURATION_MS, SIMPLE_PACKAGE_NAME);
             result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
             // Try starting the service now that the app is whitelisted...  should work!
@@ -545,14 +572,14 @@
             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
 
             CtsAppTestUtils.executeShellCmd(mInstrumentation,
-                    "cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
+                    "cmd deviceidle tempwhitelist -u " + userId + " -r " + SIMPLE_PACKAGE_NAME);
 
             // Going off the temp whitelist causes a spurious proc state report...  that's
             // not ideal, but okay.
             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
 
             // We don't want to wait for the uid to actually go idle, we can force it now.
-            cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
+            cmd = "am make-uid-idle --user " + userId + " " + SIMPLE_PACKAGE_NAME;
             result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
@@ -593,7 +620,8 @@
 
             uidWatcher.finish();
 
-            cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow";
+            cmd = "appops set --user " + userId + " "
+                    + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow";
             result = SystemUtil.runShellCommand(mInstrumentation, cmd);
             cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
             result = SystemUtil.runShellCommand(mInstrumentation, cmd);
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
index e38c925..17cc8fd 100644
--- a/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -982,6 +982,9 @@
             SystemUtil.runShellCommand(mInstrumentation,
                     "cmd deviceidle whitelist +" + PACKAGE_NAME_APP1);
 
+            // Keep the device awake
+            toggleScreenOn(true);
+
             // Start an activity
             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
@@ -1104,6 +1107,9 @@
             SystemUtil.runShellCommand(mInstrumentation,
                     "cmd deviceidle whitelist +" + PACKAGE_NAME_APP3);
 
+            // Keep the device awake
+            toggleScreenOn(true);
+
             // Start an activity
             CommandReceiver.sendCommand(mTargetContext, CommandReceiver.COMMAND_START_ACTIVITY,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
@@ -1305,6 +1311,12 @@
             SystemUtil.runShellCommand(mInstrumentation,
                     "cmd deviceidle whitelist +" + PACKAGE_NAME_APP1);
 
+            // Override the memory pressure level, force it staying at normal.
+            SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set NORMAL");
+
+            // Keep the device awake
+            toggleScreenOn(true);
+
             latchHolder[0] = new CountDownLatch(1);
 
             // Start an activity
@@ -1425,6 +1437,9 @@
             // Kill all background processes
             SystemUtil.runShellCommand(mInstrumentation, "am kill-all");
 
+            // Override the memory pressure level, force it staying at normal.
+            SystemUtil.runShellCommand(mInstrumentation, "am memory-factor set NORMAL");
+
             List<String> lru;
             // Start a new isolated service once a time, and then check the lru list
             do {
@@ -1544,6 +1559,9 @@
             SystemUtil.runShellCommand(mInstrumentation,
                     "cmd deviceidle whitelist +" + PACKAGE_NAME_APP3);
 
+            // Keep the device awake
+            toggleScreenOn(true);
+
             // Start a FGS in app1
             final Bundle extras = new Bundle();
             countDownLatchHolder[0] = new CountDownLatch(1);
diff --git a/tests/app/src/android/app/cts/BadProviderTest.java b/tests/app/src/android/app/cts/BadProviderTest.java
index 17f6ae5..c9e8b40 100644
--- a/tests/app/src/android/app/cts/BadProviderTest.java
+++ b/tests/app/src/android/app/cts/BadProviderTest.java
@@ -43,7 +43,7 @@
 public class BadProviderTest {
     private static final String AUTHORITY = "com.android.cts.stubbad.badprovider";
     private static final String TEST_PACKAGE_NAME = "com.android.cts.stubbad";
-    private static final int WAIT_TIME = 2000;
+    private static final int WAIT_TIME = 5000;
 
     private Context mContext;
 
diff --git a/tests/app/src/android/app/cts/ServiceTest.java b/tests/app/src/android/app/cts/ServiceTest.java
index 4f27d66..c25d830 100644
--- a/tests/app/src/android/app/cts/ServiceTest.java
+++ b/tests/app/src/android/app/cts/ServiceTest.java
@@ -1182,14 +1182,8 @@
         waitForResultOrThrow(DELAY, "service to be destroyed");
     }
 
-    public void testForegroundService_deferredNotification() throws Exception {
-        mExpectedServiceState = STATE_START_1;
-        startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION);
-        waitForResultOrThrow(DELAY, "service to start with deferred notification");
-        assertNoNotification(1);
-
-        // Wait ten seconds
-        final long stopTime = SystemClock.uptimeMillis() + 10_000L;
+    private void waitMillis(long timeMillis) {
+        final long stopTime = SystemClock.uptimeMillis() + timeMillis;
         while (SystemClock.uptimeMillis() < stopTime) {
             try {
                 Thread.sleep(1000L);
@@ -1197,8 +1191,16 @@
                 /* ignore */
             }
         }
+    }
 
-        // And verify that the notification is now visible
+    public void testForegroundService_deferredNotification() throws Exception {
+        mExpectedServiceState = STATE_START_1;
+        startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION);
+        waitForResultOrThrow(DELAY, "service to start with deferred notification");
+        assertNoNotification(1);
+
+        // Wait ten seconds and verify that the notification is now visible
+        waitMillis(10_000L);
         assertNotification(1, LocalForegroundService.getNotificationTitle(1));
 
         mExpectedServiceState = STATE_DESTROY;
@@ -1206,6 +1208,92 @@
         waitForResultOrThrow(DELAY, "service to be destroyed");
     }
 
+    public void testForegroundService_deferredExistingNotification() throws Exception {
+        // First, post the notification outright as not-FGS-related
+        final NotificationManager nm = getNotificationManager();
+        final String channelId = LocalForegroundService.getNotificationChannelId();
+        nm.createNotificationChannel(new NotificationChannel(channelId, channelId,
+                NotificationManager.IMPORTANCE_DEFAULT));
+        Notification.Builder builder =
+                new Notification.Builder(mContext, channelId)
+                        .setContentTitle(LocalForegroundService.getNotificationTitle(1))
+                        .setSmallIcon(R.drawable.black);
+        nm.notify(1, builder.build());
+
+        mExpectedServiceState = STATE_START_1;
+        startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION);
+        waitForResultOrThrow(DELAY, "service to start with existing notification");
+
+        // Normally deferred but should display immediately because the notification
+        // was already showing
+        assertNotification(1, LocalForegroundService.getNotificationTitle(1));
+
+        mExpectedServiceState = STATE_DESTROY;
+        mContext.stopService(mLocalForegroundService);
+        waitForResultOrThrow(DELAY, "service to be destroyed");
+    }
+
+    public void testForegroundService_deferThenImmediateNotify() throws Exception {
+        final String notificationTitle = "deferThenImmediateNotify";
+
+        mExpectedServiceState = STATE_START_1;
+        startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION);
+        waitForResultOrThrow(DELAY, "service to start with deferred notification");
+        assertNoNotification(1);
+
+        // Explicitly post a new Notification with the same id, still deferrable
+        final NotificationManager nm = getNotificationManager();
+        final String channelId = LocalForegroundService.getNotificationChannelId();
+        nm.createNotificationChannel(new NotificationChannel(channelId, channelId,
+                NotificationManager.IMPORTANCE_DEFAULT));
+        Notification.Builder builder =
+                new Notification.Builder(mContext, channelId)
+                        .setContentTitle(notificationTitle)
+                        .setSmallIcon(R.drawable.black)
+                        .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE);
+        nm.notify(1, builder.build());
+
+        // Verify that the notification is immediately shown with the new content
+        assertNotification(1, notificationTitle);
+
+        mExpectedServiceState = STATE_DESTROY;
+        mContext.stopService(mLocalForegroundService);
+        waitForResultOrThrow(DELAY, "service to be destroyed");
+    }
+
+    public void testForegroundService_deferThenDeferrableNotify() throws Exception {
+        final String notificationTitle = "deferThenDeferrableNotify";
+
+        mExpectedServiceState = STATE_START_1;
+        startForegroundService(COMMAND_START_FOREGROUND_DEFER_NOTIFICATION);
+        waitForResultOrThrow(DELAY, "service to start with deferred notification");
+        assertNoNotification(1);
+
+        // Explicitly post a new Notification with the same id, still deferrable
+        final NotificationManager nm = getNotificationManager();
+        final String channelId = LocalForegroundService.getNotificationChannelId();
+        nm.createNotificationChannel(new NotificationChannel(channelId, channelId,
+                NotificationManager.IMPORTANCE_DEFAULT));
+        Notification.Builder builder =
+                new Notification.Builder(mContext, channelId)
+                        .setContentTitle(notificationTitle)
+                        .setSmallIcon(R.drawable.black)
+                        .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_DEFERRED);
+        nm.notify(1, builder.build());
+
+        // Normally would have displayed, but should only have been taken as the eventual
+        // deferred notification.  Verify that it isn't shown yet, then re-verify after
+        // the ten second deferral period that it's both visible and has the correct
+        // (updated) title.
+        assertNoNotification(1);
+        waitMillis(10_000L);
+        assertNotification(1, notificationTitle);
+
+        mExpectedServiceState = STATE_DESTROY;
+        mContext.stopService(mLocalForegroundService);
+        waitForResultOrThrow(DELAY, "service to be destroyed");
+    }
+
     class TestSendCallback implements PendingIntent.OnFinished {
         public volatile int result = -1;
 
diff --git a/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java b/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java
index 80c3225..00a4396 100644
--- a/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java
+++ b/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java
@@ -25,6 +25,7 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.RemoteException;
+import android.os.UserHandle;
 
 import androidx.test.InstrumentationRegistry;
 
@@ -49,6 +50,7 @@
     final Parcel mData;
     final ServiceConnectionHandler[] mConnections;
     final int mUid;
+    final int mUserId;
     final UidImportanceListener mUidForegroundListener;
     final UidImportanceListener mUidGoneListener;
     final WatchUidRunner mUidWatcher;
@@ -89,6 +91,7 @@
         ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
                 mServicePackage, 0);
         mUid = appInfo.uid;
+        mUserId = UserHandle.getUserId(mUid);
 
         mUidForegroundListener = new UidImportanceListener(mContext, appInfo.uid,
                 ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, mDefaultWaitTime);
@@ -105,7 +108,8 @@
     }
 
     public void denyBackgroundOp(long timeout) throws IOException {
-        String cmd = "appops set " + mServicePackage + " RUN_IN_BACKGROUND deny";
+        String cmd = "appops set --user " + mUserId + " "
+                + mServicePackage + " RUN_IN_BACKGROUND deny";
         String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         // This is a side-effect of the app op command.
@@ -114,18 +118,21 @@
     }
 
     public void allowBackgroundOp() throws IOException {
-        String cmd = "appops set " + mServicePackage + " RUN_IN_BACKGROUND allow";
+        String cmd = "appops set --user " + mUserId + " "
+                + mServicePackage + " RUN_IN_BACKGROUND allow";
         String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
     }
 
     /** The "battery restriction" forced app standby app-op */
     public void denyAnyInBackgroundOp() throws IOException {
-        String cmd = "appops set " + mServicePackage + " RUN_ANY_IN_BACKGROUND deny";
+        String cmd = "appops set --user " + mUserId + " "
+                + mServicePackage + " RUN_ANY_IN_BACKGROUND deny";
         String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
     }
 
     public void allowAnyInBackgroundOp() throws IOException {
-        String cmd = "appops set " + mServicePackage + " RUN_ANY_IN_BACKGROUND allow";
+        String cmd = "appops set --user " + mUserId + " "
+                + mServicePackage + " RUN_ANY_IN_BACKGROUND allow";
         String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
     }
 
@@ -145,17 +152,20 @@
     }
 
     public void tempWhitelist(long duration) throws IOException {
-        String cmd = "cmd deviceidle tempwhitelist -d " + duration + " " + mServicePackage;
+        String cmd = "cmd deviceidle tempwhitelist -u " + mUserId
+                + " -d " + duration + " " + mServicePackage;
         String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
     }
 
     public void removeFromTempWhitelist() throws IOException {
-        String cmd = "cmd deviceidle tempwhitelist -r " + mServicePackage;
+        String cmd = "cmd deviceidle tempwhitelist -u " + mUserId
+                + " -r " + mServicePackage;
         SystemUtil.runShellCommand(mInstrumentation, cmd);
     }
 
     public void setAppOpMode(String opStr, String mode) throws IOException {
-        String cmd = "cmd appops set " + mServicePackage + " " + opStr + "  " + mode;
+        String cmd = "cmd appops set --user " + mUserId + " "
+                + mServicePackage + " " + opStr + "  " + mode;
         SystemUtil.runShellCommand(mInstrumentation, cmd);
     }
 
diff --git a/tests/appsearch/src/com/android/cts/appsearch/app/AppSearchManagerCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/app/AppSearchManagerCtsTest.java
new file mode 100644
index 0000000..ce0ad76
--- /dev/null
+++ b/tests/appsearch/src/com/android/cts/appsearch/app/AppSearchManagerCtsTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.app.appsearch.AppSearchManager;
+
+import org.junit.Test;
+
+public class AppSearchManagerCtsTest {
+    @Test
+    public void testSearchContext_databaseName() {
+        AppSearchManager.SearchContext searchContext =
+                new AppSearchManager.SearchContext.Builder(/*databaseName=*/"dbName")
+                        .build();
+
+        assertThat(searchContext.getDatabaseName()).isEqualTo("dbName");
+    }
+
+    @Test
+    public void testSearchContext_withInvalidDatabaseName() {
+        IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
+                () -> new AppSearchManager.SearchContext.Builder(
+                        "testDatabaseNameEndWith/").build());
+        assertThat(e).hasMessageThat().isEqualTo("Database name cannot contain '/'");
+    }
+}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java
index 65b006b..bc7f271 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/external/app/AppSearchSchemaCtsTest.java
@@ -269,4 +269,54 @@
                                 .shouldIndexNestedProperties())
                 .isEqualTo(true);
     }
+
+    @Test
+    public void testInvalidStringPropertyConfigsTokenizerNone() {
+        // Everything should work fine with the defaults.
+        final StringPropertyConfig.Builder builder = new StringPropertyConfig.Builder("property");
+        assertThat(builder.build()).isNotNull();
+
+        // Setting an indexing type other NONE with the default tokenizer type (NONE) should fail.
+        builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS);
+        expectThrows(IllegalStateException.class, () -> builder.build());
+
+        builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES);
+        expectThrows(IllegalStateException.class, () -> builder.build());
+
+        // Explicitly setting the default should work fine.
+        builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_NONE);
+        assertThat(builder.build()).isNotNull();
+
+        // Explicitly setting the default tokenizer type should result in the same behavior.
+        builder.setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_NONE)
+                .setIndexingType(StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS);
+        expectThrows(IllegalStateException.class, () -> builder.build());
+
+        builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES);
+        expectThrows(IllegalStateException.class, () -> builder.build());
+
+        builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_NONE);
+        assertThat(builder.build()).isNotNull();
+    }
+
+    @Test
+    public void testInvalidStringPropertyConfigsTokenizerPlain() {
+        // Setting indexing type to be NONE with tokenizer type PLAIN should fail. Regardless of
+        // whether NONE is set explicitly or just kept as default.
+        final StringPropertyConfig.Builder builder =
+                new StringPropertyConfig.Builder("property")
+                        .setTokenizerType(StringPropertyConfig.TOKENIZER_TYPE_PLAIN);
+        expectThrows(IllegalStateException.class, () -> builder.build());
+
+        builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_NONE);
+        expectThrows(IllegalStateException.class, () -> builder.build());
+
+        // Setting indexing type to be something other than NONE with tokenizer type PLAIN should
+        // be just fine.
+        builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS);
+        assertThat(builder.build()).isNotNull();
+
+        builder.setIndexingType(StringPropertyConfig.INDEXING_TYPE_PREFIXES);
+        assertThat(builder.build()).isNotNull();
+    }
 }
diff --git a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
index c88974e..491a81b 100644
--- a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
@@ -26,6 +26,7 @@
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.DngCreator;
@@ -35,10 +36,12 @@
 import android.hardware.camera2.cts.rs.RawConverter;
 import android.hardware.camera2.cts.rs.RenderScriptSingleton;
 import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.hardware.camera2.params.InputConfiguration;
 import android.location.Location;
 import android.media.ExifInterface;
 import android.media.Image;
 import android.media.ImageReader;
+import android.media.ImageWriter;
 import android.os.ConditionVariable;
 import android.os.SystemClock;
 import android.util.Log;
@@ -46,6 +49,8 @@
 import android.util.Size;
 import android.view.Surface;
 
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -81,6 +86,9 @@
     private static final double IMAGE_DIFFERENCE_TOLERANCE = 65;
     private static final int DEFAULT_PATCH_DIMEN = 512;
     private static final int AE_TIMEOUT_MS = 3000;
+    private static final int MAX_RESOLUTION_CAPTURE_WAIT_TIMEOUT_SCALE = 4;
+    private static final int MAX_RESOLUTION_CAPTURE_WAIT_TIMEOUT_MS =
+            CAPTURE_WAIT_TIMEOUT_MS * MAX_RESOLUTION_CAPTURE_WAIT_TIMEOUT_SCALE;
 
     // Constants used for GPS testing.
     private static final double GPS_DIFFERENCE_TOLERANCE = 0.0001;
@@ -105,6 +113,27 @@
         public CameraCharacteristics characteristics;
     }
 
+    // CapturedData for maximum resolution mode, raw and jpeg don't share the same capture result
+    // since mandatory streams for maximum resolution sensor pixel mode don't guarantee more than 1
+    // stream.
+    class CapturedDataMaximumResolution {
+        public Pair<Image, CaptureResult> raw;
+        public Pair<Image, CaptureResult> jpeg;
+        public CameraCharacteristics characteristics;
+    }
+
+    class DngDebugParams {
+        String deviceId;
+        String intermediateStr;
+        CameraCharacteristics characteristics;
+        CaptureResult captureResult;
+        FileOutputStream fileStream;
+        FileChannel fileChannel;
+        Image jpeg;
+        Image raw;
+        Bitmap rawBitmap;
+    }
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -192,6 +221,99 @@
     }
 
     /**
+     * Test basic maximum resolution raw capture and DNG saving functionality for each of the
+     * available ultra high resolution cameras.
+     *
+     * <p>
+     * For ultra high resolution each camera, capture a single RAW16 image at the first capture size
+     * reported for the maximum resolution raw format on that device, and save that image as a DNG
+     * file. No further validation is done.
+     * </p>
+     *
+     * <p>
+     * Note: Enabling adb shell setprop log.tag.DngCreatorTest VERBOSE will also cause the
+     * raw image captured for the first reported camera device to be saved to an output file.
+     * </p>
+     */
+    @Test
+    public void testSingleImageBasicMaximumResolution() throws Exception {
+        for (int i = 0; i < mCameraIdsUnderTest.length; i++) {
+            String deviceId = mCameraIdsUnderTest[i];
+            ImageReader captureReader = null;
+            ImageReader reprocessCaptureReader = null;
+            FileOutputStream fileStream = null;
+            ByteArrayOutputStream outputStream = null;
+            try {
+                // All ultra high resolution sensors must necessarily support RAW
+                if (!mAllStaticInfo.get(deviceId).isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR)) {
+                    Log.i(TAG, "ULTRA_HIGH_RESOLUTION_SENSOR capability is not supported in " +
+                            " camera " + mCameraIdsUnderTest[i] + ". Skip the test.");
+                    continue;
+                }
+
+                openDevice(deviceId);
+                Size activeArraySize = mStaticInfo.getRawDimensChecked(/*maxResolution*/true);
+
+                // Create capture image reader
+                CameraTestUtils.SimpleImageReaderListener captureReaderListener
+                        = new CameraTestUtils.SimpleImageReaderListener();
+                CameraTestUtils.SimpleImageReaderListener reprocessReaderListener
+                        = new CameraTestUtils.SimpleImageReaderListener();
+
+                captureReader = createImageReader(activeArraySize, ImageFormat.RAW_SENSOR, 2,
+                        captureReaderListener);
+
+                reprocessCaptureReader = createImageReader(activeArraySize, ImageFormat.RAW_SENSOR,
+                        2, reprocessReaderListener);
+                Pair<Image, CaptureResult> resultPair = null;
+                if (mAllStaticInfo.get(deviceId).isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING)) {
+                    resultPair =
+                            captureReprocessedRawShot(activeArraySize, captureReader,
+                                    reprocessCaptureReader, captureReaderListener,
+                                    reprocessReaderListener, /*waitForAe*/false);
+                } else {
+                    resultPair = captureSingleShotMaximumResolution(activeArraySize,
+                            captureReader, /*waitForAe*/false, captureReaderListener);
+                }
+                CameraCharacteristics characteristics = mStaticInfo.getCharacteristics();
+
+                // Test simple writeImage, no header checks
+                DngCreator dngCreator = new DngCreator(characteristics, resultPair.second);
+                outputStream = new ByteArrayOutputStream();
+                dngCreator.writeImage(outputStream, resultPair.first);
+
+                if (VERBOSE) {
+                    // Write DNG to file
+                    String dngFilePath = mDebugFileNameBase + "/camera_basic_max_resolution_" +
+                            deviceId + "_" + DEBUG_DNG_FILE;
+                    // Write out captured DNG file for the first camera device if setprop is enabled
+                    fileStream = new FileOutputStream(dngFilePath);
+                    fileStream.write(outputStream.toByteArray());
+                    fileStream.flush();
+                    fileStream.close();
+                    Log.v(TAG, "Test DNG file for camera " + deviceId + " saved to " + dngFilePath);
+                }
+                assertTrue("Generated DNG file does not pass validation",
+                        validateDngNative(outputStream.toByteArray()));
+            } finally {
+                closeDevice(deviceId);
+                closeImageReader(captureReader);
+                closeImageReader(reprocessCaptureReader);
+
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+
+                if (fileStream != null) {
+                    fileStream.close();
+                }
+            }
+        }
+    }
+
+    /**
      * Test basic raw capture and DNG saving with a thumbnail, rotation, usercomment, and GPS tags
      * set.
      *
@@ -351,6 +473,106 @@
     }
 
     /**
+     * Test basic maximum resolution RAW capture, and ensure that the rendered RAW output is
+     * similar to the maximum resolution JPEG created for a similar frame.
+     *
+     * Since mandatory streams for maximum resolution sensor pixel mode do not guarantee 2 maximum
+     * resolution streams we can't capture RAW + JPEG images of the same frame. Therefore, 2
+     * sessions are created, one for RAW capture and the other for JPEG capture.
+     *
+     * <p>
+     * This test renders the RAW buffer into an RGB bitmap using a rendering pipeline
+     * similar to one in the Adobe DNG validation tool.  JPEGs produced by the vendor hardware may
+     * have different tonemapping and saturation applied than the RGB bitmaps produced
+     * from this DNG rendering pipeline, and this test allows for fairly wide variations
+     * between the histograms for the RAW and JPEG buffers to avoid false positives.
+     * </p>
+     *
+     * <p>
+     * To ensure more subtle errors in the colorspace transforms returned for the HAL's RAW
+     * metadata, the DNGs and JPEGs produced here should also be manually compared using external
+     * DNG rendering tools.  The DNG, rendered RGB bitmap, and JPEG buffer for this test can be
+     * dumped to the SD card for further examination by enabling the 'verbose' mode for this test
+     * using:
+     * adb shell setprop log.tag.DngCreatorTest VERBOSE
+     * </p>
+     */
+    @Test
+    public void testRaw16JpegMaximumResolutionConsistency() throws Exception {
+        for (String deviceId : mCameraIdsUnderTest) {
+            ImageReader rawImageReader = null;
+            ImageReader jpegImageReader = null;
+            FileOutputStream fileStream = null;
+            FileChannel fileChannel = null;
+            try {
+                // All ultra high resolution sensors must necessarily support RAW
+                if (!mAllStaticInfo.get(deviceId).isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR)) {
+                    Log.i(TAG, "ULTRA_HIGH_RESOLUTION_SENSOR capability is not supported in " +
+                            " camera " + deviceId + ". Skip " +
+                            "testRaw16JpegMaximumResolutionConsistency");
+                    continue;
+                }
+
+                CapturedDataMaximumResolution data =
+                        captureRawJpegImagePairMaximumResolution(deviceId, rawImageReader,
+                                jpegImageReader);
+                if (data == null) {
+                    continue;
+                }
+                Image raw = data.raw.first;
+                Image jpeg = data.jpeg.first;
+
+                Bitmap rawBitmap = Bitmap.createBitmap(raw.getWidth(), raw.getHeight(),
+                        Bitmap.Config.ARGB_8888);
+
+                byte[] rawPlane = new byte[raw.getPlanes()[0].getRowStride() * raw.getHeight()];
+
+                // Render RAW image to a bitmap
+                raw.getPlanes()[0].getBuffer().get(rawPlane);
+                raw.getPlanes()[0].getBuffer().rewind();
+
+                RawConverter.convertToSRGB(RenderScriptSingleton.getRS(), raw.getWidth(),
+                        raw.getHeight(), raw.getPlanes()[0].getRowStride(), rawPlane,
+                        data.characteristics, /*captureREsult*/data.raw.second, /*offsetX*/ 0,
+                        /*offsetY*/ 0, /*out*/ rawBitmap);
+
+                rawPlane = null;
+                System.gc(); // Hint to VM
+
+                if (VERBOSE) {
+                    DngDebugParams params = new DngDebugParams();
+                    params.deviceId = deviceId;
+                    params.characteristics = data.characteristics;
+                    params.captureResult = data.raw.second;
+                    params.fileStream = fileStream;
+                    params.raw = raw;
+                    params.jpeg = jpeg;
+                    params.fileChannel = fileChannel;
+                    params.rawBitmap = rawBitmap;
+                    params.intermediateStr = "maximum_resolution_";
+
+                    debugDumpDng(params);
+                }
+
+                validateRawJpegImagePair(rawBitmap, jpeg, deviceId);
+            } finally {
+                closeImageReader(rawImageReader);
+                closeImageReader(jpegImageReader);
+
+                if (fileChannel != null) {
+                    fileChannel.close();
+                }
+                if (fileStream != null) {
+                    fileStream.close();
+                }
+            }
+        }
+    }
+
+
+
+    /**
      * Test basic RAW capture, and ensure that the rendered RAW output is similar to the JPEG
      * created for the same frame.
      *
@@ -376,7 +598,6 @@
         for (String deviceId : mCameraIdsUnderTest) {
             List<ImageReader> captureReaders = new ArrayList<>();
             FileOutputStream fileStream = null;
-            ByteArrayOutputStream outputStream = null;
             FileChannel fileChannel = null;
             try {
                 CapturedData data = captureRawJpegImagePair(deviceId, captureReaders);
@@ -404,40 +625,18 @@
                 System.gc(); // Hint to VM
 
                 if (VERBOSE) {
-                    // Generate DNG file
-                    DngCreator dngCreator =
-                            new DngCreator(data.characteristics, data.imagePair.second);
+                    DngDebugParams params = new DngDebugParams();
+                    params.deviceId = deviceId;
+                    params.characteristics = data.characteristics;
+                    params.captureResult = data.imagePair.second;
+                    params.fileStream = fileStream;
+                    params.raw = raw;
+                    params.jpeg = jpeg;
+                    params.fileChannel = fileChannel;
+                    params.rawBitmap = rawBitmap;
+                    params.intermediateStr = "";
 
-                    // Write DNG to file
-                    String dngFilePath = mDebugFileNameBase + "/camera_" + deviceId + "_" +
-                            DEBUG_DNG_FILE;
-                    // Write out captured DNG file for the first camera device if setprop is enabled
-                    fileStream = new FileOutputStream(dngFilePath);
-                    dngCreator.writeImage(fileStream, raw);
-                    fileStream.flush();
-                    fileStream.close();
-                    Log.v(TAG, "Test DNG file for camera " + deviceId + " saved to " + dngFilePath);
-
-                    // Write JPEG to file
-                    String jpegFilePath = mDebugFileNameBase + "/camera_" + deviceId + "_jpeg.jpg";
-                    // Write out captured DNG file for the first camera device if setprop is enabled
-                    fileChannel = new FileOutputStream(jpegFilePath).getChannel();
-                    ByteBuffer jPlane = jpeg.getPlanes()[0].getBuffer();
-                    fileChannel.write(jPlane);
-                    fileChannel.close();
-                    jPlane.rewind();
-                    Log.v(TAG, "Test JPEG file for camera " + deviceId + " saved to " +
-                            jpegFilePath);
-
-                    // Write jpeg generated from demosaiced RAW frame to file
-                    String rawFilePath = mDebugFileNameBase + "/camera_" + deviceId + "_raw.jpg";
-                    // Write out captured DNG file for the first camera device if setprop is enabled
-                    fileStream = new FileOutputStream(rawFilePath);
-                    rawBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileStream);
-                    fileStream.flush();
-                    fileStream.close();
-                    Log.v(TAG, "Test converted RAW file for camera " + deviceId + " saved to " +
-                            rawFilePath);
+                    debugDumpDng(params);
                 }
 
                 validateRawJpegImagePair(rawBitmap, jpeg, deviceId);
@@ -450,10 +649,6 @@
                     fileChannel.close();
                 }
 
-                if (outputStream != null) {
-                    outputStream.close();
-                }
-
                 if (fileStream != null) {
                     fileStream.close();
                 }
@@ -557,6 +752,114 @@
         }
     }
 
+   private void debugDumpDng(DngDebugParams params) throws Exception {
+        // Generate DNG file
+        DngCreator dngCreator =
+                new DngCreator(params.characteristics, params.captureResult);
+
+        // Write DNG to file
+        String dngFilePath = mDebugFileNameBase + "/camera_" + params.intermediateStr +
+                params.deviceId + "_" + DEBUG_DNG_FILE;
+        // Write out captured DNG file for the first camera device if setprop is enabled
+        params.fileStream = new FileOutputStream(dngFilePath);
+        dngCreator.writeImage(params.fileStream, params.raw);
+        params.fileStream.flush();
+        params.fileStream.close();
+        Log.v(TAG, "Test DNG file for camera " + params.deviceId + " saved to " + dngFilePath);
+
+        // Write JPEG to file
+        String jpegFilePath = mDebugFileNameBase + "/camera_" + params.intermediateStr  +
+                params.deviceId + "_jpeg.jpg";
+        // Write out captured DNG file for the first camera device if setprop is enabled
+        params.fileChannel = new FileOutputStream(jpegFilePath).getChannel();
+        ByteBuffer jPlane = params.jpeg.getPlanes()[0].getBuffer();
+        params.fileChannel.write(jPlane);
+        params.fileChannel.close();
+        jPlane.rewind();
+        Log.v(TAG, "Test JPEG file for camera " + params.deviceId + " saved to " +
+                jpegFilePath);
+
+        // Write jpeg generated from demosaiced RAW frame to file
+        String rawFilePath = mDebugFileNameBase + "/camera_" + params.intermediateStr +
+                params.deviceId + "_raw.jpg";
+        // Write out captured DNG file for the first camera device if setprop is enabled
+        params.fileStream = new FileOutputStream(rawFilePath);
+        params.rawBitmap.compress(Bitmap.CompressFormat.JPEG, 90, params.fileStream);
+        params.fileStream.flush();
+        params.fileStream.close();
+        Log.v(TAG, "Test converted RAW file for camera " + params.deviceId + " saved to " +
+                rawFilePath);
+   }
+
+    /*
+     * Create RAW + JPEG image pair with characteristics info. Assumes the device supports the RAW
+     * capability.
+     */
+    private CapturedDataMaximumResolution captureRawJpegImagePairMaximumResolution(String deviceId,
+            ImageReader rawCaptureReader, ImageReader jpegCaptureReader)
+            throws Exception {
+        CapturedDataMaximumResolution data = new CapturedDataMaximumResolution();
+        try {
+
+            openDevice(deviceId);
+            Size activeArraySize = mStaticInfo.getRawDimensChecked(/*maxResolution*/true);
+
+            // Get largest jpeg size
+            Size[] targetJpegSizes = mStaticInfo.getAvailableSizesForFormatChecked(
+                    ImageFormat.JPEG, StaticMetadata.StreamDirection.Output, /*fastSizes*/ true,
+                    /*slowSizes*/ true, /*maxResolution*/true);
+
+            Size largestJpegSize = Collections.max(Arrays.asList(targetJpegSizes),
+                    new CameraTestUtils.SizeComparator());
+
+            // Create raw image reader and capture listener
+            CameraTestUtils.SimpleImageReaderListener rawCaptureReaderListener =
+                    new CameraTestUtils.SimpleImageReaderListener();
+            rawCaptureReader = createImageReader(activeArraySize, ImageFormat.RAW_SENSOR, 2,
+                    rawCaptureReaderListener);
+
+            // Create jpeg image reader and capture listener
+            CameraTestUtils.SimpleImageReaderListener jpegCaptureListener =
+                    new CameraTestUtils.SimpleImageReaderListener();
+            jpegCaptureReader = createImageReader(largestJpegSize, ImageFormat.JPEG, 2,
+                    jpegCaptureListener);
+
+            Pair<Image, CaptureResult> jpegResultPair =
+                    captureSingleShotMaximumResolution(activeArraySize,
+                             jpegCaptureReader, /*waitForAe*/true, jpegCaptureListener);
+            data.jpeg = jpegResultPair;
+            data.characteristics = mStaticInfo.getCharacteristics();
+            // Create capture image reader
+            CameraTestUtils.SimpleImageReaderListener outputRawCaptureReaderListener
+                    = new CameraTestUtils.SimpleImageReaderListener();
+            CameraTestUtils.SimpleImageReaderListener reprocessReaderListener
+                    = new CameraTestUtils.SimpleImageReaderListener();
+
+            ImageReader outputRawCaptureReader = createImageReader(activeArraySize,
+                    ImageFormat.RAW_SENSOR, 2, outputRawCaptureReaderListener);
+            Pair<Image, CaptureResult> rawResultPair = null;
+            if (mAllStaticInfo.get(deviceId).isCapabilitySupported(
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING)) {
+                rawResultPair =
+                        captureReprocessedRawShot(activeArraySize, outputRawCaptureReader,
+                                    rawCaptureReader, outputRawCaptureReaderListener,
+                                    reprocessReaderListener, /*waitForAe*/ true);
+            } else {
+                rawResultPair = captureSingleShotMaximumResolution(activeArraySize,
+                        rawCaptureReader, /*waitForAe*/true, rawCaptureReaderListener);
+            }
+            data.raw = rawResultPair;
+            Size rawBitmapSize =
+                    new Size(rawResultPair.first.getWidth(), rawResultPair.first.getHeight());
+            assertTrue("Raw bitmap size must be equal to either pre-correction active array" +
+                    " size or pixel array size.", rawBitmapSize.equals(activeArraySize));
+
+            return data;
+        } finally {
+            closeDevice(deviceId);
+        }
+    }
+
     /*
      * Verify the image pair by comparing the center patch.
      */
@@ -656,7 +959,128 @@
     private Pair<List<Image>, CaptureResult> captureSingleRawShot(Size s,
             List<ImageReader> captureReaders, boolean waitForAe,
             List<CameraTestUtils.SimpleImageReaderListener> captureListeners) throws Exception {
-        return captureRawShots(s, captureReaders, waitForAe, captureListeners, 1).get(0);
+        return captureRawShots(s, captureReaders, waitForAe, captureListeners, 1,
+                /*maxResolution*/false).get(0);
+    }
+
+    private Pair<Image, CaptureResult> captureSingleShotMaximumResolution(Size s,
+            ImageReader captureReader, boolean waitForAe,
+            CameraTestUtils.SimpleImageReaderListener captureListener)
+            throws Exception {
+        List<ImageReader> readers = new ArrayList<ImageReader>();
+        readers.add(captureReader);
+        List<CameraTestUtils.SimpleImageReaderListener> listeners =
+                new ArrayList<CameraTestUtils.SimpleImageReaderListener>();
+        listeners.add(captureListener);
+        Pair<List<Image>, CaptureResult> res = captureRawShots(s, readers, waitForAe,
+                listeners, /*numShots*/ 1, /*maxResolution*/ true).get(0);
+        return new Pair<Image, CaptureResult>(res.first.get(0), res.second);
+    }
+
+    private Pair<Image, CaptureResult> captureReprocessedRawShot(Size sz,
+            ImageReader inputReader,
+            ImageReader reprocessOutputReader,
+            CameraTestUtils.SimpleImageReaderListener inputReaderListener,
+            CameraTestUtils.SimpleImageReaderListener reprocessReaderListener,
+            boolean waitForAe) throws Exception {
+
+        InputConfiguration inputConfig =
+            new InputConfiguration(sz.getWidth(), sz.getHeight(), ImageFormat.RAW_SENSOR);
+        CameraTestUtils.SimpleCaptureCallback inputCaptureListener =
+                new CameraTestUtils.SimpleCaptureCallback();
+        CameraTestUtils.SimpleCaptureCallback reprocessOutputCaptureListener =
+                new CameraTestUtils.SimpleCaptureCallback();
+
+        inputReader.setOnImageAvailableListener(inputReaderListener, mHandler);
+        reprocessOutputReader.setOnImageAvailableListener(reprocessReaderListener, mHandler);
+
+        ArrayList<Surface> outputSurfaces = new ArrayList<Surface>();
+        outputSurfaces.add(inputReader.getSurface());
+        outputSurfaces.add(reprocessOutputReader.getSurface());
+        BlockingSessionCallback sessionListener = new BlockingSessionCallback();
+        ImageReader previewReader = null;
+        if (waitForAe) {
+            // Also setup a small YUV output for AE metering if needed
+            Size yuvSize = (mOrderedPreviewSizes.size() == 0) ? null :
+                    mOrderedPreviewSizes.get(mOrderedPreviewSizes.size() - 1);
+            assertNotNull("Must support at least one small YUV size.", yuvSize);
+            previewReader = createImageReader(yuvSize, ImageFormat.YUV_420_888,
+                        /*maxNumImages*/2, new CameraTestUtils.ImageDropperListener());
+            outputSurfaces.add(previewReader.getSurface());
+        }
+
+        createReprocessableSession(inputConfig, outputSurfaces);
+
+        if (waitForAe) {
+            CaptureRequest.Builder precaptureRequest =
+                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+            assertNotNull("Fail to get captureRequest", precaptureRequest);
+            precaptureRequest.addTarget(previewReader.getSurface());
+            precaptureRequest.set(CaptureRequest.CONTROL_MODE,
+                    CaptureRequest.CONTROL_MODE_AUTO);
+            precaptureRequest.set(CaptureRequest.CONTROL_AE_MODE,
+                    CaptureRequest.CONTROL_AE_MODE_ON);
+
+            final ConditionVariable waitForAeCondition = new ConditionVariable(/*isOpen*/false);
+            CameraCaptureSession.CaptureCallback captureCallback =
+                    new CameraCaptureSession.CaptureCallback() {
+                @Override
+                public void onCaptureProgressed(CameraCaptureSession session,
+                        CaptureRequest request, CaptureResult partialResult) {
+                    Integer aeState = partialResult.get(CaptureResult.CONTROL_AE_STATE);
+                    if (aeState != null &&
+                            (aeState == CaptureRequest.CONTROL_AE_STATE_CONVERGED ||
+                             aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED)) {
+                        waitForAeCondition.open();
+                    }
+                }
+
+                @Override
+                public void onCaptureCompleted(CameraCaptureSession session,
+                        CaptureRequest request, TotalCaptureResult result) {
+                    int aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+                    if (aeState == CaptureRequest.CONTROL_AE_STATE_CONVERGED ||
+                            aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
+                        waitForAeCondition.open();
+                    }
+                }
+            };
+
+            startCapture(precaptureRequest.build(), /*repeating*/true, captureCallback, mHandler);
+
+            precaptureRequest.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+                    CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
+            startCapture(precaptureRequest.build(), /*repeating*/false, captureCallback, mHandler);
+            assertTrue("Timeout out waiting for AE to converge",
+                    waitForAeCondition.block(AE_TIMEOUT_MS));
+        }
+        ImageWriter inputWriter =
+                ImageWriter.newInstance(mCameraSession.getInputSurface(), 1);
+        // Prepare a request for reprocess input
+        CaptureRequest.Builder builder = mCamera.createCaptureRequest(
+                CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
+        builder.addTarget(inputReader.getSurface());
+        // This is a max resolution capture
+        builder.set(CaptureRequest.SENSOR_PIXEL_MODE,
+                CameraMetadata.SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
+        CaptureRequest inputRequest = builder.build();
+        mCameraSession.capture(inputRequest, inputCaptureListener, mHandler);
+        List<CaptureRequest> reprocessCaptureRequests = new ArrayList<>();
+
+        TotalCaptureResult inputResult =
+                inputCaptureListener.getTotalCaptureResult(
+                        MAX_RESOLUTION_CAPTURE_WAIT_TIMEOUT_MS);
+        builder = mCamera.createReprocessCaptureRequest(inputResult);
+        inputWriter.queueInputImage(inputReaderListener.getImage(
+                        MAX_RESOLUTION_CAPTURE_WAIT_TIMEOUT_MS));
+        builder.addTarget(reprocessOutputReader.getSurface());
+        reprocessCaptureRequests.add(builder.build());
+        mCameraSession.captureBurst(reprocessCaptureRequests, reprocessOutputCaptureListener,
+                mHandler);
+        TotalCaptureResult result = reprocessOutputCaptureListener.getTotalCaptureResult(
+                CAPTURE_WAIT_TIMEOUT_MS);
+        return new Pair<Image, CaptureResult>(reprocessReaderListener.getImage(
+                MAX_RESOLUTION_CAPTURE_WAIT_TIMEOUT_MS), result);
     }
 
     /**
@@ -664,27 +1088,50 @@
      *
      * <p>Capture raw images for a given size.</p>
      *
-     * @param s The size of the raw image to capture.  Must be one of the available sizes for this
+     * @param sz The size of the raw image to capture.  Must be one of the available sizes for this
      *          device.
+     *
+     * @param captureReaders The image readers which are associated with the targets for this
+     *        capture.
+     *
+     * @param waitForAe Whether we should wait for AE to converge before capturing outputs for
+     *                  the captureReaders targets
+     *
+     * @param captureListeners ImageReader listeners which wait on the captured images to be
+     *                         available.
+     *
+     * @param numShots The number of shots to be captured
+     *
+     * @param maxResolution Whether the target in captureReaders are max resolution captures. If
+     *                      this is set to true, captureReaders.size() must be == 1 ( in order to
+     *                      satisfy mandatory streams for maximum resolution sensor pixel mode).
+     *
      * @return a list of pairs containing a {@link Image} and {@link CaptureResult} used for
      *          each capture.
      */
-    private List<Pair<List<Image>, CaptureResult>> captureRawShots(Size s,
+    private List<Pair<List<Image>, CaptureResult>> captureRawShots(Size sz,
             List<ImageReader> captureReaders, boolean waitForAe,
             List<CameraTestUtils.SimpleImageReaderListener> captureListeners,
-            int numShots) throws Exception {
+            int numShots, boolean maxResolution) throws Exception {
         if (VERBOSE) {
             Log.v(TAG, "captureSingleRawShot - Capturing raw image.");
         }
 
+        int timeoutScale = maxResolution ? MAX_RESOLUTION_CAPTURE_WAIT_TIMEOUT_SCALE : 1;
         Size[] targetCaptureSizes =
                 mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
-                        StaticMetadata.StreamDirection.Output);
+                        StaticMetadata.StreamDirection.Output, /*fastSizes*/ true,
+                        /*slowSizes*/ true, maxResolution);
+
+        if (maxResolution) {
+            assertTrue("Maximum number of maximum resolution targets for a session should be 1 as" +
+                " per the mandatory streams guarantee", captureReaders.size() == 1);
+        }
 
         // Validate size
         boolean validSize = false;
         for (int i = 0; i < targetCaptureSizes.length; ++i) {
-            if (targetCaptureSizes[i].equals(s)) {
+            if (targetCaptureSizes[i].equals(sz)) {
                 validSize = true;
                 break;
             }
@@ -764,6 +1211,10 @@
 
         request.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
                 CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON);
+        if (maxResolution) {
+            request.set(CaptureRequest.SENSOR_PIXEL_MODE,
+                    CaptureRequest.SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION);
+        }
         CameraTestUtils.SimpleCaptureCallback resultListener =
                 new CameraTestUtils.SimpleCaptureCallback();
 
@@ -778,7 +1229,8 @@
 
             List<Image> resultImages = new ArrayList<Image>();
             for (CameraTestUtils.SimpleImageReaderListener captureListener : captureListeners) {
-                Image captureImage = captureListener.getImage(CAPTURE_WAIT_TIMEOUT_MS);
+                Image captureImage =
+                        captureListener.getImage(CAPTURE_WAIT_TIMEOUT_MS * timeoutScale);
 
             /*CameraTestUtils.validateImage(captureImage, s.getWidth(), s.getHeight(),
                     ImageFormat.RAW_SENSOR, null);*/
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
index 6d80169..4bad89d 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
@@ -29,6 +29,7 @@
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.InputConfiguration;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.params.SessionConfiguration;
 import android.util.Size;
@@ -256,6 +257,19 @@
     }
 
     /**
+     * Create a reprocessable {@link #CameraCaptureSession} using the currently open camera.
+     *
+     * @param inputConfiguration The inputConfiguration for this session
+     * @param outputSurfaces The set of output surfaces to configure for this session
+     */
+    protected void createReprocessableSession(InputConfiguration inputConfig,
+            List<Surface> outputSurfaces) throws Exception {
+        mCameraSessionListener = new BlockingSessionCallback();
+        mCameraSession = CameraTestUtils.configureReprocessableCameraSession(
+                mCamera, inputConfig, outputSurfaces, mCameraSessionListener, mHandler);
+    }
+
+    /**
      * Create a {@link #CameraCaptureSession} using the currently open camera with
      * OutputConfigurations.
      *
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index 866024a..8a9cf4e 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -862,7 +862,16 @@
      * Get and check pixel array size.
      */
     public Size getPixelArraySizeChecked() {
-        Key<Size> key = CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE;
+        return getPixelArraySizeChecked(/*maxResolution*/ false);
+    }
+
+    /**
+     * Get and check pixel array size.
+     */
+    public Size getPixelArraySizeChecked(boolean maxResolution) {
+        Key<Size> key = maxResolution ?
+                CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION :
+                CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE;
         Size pixelArray = getValueFromKeyNonNull(key);
         if (pixelArray == null) {
             return new Size(0, 0);
@@ -875,14 +884,23 @@
      * Get and check pre-correction active array size.
      */
     public Rect getPreCorrectedActiveArraySizeChecked() {
-        Key<Rect> key = CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE;
+        return getPreCorrectedActiveArraySizeChecked(/*maxResolution*/ false);
+    }
+
+    /**
+     * Get and check pre-correction active array size.
+     */
+    public Rect getPreCorrectedActiveArraySizeChecked(boolean maxResolution) {
+        Key<Rect> key = maxResolution ?
+                CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION :
+                        CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE;
         Rect activeArray = getValueFromKeyNonNull(key);
 
         if (activeArray == null) {
             return new Rect(0, 0, 0, 0);
         }
 
-        Size pixelArraySize = getPixelArraySizeChecked();
+        Size pixelArraySize = getPixelArraySizeChecked(maxResolution);
         checkTrueForKey(key, "values left/top are invalid", activeArray.left >= 0 && activeArray.top >= 0);
         checkTrueForKey(key, "values width/height are invalid",
                 activeArray.width() <= pixelArraySize.getWidth() &&
@@ -895,14 +913,23 @@
      * Get and check active array size.
      */
     public Rect getActiveArraySizeChecked() {
-        Key<Rect> key = CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE;
+        return getActiveArraySizeChecked(/*maxResolution*/ false);
+    }
+
+    /**
+     * Get and check active array size.
+     */
+    public Rect getActiveArraySizeChecked(boolean maxResolution) {
+        Key<Rect> key = maxResolution ?
+                CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION :
+                        CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE;
         Rect activeArray = getValueFromKeyNonNull(key);
 
         if (activeArray == null) {
             return new Rect(0, 0, 0, 0);
         }
 
-        Size pixelArraySize = getPixelArraySizeChecked();
+        Size pixelArraySize = getPixelArraySizeChecked(maxResolution);
         checkTrueForKey(key, "values left/top are invalid", activeArray.left >= 0 && activeArray.top >= 0);
         checkTrueForKey(key, "values width/height are invalid",
                 activeArray.width() <= pixelArraySize.getWidth() &&
@@ -915,14 +942,22 @@
      * Get the dimensions to use for RAW16 buffers.
      */
     public Size getRawDimensChecked() throws Exception {
+        return getRawDimensChecked(/*maxResolution*/ false);
+    }
+
+    /**
+     * Get the dimensions to use for RAW16 buffers.
+     */
+    public Size getRawDimensChecked(boolean maxResolution) throws Exception {
         Size[] targetCaptureSizes = getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
-                        StaticMetadata.StreamDirection.Output);
+                        StaticMetadata.StreamDirection.Output, /*fastSizes*/true, /*slowSizes*/true,
+                        maxResolution);
         Assert.assertTrue("No capture sizes available for RAW format!",
                 targetCaptureSizes.length != 0);
-        Rect activeArray = getPreCorrectedActiveArraySizeChecked();
+        Rect activeArray = getPreCorrectedActiveArraySizeChecked(maxResolution);
         Size preCorrectionActiveArraySize =
                 new Size(activeArray.width(), activeArray.height());
-        Size pixelArraySize = getPixelArraySizeChecked();
+        Size pixelArraySize = getPixelArraySizeChecked(maxResolution);
         Assert.assertTrue("Missing pre-correction active array size", activeArray.width() > 0 &&
                 activeArray.height() > 0);
         Assert.assertTrue("Missing pixel array size", pixelArraySize.getWidth() > 0 &&
@@ -1440,7 +1475,7 @@
      */
     public Size[] getAvailableSizesForFormatChecked(int format, StreamDirection direction) {
         return getAvailableSizesForFormatChecked(format, direction,
-                /*fastSizes*/true, /*slowSizes*/true);
+                /*fastSizes*/true, /*slowSizes*/true, /*maxResolution*/false);
     }
 
     /**
@@ -1455,7 +1490,24 @@
      */
     public Size[] getAvailableSizesForFormatChecked(int format, StreamDirection direction,
             boolean fastSizes, boolean slowSizes) {
-        Key<StreamConfigurationMap> key =
+        return  getAvailableSizesForFormatChecked(format, direction, fastSizes, slowSizes,
+                /*maxResolution*/ false);
+    }
+
+    /**
+     * Get available sizes for given format and direction, and whether to limit to slow or fast
+     * resolutions.
+     *
+     * @param format The format for the requested size array.
+     * @param direction The stream direction, input or output.
+     * @param fastSizes whether to include getOutputSizes() sizes (generally faster)
+     * @param slowSizes whether to include getHighResolutionOutputSizes() sizes (generally slower)
+     * @return The sizes of the given format, empty array if no available size is found.
+     */
+    public Size[] getAvailableSizesForFormatChecked(int format, StreamDirection direction,
+            boolean fastSizes, boolean slowSizes, boolean maxResolution) {
+        Key<StreamConfigurationMap> key = maxResolution ?
+                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION :
                 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
         StreamConfigurationMap config = getValueFromKeyNonNull(key);
 
diff --git a/tests/devicepolicy/Android.bp b/tests/devicepolicy/Android.bp
index 9ae1302..7d28aea 100644
--- a/tests/devicepolicy/Android.bp
+++ b/tests/devicepolicy/Android.bp
@@ -38,5 +38,5 @@
         "vts10",
         "general-tests",
     ],
-    sdk_version: "test_current",
+    platform_apis: true,
 }
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
index f834edc..b831add 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/LockTaskTest.java
@@ -16,7 +16,14 @@
 
 package android.devicepolicy.cts;
 
-import static com.android.bedstead.nene.permissions.Permissions.MANAGE_DEVICE_ADMINS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
+
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -33,7 +40,7 @@
 import com.android.bedstead.harrier.annotations.enterprise.NegativePolicyTest;
 import com.android.bedstead.harrier.annotations.enterprise.PositivePolicyTest;
 import com.android.bedstead.harrier.annotations.Postsubmit;
-import com.android.bedstead.harrier.policies.LockTaskPackages;
+import com.android.bedstead.harrier.policies.LockTask;
 import com.android.bedstead.nene.TestApis;
 
 import org.junit.ClassRule;
@@ -56,10 +63,25 @@
     private static final DevicePolicyManager mDevicePolicyManager =
             sTestApis.context().instrumentedContext().getSystemService(DevicePolicyManager.class);
 
+    private static final int[] INDIVIDUALLY_SETTABLE_FLAGS = new int[] {
+            LOCK_TASK_FEATURE_SYSTEM_INFO,
+            LOCK_TASK_FEATURE_HOME,
+            LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
+            LOCK_TASK_FEATURE_KEYGUARD
+    };
+
+    private static final int[] FLAGS_SETTABLE_WITH_HOME = new int[] {
+            LOCK_TASK_FEATURE_SYSTEM_INFO,
+            LOCK_TASK_FEATURE_OVERVIEW,
+            LOCK_TASK_FEATURE_NOTIFICATIONS,
+            LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
+            LOCK_TASK_FEATURE_KEYGUARD
+    };
+
     @Test
     @Postsubmit(reason = "New test")
     // TODO(scottjonathan): This omits the metrics test
-    @PositivePolicyTest(policy = LockTaskPackages.class)
+    @PositivePolicyTest(policy = LockTask.class)
     public void setLockTaskPackages_lockTaskPackagesIsSet() {
         String[] originalLockTaskPackages =
                 sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
@@ -76,8 +98,16 @@
 
     @Test
     @Postsubmit(reason = "New test")
+    @CannotSetPolicyTest(policy = LockTask.class)
+    public void getLockTaskPackages_policyIsNotAllowedToBeFetched_throwsException() {
+        assertThrows(SecurityException.class,
+                () -> sDeviceState.dpc().devicePolicyManager().getLockTaskPackages());
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
     // TODO(scottjonathan): This omits the metrics test
-    @PositivePolicyTest(policy = LockTaskPackages.class)
+    @PositivePolicyTest(policy = LockTask.class)
     public void setLockTaskPackages_empty_lockTaskPackagesIsSet() {
         String[] originalLockTaskPackages =
                 sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
@@ -95,10 +125,9 @@
     @Test
     @Postsubmit(reason = "New test")
     // TODO(scottjonathan): This omits the metrics test
-    @PositivePolicyTest(policy = LockTaskPackages.class)
-    @EnsureHasPermission(MANAGE_DEVICE_ADMINS) // Used for getPolicyExemptApps
+    @PositivePolicyTest(policy = LockTask.class)
     public void setLockTaskPackages_includesPolicyExemptApp_lockTaskPackagesIsSet() {
-        Set<String> policyExemptApps = mDevicePolicyManager.getPolicyExemptApps();
+        Set<String> policyExemptApps = sTestApis.devicePolicy().getPolicyExemptApps();
         assumeFalse("OEM does not define any policy-exempt apps",
                 policyExemptApps.isEmpty());
         String[] originalLockTaskPackages =
@@ -117,7 +146,7 @@
 
     @Test
     @Postsubmit(reason = "New test")
-    @CannotSetPolicyTest(policy = LockTaskPackages.class)
+    @CannotSetPolicyTest(policy = LockTask.class)
     public void setLockTaskPackages_policyIsNotAllowedToBeSet_throwsException() {
         assertThrows(SecurityException.class,
                 () -> sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(new String[]{}));
@@ -126,7 +155,7 @@
     @Test
     @Postsubmit(reason = "New test")
     // TODO(scottjonathan): This omits the metrics test
-    @PositivePolicyTest(policy = LockTaskPackages.class)
+    @PositivePolicyTest(policy = LockTask.class)
     public void isLockTaskPermitted_lockTaskPackageIsSet_returnsTrue() {
         String[] originalLockTaskPackages =
                 sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
@@ -142,7 +171,7 @@
 
     @Test
     @Postsubmit(reason = "New test")
-    @NegativePolicyTest(policy = LockTaskPackages.class)
+    @NegativePolicyTest(policy = LockTask.class)
     // TODO(scottjonathan): Confirm expected behaviour here
     public void isLockTaskPermitted_lockTaskPackageIsSet_policyDoesntApply_returnsFalse() {
         String[] originalLockTaskPackages =
@@ -160,7 +189,7 @@
     @Test
     @Postsubmit(reason = "New test")
     // TODO(scottjonathan): This omits the metrics test
-    @PositivePolicyTest(policy = LockTaskPackages.class)
+    @PositivePolicyTest(policy = LockTask.class)
     public void isLockTaskPermitted_lockTaskPackageIsNotSet_returnsFalse() {
         String[] originalLockTaskPackages =
                 sDeviceState.dpc().devicePolicyManager().getLockTaskPackages();
@@ -176,10 +205,9 @@
 
     @Test
     @Postsubmit(reason = "New test")
-    @PositivePolicyTest(policy = LockTaskPackages.class)
-    @EnsureHasPermission(MANAGE_DEVICE_ADMINS) // Used for getPolicyExemptApps
+    @PositivePolicyTest(policy = LockTask.class)
     public void isLockTaskPermitted_includesPolicyExemptApps() {
-        Set<String> policyExemptApps = mDevicePolicyManager.getPolicyExemptApps();
+        Set<String> policyExemptApps = sTestApis.devicePolicy().getPolicyExemptApps();
         // TODO(b/188035301): Add a unit test which ensures this actually gets tested
         assumeFalse("OEM does not define any policy-exempt apps",
                 policyExemptApps.isEmpty());
@@ -197,4 +225,77 @@
             sDeviceState.dpc().devicePolicyManager().setLockTaskPackages(originalLockTaskPackages);
         }
     }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    public void setLockTaskFeatures_overviewFeature_throwsException() {
+        // Overview can only be used in combination with home
+        int originalLockTaskFeatures =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskFeatures();
+
+        try {
+            assertThrows(IllegalArgumentException.class, () -> {
+                sDeviceState.dpc().devicePolicyManager()
+                        .setLockTaskFeatures(LOCK_TASK_FEATURE_OVERVIEW);
+            });
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskFeatures(originalLockTaskFeatures);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    public void setLockTaskFeatures_notificationsFeature_throwsException() {
+        // Notifications can only be used in combination with home
+        int originalLockTaskFeatures =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskFeatures();
+
+        try {
+            assertThrows(IllegalArgumentException.class, () -> {
+                sDeviceState.dpc().devicePolicyManager()
+                        .setLockTaskFeatures(LOCK_TASK_FEATURE_NOTIFICATIONS);
+            });
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskFeatures(originalLockTaskFeatures);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = LockTask.class)
+    // TODO(scottjonathan): Support additional parameterization for cases like this
+    public void setLockTaskFeatures_multipleFeatures_setsFeatures() {
+        int originalLockTaskFeatures =
+                sDeviceState.dpc().devicePolicyManager().getLockTaskFeatures();
+
+        try {
+            for (int flag : FLAGS_SETTABLE_WITH_HOME) {
+                sDeviceState.dpc().devicePolicyManager().setLockTaskFeatures(
+                        LOCK_TASK_FEATURE_HOME | flag);
+
+                assertThat(sDeviceState.dpc().devicePolicyManager().getLockTaskFeatures())
+                        .isEqualTo(LOCK_TASK_FEATURE_HOME | flag);
+            }
+        } finally {
+            sDeviceState.dpc().devicePolicyManager().setLockTaskFeatures(originalLockTaskFeatures);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @CannotSetPolicyTest(policy = LockTask.class)
+    public void setLockTaskFeatures_policyIsNotAllowedToBeSet_throwsException() {
+        assertThrows(SecurityException.class, () ->
+                sDeviceState.dpc().devicePolicyManager().setLockTaskFeatures(LOCK_TASK_FEATURE_NONE));
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @CannotSetPolicyTest(policy = LockTask.class)
+    public void getLockTaskFeatures_policyIsNotAllowedToBeFetched_throwsException() {
+        assertThrows(SecurityException.class, () ->
+                sDeviceState.dpc().devicePolicyManager().getLockTaskFeatures());
+    }
 }
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/NetworkResetTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/NetworkResetTest.java
new file mode 100644
index 0000000..bf11cf7
--- /dev/null
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/NetworkResetTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.devicepolicy.cts;
+
+import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+import static android.os.UserManager.DISALLOW_CONFIG_PRIVATE_DNS;
+import static android.os.UserManager.DISALLOW_NETWORK_RESET;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivitySettingsManager;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.EnsureHasPermission;
+import com.android.bedstead.harrier.annotations.Postsubmit;
+import com.android.bedstead.harrier.annotations.enterprise.PositivePolicyTest;
+import com.android.bedstead.harrier.policies.DisallowNetworkReset;
+import com.android.bedstead.harrier.policies.DisallowPrivateDnsConfig;
+import com.android.bedstead.nene.TestApis;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+// TODO(b/189280629): Move this test to to net test folder to live with other network reset tests.
+@RunWith(BedsteadJUnit4.class)
+public class NetworkResetTest {
+    @ClassRule @Rule
+    public static final DeviceState sDeviceState = new DeviceState();
+
+    private static final TestApis sTestApis = new TestApis();
+    private static final Context sContext = sTestApis.context().instrumentedContext();
+    private static final UserManager sUserManager = sContext.getSystemService(UserManager.class);
+    private static final ConnectivityManager sConnectivityManager =
+            sContext.getSystemService(ConnectivityManager.class);
+    private boolean mOriginalAirplaneMode;
+    private int mOriginalPrivateDnsMode;
+    private int mOriginalAvoidBadWifi;
+
+    @Before
+    public void setUp() throws Exception {
+        mOriginalAirplaneMode = getAirplaneMode();
+        mOriginalPrivateDnsMode = getPrivateDnsMode();
+        mOriginalAvoidBadWifi = getNetworkAvoidBadWifi();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        restoreSettings(mOriginalAirplaneMode, mOriginalPrivateDnsMode, mOriginalAvoidBadWifi);
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = DisallowNetworkReset.class)
+    @EnsureHasPermission({NETWORK_SETTINGS, WRITE_SECURE_SETTINGS})
+    public void factoryReset_disallowedByNetworkResetPolicy_doesNotFactoryReset() throws Exception {
+        final boolean originalUserRestriction =
+                sUserManager.hasUserRestriction(DISALLOW_NETWORK_RESET);
+        try {
+            sConnectivityManager.setAirplaneMode(true);
+            sDeviceState.dpc().devicePolicyManager().addUserRestriction(DISALLOW_NETWORK_RESET);
+
+            sConnectivityManager.factoryReset();
+
+            // As the factory reset should have been rejected, it's expected that the airplane mode
+            // should not be changed.
+            assertThat(getAirplaneMode()).isTrue();
+        } finally {
+            restoreUserRestriction(originalUserRestriction, DISALLOW_NETWORK_RESET);
+        }
+    }
+
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = DisallowPrivateDnsConfig.class)
+    @EnsureHasPermission({NETWORK_SETTINGS, WRITE_SECURE_SETTINGS})
+    public void factoryReset_disallowedByConfigPrivateDnsPolicy_doesPartialFactoryReset()
+            throws Exception {
+        final boolean originalUserRestriction =
+                sUserManager.hasUserRestriction(DISALLOW_CONFIG_PRIVATE_DNS);
+        try {
+            ConnectivitySettingsManager.setPrivateDnsMode(sContext,
+                    ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF);
+            sDeviceState.dpc().devicePolicyManager()
+                    .addUserRestriction(DISALLOW_CONFIG_PRIVATE_DNS);
+
+            sConnectivityManager.factoryReset();
+
+            // As setting private dns should be rejected, it's expected that private dns mode
+            // should not be changed.
+            assertThat(getPrivateDnsMode()).isEqualTo(
+                    ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF);
+        } finally {
+            restoreUserRestriction(originalUserRestriction, DISALLOW_CONFIG_PRIVATE_DNS);
+        }
+    }
+
+    @Test
+    @Postsubmit(reason = "New test")
+    @PositivePolicyTest(policy = DisallowNetworkReset.class)
+    @EnsureHasPermission({NETWORK_SETTINGS, WRITE_SECURE_SETTINGS})
+    public void factoryReset_noPolicyRestrictions_resetsToDefault() throws Exception {
+        final boolean originalPrivateDnsUserRestriction =
+                sUserManager.hasUserRestriction(DISALLOW_CONFIG_PRIVATE_DNS);
+        final boolean originalNetworkResetUserRestriction =
+                sUserManager.hasUserRestriction(DISALLOW_NETWORK_RESET);
+        try {
+            sConnectivityManager.setAirplaneMode(true);
+            ConnectivitySettingsManager.setPrivateDnsMode(sContext,
+                    ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF);
+            // Ensure no policy set.
+            sDeviceState.dpc().devicePolicyManager()
+                    .clearUserRestriction(DISALLOW_CONFIG_PRIVATE_DNS);
+            sDeviceState.dpc().devicePolicyManager()
+                    .clearUserRestriction(DISALLOW_NETWORK_RESET);
+
+            sConnectivityManager.factoryReset();
+
+            // Verify settings reset to default setting.
+            assertThat(getPrivateDnsMode()).isEqualTo(
+                    ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC);
+            assertThat(getAirplaneMode()).isFalse();
+        } finally {
+            restoreUserRestriction(originalPrivateDnsUserRestriction, DISALLOW_CONFIG_PRIVATE_DNS);
+            restoreUserRestriction(originalNetworkResetUserRestriction, DISALLOW_NETWORK_RESET);
+        }
+    }
+
+    private boolean getAirplaneMode() throws Exception {
+        return Settings.Global.getInt(
+                sContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON) != 0;
+    }
+
+    private int getPrivateDnsMode() {
+        return ConnectivitySettingsManager.getPrivateDnsMode(sContext);
+    }
+
+    private int getNetworkAvoidBadWifi() {
+        return ConnectivitySettingsManager.getNetworkAvoidBadWifi(sContext);
+    }
+
+    private void restoreSettings(boolean airplaneMode, int privateDnsMode, int avoidBadWifi) {
+        sConnectivityManager.setAirplaneMode(airplaneMode);
+        ConnectivitySettingsManager.setPrivateDnsMode(sContext, privateDnsMode);
+        ConnectivitySettingsManager.setNetworkAvoidBadWifi(sContext, avoidBadWifi);
+    }
+
+    private void restoreUserRestriction(boolean originalUserRestriction, String policy) {
+        if (originalUserRestriction) {
+            sDeviceState.dpc().devicePolicyManager().addUserRestriction(policy);
+        } else {
+            sDeviceState.dpc().devicePolicyManager().clearUserRestriction(policy);
+        }
+    }
+}
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
index 94c1b22..7d8416e 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricActivityTests.java
@@ -81,7 +81,6 @@
 
         // Nothing happened yet
         BiometricCallbackHelper.State callbackState = getCallbackState(journal);
-        assertNotNull(callbackState);
         assertEquals(callbackState.toString(), 0, callbackState.mNumAuthRejected);
         assertEquals(callbackState.toString(), 0, callbackState.mNumAuthAccepted);
         assertEquals(callbackState.toString(), 0, callbackState.mAcquiredReceived.size());
@@ -92,7 +91,6 @@
 
         mInstrumentation.waitForIdleSync();
         callbackState = getCallbackState(journal);
-        assertNotNull(callbackState);
         assertTrue(callbackState.toString(), callbackState.mErrorsReceived.isEmpty());
         assertTrue(callbackState.toString(), callbackState.mAcquiredReceived.isEmpty());
         assertEquals(callbackState.toString(), 1, callbackState.mNumAuthAccepted);
@@ -136,7 +134,6 @@
         session.rejectAuthentication(userId);
         mInstrumentation.waitForIdleSync();
         callbackState = getCallbackState(journal);
-        assertNotNull(callbackState);
         assertEquals(callbackState.toString(), 1, callbackState.mNumAuthRejected);
         assertEquals(callbackState.toString(), 0, callbackState.mNumAuthAccepted);
         assertEquals(callbackState.toString(), 0, callbackState.mAcquiredReceived.size());
@@ -154,7 +151,6 @@
         session.notifyError(userId, BiometricPrompt.BIOMETRIC_ERROR_CANCELED);
         mInstrumentation.waitForIdleSync();
         callbackState = getCallbackState(journal);
-        assertNotNull(callbackState);
         assertEquals(callbackState.toString(), 1, callbackState.mNumAuthRejected);
         assertEquals(callbackState.toString(), 0, callbackState.mNumAuthAccepted);
         assertEquals(callbackState.toString(), 0, callbackState.mAcquiredReceived.size());
@@ -202,7 +198,6 @@
         session.rejectAuthentication(userId);
         mInstrumentation.waitForIdleSync();
         callbackState = getCallbackState(journal);
-        assertNotNull(callbackState);
         assertEquals(callbackState.toString(), 1, callbackState.mNumAuthRejected);
         assertEquals(callbackState.toString(), 0, callbackState.mNumAuthAccepted);
         assertEquals(callbackState.toString(), 0, callbackState.mAcquiredReceived.size());
@@ -221,7 +216,6 @@
 
         mInstrumentation.waitForIdleSync();
         callbackState = getCallbackState(journal);
-        assertNotNull(callbackState);
         assertTrue(callbackState.toString(), callbackState.mErrorsReceived.isEmpty());
         assertTrue(callbackState.toString(), callbackState.mAcquiredReceived.isEmpty());
         assertEquals(callbackState.toString(), 1, callbackState.mNumAuthAccepted);
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSecurityTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSecurityTests.java
index 4f7a97fa..7ffda4f 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSecurityTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSecurityTests.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
 import android.content.ComponentName;
@@ -34,6 +35,8 @@
 import android.server.wm.TestJournalProvider.TestJournalContainer;
 import android.util.Log;
 
+import org.junit.After;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 import java.util.List;
@@ -45,6 +48,19 @@
 public class BiometricSecurityTests extends BiometricTestBase {
     private static final String TAG = "BiometricTests/Security";
 
+    private static final String DEVICE_CONFIG_NAMESPACE = "biometrics";
+    private static final String DEVICE_CONFIG_BIO_STRENGTH_KEY = "biometric_strengths";
+
+    @BeforeClass
+    public static void ensureReset() throws Exception {
+        revertSensorStrengths();
+    }
+
+    @After
+    public void teardown() throws Exception {
+        revertSensorStrengths();
+    }
+
     /**
      * A strong biometric should be able to perform auth with any requested strength, since it is
      * the highest biometric class. For example,
@@ -105,7 +121,7 @@
             testBiometricStrength_forSensor_authDisallowed(sensorId,
                     Authenticators.BIOMETRIC_WEAK /* originalStrength */,
                     Authenticators.BIOMETRIC_STRONG /* requestedStrength */,
-                    sensors.size() > 1 /* hasMultiSensors */);
+                    mSensorProperties.size() > 1 /* hasMultiSensors */);
 
             testBiometricStrength_forSensor_authAllowed(sensorId,
                     Authenticators.BIOMETRIC_WEAK /* originalStrength */,
@@ -162,7 +178,7 @@
         final ComponentName componentName = getComponentName(requestedStrength);
 
         // Reset to the original strength in case it's ever changed before the test
-        updateStrength(sensorId, originalStrength);
+        updateStrengthAndVerify(sensorId, originalStrength);
 
         try (BiometricTestSession session = mBiometricManager.createTestSession(sensorId);
              ActivitySession activitySession = new ActivitySession(this, componentName)) {
@@ -209,11 +225,10 @@
         final ComponentName componentName = getComponentName(requestedStrength);
 
         // Reset to the original strength in case it's ever changed before the test
-        updateStrength(sensorId, originalStrength);
+        updateStrengthAndVerify(sensorId, originalStrength);
 
         try (BiometricTestSession session = mBiometricManager.createTestSession(sensorId);
              ActivitySession activitySession = new ActivitySession(this, componentName)) {
-            final int userId = 0;
             waitForAllUnenrolled();
             enrollForSensor(session, sensorId);
             final TestJournal journal =
@@ -291,7 +306,7 @@
                         testCases[i][0] /* originalStrength */,
                         testCases[i][1] /* targetStrength */,
                         testCases[i][2] /* requestedStrength */,
-                        sensors.size() > 1 /* hasMultiSensors */);
+                        mSensorProperties.size() > 1 /* hasMultiSensors */);
             }
         }
     }
@@ -327,7 +342,7 @@
                         testCases[i][0] /* originalStrength */,
                         testCases[i][1] /* targetStrength */,
                         testCases[i][2] /* requestedStrength */,
-                        sensors.size() > 1 /* hasMultiSensors */);
+                        mSensorProperties.size() > 1 /* hasMultiSensors */);
             }
         }
     }
@@ -343,9 +358,6 @@
 
         final ComponentName componentName = getComponentName(requestedStrength);
 
-        // Reset to the original strength in case it's ever changed before the test
-        updateStrength(sensorId, originalStrength);
-
         try (BiometricTestSession session = mBiometricManager.createTestSession(sensorId);
              ActivitySession activitySession = new ActivitySession(this, componentName)) {
             final int userId = 0;
@@ -358,7 +370,7 @@
             BiometricServiceState state;
 
             // Downgrade the biometric strength to the target strength
-            updateStrength(sensorId, targetStrength);
+            updateStrengthAndVerify(sensorId, targetStrength);
 
             // After downgrading, check whether auth works
             // TODO: should check if targetStrength is at least as strong as the requestedStrength,
@@ -412,9 +424,6 @@
                         BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED, hasMultiSensors);
             }
         }
-
-        // Cleanup: reset to the original strength
-        updateStrength(sensorId, originalStrength);
     }
 
     /**
@@ -447,7 +456,7 @@
                         testCases[i][0] /* originalStrength */,
                         testCases[i][1] /* targetStrength */,
                         testCases[i][2] /* requestedStrength */,
-                        sensors.size() > 1 /* hasMultiSensors */);
+                        mSensorProperties.size() > 1 /* hasMultiSensors */);
             }
         }
     }
@@ -513,11 +522,10 @@
         final ComponentName componentName = getComponentName(requestedStrength);
 
         // Reset to the original strength in case it's ever changed before the test
-        updateStrength(sensorId, originalStrength);
+        updateStrengthAndVerify(sensorId, originalStrength);
 
         try (BiometricTestSession session = mBiometricManager.createTestSession(sensorId);
              ActivitySession activitySession = new ActivitySession(this, componentName)) {
-            final int userId = 0;
             waitForAllUnenrolled();
             enrollForSensor(session, sensorId);
             final TestJournal journal =
@@ -525,7 +533,7 @@
 
             // Try to upgrade the biometric strength to the target strength. The upgrading operation
             // is no-op since the biometric can't be upgraded past its original strength.
-            updateStrength(sensorId, targetStrength);
+            updateStrengthAndIdle(sensorId, targetStrength);
             final int currentStrength = getCurrentStrength(sensorId);
             assertTrue("currentStrength: " + currentStrength, currentStrength == originalStrength);
 
@@ -550,9 +558,6 @@
             checkErrCode(callbackState.toString(), (int) callbackState.mErrorsReceived.get(0),
                     BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE, hasMultiSensors);
         }
-
-        // Cleanup: reset to the original strength
-        updateStrength(sensorId, originalStrength);
     }
 
     private void checkErrCode(String msg, int errCode, int expectedErrCode,
@@ -568,16 +573,61 @@
         }
     }
 
-    private ComponentName getComponentName(int requestedStrength) {
+    private static ComponentName getComponentName(int requestedStrength) {
         assertTrue("requestedStrength: " + requestedStrength,
                 requestedStrength == Authenticators.BIOMETRIC_STRONG ||
                         requestedStrength == Authenticators.BIOMETRIC_WEAK);
 
         if (requestedStrength == Authenticators.BIOMETRIC_STRONG) {
             return CLASS_3_BIOMETRIC_ACTIVITY;
-        } else {
-            return CLASS_2_BIOMETRIC_ACTIVITY;
+        }
+        return CLASS_2_BIOMETRIC_ACTIVITY;
+    }
+
+    private static void revertSensorStrengths() throws Exception {
+        Log.d(TAG, "revertSensorStrengths");
+        Utils.executeShellCommand("device_config delete " +
+                DEVICE_CONFIG_NAMESPACE + " " +
+                DEVICE_CONFIG_BIO_STRENGTH_KEY);
+        // this is probably not needed, but there are not too many tests so pause to ensure
+        // the settings have settled
+        Thread.sleep(1000);
+    }
+
+    private void updateStrengthAndVerify(int sensorId, int targetStrength) throws Exception {
+        updateSensorStrength(sensorId, targetStrength, /* verify */ true);
+    }
+
+    private void updateStrengthAndIdle(int sensorId, int targetStrength) throws Exception {
+        updateSensorStrength(sensorId, targetStrength, /* verify */ false);
+    }
+
+    private void updateSensorStrength(int sensorId, int targetStrength, boolean verify)
+            throws Exception {
+        Log.d(TAG, "updateStrength: update sensorId=" + sensorId + " to targetStrength="
+                + targetStrength);
+        Utils.executeShellCommand("device_config put " +
+                DEVICE_CONFIG_NAMESPACE + " " +
+                DEVICE_CONFIG_BIO_STRENGTH_KEY + " " +
+                String.format("%s:%s", sensorId, targetStrength));
+
+        final boolean matchesTarget = waitForSensorToBecomeStrength(sensorId, targetStrength);
+        if (verify && !matchesTarget) {
+            fail("Timed out waiting for sensorId " + sensorId + " to become target strength: "
+                    + targetStrength);
         }
     }
 
+    private boolean waitForSensorToBecomeStrength(int sensorId, int targetStrength)
+            throws Exception {
+        for (int i = 0; i < 20; i++) {
+            final int currentStrength = getCurrentStrength(sensorId);
+            if (currentStrength == targetStrength) {
+                return true;
+            }
+            Log.d(TAG, "Not at target strength yet, current: " + currentStrength);
+            Thread.sleep(300);
+        }
+        return false;
+    }
 }
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
index b24206e..db0fd8b 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
@@ -78,12 +78,9 @@
     private static final String TAG = "BiometricTestBase";
     private static final String DUMPSYS_BIOMETRIC = Utils.DUMPSYS_BIOMETRIC;
     private static final String FLAG_CLEAR_SCHEDULER_LOG = " --clear-scheduler-buffer";
-    private static final String DOWNGRADE_BIOMETRIC_STRENGTH =
-            "device_config put biometrics biometric_strengths ";
 
     // Negative-side (left) buttons
     protected static final String BUTTON_ID_NEGATIVE = "button_negative";
-    protected static final String BUTTON_ID_CANCEL = "button_cancel";
     protected static final String BUTTON_ID_USE_CREDENTIAL = "button_use_credential";
 
     // Positive-side (right) buttons
@@ -171,20 +168,6 @@
         Log.d(TAG, "Timed out waiting for state to not equal: " + state);
     }
 
-    private void waitForSensorToBecomeStrength(int sensorId, int targetStrength) throws Exception {
-        for (int i = 0; i < 20; i++) {
-            final int currentStrength = getCurrentStrength(sensorId);
-            if (currentStrength != targetStrength) {
-                Log.d(TAG, "Not become target strength yet, current: " + currentStrength);
-                Thread.sleep(300);
-            } else {
-                return;
-            }
-        }
-        Log.d(TAG, "Timed out waiting for sensorId " + sensorId + " to become target strength: "
-                + targetStrength);
-    }
-
     private boolean anyEnrollmentsExist() throws Exception {
         final BiometricServiceState serviceState = getCurrentState();
 
@@ -451,8 +434,7 @@
                 });
     }
 
-    protected void launchActivityAndWaitForResumed(@NonNull ActivitySession activitySession)
-            throws Exception {
+    protected void launchActivityAndWaitForResumed(@NonNull ActivitySession activitySession) {
         activitySession.start();
         mWmState.waitForActivityState(activitySession.getComponentName(),
                 WindowManagerState.STATE_RESUMED);
@@ -464,15 +446,6 @@
         mInstrumentation.waitForIdleSync();
     }
 
-    protected void updateStrength(int sensorId, int targetStrength) throws Exception {
-        Log.d(TAG, "updateStrength: update sensorId=" + sensorId + " to targetStrength="
-                + targetStrength);
-        final String shellCommand = DOWNGRADE_BIOMETRIC_STRENGTH +
-                String.format("%s:%s", sensorId, targetStrength);
-        Utils.executeShellCommand(shellCommand);
-        waitForSensorToBecomeStrength(sensorId, targetStrength);
-    }
-
     protected int getCurrentStrength(int sensorId) throws Exception {
         final BiometricServiceState serviceState = getCurrentState();
         return serviceState.mSensorStates.sensorStates.get(sensorId).getCurrentStrength();
@@ -492,13 +465,10 @@
     @NonNull
     protected static BiometricCallbackHelper.State getCallbackState(@NonNull TestJournal journal) {
         Utils.waitFor("Waiting for authentication callback",
-                () -> journal.extras.containsKey(BiometricCallbackHelper.KEY));
+                () -> journal.extras.containsKey(BiometricCallbackHelper.KEY),
+                (lastResult) -> fail("authentication callback never received - died waiting"));
 
         final Bundle bundle = journal.extras.getBundle(BiometricCallbackHelper.KEY);
-        if (bundle == null) {
-            return new BiometricCallbackHelper.State();
-        }
-
         final BiometricCallbackHelper.State state =
                 BiometricCallbackHelper.State.fromBundle(bundle);
 
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/Utils.java b/tests/framework/base/biometrics/src/android/server/biometrics/Utils.java
index c90061e..2d2dea7 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/Utils.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/Utils.java
@@ -127,6 +127,7 @@
      * @return The result of the command.
      */
     public static byte[] executeShellCommand(String cmd) {
+        Log.d(TAG, "execute: " + cmd);
         try {
             ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
                     .executeShellCommand(cmd);
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index 257f867..75cf23c 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -129,6 +129,9 @@
 
         <activity android:name="android.server.wm.lifecycle.ActivityLifecycleClientTestBase$ResultActivity"/>
 
+        <activity android:name="android.server.wm.lifecycle.ActivityLifecycleClientTestBase$TranslucentResultActivity"
+                  android:theme="@android:style/Theme.Dialog"/>
+
         <activity android:name="android.server.wm.lifecycle.ActivityLifecycleClientTestBase$SingleTopActivity"
              android:launchMode="singleTop"/>
 
@@ -321,6 +324,12 @@
                   android:turnScreenOn="true"
                   android:showWhenLocked="true"/>
 
+        <activity android:name="android.server.wm.PrivacyIndicatorBoundsTests$TestActivity"
+                  android:configChanges="orientation|screenSize"
+                  android:screenOrientation="nosensor"
+                  android:turnScreenOn="true"
+                  android:showWhenLocked="true"/>
+
         <activity android:name="android.server.wm.WindowInsetsAnimationSynchronicityTests$TestActivity"
              android:turnScreenOn="true"
              android:showWhenLocked="true"/>
@@ -485,11 +494,23 @@
                   android:screenOrientation="portrait"
                   android:exported="true"/>
 
+        <activity android:name="android.server.wm.CompatChangeTests$NonResizeableAspectRatioActivity"
+                  android:resizeableActivity="false"
+                  android:screenOrientation="portrait"
+                  android:minAspectRatio="1.6"
+                  android:exported="true"/>
+
+        <activity android:name="android.server.wm.CompatChangeTests$NonResizeableLargeAspectRatioActivity"
+                  android:resizeableActivity="false"
+                  android:screenOrientation="portrait"
+                  android:minAspectRatio="3"
+                  android:exported="true"/>
+
         <activity android:name="android.server.wm.CompatChangeTests$SupportsSizeChangesPortraitActivity"
                   android:resizeableActivity="false"
                   android:screenOrientation="portrait"
                   android:exported="true">
-            <meta-data android:name="android.supports_size_changes"
+        <meta-data android:name="android.supports_size_changes"
                        android:value="true"/>
         </activity>
 
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index 381cd84d..9b53270 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -598,13 +598,16 @@
         <activity android:name=".HandleSplashScreenExitActivity"
                   android:theme="@style/ShowBrandingTheme"
                   android:configChanges="uiMode"
-                  android:exported="true"/>
+                  android:exported="true"
+                  android:taskAffinity="nobody.but.TestSplashScreenAffinity"/>
         <activity android:name=".SplashScreenReplaceIconActivity"
                   android:exported="true"
-                  android:theme="@style/ReplaceIconTheme"/>
+                  android:theme="@style/ReplaceIconTheme"
+                  android:taskAffinity="nobody.but.TestSplashScreenAffinity"/>
         <activity android:name=".SplashScreenReplaceThemeActivity"
                   android:exported="true"
-                  android:theme="@style/ReplaceIconTheme"/>
+                  android:theme="@style/ReplaceIconTheme"
+                  android:taskAffinity="nobody.but.TestSplashScreenAffinity"/>
 
         <service android:name=".OverlayTestService"
                  android:exported="true" />
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
index 58af342..8d6cdca 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
@@ -269,6 +269,7 @@
         public static final String ICON_BACKGROUND_COLOR = "icon_background_color";
         public static final String ICON_ANIMATION_DURATION = "icon_animation_duration";
         public static final String ICON_ANIMATION_START = "icon_animation_start";
+        public static final String CENTER_VIEW_IS_SURFACE_VIEW = "center_view_is_surface_view";
 
         public static final String REQUEST_HANDLE_EXIT_ON_CREATE = "handle_exit_onCreate";
         public static final String REQUEST_HANDLE_EXIT_ON_RESUME = "handle_exit_onResume";
@@ -311,6 +312,7 @@
         public static final String EXTRA_INTENTS = "intents";
         public static final String EXTRA_NO_IDLE = "no_idle";
         public static final String COMMAND_NAVIGATE_UP_TO = "navigate_up_to";
+        public static final String COMMAND_START_ACTIVITY = "start_activity";
         public static final String COMMAND_START_ACTIVITIES = "start_activities";
     }
 
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenReplaceIconActivity.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenReplaceIconActivity.java
index c8e72b2..9c66d92 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenReplaceIconActivity.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/SplashScreenReplaceIconActivity.java
@@ -17,6 +17,7 @@
 package android.server.wm.app;
 
 import static android.server.wm.app.Components.TestStartingWindowKeys.CANCEL_HANDLE_EXIT;
+import static android.server.wm.app.Components.TestStartingWindowKeys.CENTER_VIEW_IS_SURFACE_VIEW;
 import static android.server.wm.app.Components.TestStartingWindowKeys.CONTAINS_CENTER_VIEW;
 import static android.server.wm.app.Components.TestStartingWindowKeys.DELAY_RESUME;
 import static android.server.wm.app.Components.TestStartingWindowKeys.ICON_ANIMATION_DURATION;
@@ -31,6 +32,7 @@
 import android.os.SystemClock;
 import android.server.wm.TestJournalProvider;
 import android.util.Log;
+import android.view.SurfaceView;
 import android.view.View;
 import android.window.SplashScreen;
 import android.window.SplashScreenView;
@@ -64,6 +66,7 @@
     private void onSplashScreenExit(SplashScreenView view) {
         final Context baseContext = getBaseContext();
         final View centerView = view.getIconView();
+        final boolean isSurfaceView = view.getIconView() instanceof SurfaceView;
         TestJournalProvider.putExtras(baseContext, REPLACE_ICON_EXIT, bundle -> {
             bundle.putBoolean(RECEIVE_SPLASH_SCREEN_EXIT, true);
             bundle.putBoolean(CONTAINS_CENTER_VIEW, centerView != null);
@@ -71,6 +74,7 @@
                     ? view.getIconAnimationDuration().toMillis() : 0);
             bundle.putLong(ICON_ANIMATION_START, view.getIconAnimationStart() != null
                     ? view.getIconAnimationStart().toEpochMilli() : 0);
+            bundle.putBoolean(CENTER_VIEW_IS_SURFACE_VIEW, isSurfaceView);
         });
         view.remove();
     }
diff --git a/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java b/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java
index e4203c5..5cf68b5 100644
--- a/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java
+++ b/tests/framework/base/windowmanager/app_base/src/android/server/wm/app/TestActivity.java
@@ -17,6 +17,7 @@
 package android.server.wm.app;
 
 import static android.server.wm.app.Components.TestActivity.COMMAND_NAVIGATE_UP_TO;
+import static android.server.wm.app.Components.TestActivity.COMMAND_START_ACTIVITY;
 import static android.server.wm.app.Components.TestActivity.EXTRA_CONFIG_ASSETS_SEQ;
 import static android.server.wm.app.Components.TestActivity.EXTRA_FIXED_ORIENTATION;
 import static android.server.wm.app.Components.TestActivity.EXTRA_INTENTS;
@@ -108,6 +109,14 @@
     @Override
     public void handleCommand(String command, Bundle data) {
         switch (command) {
+            case COMMAND_START_ACTIVITY:
+                final Intent startIntent = data.getParcelable(EXTRA_INTENT);
+                try {
+                    startActivity(startIntent);
+                } catch (Exception e) {
+                    Log.w(getTag(), "Failed to startActivity: " + startIntent, e);
+                }
+                break;
             case COMMAND_START_ACTIVITIES:
                 final Parcelable[] intents = data.getParcelableArray(EXTRA_INTENTS);
                 startActivities(Arrays.copyOf(intents, intents.length, Intent[].class));
diff --git a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
index c9a0876..8e30d28 100644
--- a/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
+++ b/tests/framework/base/windowmanager/backgroundactivity/src/android/server/wm/BackgroundActivityLaunchTest.java
@@ -488,7 +488,7 @@
             return;
         }
 
-        String cmdResult = runShellCommand("dpm set-device-owner --user cur "
+        String cmdResult = runShellCommand("dpm set-device-owner --user 0 "
                 + APP_A_SIMPLE_ADMIN_RECEIVER.flattenToString());
         assertThat(cmdResult).contains("Success");
         EventReceiver receiver = new EventReceiver(
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
index 1cda8b0..d0265f1f 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
@@ -54,8 +54,6 @@
 import android.provider.Settings;
 import android.server.wm.settings.SettingsSession;
 
-import androidx.test.filters.FlakyTest;
-
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -238,7 +236,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 188207199)
     public void testTranslucentAssistantActivityStackVisibility() throws Exception {
         try (final AssistantSession assistantSession = new AssistantSession()) {
             assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
index 56016cd..e7c5894 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
@@ -16,7 +16,10 @@
 
 package android.server.wm;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -25,7 +28,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
 
 import android.app.Activity;
 import android.compat.testing.PlatformCompatChangeRule;
@@ -34,7 +36,6 @@
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.server.wm.WindowManagerTestBase.FocusableActivity;
-import android.server.wm.app.AbstractLifecycleLogActivity;
 
 import androidx.test.filters.FlakyTest;
 
@@ -66,9 +67,22 @@
             component(ResizeablePortraitActivity.class);
     private static final ComponentName NON_RESIZEABLE_PORTRAIT_ACTIVITY =
             component(NonResizeablePortraitActivity.class);
+    private static final ComponentName NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY =
+            component(NonResizeableAspectRatioActivity.class);
+    private static final ComponentName NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY =
+            component(NonResizeableLargeAspectRatioActivity.class);
     private static final ComponentName SUPPORTS_SIZE_CHANGES_PORTRAIT_ACTIVITY =
             component(SupportsSizeChangesPortraitActivity.class);
 
+    // Device aspect ratio (both portrait and landscape orientations) for min aspect ratio tests
+    private static final float SIZE_COMPAT_DISPLAY_ASPECT_RATIO = 1.2f;
+    // Fixed orientation min aspect ratio
+    private static final float FIXED_ORIENTATION_MIN_ASPECT_RATIO = 1.03f;
+    // The min aspect ratio of NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY.
+    private static final float ACTIVITY_MIN_ASPECT_RATIO = 1.6f;
+
+    private static final float FLOAT_EQUALITY_DELTA = 0.01f;
+
     @Rule
     public TestRule compatChangeRule = new PlatformCompatChangeRule();
 
@@ -81,6 +95,8 @@
 
         mDisplayMetricsSession =
                 createManagedDisplayMetricsSession(DEFAULT_DISPLAY);
+        createManagedLetterboxAspectRatioSession(DEFAULT_DISPLAY,
+                        FIXED_ORIENTATION_MIN_ASPECT_RATIO);
     }
 
     /**
@@ -149,8 +165,8 @@
      * Test that a min aspect ratio activity in letterbox results in sandboxed Display APIs.
      */
     @Test
-    public void testSandboxForNonResizablePortraitActivity() {
-        runSandboxTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /* isSandboxed= */ true);
+    public void testSandboxForNonResizableAspectRatioActivity() {
+        runSandboxTest(/* isSandboxed= */ true);
     }
 
     /**
@@ -159,8 +175,8 @@
      */
     @Test
     @EnableCompatChanges({ActivityInfo.NEVER_SANDBOX_DISPLAY_APIS})
-    public void testSandboxForNonResizablePortraitActivityNeverSandboxDisplayApisEnabled() {
-        runSandboxTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /* isSandboxed= */ false);
+    public void testSandboxForNonResizableAspectRatioActivityNeverSandboxDisplayApisEnabled() {
+        runSandboxTest(/* isSandboxed= */ false);
     }
 
     /**
@@ -169,27 +185,100 @@
      */
     @Test
     @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
-    public void testSandboxForNonResizablePortraitActivityAlwaysSandboxDisplayApisEnabled() {
-        runSandboxTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /* isSandboxed= */ true);
+    public void testSandboxForNonResizableAspectRatioActivityAlwaysSandboxDisplayApisEnabled() {
+        runSandboxTest(/* isSandboxed= */ true);
     }
 
     /**
-     * Test that a resizable portrait activity in split screen does have the Display APIs sandboxed
-     * when the {@link ActivityInfo#ALWAYS_SANDBOX_DISPLAY_APIS} compat change is enabled.
+     * Test that only applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO} has no effect on its
+     * own. The aspect ratio of the activity should be the same as that of the task, which should be
+     * in line with that of the display.
      */
     @Test
-    @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
-    public void testSandboxForResizablePortraitActivityAlwaysSandboxDisplayApisEnabled() {
-        assumeTrue("Skipping test: no split multi-window support",
-                supportsSplitScreenMultiWindow());
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO})
+    public void testOverrideMinAspectRatioMissingSpecificOverride() {
+        // Note that we're using getBounds() in portrait, rather than getAppBounds() like other
+        // tests, because we're comparing to the display size and therefore need to consider insets.
+        runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY,
+                /* expectedInPortrait= */ SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
+                /* expectedInLandscape= */ FIXED_ORIENTATION_MIN_ASPECT_RATIO,
+                /* useAppBoundsInPortrait= */false);
+    }
 
-        // Launch a resizable activity into split screen.
-        launchActivityOnDisplay(RESIZEABLE_PORTRAIT_ACTIVITY, DEFAULT_DISPLAY);
-        putActivityInPrimarySplit(RESIZEABLE_PORTRAIT_ACTIVITY);
-        mWmState.computeState(RESIZEABLE_PORTRAIT_ACTIVITY);
+    /**
+     * Test that only applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE} has no effect on
+     * its own without the presence of {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO}.
+     */
+    @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE})
+    public void testOverrideMinAspectRatioMissingGeneralOverride() {
+        // Note that we're using getBounds() in portrait, rather than getAppBounds() like other
+        // tests, because we're comparing to the display size and therefore need to consider insets.
+        runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY,
+                /* expectedInPortrait= */ SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
+                /* expectedInLandscape= */ FIXED_ORIENTATION_MIN_ASPECT_RATIO,
+                /* useAppBoundsInPortrait= */false);
+    }
 
-        // The resizable activity is sandboxed, due to the config being enabled.
-        assertSandboxed(RESIZEABLE_PORTRAIT_ACTIVITY, /* expectedSandboxed= */ true);
+    /**
+     * Test that applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE} sets the min aspect
+     * ratio to {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE}.
+     */
+    @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE})
+    public void testOverrideMinAspectRatioLargeAspectRatio() {
+        runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY,
+                /* expected= */ OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE);
+    }
+
+    /**
+     * Test that applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_MEDIUM} sets the min aspect
+     * ratio to {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE}.
+     */
+    @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+    public void testOverrideMinAspectRatioMediumAspectRatio() {
+        runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY,
+                /* expected= */ OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE);
+    }
+
+    /**
+     * Test that applying multiple min aspect ratio overrides result in the largest one taking
+     * effect.
+     */
+    @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE,
+            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+    public void testOverrideMinAspectRatioBothAspectRatios() {
+        runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY,
+                /* expected= */ OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE);
+    }
+
+    /**
+     * Test that the min aspect ratio of the activity as defined in the manifest is ignored if
+     * there is an override for a larger min aspect ratio present (16:9 > 1.6).
+     */
+    @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE})
+    public void testOverrideMinAspectRatioActivityMinAspectRatioSmallerThanOverride() {
+        runMinAspectRatioTest(NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY,
+                /* expected= */ OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE);
+    }
+
+    /**
+     * Test that the min aspect ratio of the activity as defined in the manifest is upheld if
+     * there is a n override for a smaller min aspect ratio present (3:2 < 1.6).
+     */
+    @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+    public void testOverrideMinAspectRatioActivityMinAspectRatioLargerThanOverride() {
+        runMinAspectRatioTest(NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY,
+                /* expected= */ ACTIVITY_MIN_ASPECT_RATIO);
     }
 
     /**
@@ -203,7 +292,7 @@
      */
     private void runSizeCompatTest(ComponentName activity, boolean inSizeCompatModeAfterResize) {
         runSizeCompatTest(activity, /* resizeRatio= */ 0.5, inSizeCompatModeAfterResize);
-        mDisplayMetricsSession.restoreDisplayMetrics();
+        restoreDisplay(activity);
         runSizeCompatTest(activity, /* resizeRatio= */ 2, inSizeCompatModeAfterResize);
     }
 
@@ -218,7 +307,7 @@
      */
     private void runSizeCompatTest(ComponentName activity, double resizeRatio,
             boolean inSizeCompatModeAfterResize) {
-        launchActivityOnDisplay(activity, DEFAULT_DISPLAY);
+        launchActivity(activity);
 
         assertSizeCompatMode(activity, /* expectedInSizeCompatMode= */ false);
 
@@ -243,40 +332,129 @@
      * Similar to {@link #runSizeCompatTest(ComponentName, boolean)}, but the activity is expected
      * to be in size compat mode after resizing the display.
      *
-     * @param activity    the activity under test
      * @param isSandboxed when {@code true}, {@link android.app.WindowConfiguration#getMaxBounds()}
      *                    are sandboxed to the activity bounds. Otherwise, they inherit the
      *                    DisplayArea bounds
      */
-    private void runSandboxTest(ComponentName activity, boolean isSandboxed) {
+    private void runSandboxTest(boolean isSandboxed) {
+        ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY;
         runSizeCompatTest(activity, /* resizeRatio= */ 0.5, /* inSizeCompatModeAfterResize=*/ true);
         assertSandboxed(activity, isSandboxed);
-        mDisplayMetricsSession.restoreDisplayMetrics();
+        restoreDisplay(activity);
         runSizeCompatTest(activity, /* resizeRatio= */ 2, /* inSizeCompatModeAfterResize=*/ true);
         assertSandboxed(activity, isSandboxed);
     }
 
-    private void assertSandboxed(ComponentName activity, boolean expectedSandboxed) {
-        mWmState.computeState(new WaitForValidActivityState(activity));
-        final WindowManagerState.ActivityTask activityTask = mWmState.getTaskByActivity(activity);
-        assertNotNull(activityTask);
-        final Rect activityBounds = activityTask.getBounds();
-        final Rect maxBounds = activityTask.mFullConfiguration.windowConfiguration.getMaxBounds();
-        WindowManagerState.DisplayArea tda = mWmState.getTaskDisplayArea(activity);
+    private void assertSandboxed(ComponentName activityName, boolean expectedSandboxed) {
+        mWmState.computeState(new WaitForValidActivityState(activityName));
+        final WindowManagerState.Activity activity = mWmState.getActivity(activityName);
+        assertNotNull(activity);
+        final Rect activityBounds = activity.getBounds();
+        final Rect maxBounds = activity.getMaxBounds();
+        WindowManagerState.DisplayArea tda = mWmState.getTaskDisplayArea(activityName);
+        assertNotNull(tda);
         if (expectedSandboxed) {
             assertEquals(
                     "The Window has max bounds sandboxed to the window bounds",
                     activityBounds, maxBounds);
-        } else if (tda != null) {
+        } else {
             assertEquals(
                     "The Window is not sandboxed, with max bounds reflecting the DisplayArea",
-                    tda.mFullConfiguration.windowConfiguration.getBounds(), maxBounds);
+                    tda.getBounds(), maxBounds);
         }
     }
 
+    /**
+     * Launches the provided activity twice. The first time, the display is resized to a portrait
+     * aspect ratio. The second time, the display is resized to a landscape aspect ratio.
+     *
+     * @param activity the activity under test.
+     * @param expected the expected aspect ratio in both portrait and landscape displays.
+     */
+    private void runMinAspectRatioTest(ComponentName activity, float expected) {
+        runMinAspectRatioTest(activity, expected, expected, /* useAppBoundsInPortrait= */ true);
+    }
+
+    /**
+     * Launches the provided activity twice. The first time, the display is resized to a portrait
+     * aspect ratio. The second time, the display is resized to a landscape aspect ratio.
+     *
+     * @param activity               the activity under test.
+     * @param expectedInPortrait     the expected aspect ratio in portrait display.
+     * @param expectedInLandscape    the expected aspect ratio in portrait display.
+     * @param useAppBoundsInPortrait whether to use {@code activity#getAppBounds} rather than
+     *                               {@code activity.getBounds} in portrait display.
+     */
+    private void runMinAspectRatioTest(ComponentName activity, float expectedInPortrait,
+            float expectedInLandscape, boolean useAppBoundsInPortrait) {
+        // Change the aspect ratio of the display to something that is smaller than all the aspect
+        // ratios used throughout those tests but still portrait. This ensures we're using
+        // enforcing aspect ratio behaviour within orientation.
+        mDisplayMetricsSession.changeAspectRatio(SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
+                ORIENTATION_PORTRAIT);
+        launchActivity(activity);
+        assertEquals(expectedInPortrait,
+                getActivityAspectRatio(activity, /* useAppBounds= */ useAppBoundsInPortrait),
+                FLOAT_EQUALITY_DELTA);
+
+        // Change the orientation of the display to landscape. In this case we should see
+        // fixed orientation letterboxing and the aspect ratio should be applied there.
+        mDisplayMetricsSession.changeAspectRatio(SIZE_COMPAT_DISPLAY_ASPECT_RATIO,
+                ORIENTATION_LANDSCAPE);
+        launchActivity(activity);
+        // A different aspect ratio logic is applied in fixed orientation letterboxing, so we need
+        // to use getBounds() rather than getAppBounds() here.
+        assertEquals(expectedInLandscape,
+                getActivityAspectRatio(activity, /* useAppBounds= */ false),
+                FLOAT_EQUALITY_DELTA);
+    }
+
+    /**
+     * Restore the display size and ensure configuration changes are complete.
+     */
+    private void restoreDisplay(ComponentName activity) {
+        final Rect originalTaskBounds = mWmState.getTaskByActivity(activity).getBounds();
+        mDisplayMetricsSession.restoreDisplayMetrics();
+        // Ensure configuration changes are complete after resizing the display.
+        waitForTaskBoundsChanged(activity, originalTaskBounds);
+    }
+
+    /**
+     * Resize the display and ensure configuration changes are complete.
+     */
     private void resizeDisplay(ComponentName activity, double sizeRatio) {
+        final Rect originalTaskBounds = mWmState.getTaskByActivity(activity).getBounds();
         mDisplayMetricsSession.changeDisplayMetrics(sizeRatio, /* densityRatio= */ 1);
         mWmState.computeState(new WaitForValidActivityState(activity));
+        // Ensure configuration changes are complete after resizing the display.
+        waitForTaskBoundsChanged(activity, originalTaskBounds);
+    }
+
+    /**
+     * Waits until the given activity has updated task bounds.
+     */
+    private void waitForTaskBoundsChanged(ComponentName activityName, Rect priorTaskBounds) {
+        mWmState.waitForWithAmState(wmState -> {
+            WindowManagerState.ActivityTask task = wmState.getTaskByActivity(activityName);
+            return task != null && !task.getBounds().equals(priorTaskBounds);
+        }, "checking task bounds updated");
+    }
+
+    private float getActivityAspectRatio(ComponentName componentName, boolean useAppBounds) {
+        WindowManagerState.Activity activity = mWmState.getActivity(componentName);
+        assertNotNull(activity);
+        Rect bounds = useAppBounds ? activity.getAppBounds() : activity.getBounds();
+        assertNotNull(bounds);
+        return Math.max(bounds.height(), bounds.width())
+                / (float) (Math.min(bounds.height(), bounds.width()));
+    }
+
+    private void launchActivity(ComponentName activity) {
+        getLaunchActivityBuilder()
+                .setDisplayId(DEFAULT_DISPLAY)
+                .setTargetActivity(activity)
+                .setUseInstrumentation()
+                .execute();
     }
 
     private static ComponentName component(Class<? extends Activity> activity) {
@@ -286,9 +464,15 @@
     public static class ResizeablePortraitActivity extends FocusableActivity {
     }
 
-    public static class NonResizeablePortraitActivity extends AbstractLifecycleLogActivity {
+    public static class NonResizeablePortraitActivity extends FocusableActivity {
     }
 
-    public static class SupportsSizeChangesPortraitActivity extends AbstractLifecycleLogActivity {
+    public static class NonResizeableAspectRatioActivity extends FocusableActivity {
+    }
+
+    public static class NonResizeableLargeAspectRatioActivity extends FocusableActivity {
+    }
+
+    public static class SupportsSizeChangesPortraitActivity extends FocusableActivity {
     }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java b/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java
index 0698c153..78ff7a7 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DragDropTest.java
@@ -60,7 +60,6 @@
 
 @Presubmit
 @RunWith(AndroidJUnit4.class)
-@FlakyTest(bugId = 186608789)
 public class DragDropTest extends WindowManagerTestBase {
     static final String TAG = "DragDropTest";
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTestBase.java
index 5ad4c018..60bbefb 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTestBase.java
@@ -26,13 +26,7 @@
 
 class KeyguardTestBase extends ActivityManagerTestBase {
 
-    KeyguardManager mKeyguardManager;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
-    }
+    final KeyguardManager mKeyguardManager = mKm;
 
     static void assertOnDismissSucceeded(ComponentName testingComponentName) {
         assertDismissCallback(testingComponentName, ENTRY_ON_DISMISS_SUCCEEDED);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java
index f5e7dc9..369069a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java
@@ -39,7 +39,6 @@
  */
 @Presubmit
 @android.server.wm.annotation.Group3
-@FlakyTest(bugId = 186608789)
 public class MultiDisplayKeyguardTests extends MultiDisplayTestBase {
 
     @Before
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
index ab6a12e..afb3ffd 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
@@ -17,6 +17,7 @@
 package android.server.wm;
 
 import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.provider.Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS;
 import static android.server.wm.StateLogger.log;
 import static android.server.wm.UiDeviceUtils.pressSleepButton;
@@ -284,6 +285,20 @@
             return ReportedDisplayMetrics.getDisplayMetrics(mDisplayId);
         }
 
+        void changeAspectRatio(double aspectRatio, int orientation) {
+            final Size originalSize = mInitialDisplayMetrics.physicalSize;
+            final int smaller = originalSize.getWidth();
+            final int larger = (int) (smaller * aspectRatio);
+            Size overrideSize;
+            if (orientation == ORIENTATION_LANDSCAPE) {
+                overrideSize = new Size(larger, smaller);
+            }
+            else {
+                overrideSize = new Size(smaller, larger);
+            }
+            overrideDisplayMetrics(overrideSize, mInitialDisplayMetrics.physicalDensity);
+        }
+
         void changeDisplayMetrics(double sizeRatio, double densityRatio) {
             final Size originalSize = mInitialDisplayMetrics.physicalSize;
             final int density = mInitialDisplayMetrics.physicalDensity;
@@ -313,6 +328,48 @@
         return mObjectTracker.manage(new DisplayMetricsSession(displayId));
     }
 
+    public static class LetterboxAspectRatioSession implements AutoCloseable {
+        private static final String WM_SET_IGNORE_ORIENTATION_REQUEST =
+                "wm set-ignore-orientation-request ";
+        private static final String WM_GET_IGNORE_ORIENTATION_REQUEST =
+                "wm get-ignore-orientation-request";
+        private static final Pattern IGNORE_ORIENTATION_REQUEST_PATTERN =
+                Pattern.compile("ignoreOrientationRequest (true|false) for displayId=\\d+");
+
+        private static final String WM_SET_LETTERBOX_STYLE_ASPECT_RATIO =
+                "wm set-letterbox-style --aspectRatio ";
+        private static final String WM_RESET_LETTERBOX_STYLE_ASPECT_RATIO
+                = "wm reset-letterbox-style aspectRatio";
+
+        final int mDisplayId;
+        final boolean mInitialIgnoreOrientationRequest;
+
+        LetterboxAspectRatioSession(int displayId, float aspectRatio) {
+            mDisplayId = displayId;
+            Matcher matcher = IGNORE_ORIENTATION_REQUEST_PATTERN.matcher(
+                    executeShellCommand(WM_GET_IGNORE_ORIENTATION_REQUEST + " -d " + mDisplayId));
+            assertTrue("get-ignore-orientation-request should match pattern", matcher.find());
+            mInitialIgnoreOrientationRequest = Boolean.parseBoolean(matcher.group(1));
+
+            executeShellCommand("wm set-ignore-orientation-request true -d " + mDisplayId);
+            executeShellCommand(WM_SET_LETTERBOX_STYLE_ASPECT_RATIO + aspectRatio);
+        }
+
+        @Override
+        public void close() {
+            executeShellCommand(
+                    WM_SET_IGNORE_ORIENTATION_REQUEST + mInitialIgnoreOrientationRequest + " -d "
+                            + mDisplayId);
+            executeShellCommand(WM_RESET_LETTERBOX_STYLE_ASPECT_RATIO);
+        }
+    }
+
+    /** @see ObjectTracker#manage(AutoCloseable) */
+    protected LetterboxAspectRatioSession createManagedLetterboxAspectRatioSession(int displayId,
+            float aspectRatio) {
+        return mObjectTracker.manage(new LetterboxAspectRatioSession(displayId, aspectRatio));
+    }
+
     void waitForDisplayGone(Predicate<DisplayContent> displayPredicate) {
         waitForOrFail("displays to be removed", () -> {
             mWmState.computeState();
@@ -320,11 +377,6 @@
         });
     }
 
-    void assertSecurityExceptionFromActivityLauncher() {
-        waitForOrFail("SecurityException from " + ActivityLauncher.TAG,
-            ActivityLauncher::hasCaughtSecurityException);
-    }
-
     /** @see ObjectTracker#manage(AutoCloseable) */
     protected VirtualDisplaySession createManagedVirtualDisplaySession() {
         return mObjectTracker.manage(new VirtualDisplaySession());
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java
new file mode 100644
index 0000000..3d6d97c
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java
@@ -0,0 +1,166 @@
+/*
+ * 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.server.wm;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.server.wm.RoundedCornerTests.TestActivity.EXTRA_ORIENTATION;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.app.AppOpsManager;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.platform.test.annotations.Presubmit;
+import android.view.Gravity;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.compatibility.common.util.PollingCheck;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@Presubmit
+@RunWith(Parameterized.class)
+public class PrivacyIndicatorBoundsTests {
+
+    private static final String TAG = PrivacyIndicatorBoundsTests.class.getSimpleName();
+    private static final long TIMEOUT_MS = 1000;
+
+    @Parameterized.Parameters(name= "{1}({0})")
+    public static Object[][] data() {
+        return new Object[][]{
+                {SCREEN_ORIENTATION_PORTRAIT, "SCREEN_ORIENTATION_PORTRAIT"},
+                {SCREEN_ORIENTATION_LANDSCAPE, "SCREEN_ORIENTATION_LANDSCAPE"},
+                {SCREEN_ORIENTATION_REVERSE_LANDSCAPE, "SCREEN_ORIENTATION_REVERSE_LANDSCAPE"},
+                {SCREEN_ORIENTATION_REVERSE_PORTRAIT, "SCREEN_ORIENTATION_REVERSE_PORTRAIT"},
+        };
+    }
+
+    @Parameterized.Parameter(0)
+    public int orientation;
+
+    @Parameterized.Parameter(1)
+    public String orientationName;
+
+    @Rule
+    public final ActivityTestRule<TestActivity> mTestActivity =
+            new ActivityTestRule<>(TestActivity.class, false /* initialTouchMode */,
+                    false /* launchActivity */);
+
+
+    @Test
+    public void testStaticBoundsAreNotNull() {
+        final PrivacyIndicatorBoundsTests.TestActivity activity = mTestActivity.launchActivity(
+                new Intent().putExtra(EXTRA_ORIENTATION, orientation));
+        getInstrumentation().runOnMainSync(() -> {
+            activity.addChildWindow();
+        });
+
+        final View childWindowRoot = activity.getChildWindowRoot();
+        PollingCheck.waitFor(TIMEOUT_MS, () -> childWindowRoot.getWidth() > 0);
+        PollingCheck.waitFor(TIMEOUT_MS, () -> activity.getDispatchedInsets() != null);
+        WindowInsets insets = activity.getDispatchedInsets();
+        assertNotNull(insets);
+        Rect screenBounds = activity.getScreenBounds();
+        assertNotNull(screenBounds);
+        Rect bounds = insets.getPrivacyIndicatorBounds();
+        assertNotNull(bounds);
+        assertEquals(bounds.top, 0);
+        // TODO 188788786: Figure out why the screen bounds are different in cuttlefish,
+        // causing failures
+        // assertTrue(bounds + " not contained in " + screenBounds, screenBounds.contains(bounds));
+        assertTrue(bounds.left >= 0);
+        assertTrue(bounds.right >= 0);
+    }
+
+    public static class TestActivity extends Activity {
+        static final String EXTRA_ORIENTATION = "extra.orientation";
+
+        private View mChildWindowRoot;
+        private WindowInsets mDispatchedInsets;
+        private Rect mScreenBounds = null;
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+            getWindow().getDecorView().getWindowInsetsController().hide(
+                    android.view.WindowInsets.Type.statusBars());
+            getWindow().getAttributes().layoutInDisplayCutoutMode =
+                    LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+            if (getIntent() != null) {
+                setRequestedOrientation(getIntent().getIntExtra(
+                        EXTRA_ORIENTATION, SCREEN_ORIENTATION_UNSPECIFIED));
+            }
+
+        }
+
+        void addChildWindow() {
+            final WindowMetrics windowMetrics = getWindowManager().getMaximumWindowMetrics();
+            mScreenBounds = windowMetrics.getBounds();
+            final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
+            attrs.x = mScreenBounds.left;
+            attrs.y = mScreenBounds.top;
+            attrs.width = mScreenBounds.width();
+            attrs.height = mScreenBounds.height();
+            attrs.gravity = Gravity.LEFT | Gravity.TOP;
+            attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+            attrs.flags = FLAG_NOT_FOCUSABLE;
+            attrs.setFitInsetsTypes(0);
+            mChildWindowRoot = new View(this);
+            mChildWindowRoot.setOnApplyWindowInsetsListener(
+                    (v, insets) -> {
+                        mDispatchedInsets = insets;
+                        return insets;
+                    });
+            getWindowManager().addView(mChildWindowRoot, attrs);
+        }
+
+        View getChildWindowRoot() {
+            return mChildWindowRoot;
+        }
+
+        WindowInsets getDispatchedInsets() {
+            return mDispatchedInsets;
+        }
+
+        Rect getScreenBounds() {
+            return mScreenBounds;
+        }
+    }
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
index dad6ddb..08f4caa 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -20,15 +20,21 @@
 import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
 import static android.app.UiModeManager.MODE_NIGHT_NO;
 import static android.app.UiModeManager.MODE_NIGHT_YES;
+import static android.content.Intent.ACTION_MAIN;
+import static android.content.Intent.CATEGORY_HOME;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.server.wm.CliIntentExtra.extraBool;
 import static android.server.wm.CliIntentExtra.extraString;
 import static android.server.wm.WindowManagerState.STATE_RESUMED;
-import static android.server.wm.WindowManagerState.STATE_STOPPED;
 import static android.server.wm.app.Components.HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY;
+import static android.server.wm.app.Components.HOME_ACTIVITY;
 import static android.server.wm.app.Components.SPLASHSCREEN_ACTIVITY;
 import static android.server.wm.app.Components.SPLASH_SCREEN_REPLACE_ICON_ACTIVITY;
 import static android.server.wm.app.Components.SPLASH_SCREEN_REPLACE_THEME_ACTIVITY;
+import static android.server.wm.app.Components.TestActivity.COMMAND_START_ACTIVITY;
+import static android.server.wm.app.Components.TestActivity.EXTRA_INTENT;
 import static android.server.wm.app.Components.TestStartingWindowKeys.CANCEL_HANDLE_EXIT;
+import static android.server.wm.app.Components.TestStartingWindowKeys.CENTER_VIEW_IS_SURFACE_VIEW;
 import static android.server.wm.app.Components.TestStartingWindowKeys.CONTAINS_BRANDING_VIEW;
 import static android.server.wm.app.Components.TestStartingWindowKeys.CONTAINS_CENTER_VIEW;
 import static android.server.wm.app.Components.TestStartingWindowKeys.DELAY_RESUME;
@@ -70,6 +76,7 @@
 import android.graphics.Color;
 import android.graphics.Insets;
 import android.graphics.Rect;
+import android.os.Bundle;
 import android.platform.test.annotations.Presubmit;
 import android.view.WindowManager;
 import android.view.WindowMetrics;
@@ -81,12 +88,14 @@
 import org.junit.Test;
 
 import java.util.Collections;
+import java.util.function.Consumer;
 
 /**
  * Build/Install/Run:
  * atest CtsWindowManagerDeviceTestCases:SplashscreenTests
  */
 @Presubmit
+@android.server.wm.annotation.Group1
 public class SplashscreenTests extends ActivityManagerTestBase {
 
     private static final int CENTER_ICON_SIZE = 160;
@@ -102,6 +111,27 @@
         mWmState.setSanityCheckWithFocusedWindow(true);
     }
 
+    private CommandSession.ActivitySession prepareTestLauncher() {
+        createManagedHomeActivitySession(HOME_ACTIVITY);
+        return createManagedActivityClientSession()
+                .startActivity(new Intent(ACTION_MAIN)
+                        .addCategory(CATEGORY_HOME)
+                        .addFlags(FLAG_ACTIVITY_NEW_TASK)
+                        .setComponent(HOME_ACTIVITY));
+    }
+
+    private void startActivityFromTestLauncher(CommandSession.ActivitySession homeActivity,
+            ComponentName componentName, Consumer<Intent> fillExtra) {
+
+        final Bundle data = new Bundle();
+        final Intent startIntent = new Intent();
+        startIntent.setComponent(componentName);
+        startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        fillExtra.accept(startIntent);
+        data.putParcelable(EXTRA_INTENT, startIntent);
+        homeActivity.sendCommand(COMMAND_START_ACTIVITY, data);
+    }
+
     @Test
     public void testSplashscreenContent() {
         launchActivityNoWait(SPLASHSCREEN_ACTIVITY);
@@ -155,6 +185,18 @@
         assertColors(image, bottomInsetsBounds, primaryColor, 0.80f, secondaryColor, 0.10f, null);
     }
 
+    // For real devices, gamma correction might be applied on hardware driver, so the colors may
+    // not exactly match.
+    private static boolean isSimilarColor(int a, int b) {
+        if (a == b) {
+            return true;
+        }
+        return Math.abs(Color.alpha(a) - Color.alpha(b)) +
+                Math.abs(Color.red(a) - Color.red(b)) +
+                Math.abs(Color.green(a) - Color.green(b)) +
+                Math.abs(Color.blue(a) - Color.blue(b)) < 10;
+    }
+
     private void assertColors(Bitmap img, Rect bounds, int primaryColor, float expectedPrimaryRatio,
             int secondaryColor, float acceptableWrongRatio, Rect ignoreRect) {
 
@@ -175,9 +217,9 @@
                     continue;
                 }
                 final int color = img.getPixel(x, y);
-                if (primaryColor == color) {
+                if (isSimilarColor(primaryColor, color)) {
                     primaryPixels++;
-                } else if (secondaryColor == color) {
+                } else if (isSimilarColor(secondaryColor, color)) {
                     secondaryPixels++;
                 } else {
                     img.setPixel(x, y, Color.MAGENTA);
@@ -226,10 +268,12 @@
     private void launchRuntimeHandleExitAnimationActivity(boolean extraOnCreate,
             boolean extraOnResume, boolean extraCancel, boolean expectResult) throws Exception {
         TestJournalProvider.TestJournalContainer.start();
-        launchActivity(HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY,
-                extraBool(REQUEST_HANDLE_EXIT_ON_CREATE, extraOnCreate),
-                extraBool(REQUEST_HANDLE_EXIT_ON_RESUME, extraOnResume),
-                extraBool(CANCEL_HANDLE_EXIT, extraCancel));
+        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
+        startActivityFromTestLauncher(homeActivity, HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY, intent -> {
+            intent.putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, extraOnCreate);
+            intent.putExtra(REQUEST_HANDLE_EXIT_ON_RESUME, extraOnResume);
+            intent.putExtra(CANCEL_HANDLE_EXIT, extraCancel);
+        });
 
         mWmState.computeState(HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY);
         mWmState.assertVisibility(HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY, true);
@@ -278,9 +322,12 @@
     @Test
     public void testHandleExitIconAnimatingActivity() throws Exception {
         assumeFalse(isLeanBack());
+        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
         TestJournalProvider.TestJournalContainer.start();
-        launchActivity(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY,
-                extraBool(REQUEST_HANDLE_EXIT_ON_CREATE, true));
+
+        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, intent -> {
+            intent.putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, true);
+        });
         mWmState.computeState(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY);
         mWmState.assertVisibility(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, true);
         final TestJournalProvider.TestJournal journal =
@@ -293,15 +340,18 @@
         assertTrue(iconAnimationStart != 0);
         assertEquals(iconAnimationDuration, 500);
         assertFalse(journal.extras.getBoolean(CONTAINS_BRANDING_VIEW));
+        assertTrue(journal.extras.getBoolean(CENTER_VIEW_IS_SURFACE_VIEW));
     }
 
     @Test
     public void testCancelHandleExitIconAnimatingActivity() {
         assumeFalse(isLeanBack());
+        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
         TestJournalProvider.TestJournalContainer.start();
-        launchActivity(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY,
-                extraBool(REQUEST_HANDLE_EXIT_ON_CREATE, true),
-                extraBool(CANCEL_HANDLE_EXIT, true));
+        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, intent -> {
+            intent.putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, true);
+            intent.putExtra(CANCEL_HANDLE_EXIT, true);
+        });
         mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, STATE_RESUMED);
         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
 
@@ -319,7 +369,7 @@
         final String shortCutId = "shortcut1";
         final ShortcutInfo.Builder b = new ShortcutInfo.Builder(
                 mContext, shortCutId);
-        final Intent i = new Intent(Intent.ACTION_MAIN)
+        final Intent i = new Intent(ACTION_MAIN)
                 .setComponent(SPLASHSCREEN_ACTIVITY);
         final ShortcutInfo shortcut = b.setShortLabel("label")
                 .setLongLabel("long label")
@@ -337,32 +387,39 @@
 
     @Test
     public void testOverrideSplashscreenTheme() {
+        assumeFalse(isLeanBack());
+        final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
+
+        // Pre-launch the activity to ensure status is cleared on the device
+        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
+                intent -> {});
+        mWmState.waitAndAssertActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
+
         // Launch the activity a first time, check that the splashscreen use the default theme,
         // and override the theme for the next launch
-        launchActivity(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
-                extraBool(OVERRIDE_THEME_ENABLED, true));
-
-        mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY, STATE_STOPPED);
-
         TestJournalProvider.TestJournal journal = TestJournalProvider.TestJournalContainer.get(
                 OVERRIDE_THEME_COMPONENT);
+
+        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
+                intent -> intent.putExtra(OVERRIDE_THEME_ENABLED, true));
+        mWmState.waitForActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
         assertEquals(Integer.toHexString(Color.BLUE),
                 Integer.toHexString(journal.extras.getInt(OVERRIDE_THEME_COLOR)));
 
         // Launch the activity a second time, check that the theme has been overridden and reset
         // to the default theme
-        launchActivity(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
-
-        mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY, STATE_STOPPED);
+        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
+                intent -> {});
+        mWmState.waitForActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
 
         journal = TestJournalProvider.TestJournalContainer.get(OVERRIDE_THEME_COMPONENT);
         assertEquals(Integer.toHexString(Color.RED),
                 Integer.toHexString(journal.extras.getInt(OVERRIDE_THEME_COLOR)));
 
         // Launch the activity a third time just to check that the theme has indeed been reset.
-        launchActivity(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
-
-        mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY, STATE_STOPPED);
+        startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_THEME_ACTIVITY,
+                intent -> {});
+        mWmState.waitForActivityRemoved(SPLASH_SCREEN_REPLACE_THEME_ACTIVITY);
 
         journal = TestJournalProvider.TestJournalContainer.get(OVERRIDE_THEME_COMPONENT);
         assertEquals(Integer.toHexString(Color.BLUE),
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
index 145b700..1ba6672 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
@@ -16,10 +16,15 @@
 
 package android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.server.wm.WindowManagerState.STATE_INITIALIZING;
 import static android.server.wm.WindowManagerState.STATE_STOPPED;
-import static android.server.wm.app.Components.ALT_LAUNCHING_ACTIVITY;
+import static android.server.wm.app.Components.BROADCAST_RECEIVER_ACTIVITY;
 import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
 import static android.server.wm.app.Components.NO_RELAUNCH_ACTIVITY;
 import static android.server.wm.app.Components.TEST_ACTIVITY;
@@ -40,7 +45,6 @@
 
 import android.app.Activity;
 import android.app.ActivityOptions;
-import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Bundle;
@@ -48,8 +52,6 @@
 import android.server.wm.CommandSession.ActivitySession;
 import android.server.wm.intent.Activities;
 
-import androidx.test.filters.FlakyTest;
-
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -73,7 +75,7 @@
         final ComponentName defaultHome = getDefaultHomeComponent();
         final int[] allActivityTypes = Arrays.copyOf(ALL_ACTIVITY_TYPE_BUT_HOME,
                 ALL_ACTIVITY_TYPE_BUT_HOME.length + 1);
-        allActivityTypes[allActivityTypes.length - 1] = WindowConfiguration.ACTIVITY_TYPE_HOME;
+        allActivityTypes[allActivityTypes.length - 1] = ACTIVITY_TYPE_HOME;
         removeRootTasksWithActivityTypes(allActivityTypes);
 
         waitAndAssertResumedActivity(defaultHome,
@@ -90,7 +92,6 @@
      * from an {@link Activity} {@link android.content.Context}.
      */
     @Test
-    @FlakyTest(bugId = 188207199)
     public void testStartActivityContexts() {
         // Note by default LaunchActivityBuilder will use LAUNCHING_ACTIVITY to launch the target.
 
@@ -203,7 +204,6 @@
      * activity because the caller C in different uid cannot launch a non-exported activity.
      */
     @Test
-    @FlakyTest(bugId = 188207199)
     public void testStartActivityByNavigateUpToFromDiffUid() {
         final Intent intent1 = new Intent(mContext, Activities.RegularActivity.class);
         final String regularActivityName = Activities.RegularActivity.class.getName();
@@ -261,6 +261,49 @@
                 taskIds[1], taskIds[2]);
     }
 
+    @Test
+    public void testNormalActivityCanNotSetActivityType() {
+        // Activities should not be started if the launch activity type is set.
+        boolean useShellPermission = false;
+        startingActivityWithType(ACTIVITY_TYPE_STANDARD, useShellPermission);
+        startingActivityWithType(ACTIVITY_TYPE_HOME, useShellPermission);
+        startingActivityWithType(ACTIVITY_TYPE_RECENTS, useShellPermission);
+        startingActivityWithType(ACTIVITY_TYPE_ASSISTANT, useShellPermission);
+        startingActivityWithType(ACTIVITY_TYPE_DREAM, useShellPermission);
+
+        // Activities can be started because they are started with shell permissions.
+        useShellPermission = true;
+        startingActivityWithType(ACTIVITY_TYPE_STANDARD, useShellPermission);
+        startingActivityWithType(ACTIVITY_TYPE_HOME, useShellPermission);
+        startingActivityWithType(ACTIVITY_TYPE_RECENTS, useShellPermission);
+        startingActivityWithType(ACTIVITY_TYPE_ASSISTANT, useShellPermission);
+        startingActivityWithType(ACTIVITY_TYPE_DREAM, useShellPermission);
+    }
+
+    private void startingActivityWithType(int type, boolean useShellPermission) {
+        separateTestJournal();
+        getLaunchActivityBuilder()
+                .setTargetActivity(BROADCAST_RECEIVER_ACTIVITY)
+                .setUseInstrumentation()
+                .setWithShellPermission(useShellPermission)
+                .setActivityType(type)
+                .setWaitForLaunched(false)
+                .setMultipleTask(true)
+                .execute();
+
+        mWmState.computeState();
+        if (useShellPermission) {
+            waitAndAssertResumedActivity(BROADCAST_RECEIVER_ACTIVITY,
+                    "Activity should be started and resumed");
+            mWmState.assertFrontStackActivityType("The activity type should be same as requested.",
+                    type);
+            mBroadcastActionTrigger.finishBroadcastReceiverActivity();
+            mWmState.waitAndAssertActivityRemoved(BROADCAST_RECEIVER_ACTIVITY);
+        } else {
+            assertSecurityExceptionFromActivityLauncher();
+        }
+    }
+
     /**
      * Assume there are 3 activities (A1, A2, B1) with default launch mode. The uid of B1 is
      * different from A1 and A2. After A1 called {@link Activity#startActivities} to start B1 and
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
index 571fa9d..12cc716 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
@@ -19,20 +19,15 @@
 import static android.server.wm.UiDeviceUtils.pressHomeButton;
 import static android.server.wm.UiDeviceUtils.pressUnlockButton;
 import static android.server.wm.UiDeviceUtils.pressWakeupButton;
-import static android.view.SurfaceControlViewHost.*;
+import static android.view.SurfaceControlViewHost.SurfacePackage;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.FlakyTest;
-import androidx.test.rule.ActivityTestRule;
-import org.junit.Before;
-import org.junit.Test;
-
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.Instrumentation;
@@ -53,11 +48,19 @@
 import android.widget.Button;
 import android.widget.FrameLayout;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
+import androidx.test.rule.ActivityTestRule;
+
 import com.android.compatibility.common.util.CtsTouchUtils;
 import com.android.compatibility.common.util.WidgetTestUtils;
 
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Ensure end-to-end functionality of SurfaceControlViewHost.
@@ -433,4 +436,87 @@
         CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mSurfaceView);
         assertTrue(mClicked);
     }
+
+    @Test
+    public void testTransferSurfacePackage() throws Throwable {
+        // Create a surface view and wait for its surface to be created.
+        CountDownLatch surfaceCreated = new CountDownLatch(1);
+        CountDownLatch surface2Created = new CountDownLatch(1);
+        CountDownLatch viewDetached = new CountDownLatch(1);
+        AtomicReference<SurfacePackage> surfacePackageRef = new AtomicReference<>(null);
+        AtomicReference<SurfacePackage> surfacePackageCopyRef = new AtomicReference<>(null);
+        AtomicReference<SurfaceView> secondSurfaceRef = new AtomicReference<>(null);
+
+        mActivityRule.runOnUiThread(() -> {
+            final FrameLayout content = new FrameLayout(mActivity);
+            mSurfaceView = new SurfaceView(mActivity);
+            mSurfaceView.setZOrderOnTop(true);
+            content.addView(mSurfaceView, new FrameLayout.LayoutParams(DEFAULT_SURFACE_VIEW_WIDTH,
+                    DEFAULT_SURFACE_VIEW_HEIGHT, Gravity.LEFT | Gravity.TOP));
+            mActivity.setContentView(content, new ViewGroup.LayoutParams(DEFAULT_SURFACE_VIEW_WIDTH,
+                    DEFAULT_SURFACE_VIEW_HEIGHT));
+            mSurfaceView.getHolder().addCallback(new SurfaceCreatedCallback(surfaceCreated));
+
+            // Create an embedded view.
+            mVr = new SurfaceControlViewHost(mActivity, mActivity.getDisplay(),
+                    mSurfaceView.getHostToken());
+            mEmbeddedView = new Button(mActivity);
+            mEmbeddedView.setOnClickListener((View v) -> mClicked = true);
+            mVr.setView(mEmbeddedView, mEmbeddedViewWidth, mEmbeddedViewHeight);
+
+            SurfacePackage surfacePackage = mVr.getSurfacePackage();
+            surfacePackageRef.set(surfacePackage);
+            surfacePackageCopyRef.set(new SurfacePackage(surfacePackage));
+
+            // Assign the surface package to the first surface
+            mSurfaceView.setChildSurfacePackage(surfacePackage);
+
+
+            // Create the second surface view to which we'll assign the surface package copy
+            SurfaceView secondSurface = new SurfaceView(mActivity);
+            secondSurfaceRef.set(secondSurface);
+
+            mSurfaceView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+                @Override
+                public void onViewAttachedToWindow(View v) {
+                }
+
+                @Override
+                public void onViewDetachedFromWindow(View v) {
+                    viewDetached.countDown();
+                }
+            });
+
+            secondSurface.getHolder().addCallback(new SurfaceCreatedCallback(surface2Created));
+
+        });
+        surfaceCreated.await();
+
+        // Add the second surface view and assign it the surface package copy
+        mActivityRule.runOnUiThread(() -> {
+            ViewGroup content = (ViewGroup) mSurfaceView.getParent();
+            content.addView(secondSurfaceRef.get(),
+                    new FrameLayout.LayoutParams(DEFAULT_SURFACE_VIEW_WIDTH,
+                            DEFAULT_SURFACE_VIEW_HEIGHT, Gravity.TOP | Gravity.LEFT));
+            secondSurfaceRef.get().setZOrderOnTop(true);
+            surfacePackageRef.get().release();
+            secondSurfaceRef.get().setChildSurfacePackage(surfacePackageCopyRef.get());
+
+            content.removeView(mSurfaceView);
+        });
+
+        // Wait for the first surface to be removed
+        surface2Created.await();
+        viewDetached.await();
+
+        mInstrumentation.waitForIdleSync();
+        waitUntilEmbeddedViewDrawn();
+
+        // Check if SurfacePackage copy remains valid even though the original package has
+        // been released and the original surface view removed.
+        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule,
+                secondSurfaceRef.get());
+        assertTrue(mClicked);
+    }
+
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java
index 2ca333e..c5f4a216 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TransitionSelectionTests.java
@@ -41,6 +41,8 @@
 import android.content.ComponentName;
 import android.platform.test.annotations.Presubmit;
 
+import androidx.test.filters.FlakyTest;
+
 import org.junit.Test;
 
 /**
@@ -84,6 +86,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 188904549)
     public void testOpenActivity_BothWallpaper() {
         testOpenActivity(true /*bottomWallpaper*/, true /*topWallpaper*/,
                 false /*slowStop*/, TRANSIT_WALLPAPER_INTRA_OPEN);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowUntrustedTouchTest.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowUntrustedTouchTest.java
index 2f7b5a5..dcd453c 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowUntrustedTouchTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowUntrustedTouchTest.java
@@ -53,8 +53,8 @@
 import android.provider.Settings;
 import android.server.wm.overlay.Components;
 import android.server.wm.overlay.R;
-import android.server.wm.shared.IUntrustedTouchTestService;
 import android.server.wm.shared.BlockingResultReceiver;
+import android.server.wm.shared.IUntrustedTouchTestService;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.view.Display;
@@ -67,7 +67,6 @@
 
 import androidx.annotation.AnimRes;
 import androidx.annotation.Nullable;
-import androidx.test.filters.FlakyTest;
 import androidx.test.rule.ActivityTestRule;
 
 import com.android.compatibility.common.util.AppOpsUtils;
@@ -521,7 +520,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 186608789)
     public void testWhenTwoActivityWindowsFromDifferentAppsTogetherBelowThreshold_blocksTouch()
             throws Throwable {
         addActivityOverlay(APP_A, /* opacity */ .7f);
@@ -764,7 +762,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 188207199)
     public void testWhenOneCustomToastWindow_blocksTouch() throws Throwable {
         addToastOverlay(APP_A, /* custom */ true);
 
@@ -783,7 +780,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 188207199)
     public void testWhenOneCustomToastWindowAndOneSelfSawWindow_blocksTouch()
             throws Throwable {
         addSawOverlay(APP_SELF, WINDOW_1, .9f);
@@ -795,7 +791,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 188207199)
     public void testWhenOneCustomToastWindowAndOneSawWindowBelowThreshold_blocksTouch()
             throws Throwable {
         addSawOverlay(APP_A, WINDOW_1, .5f);
@@ -807,7 +802,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 188207199)
     public void testWhenOneCustomToastWindowAndOneSawWindowBelowThresholdFromDifferentApp_blocksTouch()
             throws Throwable {
         addSawOverlay(APP_A, WINDOW_1, .5f);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java
index 461c649..1d51c35 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleClientTestBase.java
@@ -36,7 +36,6 @@
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_GAINED;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_LOST;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_USER_LEAVE_HINT;
-import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.PRE_ON_CREATE;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
@@ -343,7 +342,6 @@
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             mLifecycleLogClient = LifecycleLog.LifecycleLogClient.create(this);
-            mLifecycleLogClient.onActivityCallback(PRE_ON_CREATE);
             mLifecycleLogClient.onActivityCallback(ON_CREATE);
 
             final Intent intent = getIntent();
@@ -537,6 +535,8 @@
         public static final String EXTRA_LAUNCH_ON_RESULT = "LAUNCH_ON_RESULT";
         public static final String EXTRA_LAUNCH_ON_RESUME_AFTER_RESULT =
                 "LAUNCH_ON_RESUME_AFTER_RESULT";
+        public static final String EXTRA_USE_TRANSLUCENT_RESULT =
+                "USE_TRANSLUCENT_RESULT";
 
         boolean mReceivedResultOk;
 
@@ -552,7 +552,14 @@
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
-            final Intent intent = new Intent(this, ResultActivity.class);
+
+            final Intent intent;
+            if (getIntent().hasExtra(EXTRA_USE_TRANSLUCENT_RESULT)) {
+                intent = new Intent(this, TranslucentResultActivity.class);
+            } else {
+                intent = new Intent(this, ResultActivity.class);
+            }
+
             final Bundle forwardExtras = getIntent().getBundleExtra(EXTRA_FORWARD_EXTRAS);
             if (forwardExtras != null) {
                 intent.putExtras(forwardExtras);
@@ -579,6 +586,10 @@
         }
     }
 
+    /** Translucent activity that is started for result. */
+    public static class TranslucentResultActivity extends ResultActivity {
+    }
+
     /** Test activity that is started for result. */
     public static class ResultActivity extends CallbackTrackingActivity {
         @Override
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleFreeformTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleFreeformTests.java
index 64d53d8..14cb77f 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleFreeformTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleFreeformTests.java
@@ -133,7 +133,7 @@
                 .setOptions(launchOptions)
                 .launch();
 
-        final Activity secondActivity = launchActivityInFullscreenAndWait(SecondActivity.class);
+        final Activity secondActivity = launchActivityAndWait(SecondActivity.class);
 
         new Launcher(ThirdActivity.class)
                 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
@@ -191,8 +191,7 @@
                 .setOptions(launchOptions)
                 .launch();
 
-        final Activity transparentActivity =
-            launchActivityInFullscreenAndWait(TranslucentActivity.class);
+        final Activity transparentActivity = launchActivityAndWait(TranslucentActivity.class);
 
         new Launcher(ThirdActivity.class)
                 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleLegacySplitScreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleLegacySplitScreenTests.java
index f7b7f49..79e56a0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleLegacySplitScreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleLegacySplitScreenTests.java
@@ -31,7 +31,6 @@
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_GAINED;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_LOST;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_USER_LEAVE_HINT;
-import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.PRE_ON_CREATE;
 import static android.server.wm.lifecycle.LifecycleVerifier.transition;
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -190,7 +189,7 @@
         // Check that activity was restarted and result was delivered
         waitAndAssertActivityStates(state(callbackTrackingActivity, ON_RESUME));
         LifecycleVerifier.assertSequence(CallbackTrackingActivity.class, getLifecycleLog(),
-                Arrays.asList(ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE,
+                Arrays.asList(ON_DESTROY, ON_CREATE, ON_START, ON_POST_CREATE,
                         ON_ACTIVITY_RESULT, ON_RESUME), "restart");
     }
 
@@ -283,7 +282,7 @@
 
         // Wait for the activity to relaunch and receive multi-window mode change
         final List<LifecycleLog.ActivityCallback> expectedEnterSequence =
-                Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY, PRE_ON_CREATE,
+                Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY,
                         ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED,
                         ON_TOP_POSITION_LOST, ON_PAUSE);
         waitForActivityTransitions(CallbackTrackingActivity.class, expectedEnterSequence);
@@ -297,7 +296,7 @@
 
         // Wait for the activity to relaunch and receive multi-window mode change
         final List<LifecycleLog.ActivityCallback> expectedExitSequence =
-                Arrays.asList(ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START,
+                Arrays.asList(ON_STOP, ON_DESTROY, ON_CREATE, ON_START,
                         ON_POST_CREATE, ON_RESUME, ON_PAUSE, ON_RESUME, ON_TOP_POSITION_GAINED);
         waitForActivityTransitions(CallbackTrackingActivity.class, expectedExitSequence);
         LifecycleVerifier.assertOrder(getLifecycleLog(), CallbackTrackingActivity.class,
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
index 1aabf7f..0ecc7f4 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
@@ -26,7 +26,6 @@
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_RESUME;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_START;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_STOP;
-import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.PRE_ON_CREATE;
 
 import static org.junit.Assume.assumeTrue;
 
@@ -102,8 +101,7 @@
                 getLifecycleLog(), Arrays.asList(expectedSequence, extraCycleSequence),
                 "activityEnteringPipOnTop");
         LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE),
-                "launchAndEnterPip");
+                Arrays.asList(ON_CREATE, ON_START, ON_RESUME, ON_PAUSE), "launchAndEnterPip");
     }
 
     @Test
@@ -275,7 +273,7 @@
         // Wait for it to launch and pause. Other activities should not be affected.
         waitAndAssertActivityStates(state(secondActivity, ON_RESUME));
         LifecycleVerifier.assertSequence(PipActivity.class, getLifecycleLog(),
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE),
+                Arrays.asList(ON_CREATE, ON_START, ON_RESUME, ON_PAUSE),
                 "launchAndEnterPip");
         LifecycleVerifier.assertEmptySequence(FirstActivity.class, getLifecycleLog(),
                 "launchPipOnTop");
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java
index 24e6300..a3cfcbf 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java
@@ -42,7 +42,6 @@
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_GAINED;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_LOST;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_USER_LEAVE_HINT;
-import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.PRE_ON_CREATE;
 import static android.server.wm.lifecycle.LifecycleVerifier.transition;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
@@ -314,7 +313,6 @@
                 state(ResultActivity.class, ON_DESTROY));
         LifecycleVerifier.assertOrder(getLifecycleLog(), Arrays.asList(
                 // Base launching activity starting.
-                transition(LaunchForResultActivity.class, PRE_ON_CREATE),
                 transition(LaunchForResultActivity.class, ON_CREATE),
                 transition(LaunchForResultActivity.class, ON_START),
                 transition(LaunchForResultActivity.class, ON_POST_CREATE),
@@ -323,7 +321,6 @@
                 // An activity is automatically launched for result.
                 transition(LaunchForResultActivity.class, ON_TOP_POSITION_LOST),
                 transition(LaunchForResultActivity.class, ON_PAUSE),
-                transition(ResultActivity.class, PRE_ON_CREATE),
                 transition(ResultActivity.class, ON_CREATE),
                 transition(ResultActivity.class, ON_START),
                 transition(ResultActivity.class, ON_RESUME),
@@ -336,7 +333,6 @@
                 // New activity is launched after receiving result in base activity.
                 transition(LaunchForResultActivity.class, ON_TOP_POSITION_LOST),
                 transition(LaunchForResultActivity.class, ON_PAUSE),
-                transition(CallbackTrackingActivity.class, PRE_ON_CREATE),
                 transition(CallbackTrackingActivity.class, ON_CREATE),
                 transition(CallbackTrackingActivity.class, ON_START),
                 transition(CallbackTrackingActivity.class, ON_RESUME),
@@ -385,9 +381,7 @@
         waitAndAssertActivityStates(state(CallbackTrackingActivity.class, ON_TOP_POSITION_GAINED));
 
         LifecycleVerifier.assertEntireSequence(Arrays.asList(
-                transition(NoDisplayActivity.class, PRE_ON_CREATE),
                 transition(NoDisplayActivity.class, ON_CREATE),
-                transition(CallbackTrackingActivity.class, PRE_ON_CREATE),
                 transition(CallbackTrackingActivity.class, ON_CREATE),
                 transition(CallbackTrackingActivity.class, ON_START),
                 transition(CallbackTrackingActivity.class, ON_POST_CREATE),
@@ -540,10 +534,10 @@
                 state(translucentActivity, ON_RESUME));
 
         LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
-                Arrays.asList(ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME,
+                Arrays.asList(ON_DESTROY, ON_CREATE, ON_START, ON_RESUME,
                         ON_PAUSE), "becomingVisiblePaused");
         final List<LifecycleLog.ActivityCallback> expectedSequence =
-                Arrays.asList(ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME);
+                Arrays.asList(ON_DESTROY, ON_CREATE, ON_START, ON_RESUME);
         LifecycleVerifier.assertSequence(TranslucentActivity.class, getLifecycleLog(),
                 expectedSequence, "becomingVisibleResumed");
     }
@@ -566,7 +560,7 @@
 
         // verify the result have sent back to original activity
         final List<LifecycleLog.ActivityCallback> expectedSequence =
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                         ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP,
                         ON_ACTIVITY_RESULT, ON_RESTART, ON_START, ON_RESUME,
                         ON_TOP_POSITION_GAINED);
@@ -581,24 +575,24 @@
                 .launch();
 
         final List<LifecycleLog.ActivityCallback> expectedSequence =
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                         ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST,
                         ON_PAUSE, ON_ACTIVITY_RESULT, ON_RESUME, ON_TOP_POSITION_GAINED);
         waitForActivityTransitions(LaunchForResultActivity.class, expectedSequence);
 
         // TODO(b/79218023): First activity might also be stopped before getting result.
         final List<LifecycleLog.ActivityCallback> sequenceWithStop =
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                         ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST,
                         ON_PAUSE, ON_STOP, ON_ACTIVITY_RESULT, ON_RESTART, ON_START, ON_RESUME,
                         ON_TOP_POSITION_GAINED);
         final List<LifecycleLog.ActivityCallback> thirdSequence =
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                         ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST,
                         ON_PAUSE, ON_STOP, ON_ACTIVITY_RESULT, ON_RESTART, ON_START, ON_RESUME,
                         ON_TOP_POSITION_GAINED);
         final List<LifecycleLog.ActivityCallback> fourthSequence =
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                         ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST,
                         ON_PAUSE, ON_STOP, ON_RESTART, ON_START, ON_ACTIVITY_RESULT, ON_RESUME,
                         ON_TOP_POSITION_GAINED);
@@ -633,17 +627,17 @@
         final List<List<LifecycleLog.ActivityCallback>> expectedSequences;
         if (isTranslucent) {
             expectedSequences = Arrays.asList(
-                    Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                    Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                             ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST, ON_PAUSE,
                             ON_ACTIVITY_RESULT, ON_RESUME, ON_TOP_POSITION_GAINED)
             );
         } else {
             expectedSequences = Arrays.asList(
-                    Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                    Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                             ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST,
                             ON_PAUSE, ON_STOP, ON_RESTART, ON_START, ON_ACTIVITY_RESULT, ON_RESUME,
                             ON_TOP_POSITION_GAINED),
-                    Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                    Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                             ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST,
                             ON_PAUSE, ON_STOP, ON_ACTIVITY_RESULT, ON_RESTART, ON_START, ON_RESUME,
                             ON_TOP_POSITION_GAINED)
@@ -666,7 +660,7 @@
 
         LifecycleVerifier.assertSequence(CallbackTrackingActivity.class,
                 getLifecycleLog(),
-                Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY, PRE_ON_CREATE,
+                Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY,
                         ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED),
                 "recreate");
     }
@@ -688,7 +682,7 @@
 
         LifecycleVerifier.assertSequence(CallbackTrackingActivity.class,
                 getLifecycleLog(),
-                Arrays.asList(ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START,
+                Arrays.asList(ON_STOP, ON_DESTROY, ON_CREATE, ON_START,
                         ON_POST_CREATE, ON_RESUME, ON_PAUSE),
                 "recreate");
     }
@@ -709,10 +703,10 @@
 
         final List<LifecycleLog.ActivityCallback> callbacks;
         if (isTranslucent(secondActivity)) {
-            callbacks = Arrays.asList(ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START,
+            callbacks = Arrays.asList(ON_STOP, ON_DESTROY, ON_CREATE, ON_START,
                     ON_POST_CREATE, ON_RESUME, ON_PAUSE);
         } else {
-            callbacks = Arrays.asList(ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START,
+            callbacks = Arrays.asList(ON_DESTROY, ON_CREATE, ON_START,
                     ON_POST_CREATE, ON_RESUME, ON_PAUSE, ON_STOP);
         }
 
@@ -786,13 +780,12 @@
         if (isTranslucent(secondActivity)) {
             expectedRelaunchSequence = Arrays.asList(ON_NEW_INTENT, ON_RESUME,
                     ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST,
-                    ON_PAUSE, ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START,
+                    ON_PAUSE, ON_STOP, ON_DESTROY, ON_CREATE, ON_START,
                     ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED);
         } else {
             expectedRelaunchSequence = Arrays.asList(ON_RESTART, ON_START, ON_NEW_INTENT, ON_RESUME,
                     ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY,
-                    PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
-                    ON_TOP_POSITION_GAINED);
+                    ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED);
         }
 
         waitForActivityTransitions(SingleTopActivity.class, expectedRelaunchSequence);
@@ -884,33 +877,33 @@
     @Test
     public void testFinishInOnCreate() throws Exception {
         verifyFinishAtStage( ResultActivity.class, EXTRA_FINISH_IN_ON_CREATE,
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_DESTROY), "onCreate");
+                Arrays.asList(ON_CREATE, ON_DESTROY), "onCreate");
     }
 
     @Test
     public void testFinishInOnCreateNoDisplay() throws Exception {
         verifyFinishAtStage(NoDisplayActivity.class, EXTRA_FINISH_IN_ON_CREATE,
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_DESTROY), "onCreate");
+                Arrays.asList(ON_CREATE, ON_DESTROY), "onCreate");
     }
 
     @Test
     public void testFinishInOnStart() throws Exception {
         verifyFinishAtStage(ResultActivity.class, EXTRA_FINISH_IN_ON_START,
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_STOP,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_STOP,
                         ON_DESTROY), "onStart");
     }
 
     @Test
     public void testFinishInOnStartNoDisplay() throws Exception {
         verifyFinishAtStage(NoDisplayActivity.class, EXTRA_FINISH_IN_ON_START,
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_STOP,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_STOP,
                         ON_DESTROY), "onStart");
     }
 
     @Test
     public void testFinishInOnResume() throws Exception {
         verifyFinishAtStage(ResultActivity.class, EXTRA_FINISH_IN_ON_RESUME,
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                         ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP,
                         ON_DESTROY), "onResume");
     }
@@ -918,7 +911,7 @@
     @Test
     public void testFinishInOnResumeNoDisplay() throws Exception {
         verifyFinishAtStage(NoDisplayActivity.class, EXTRA_FINISH_IN_ON_RESUME,
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                         ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP,
                         ON_DESTROY), "onResume");
     }
@@ -948,7 +941,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 186608789)
     public void testFinishBelowDialogActivity() throws Exception {
         verifyFinishAtStage(ResultActivity.class, EXTRA_FINISH_IN_ON_PAUSE, "onPause",
                 TranslucentCallbackTrackingActivity.class);
@@ -973,7 +965,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 186608789)
     public void testFinishBelowTranslucentActivityAfterDelay() throws Exception {
         final Activity bottomActivity = launchActivityAndWait(CallbackTrackingActivity.class);
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
index d5a51e9..5a41c48 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
@@ -35,7 +35,6 @@
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_STOP;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_GAINED;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_LOST;
-import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.PRE_ON_CREATE;
 import static android.server.wm.lifecycle.LifecycleVerifier.transition;
 import static android.view.Display.DEFAULT_DISPLAY;
 
@@ -175,7 +174,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 186608789)
     public void testTopPositionSwitchToTranslucentActivityOnTop() throws Exception {
         final Activity activity = launchActivityAndWait(CallbackTrackingActivity.class);
 
@@ -201,10 +199,8 @@
 
         waitAndAssertActivityStates(state(baseActivity, ON_STOP));
 
-        final List<ActivityCallback> expectedTopActivitySequence =
-                Arrays.asList(
-                        PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
-                        ON_TOP_POSITION_GAINED);
+        final List<ActivityCallback> expectedTopActivitySequence = Arrays.asList(
+                ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED);
         waitForActivityTransitions(ResultActivity.class, expectedTopActivitySequence);
 
         final List<Pair<String, ActivityCallback>> observedTransitions =
@@ -212,7 +208,6 @@
         final List<Pair<String, ActivityCallback>> expectedTransitions = Arrays.asList(
                 transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
                 transition(CallbackTrackingActivity.class, ON_PAUSE),
-                transition(LaunchForResultActivity.class, PRE_ON_CREATE),
                 transition(LaunchForResultActivity.class, ON_CREATE),
                 transition(LaunchForResultActivity.class, ON_START),
                 transition(LaunchForResultActivity.class, ON_POST_CREATE),
@@ -220,7 +215,6 @@
                 transition(LaunchForResultActivity.class, ON_TOP_POSITION_GAINED),
                 transition(LaunchForResultActivity.class, ON_TOP_POSITION_LOST),
                 transition(LaunchForResultActivity.class, ON_PAUSE),
-                transition(ResultActivity.class, PRE_ON_CREATE),
                 transition(ResultActivity.class, ON_CREATE),
                 transition(ResultActivity.class, ON_START),
                 transition(ResultActivity.class, ON_POST_CREATE),
@@ -238,26 +232,25 @@
         getLifecycleLog().clear();
         final Activity launchForResultActivity = new Launcher(LaunchForResultActivity.class)
                 .customizeIntent(LaunchForResultActivity.forwardFlag(EXTRA_FINISH_IN_ON_RESUME))
+                // Start the TranslucentResultActivity to avoid activity below stopped sometimes
+                // and resulted in different lifecycle events.
+                .setExtraFlags(LaunchForResultActivity.EXTRA_USE_TRANSLUCENT_RESULT)
                 .launch();
 
         waitAndAssertActivityStates(state(baseActivity, ON_STOP));
         final List<ActivityCallback> expectedLaunchingSequence =
-                Arrays.asList(
-                        PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                         ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST, ON_PAUSE,
                         ON_ACTIVITY_RESULT, ON_RESUME, ON_TOP_POSITION_GAINED);
         waitForActivityTransitions(LaunchForResultActivity.class, expectedLaunchingSequence);
 
-        final List<ActivityCallback> expectedTopActivitySequence =
-                Arrays.asList(
-                        PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
-                        ON_TOP_POSITION_GAINED);
-        waitForActivityTransitions(ResultActivity.class, expectedTopActivitySequence);
+        final List<ActivityCallback> expectedTopActivitySequence = Arrays.asList(ON_CREATE,
+                ON_START, ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED);
+        waitForActivityTransitions(TranslucentResultActivity.class, expectedTopActivitySequence);
 
         LifecycleVerifier.assertEntireSequence(Arrays.asList(
                 transition(CallbackTrackingActivity.class, ON_TOP_POSITION_LOST),
                 transition(CallbackTrackingActivity.class, ON_PAUSE),
-                transition(LaunchForResultActivity.class, PRE_ON_CREATE),
                 transition(LaunchForResultActivity.class, ON_CREATE),
                 transition(LaunchForResultActivity.class, ON_START),
                 transition(LaunchForResultActivity.class, ON_POST_CREATE),
@@ -265,19 +258,18 @@
                 transition(LaunchForResultActivity.class, ON_TOP_POSITION_GAINED),
                 transition(LaunchForResultActivity.class, ON_TOP_POSITION_LOST),
                 transition(LaunchForResultActivity.class, ON_PAUSE),
-                transition(ResultActivity.class, PRE_ON_CREATE),
-                transition(ResultActivity.class, ON_CREATE),
-                transition(ResultActivity.class, ON_START),
-                transition(ResultActivity.class, ON_POST_CREATE),
-                transition(ResultActivity.class, ON_RESUME),
-                transition(ResultActivity.class, ON_TOP_POSITION_GAINED),
-                transition(ResultActivity.class, ON_TOP_POSITION_LOST),
-                transition(ResultActivity.class, ON_PAUSE),
+                transition(TranslucentResultActivity.class, ON_CREATE),
+                transition(TranslucentResultActivity.class, ON_START),
+                transition(TranslucentResultActivity.class, ON_POST_CREATE),
+                transition(TranslucentResultActivity.class, ON_RESUME),
+                transition(TranslucentResultActivity.class, ON_TOP_POSITION_GAINED),
+                transition(TranslucentResultActivity.class, ON_TOP_POSITION_LOST),
+                transition(TranslucentResultActivity.class, ON_PAUSE),
                 transition(LaunchForResultActivity.class, ON_ACTIVITY_RESULT),
                 transition(LaunchForResultActivity.class, ON_RESUME),
                 transition(LaunchForResultActivity.class, ON_TOP_POSITION_GAINED),
-                transition(ResultActivity.class, ON_STOP),
-                transition(ResultActivity.class, ON_DESTROY),
+                transition(TranslucentResultActivity.class, ON_STOP),
+                transition(TranslucentResultActivity.class, ON_DESTROY),
                 transition(CallbackTrackingActivity.class, ON_STOP)),
                 getLifecycleLog(), "Double launch sequence must match");
     }
@@ -419,7 +411,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 186608789)
     public void testTopPositionNewIntentForPaused() throws Exception {
         // Launch single top activity
         final Activity singleTopActivity = launchActivityAndWait(SingleTopActivity.class);
@@ -719,8 +710,7 @@
             // TODO(b/123432490): Fix extra pause/resume
             LifecycleVerifier.assertSequence(ShowWhenLockedCallbackTrackingActivity.class,
                     getLifecycleLog(),
-                    Arrays.asList(
-                            PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                    Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                             ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST, ON_PAUSE, ON_RESUME,
                             ON_TOP_POSITION_GAINED),
                     "launchAboveKeyguard");
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
index ed92d35..e777034 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityTests.java
@@ -121,7 +121,6 @@
      * for root of task. This version verifies lifecycle when top activity is translucent
      */
     @Test
-    @FlakyTest(bugId = 186608789)
     public void testFinishTask_FromRoot_TranslucentOnTop() throws Exception {
         final Class<? extends Activity> rootActivityClass = CallbackTrackingActivity.class;
         final Activity rootActivity = launchActivityAndWait(rootActivityClass);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleLog.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleLog.java
index f000dd8..281830a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleLog.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleLog.java
@@ -38,7 +38,6 @@
 public class LifecycleLog extends ContentProvider {
 
     public enum ActivityCallback {
-        PRE_ON_CREATE,
         ON_CREATE,
         ON_START,
         ON_RESUME,
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleVerifier.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleVerifier.java
index 6f005b2..ff29d13 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleVerifier.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/LifecycleVerifier.java
@@ -28,7 +28,6 @@
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_STOP;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_GAINED;
 import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.ON_TOP_POSITION_LOST;
-import static android.server.wm.lifecycle.LifecycleLog.ActivityCallback.PRE_ON_CREATE;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -70,9 +69,9 @@
     public static List<LifecycleLog.ActivityCallback> getLaunchSequence(
             Class<? extends Activity> activityClass) {
         return CALLBACK_TRACKING_CLASS.isAssignableFrom(activityClass)
-                ? Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                ? Arrays.asList(ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
                 ON_TOP_POSITION_GAINED)
-                : Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME);
+                : Arrays.asList(ON_CREATE, ON_START, ON_RESUME);
     }
 
     static List<ActivityCallback> getLaunchAndDestroySequence(
@@ -111,7 +110,6 @@
         }
         // Next the existing activity is paused and the next one is launched
         expectedTransitions.add(transition(existingActivity, ON_PAUSE));
-        expectedTransitions.add(transition(launchingActivity, PRE_ON_CREATE));
         expectedTransitions.add(transition(launchingActivity, ON_CREATE));
         expectedTransitions.add(transition(launchingActivity, ON_START));
         if (includingCallbacks) {
@@ -143,8 +141,8 @@
 
         final boolean includeCallbacks = CALLBACK_TRACKING_CLASS.isAssignableFrom(activityClass);
 
-        final List<ActivityCallback> expectedTransitions = new ArrayList<>();
-        expectedTransitions.addAll(Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START));
+        final List<ActivityCallback> expectedTransitions = new ArrayList<>(
+                Arrays.asList(ON_CREATE, ON_START));
         if (includeCallbacks) {
             expectedTransitions.add(ON_POST_CREATE);
         }
@@ -164,7 +162,7 @@
         final String errorMessage = errorDuringTransition(activityClass, "launch and pause");
 
         final List<ActivityCallback> expectedTransitions =
-                Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE);
+                Arrays.asList(ON_CREATE, ON_START, ON_RESUME, ON_PAUSE);
         assertEquals(errorMessage, expectedTransitions, observedTransitions);
     }
 
@@ -200,7 +198,7 @@
         final String errorMessage = errorDuringTransition(activityClass, "recreateA  and pause");
 
         final List<LifecycleLog.ActivityCallback> expectedTransitions =
-                Arrays.asList(ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME);
+                Arrays.asList(ON_DESTROY, ON_CREATE, ON_START, ON_RESUME);
         assertEquals(errorMessage, expectedTransitions, observedTransitions);
     }
 
@@ -212,7 +210,7 @@
         final String errorMessage = errorDuringTransition(activityClass, "launch and destroy");
 
         final List<LifecycleLog.ActivityCallback> expectedTransitions = Arrays.asList(
-                PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY);
+                ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY);
         assertEquals(errorMessage, expectedTransitions, observedTransitions);
     }
 
@@ -281,17 +279,17 @@
         final List<LifecycleLog.ActivityCallback> expectedTransitions;
         if (startState == ON_PAUSE) {
             expectedTransitions = Arrays.asList(
-                    ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE);
+                    ON_STOP, ON_DESTROY, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE);
         } else if (startState == ON_STOP) {
             expectedTransitions = Arrays.asList(
-                    ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP);
+                    ON_DESTROY, ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP);
         } else if (startState == ON_RESUME) {
             expectedTransitions = Arrays.asList(
-                    ON_PAUSE, ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_RESUME);
+                    ON_PAUSE, ON_STOP, ON_DESTROY, ON_CREATE, ON_START, ON_RESUME);
         } else if (startState == ON_TOP_POSITION_GAINED) {
             // Looks like we're tracking the callbacks here
             expectedTransitions = Arrays.asList(
-                    ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE,
+                    ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY, ON_CREATE,
                     ON_START, ON_POST_CREATE, ON_RESUME, ON_TOP_POSITION_GAINED);
         } else {
             throw new IllegalArgumentException("Start state not supported: " + startState);
@@ -306,13 +304,10 @@
         return CALLBACK_TRACKING_CLASS.isAssignableFrom(activityClass)
                 ? CONFIG_CHANGE_HANDLING_CLASS.isAssignableFrom(activityClass)
                 ? Arrays.asList(ON_MULTI_WINDOW_MODE_CHANGED, ON_TOP_POSITION_LOST)
-                : Arrays.asList(
-                ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY, PRE_ON_CREATE,
-                ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
-                ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST)
-                : Arrays.asList(
-                        ON_PAUSE, ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START,
-                ON_RESUME);
+                : Arrays.asList(ON_TOP_POSITION_LOST, ON_PAUSE, ON_STOP, ON_DESTROY,
+                        ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+                        ON_TOP_POSITION_GAINED, ON_TOP_POSITION_LOST)
+                : Arrays.asList(ON_PAUSE, ON_STOP, ON_DESTROY, ON_CREATE, ON_START, ON_RESUME);
     }
 
     // TODO(b/149338177): Remove this workaround once test passes with TestTaskOrganizer not to
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 acc36e5..bb1c387 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
@@ -134,6 +134,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.PowerManager;
 import android.os.RemoteCallback;
 import android.os.SystemClock;
 import android.os.SystemProperties;
@@ -241,6 +242,7 @@
     protected final ActivityTaskManager mAtm = mContext.getSystemService(ActivityTaskManager.class);
     protected final DisplayManager mDm = mContext.getSystemService(DisplayManager.class);
     protected final WindowManager mWm = mContext.getSystemService(WindowManager.class);
+    protected final KeyguardManager mKm = mContext.getSystemService(KeyguardManager.class);
 
     /** The tracker to manage objects (especially {@link AutoCloseable}) in a test method. */
     protected final ObjectTracker mObjectTracker = new ObjectTracker();
@@ -569,8 +571,11 @@
 
     @Before
     public void setUp() throws Exception {
-        pressWakeupButton();
-        pressUnlockButton();
+        if (isKeyguardLocked() || !Objects.requireNonNull(
+                mContext.getSystemService(PowerManager.class)).isInteractive()) {
+            pressWakeupButton();
+            pressUnlockButton();
+        }
         launchHomeActivityNoWait();
         removeRootTasksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
 
@@ -1022,6 +1027,10 @@
         assertTrue(message, mWmState.hasActivityState(activityName, state));
     }
 
+    protected boolean isKeyguardLocked() {
+        return mKm != null && mKm.isKeyguardLocked();
+    }
+
     protected void waitAndAssertActivityStateOnDisplay(ComponentName activityName, String state,
             int displayId, String message) {
         waitAndAssertActivityState(activityName, state, message);
@@ -1462,7 +1471,10 @@
             }
 
             setLockDisabled(mIsLockDisabled);
+            final boolean wasCredentialSet = mLockCredentialSet;
+            boolean wasDeviceLocked = false;
             if (mLockCredentialSet) {
+                wasDeviceLocked = mKm != null && mKm.isDeviceLocked();
                 removeLockCredential();
                 mLockCredentialSet = false;
             }
@@ -1475,12 +1487,33 @@
             // If Keyguard is occluded, pressing the back key can hide the ShowWhenLocked activity.
             pressBackButton();
 
+            // If the credential wasn't set, the steps for restoring can be simpler.
+            if (!wasCredentialSet) {
+                mWmState.computeState();
+                if (WindowManagerStateHelper.isKeyguardShowingAndNotOccluded(mWmState)) {
+                    // Keyguard is showing and not occluded so only need to unlock.
+                    unlockDevice();
+                    return;
+                }
+
+                final ComponentName home = mWmState.getHomeActivityName();
+                if (home != null && mWmState.hasActivityState(home, STATE_RESUMED)) {
+                    // Home is resumed so nothing to do (e.g. after finishing show-when-locked app).
+                    return;
+                }
+            }
+
             // If device is unlocked, there might have ShowWhenLocked activity runs on,
             // use home key to clear all activity at foreground.
             pressHomeButton();
-            sleepDevice();
-            wakeUpDevice();
-            unlockDevice();
+            if (wasDeviceLocked) {
+                // The removal of credential needs an extra cycle to take effect.
+                sleepDevice();
+                wakeUpDevice();
+            }
+            if (isKeyguardLocked()) {
+                unlockDevice();
+            }
         }
 
         /**
@@ -2010,6 +2043,11 @@
                 countSpec(ActivityCallback.ON_CONFIGURATION_CHANGED, CountSpec.EQUALS, 0));
     }
 
+    static void assertSecurityExceptionFromActivityLauncher() {
+        waitForOrFail("SecurityException from " + ActivityLauncher.TAG,
+                ActivityLauncher::hasCaughtSecurityException);
+    }
+
     private static final Pattern sCurrentUiModePattern = Pattern.compile("mCurUiMode=0x(\\d+)");
     private static final Pattern sUiModeLockedPattern =
             Pattern.compile("mUiModeLocked=(true|false)");
@@ -2542,8 +2580,7 @@
         protected void verify() throws Throwable {
             if (mLastError != null) {
                 // Try to recover the bad state of device to avoid subsequent test failures.
-                final KeyguardManager kgm = mContext.getSystemService(KeyguardManager.class);
-                if (kgm != null && kgm.isKeyguardLocked()) {
+                if (isKeyguardLocked()) {
                     mLastError.addSuppressed(new IllegalStateException("Keyguard is locked"));
                     // To clear the credential immediately, the screen need to be turned on.
                     pressWakeupButton();
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 e8a4280..accfd35 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
@@ -1478,6 +1478,22 @@
         public boolean inSizeCompatMode() {
             return inSizeCompatMode;
         }
+
+        @Override
+        public Rect getBounds() {
+            if (mBounds == null) {
+                return mFullConfiguration.windowConfiguration.getBounds();
+            }
+            return mBounds;
+        }
+
+        public Rect getMaxBounds() {
+            return mFullConfiguration.windowConfiguration.getMaxBounds();
+        }
+
+        public Rect getAppBounds() {
+            return mFullConfiguration.windowConfiguration.getAppBounds();
+        }
     }
 
     static abstract class ActivityContainer extends WindowContainer {
@@ -1610,6 +1626,14 @@
             return mIsOrganized;
         }
 
+        @Override
+        public Rect getBounds() {
+            if (mBounds == null) {
+                return mFullConfiguration.windowConfiguration.getBounds();
+            }
+            return mBounds;
+        }
+
         boolean containsActivity(ComponentName activityName) {
             if (!mIsTaskDisplayArea) {
                 return false;
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
index c89370b..0a70d01 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
@@ -158,9 +158,13 @@
                 waitForWithAmState(state -> state.getDreamTask() == null, "DreamActivity gone"));
     }
 
+    public static boolean isKeyguardShowingAndNotOccluded(WindowManagerState state) {
+        return state.getKeyguardControllerState().keyguardShowing
+                && !state.getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY);
+    }
+
     public void waitForKeyguardShowingAndNotOccluded() {
-        waitForWithAmState(state -> state.getKeyguardControllerState().keyguardShowing
-                        && !state.getKeyguardControllerState().isKeyguardOccluded(DEFAULT_DISPLAY),
+        waitForWithAmState(WindowManagerStateHelper::isKeyguardShowingAndNotOccluded,
                 "Keyguard showing");
     }
 
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java
index 36516a2..5c738e1 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/FocusHandlingTest.java
@@ -50,6 +50,7 @@
 import android.view.WindowManager;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.cts.util.AutoCloseableWrapper;
 import android.view.inputmethod.cts.util.EndToEndImeTestBase;
 import android.view.inputmethod.cts.util.TestActivity;
 import android.view.inputmethod.cts.util.TestUtils;
@@ -296,64 +297,63 @@
                     () -> TextUtils.equals(editText.getText(), "test commit"), TIMEOUT);
             instrumentation.runOnMainSync(() -> editText.setText(""));
 
-            // Create a popup window that cannot be the IME target.
-            final PopupWindow popupWindow = TestUtils.getOnMainSync(() -> {
-                final Context context = instrumentation.getTargetContext();
-                final PopupWindow popup = new PopupWindow(context);
-                popup.setFocusable(true);
-                popup.setInputMethodMode(INPUT_METHOD_NOT_NEEDED);
-                final TextView textView = new TextView(context);
-                textView.setText("Test Text");
-                popup.setContentView(textView);
-                return popup;
-            });
+            // Create then show a popup window that cannot be the IME target.
+            try (AutoCloseableWrapper<PopupWindow> popupWindowWrapper = AutoCloseableWrapper.create(
+                TestUtils.getOnMainSync(() -> {
+                    final Context context = instrumentation.getTargetContext();
+                    final PopupWindow popup = new PopupWindow(context);
+                    popup.setFocusable(true);
+                    popup.setInputMethodMode(INPUT_METHOD_NOT_NEEDED);
+                    final TextView textView = new TextView(context);
+                    textView.setText("Test Text");
+                    popup.setContentView(textView);
+                    popup.showAsDropDown(editText);
+                    return popup;
+                }), popupWindow -> runOnMainSync(popupWindow::dismiss))
+            ) {
+                instrumentation.waitForIdleSync();
 
-            // Show the popup window.
-            instrumentation.runOnMainSync(() -> popupWindow.showAsDropDown(editText));
-            instrumentation.waitForIdleSync();
+                // Make sure that the EditText no longer has window-focus
+                TestUtils.waitOnMainUntil(() -> !editText.hasWindowFocus(), TIMEOUT);
 
-            // Make sure that the EditText no longer has window-focus
-            TestUtils.waitOnMainUntil(() -> !editText.hasWindowFocus(), TIMEOUT);
+                // Make sure that InputConnection#commitText() works.
+                final ImeCommand commit2 = imeSession.callCommitText("Hello!", 1);
+                expectCommand(stream, commit2, TIMEOUT);
+                TestUtils.waitOnMainUntil(
+                        () -> TextUtils.equals(editText.getText(), "Hello!"), TIMEOUT);
+                instrumentation.runOnMainSync(() -> editText.setText(""));
 
-            // Make sure that InputConnection#commitText() works.
-            final ImeCommand commit2 = imeSession.callCommitText("Hello!", 1);
-            expectCommand(stream, commit2, TIMEOUT);
-            TestUtils.waitOnMainUntil(
-                    () -> TextUtils.equals(editText.getText(), "Hello!"), TIMEOUT);
-            instrumentation.runOnMainSync(() -> editText.setText(""));
+                stream.skipAll();
 
-            stream.skipAll();
+                final String marker2 = getTestMarker();
+                // Call InputMethodManager#restartInput()
+                instrumentation.runOnMainSync(() -> {
+                    editText.setPrivateImeOptions(marker2);
+                    editText.getContext()
+                            .getSystemService(InputMethodManager.class)
+                            .restartInput(editText);
+                });
 
-            final String marker2 = getTestMarker();
-            // Call InputMethodManager#restartInput()
-            instrumentation.runOnMainSync(() -> {
-                editText.setPrivateImeOptions(marker2);
-                editText.getContext()
-                        .getSystemService(InputMethodManager.class)
-                        .restartInput(editText);
-            });
+                // Make sure that onStartInput() is called with restarting == true.
+                expectEvent(stream, event -> {
+                    if (!TextUtils.equals("onStartInput", event.getEventName())) {
+                        return false;
+                    }
+                    if (!event.getArguments().getBoolean("restarting")) {
+                        return false;
+                    }
+                    final EditorInfo editorInfo = event.getArguments().getParcelable("editorInfo");
+                    return TextUtils.equals(marker2, editorInfo.privateImeOptions);
+                }, TIMEOUT);
 
-            // Make sure that onStartInput() is called with restarting == true.
-            expectEvent(stream, event -> {
-                if (!TextUtils.equals("onStartInput", event.getEventName())) {
-                    return false;
-                }
-                if (!event.getArguments().getBoolean("restarting")) {
-                    return false;
-                }
-                final EditorInfo editorInfo = event.getArguments().getParcelable("editorInfo");
-                return TextUtils.equals(marker2, editorInfo.privateImeOptions);
-            }, TIMEOUT);
+                // Make sure that InputConnection#commitText() works.
+                final ImeCommand commit3 = imeSession.callCommitText("World!", 1);
+                expectCommand(stream, commit3, TIMEOUT);
+                TestUtils.waitOnMainUntil(
+                        () -> TextUtils.equals(editText.getText(), "World!"), TIMEOUT);
+                instrumentation.runOnMainSync(() -> editText.setText(""));
+            }
 
-            // Make sure that InputConnection#commitText() works.
-            final ImeCommand commit3 = imeSession.callCommitText("World!", 1);
-            expectCommand(stream, commit3, TIMEOUT);
-            TestUtils.waitOnMainUntil(
-                    () -> TextUtils.equals(editText.getText(), "World!"), TIMEOUT);
-            instrumentation.runOnMainSync(() -> editText.setText(""));
-
-            // Dismiss the popup window.
-            instrumentation.runOnMainSync(() -> popupWindow.dismiss());
             instrumentation.waitForIdleSync();
 
             // Make sure that the EditText now has window-focus again.
@@ -400,29 +400,31 @@
             expectEvent(stream, editorMatcher("onStartInputView", marker), TIMEOUT);
             expectImeVisible(TIMEOUT);
 
-            // Create a non-focusable PopupWindow with INPUT_METHOD_NEEDED.
-            final PopupWindow popupWindow = TestUtils.getOnMainSync(() -> {
-                final Context context = instrumentation.getTargetContext();
-                final PopupWindow popup = new PopupWindow(context);
-                popup.setFocusable(false);
-                popup.setInputMethodMode(INPUT_METHOD_NEEDED);
-                final TextView textView = new TextView(context);
-                textView.setText("Popup");
-                popup.setContentView(textView);
-                return popup;
-            });
+            // Create then show a non-focusable PopupWindow with INPUT_METHOD_NEEDED.
+            try (AutoCloseableWrapper<PopupWindow> popupWindowWrapper = AutoCloseableWrapper.create(
+                TestUtils.getOnMainSync(() -> {
+                    final Context context = instrumentation.getTargetContext();
+                    final PopupWindow popup = new PopupWindow(context);
+                    popup.setFocusable(false);
+                    popup.setInputMethodMode(INPUT_METHOD_NEEDED);
+                    final TextView textView = new TextView(context);
+                    textView.setText("Popup");
+                    popup.setContentView(textView);
+                    // Show the popup window.
+                    popup.showAsDropDown(editText);
+                    return popup;
+                }), popup -> TestUtils.runOnMainSync(popup::dismiss))
+            ) {
+                instrumentation.waitForIdleSync();
 
-            // Show the popup window.
-            runOnMainSync(() -> popupWindow.showAsDropDown(editText));
-            instrumentation.waitForIdleSync();
+                // Make sure that the IME remains to be visible.
+                expectImeVisible(TIMEOUT);
 
-            // Make sure that the IME remains to be visible.
-            expectImeVisible(TIMEOUT);
+                SystemClock.sleep(NOT_EXPECT_TIMEOUT);
 
-            SystemClock.sleep(NOT_EXPECT_TIMEOUT);
-
-            // Make sure that the IME remains to be visible.
-            expectImeVisible(TIMEOUT);
+                // Make sure that the IME remains to be visible.
+                expectImeVisible(TIMEOUT);
+            }
         }
     }
 
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
index c1f1be2..0723d3f 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
@@ -288,7 +288,7 @@
             eraseFontScale();
 
             // Case 2: Activity *doesn't* handle configChanges="fontScale" and restarts.
-            final Activity activity = createTestActivity2(SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+            createTestActivity2(SOFT_INPUT_STATE_ALWAYS_VISIBLE);
             expectEvent(stream, event -> "onStartInput".equals(event.getEventName()), TIMEOUT);
             // MockIme handles fontScale. Make sure changing fontScale doesn't restart IME.
             enableFontScale();
@@ -296,8 +296,6 @@
             // Make sure IME was not restarted.
             notExpectEvent(stream, event -> "onCreate".equals(event.getEventName()),
                     EXPECTED_TIMEOUT);
-            notExpectEvent(stream, event -> "onStartInput".equals(event.getEventName()),
-                    EXPECTED_TIMEOUT);
         } finally {
             eraseFontScale();
         }
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java b/tests/inputmethod/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java
new file mode 100644
index 0000000..90dd247
--- /dev/null
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java
@@ -0,0 +1,92 @@
+/*
+ * 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.inputmethod.cts.util;
+
+import androidx.annotation.AnyThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.Objects;
+
+/**
+ * A utility class to mix-in cleanup operations into any existing class by using
+ * {@link AutoCloseable} protocol.
+ *
+ * @param <T> Class to be cleaned up.
+ */
+public final class AutoCloseableWrapper<T> implements AutoCloseable {
+
+    /**
+     * Instantiates {@link AutoCloseableWrapper} object.
+     *
+     * @param object Object that needs to be cleaned up.
+     * @param closingFunction Operation to clean up the object.
+     * @param <U> Type of the object to be cleaned up.
+     * @return {@link AutoCloseableWrapper} that wraps {@code object}.
+     */
+    @AnyThread
+    public static <U> AutoCloseableWrapper create(@Nullable U object,
+            @NonNull ClosingFunction<U> closingFunction) {
+        Objects.requireNonNull(object, "object cannot be null");
+        Objects.requireNonNull(closingFunction, "closingFunction cannot be null");
+        return new AutoCloseableWrapper<>(object, closingFunction);
+    }
+
+    /**
+     * An internal utility interface in case the closing operation throws {@link Exception}.
+     *
+     * @param <U> Class to be cleaned up.
+     */
+    @FunctionalInterface
+    public interface ClosingFunction<U> {
+        /**
+         * Perform cleanup operation.
+         *
+         * @param object Object to be cleaned up.
+         * @throws Exception For whatever reason this operations has failed.
+         */
+        void close(U object) throws Exception;
+    }
+
+    @NonNull
+    private final T mObject;
+
+    @NonNull
+    private final ClosingFunction<T> mCloser;
+
+    private AutoCloseableWrapper(@NonNull T object, @NonNull ClosingFunction<T> closer) {
+        mObject = object;
+        mCloser = closer;
+    }
+
+    /**
+     * @return The wrapped object.
+     */
+    @AnyThread
+    @NonNull
+    public T get() {
+        return mObject;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void close() throws Exception {
+        mCloser.close(mObject);
+    }
+}
diff --git a/tests/libcore/jsr166/Android.bp b/tests/libcore/jsr166/Android.bp
index 67fb0b74..0ab6329 100644
--- a/tests/libcore/jsr166/Android.bp
+++ b/tests/libcore/jsr166/Android.bp
@@ -37,5 +37,6 @@
     test_suites: [
         "cts",
         "general-tests",
+        "mts",
     ],
 }
diff --git a/tests/libcore/jsr166/AndroidTest.xml b/tests/libcore/jsr166/AndroidTest.xml
index f2aaee5..93a2b76 100644
--- a/tests/libcore/jsr166/AndroidTest.xml
+++ b/tests/libcore/jsr166/AndroidTest.xml
@@ -45,4 +45,13 @@
     <object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
         <option name="screenshot-on-failure" value="false" />
     </object>
+
+    <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if
+         one of the Mainline modules below is present on the device used for testing. -->
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <!-- ART Mainline Module (internal version). -->
+        <option name="mainline-module-package-name" value="com.google.android.art" />
+        <!-- ART Mainline Module (external (AOSP) version). -->
+        <option name="mainline-module-package-name" value="com.android.art" />
+    </object>
 </configuration>
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
index 4c4c412..536332c 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
@@ -28,14 +28,12 @@
 import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF;
 import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF;
 import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
-import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
 
 import static androidx.test.ext.truth.content.IntentSubject.assertThat;
 import static androidx.test.ext.truth.location.LocationSubject.assertThat;
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static com.android.compatibility.common.util.LocationUtils.createLocation;
-import static com.android.compatibility.common.util.SettingsUtils.NAMESPACE_GLOBAL;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -89,7 +87,6 @@
 import com.android.compatibility.common.util.LocationUtils;
 import com.android.compatibility.common.util.ScreenUtils;
 import com.android.compatibility.common.util.ScreenUtils.ScreenResetter;
-import com.android.compatibility.common.util.SettingsUtils.SettingResetter;
 
 import org.junit.After;
 import org.junit.Before;
@@ -120,6 +117,8 @@
     private static final String INVALID_LOCATION_ATTRIBUTION_TAG =
             "invalid_location_attribution_tag";
 
+    private static final String IGNORE_SETTINGS_ALLOWLIST = "ignore_settings_allowlist";
+
     private Random mRandom;
     private Context mContext;
     private LocationManager mManager;
@@ -798,11 +797,14 @@
     public void testRequestLocationUpdates_LocationSettingsIgnored() throws Exception {
         try (LocationListenerCapture capture = new LocationListenerCapture(mContext);
              ScreenResetter ignored1 = new ScreenResetter();
-             SettingResetter ignored2 = new SettingResetter(NAMESPACE_GLOBAL,
-                     LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST, mContext.getPackageName());
+             DeviceConfigStateHelper locationDeviceConfigStateHelper =
+                     new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_LOCATION);
              DeviceConfigStateHelper batterySaverDeviceConfigStateHelper =
                      new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_BATTERY_SAVER)) {
 
+            locationDeviceConfigStateHelper.set(IGNORE_SETTINGS_ALLOWLIST,
+                    mContext.getPackageName());
+
             getInstrumentation().getUiAutomation()
                     .adoptShellPermissionIdentity(WRITE_SECURE_SETTINGS);
             try {
diff --git a/tests/location/location_privileged/src/android/location/cts/privileged/SatellitePvtTest.java b/tests/location/location_privileged/src/android/location/cts/privileged/SatellitePvtTest.java
index 2831db6..7495d5b 100644
--- a/tests/location/location_privileged/src/android/location/cts/privileged/SatellitePvtTest.java
+++ b/tests/location/location_privileged/src/android/location/cts/privileged/SatellitePvtTest.java
@@ -45,9 +45,9 @@
      */
     @Test
     public void testWriteToParcel() {
-        SatellitePvt satellitePvt1 = createTestSatellitePvt(/*flags=*/ 7, POSITION_ECEF_M,
-                                        VELOCITY_ECEF_MPS, CLOCK_INFO,
-                                        /*ionoDelayMeters=*/ 12.0, /*tropoDelayMeters=*/ 13.0);
+        SatellitePvt satellitePvt1 = createTestSatellitePvt(POSITION_ECEF_M, VELOCITY_ECEF_MPS,
+                                        CLOCK_INFO, /*ionoDelayMeters=*/ 12.0,
+                                        /*tropoDelayMeters=*/ 13.0);
         Parcel parcel = Parcel.obtain();
         satellitePvt1.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
@@ -57,7 +57,6 @@
     }
 
     private static void verifyTestValues(SatellitePvt satPvt1, SatellitePvt satPvt2) {
-        assertEquals(satPvt1.getFlags(), satPvt2.getFlags(), DELTA);
         assertEquals(satPvt1.getPositionEcef().getXMeters(),
                      satPvt2.getPositionEcef().getXMeters(), DELTA);
         assertEquals(satPvt1.getPositionEcef().getYMeters(),
@@ -85,10 +84,9 @@
     }
 
     private static SatellitePvt createTestSatellitePvt (
-            int flags, PositionEcef positionEcef, VelocityEcef velocityEcef, ClockInfo clockInfo,
+            PositionEcef positionEcef, VelocityEcef velocityEcef, ClockInfo clockInfo,
                     double ionoDelayMeters, double tropoDelayMeters) {
         return new SatellitePvt.Builder()
-                .setFlags(flags)
                 .setPositionEcef(positionEcef)
                 .setVelocityEcef(velocityEcef)
                 .setClockInfo(clockInfo)
diff --git a/tests/musicrecognition/src/android/musicrecognition/cts/MusicRecognitionManagerTest.java b/tests/musicrecognition/src/android/musicrecognition/cts/MusicRecognitionManagerTest.java
index 6c92f79..0502df3 100644
--- a/tests/musicrecognition/src/android/musicrecognition/cts/MusicRecognitionManagerTest.java
+++ b/tests/musicrecognition/src/android/musicrecognition/cts/MusicRecognitionManagerTest.java
@@ -111,6 +111,29 @@
     }
 
     @Test
+    public void testRecognitionRequest() {
+        AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, 16_000,
+                AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 256_000);
+
+        RecognitionRequest request = new RecognitionRequest.Builder()
+                .setAudioAttributes(new AudioAttributes.Builder()
+                        .setInternalCapturePreset(MediaRecorder.AudioSource.MIC)
+                        .build())
+                .setAudioFormat(record.getFormat())
+                .setCaptureSession(record.getAudioSessionId())
+                .setMaxAudioLengthSeconds(8)
+                // Drop the first second of audio.
+                .setIgnoreBeginningFrames(16_000)
+                .build();
+
+        assertThat(request.getAudioFormat()).isEqualTo(record.getFormat());
+        assertThat(request.getMaxAudioLengthSeconds()).isEqualTo(8);
+        assertThat(request.getCaptureSession()).isEqualTo(record.getAudioSessionId());
+        assertThat(request.getIgnoreBeginningFrames()).isEqualTo(16_000);
+        assertThat(request.getAudioAttributes()).isEqualTo(record.getAudioAttributes());
+    }
+
+    @Test
     public void testOnRecognitionFailed() throws Exception {
         mWatcher.failureCode = MusicRecognitionManager.RECOGNITION_FAILED_NO_CONNECTIVITY;
 
diff --git a/tests/searchui/src/android/searchuiservice/cts/SearchTargetTest.java b/tests/searchui/src/android/searchuiservice/cts/SearchTargetTest.java
index f4b66e9..fe9ae67 100644
--- a/tests/searchui/src/android/searchuiservice/cts/SearchTargetTest.java
+++ b/tests/searchui/src/android/searchuiservice/cts/SearchTargetTest.java
@@ -62,7 +62,7 @@
             .setUserHandle(UserHandle.CURRENT)
             .setSearchAction(SEARCH_ACTION)
             .setScore(SCORE)
-            .setShouldHide(SHOULD_HIDE)
+            .setHidden(SHOULD_HIDE)
             .setParentId(PARENTID)
             .setExtras(EXTRAS);
 
diff --git a/tests/sensor/src/android/hardware/cts/helpers/SensorCtsHelper.java b/tests/sensor/src/android/hardware/cts/helpers/SensorCtsHelper.java
index 41af5fa..597496e 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -387,6 +387,11 @@
                 // Hinge angle sensor must have a resolution the same or smaller
                 // than 360 degrees.
                 return 360f;
+            case Sensor.TYPE_PROXIMITY:
+                // Binary prox sensors must have a resolution of 5, but it's not
+                // expected / recommended that prox sensors use higher than
+                // this.
+                return 5f;
         }
 
         // Any sensor not specified above must use a resolution of 1.
diff --git a/tests/suspendapps/tests/src/android/suspendapps/cts/SuspendPackagesTest.java b/tests/suspendapps/tests/src/android/suspendapps/cts/SuspendPackagesTest.java
index 0fd3cde..291d9cc 100644
--- a/tests/suspendapps/tests/src/android/suspendapps/cts/SuspendPackagesTest.java
+++ b/tests/suspendapps/tests/src/android/suspendapps/cts/SuspendPackagesTest.java
@@ -46,6 +46,7 @@
 import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.platform.test.annotations.SystemUserOnly;
+import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
@@ -67,13 +68,16 @@
 @RunWith(AndroidJUnit4.class)
 @LargeTest
 public class SuspendPackagesTest {
+
+    private static final String TAG = SuspendPackagesTest.class.getSimpleName();
+
     private Context mContext;
     private PackageManager mPackageManager;
     private AppOpsManager mAppOpsManager;
     private TestAppInterface mTestAppInterface;
 
     private void addAndAssertDeviceOwner() {
-        SystemUtil.runShellCommand("dpm set-device-owner --user cur " + DEVICE_ADMIN_COMPONENT,
+        SystemUtil.runShellCommand("dpm set-device-owner --user 0 " + DEVICE_ADMIN_COMPONENT,
                 output -> output.startsWith("Success"));
     }
 
@@ -84,6 +88,8 @@
 
     @Before
     public void setUp() {
+        Log.d(TAG, "Running as user " + UserHandle.myUserId());
+
         mContext = InstrumentationRegistry.getTargetContext();
         mPackageManager = mContext.getPackageManager();
         mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
diff --git a/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
index 6a921b1..cac8ab4 100644
--- a/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
+++ b/tests/tests/appenumeration/app/source/src/android/appenumeration/cts/query/TestActivity.java
@@ -71,6 +71,7 @@
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.SharedLibraryInfo;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
@@ -227,6 +228,9 @@
                 final int expectedEventCode = intent.getBundleExtra(EXTRA_DATA)
                         .getInt(EXTRA_FLAGS, CALLBACK_EVENT_INVALID);
                 awaitLauncherAppsCallback(remoteCallback, expectedEventCode, TIMEOUT_MS);
+            } else if (Constants.ACTION_GET_SHAREDLIBRARY_DEPENDENT_PACKAGES.equals(action)) {
+                final String sharedLibName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+                sendGetSharedLibraryDependentPackages(remoteCallback, sharedLibName);
             } else {
                 sendError(remoteCallback, new Exception("unknown action " + action));
             }
@@ -552,6 +556,22 @@
         finish();
     }
 
+    private void sendGetSharedLibraryDependentPackages(RemoteCallback remoteCallback,
+            String sharedLibName) {
+        final List<SharedLibraryInfo> sharedLibraryInfos = getPackageManager()
+                .getSharedLibraries(0 /* flags */);
+        SharedLibraryInfo sharedLibraryInfo = sharedLibraryInfos.stream().filter(
+                info -> sharedLibName.equals(info.getName())).findAny().orElse(null);
+        final String[] dependentPackages = sharedLibraryInfo == null ? null
+                : sharedLibraryInfo.getDependentPackages().stream()
+                        .map(versionedPackage -> versionedPackage.getPackageName())
+                        .distinct().collect(Collectors.toList()).toArray(new String[]{});
+        final Bundle result = new Bundle();
+        result.putStringArray(Intent.EXTRA_PACKAGES, dependentPackages);
+        remoteCallback.sendResult(result);
+        finish();
+    }
+
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
diff --git a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
index c716634..f7bea6a 100644
--- a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
+++ b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
@@ -196,6 +196,8 @@
             PKG_BASE + "cts.action.LAUNCHER_APPS_IS_ACTIVITY_ENABLED";
     public static final String ACTION_AWAIT_LAUNCHER_APPS_CALLBACK =
             PKG_BASE + "cts.action.AWAIT_LAUNCHER_APPS_CALLBACK";
+    public static final String ACTION_GET_SHAREDLIBRARY_DEPENDENT_PACKAGES =
+            PKG_BASE + "cts.action.GET_SHAREDLIBRARY_DEPENDENT_PACKAGES";
 
     public static final String EXTRA_REMOTE_CALLBACK = "remoteCallback";
     public static final String EXTRA_REMOTE_READY_CALLBACK = "remoteReadyCallback";
diff --git a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
index a5b5ff3..ca0de3c 100644
--- a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
+++ b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
@@ -25,6 +25,7 @@
 import static android.appenumeration.cts.Constants.ACTION_GET_NAME_FOR_UID;
 import static android.appenumeration.cts.Constants.ACTION_GET_PACKAGES_FOR_UID;
 import static android.appenumeration.cts.Constants.ACTION_GET_PACKAGE_INFO;
+import static android.appenumeration.cts.Constants.ACTION_GET_SHAREDLIBRARY_DEPENDENT_PACKAGES;
 import static android.appenumeration.cts.Constants.ACTION_GET_SYNCADAPTER_PACKAGES_FOR_AUTHORITY;
 import static android.appenumeration.cts.Constants.ACTION_GET_SYNCADAPTER_TYPES;
 import static android.appenumeration.cts.Constants.ACTION_HAS_SIGNING_CERTIFICATE;
@@ -117,6 +118,7 @@
 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
 import static org.hamcrest.Matchers.hasItemInArray;
 import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -178,6 +180,9 @@
 
     private static PackageManager sPm;
 
+    // The shared library for getting dependent packages
+    private static final String TEST_SHARED_LIB_NAME = "android.test.runner";
+
     @Rule
     public TestName name = new TestName();
 
@@ -1000,6 +1005,28 @@
                 this::getInstalledAppWidgetProviders);
     }
 
+    @Test
+    public void queriesNothing_cannotSeeSharedLibraryDependentPackages() throws Exception {
+        assertNotVisible(QUERIES_NOTHING, TARGET_NO_API, this::getSharedLibraryDependentPackages);
+        assertNotVisible(QUERIES_NOTHING, TARGET_FILTERS, this::getSharedLibraryDependentPackages);
+        assertNotVisible(QUERIES_NOTHING, TARGET_SHARED_USER,
+                this::getSharedLibraryDependentPackages);
+
+    }
+
+    @Test
+    public void queriesPackage_canSeeSharedLibraryDependentPackages() throws Exception {
+        assertVisible(QUERIES_PACKAGE, TARGET_NO_API, this::getSharedLibraryDependentPackages);
+        assertVisible(QUERIES_PACKAGE, TARGET_SHARED_USER, this::getSharedLibraryDependentPackages);
+    }
+
+    @Test
+    public void queriesNothingSharedUser_canSeeSharedUserInSharedLibraryDependentPackages()
+            throws Exception {
+        assertVisible(QUERIES_NOTHING_SHARED_USER, TARGET_SHARED_USER,
+                this::getSharedLibraryDependentPackages);
+    }
+
     private void assertNotVisible(String sourcePackageName, String targetPackageName)
             throws Exception {
         if (!sGlobalFeatureEnabled) return;
@@ -1063,6 +1090,8 @@
             ThrowingFunction<String, String[]> commandMethod) throws Exception {
         if (!sGlobalFeatureEnabled) return;
         final String[] packageNames = commandMethod.apply(sourcePackageName);
+        assertThat("The list of package names should not be null",
+                packageNames, notNullValue());
         assertThat(sourcePackageName + " should be able to see " + targetPackageName,
                 packageNames, hasItemInArray(targetPackageName));
     }
@@ -1071,6 +1100,8 @@
             ThrowingFunction<String, String[]> commandMethod) throws Exception {
         if (!sGlobalFeatureEnabled) return;
         final String[] packageNames = commandMethod.apply(sourcePackageName);
+        assertThat("The list of package names should not be null",
+                packageNames, notNullValue());
         assertThat(sourcePackageName + " should not be able to see " + targetPackageName,
                 packageNames, not(hasItemInArray(targetPackageName)));
     }
@@ -1290,6 +1321,13 @@
         return response.getBoolean(Intent.EXTRA_RETURN_RESULT);
     }
 
+    private String[] getSharedLibraryDependentPackages(String sourcePackageName) throws Exception {
+        final Bundle extraData = new Bundle();
+        final Bundle response = sendCommandBlocking(sourcePackageName, TEST_SHARED_LIB_NAME,
+                extraData, ACTION_GET_SHAREDLIBRARY_DEPENDENT_PACKAGES);
+        return response.getStringArray(Intent.EXTRA_PACKAGES);
+    }
+
     interface Result {
         Bundle await() throws Exception;
     }
diff --git a/tests/tests/appop/AndroidTest.xml b/tests/tests/appop/AndroidTest.xml
index f61a15d..f817422 100644
--- a/tests/tests/appop/AndroidTest.xml
+++ b/tests/tests/appop/AndroidTest.xml
@@ -41,6 +41,7 @@
         <option name="push-file" key="CtsAppToBlame2.apk" value="/data/local/tmp/cts/appops/CtsAppToBlame2.apk" />
         <option name="push-file" key="CtsAppToCollect.apk" value="/data/local/tmp/cts/appops/CtsAppToCollect.apk" />
         <option name="push-file" key="AppWithDuplicateAttribution.apk" value="/data/local/tmp/cts/appops/AppWithDuplicateAttribution.apk" />
+        <option name="push-file" key="AppForDiscreteTest.apk" value="/data/local/tmp/cts/appops/AppForDiscreteTest.apk" />
         <option name="push-file" key="AppWithAttributionInheritingFromExisting.apk" value="/data/local/tmp/cts/appops/AppWithAttributionInheritingFromExisting.apk" />
         <option name="push-file" key="AppWithAttributionInheritingFromSameAsOther.apk" value="/data/local/tmp/cts/appops/AppWithAttributionInheritingFromSameAsOther.apk" />
         <option name="push-file" key="AppWithAttributionInheritingFromSelf.apk" value="/data/local/tmp/cts/appops/AppWithAttributionInheritingFromSelf.apk" />
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
index e3a0247..bba1829 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
@@ -24,16 +24,6 @@
 import org.junit.Assert.fail
 import org.junit.Assume.assumeTrue
 
-import android.app.AppOpsManager.MODE_ALLOWED
-import android.app.AppOpsManager.MODE_DEFAULT
-import android.app.AppOpsManager.MODE_ERRORED
-import android.app.AppOpsManager.MODE_IGNORED
-import android.app.AppOpsManager.OPSTR_PICTURE_IN_PICTURE
-import android.app.AppOpsManager.OPSTR_READ_CALENDAR
-import android.app.AppOpsManager.OPSTR_RECORD_AUDIO
-import android.app.AppOpsManager.OPSTR_WIFI_SCAN
-import android.app.AppOpsManager.OPSTR_WRITE_CALENDAR
-
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.timeout
 import org.mockito.Mockito.verify
@@ -41,8 +31,19 @@
 
 import android.Manifest.permission
 import android.app.AppOpsManager
-import android.app.AppOpsManager.OPSTR_FINE_LOCATION
+import android.app.AppOpsManager.MODE_ALLOWED
+import android.app.AppOpsManager.MODE_DEFAULT
+import android.app.AppOpsManager.MODE_ERRORED
+import android.app.AppOpsManager.MODE_IGNORED
 import android.app.AppOpsManager.OnOpChangedListener
+import android.app.AppOpsManager.OPSTR_FINE_LOCATION
+import android.app.AppOpsManager.OPSTR_PHONE_CALL_CAMERA
+import android.app.AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE
+import android.app.AppOpsManager.OPSTR_PICTURE_IN_PICTURE
+import android.app.AppOpsManager.OPSTR_READ_CALENDAR
+import android.app.AppOpsManager.OPSTR_RECORD_AUDIO
+import android.app.AppOpsManager.OPSTR_WIFI_SCAN
+import android.app.AppOpsManager.OPSTR_WRITE_CALENDAR
 import android.content.Context
 import android.os.Process
 import android.platform.test.annotations.AppModeFull
@@ -231,7 +232,7 @@
     }
 
     @Test
-    @AppModeFull(reason="Instant app cannot query for the shell package")
+    @AppModeFull(reason = "Instant app cannot query for the shell package")
     fun overlappingActiveAttributionOps() {
         runWithShellPermissionIdentity {
             val gotActive = CompletableFuture<Unit>()
@@ -292,8 +293,8 @@
             val receivedActiveState = LinkedBlockingDeque<Boolean>()
             val activeWatcher =
                     AppOpsManager.OnOpActiveChangedListener { _, uid, packageName, active ->
-                        if (packageName == SHELL_PACKAGE_NAME
-                                && uid == Process.SHELL_UID) {
+                        if (packageName == SHELL_PACKAGE_NAME &&
+                                uid == Process.SHELL_UID) {
                             receivedActiveState.push(active)
                         }
                     }
@@ -586,6 +587,16 @@
             }
         }
     }
+    
+    @Test
+    fun ensurePhoneCallOpsRestricted() {
+        val micReturn = mAppOps.noteOp(OPSTR_PHONE_CALL_MICROPHONE, Process.myUid(), mOpPackageName,
+                null, null)
+        assertEquals(MODE_IGNORED, micReturn)
+        val cameraReturn = mAppOps.noteOp(OPSTR_PHONE_CALL_CAMERA, Process.myUid(),
+                mOpPackageName, null, null)
+        assertEquals(MODE_IGNORED, cameraReturn)
+    }
 
     private fun runWithShellPermissionIdentity(command: () -> Unit) {
         val uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation()
diff --git a/tests/tests/appop/src/android/app/appops/cts/DiscreteAppopsTest.kt b/tests/tests/appop/src/android/app/appops/cts/DiscreteAppopsTest.kt
index cb6baf0..bc7763a 100644
--- a/tests/tests/appop/src/android/app/appops/cts/DiscreteAppopsTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/DiscreteAppopsTest.kt
@@ -35,18 +35,17 @@
 import android.content.Intent
 import android.content.ServiceConnection
 import android.os.IBinder
+import android.platform.test.annotations.AppModeFull
 import android.provider.DeviceConfig
 import android.provider.DeviceConfig.NAMESPACE_PRIVACY
 import android.provider.Settings
 import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.runner.AndroidJUnit4
 import androidx.test.uiautomator.UiDevice
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Assert
 import org.junit.Before
 import org.junit.Test
-import org.junit.runner.RunWith
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.locks.ReentrantLock
 import java.util.concurrent.TimeUnit
@@ -68,13 +67,13 @@
 private const val INTERVAL_COMPRESSION_MULTIPLIER = 10
 private const val SNAPSHOT_INTERVAL_MILLIS = 1000L
 
-@RunWith(AndroidJUnit4::class)
+@AppModeFull(reason = "This test connects to other test app")
 class DiscreteAppopsTest {
     private var previousAppOpsConstants: String? = null
 
     private val instrumentation get() = InstrumentationRegistry.getInstrumentation()
     private val context get() = instrumentation.context
-    private val uid by lazy { context.packageManager.getPackageUid(PACKAGE_NAME, 0) }
+    private val uid = context.packageManager.getPackageUid(PACKAGE_NAME, 0)
 
     private val uiAutomation get() = instrumentation.uiAutomation
     private lateinit var foregroundControlService: IAppOpsForegroundControlService
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp b/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
index 095d560..68b2d3f 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
@@ -22,7 +22,7 @@
         "test_package/Baz.aidl",
         "test_package/ICompatTest.aidl",
     ],
-    visibility: ["//visibility:private"]
+    visibility: ["//visibility:private"],
 }
 
 filegroup {
@@ -43,7 +43,7 @@
         "test_package/MyExt.aidl",
         "test_package/SimpleUnion.aidl",
     ],
-    visibility: ["//visibility:private"]
+    visibility: ["//visibility:private"],
 }
 
 aidl_interface {
@@ -55,8 +55,9 @@
         },
         cpp: {
             enabled: false,
-        }
+        },
     },
+    versions: ["1"],
 }
 
 aidl_interface {
@@ -72,7 +73,7 @@
         },
         cpp: {
             enabled: false,
-        }
+        },
     },
 }
 
@@ -96,7 +97,7 @@
     visibility: [
         ":__subpackages__",
         "//system/tools/aidl/build:__pkg__",
-    ]
+    ],
 }
 
 cc_defaults {
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/.hash b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/.hash
new file mode 100644
index 0000000..b1282bb
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/.hash
@@ -0,0 +1 @@
+fc8f1d01825cc2845cc7f3fb17cd440a9dd95007
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/Bar.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/Bar.aidl
new file mode 100644
index 0000000..2aaf974
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/Bar.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+parcelable Bar {
+  String a = "BAR";
+  String b = "BAR2";
+  float c = 4.200000f;
+  int d = 100;
+  String e = "HELLO";
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ByteEnum.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ByteEnum.aidl
new file mode 100644
index 0000000..944573e
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ByteEnum.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+@Backing(type="byte")
+enum ByteEnum {
+  FOO = 1,
+  BAR = 2,
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ExtendableParcelable.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ExtendableParcelable.aidl
new file mode 100644
index 0000000..dbbb82c
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ExtendableParcelable.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+parcelable ExtendableParcelable {
+  int a;
+  @nullable @utf8InCpp String b;
+  ParcelableHolder ext;
+  long c;
+  ParcelableHolder ext2;
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/FixedSize.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/FixedSize.aidl
new file mode 100644
index 0000000..f4908e2
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/FixedSize.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+@FixedSize
+parcelable FixedSize {
+  int a;
+  test_package.LongEnum b;
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/Foo.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/Foo.aidl
new file mode 100644
index 0000000..5e260ff
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/Foo.aidl
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+parcelable Foo {
+  String a = "FOO";
+  int b = 42;
+  float c = 3.140000f;
+  test_package.Bar d;
+  test_package.Bar e;
+  int f = 3;
+  test_package.ByteEnum shouldBeByteBar;
+  test_package.IntEnum shouldBeIntBar;
+  test_package.LongEnum shouldBeLongBar;
+  test_package.ByteEnum[] shouldContainTwoByteFoos;
+  test_package.IntEnum[] shouldContainTwoIntFoos;
+  test_package.LongEnum[] shouldContainTwoLongFoos;
+  @nullable String[] g;
+  @nullable test_package.SimpleUnion u;
+  int shouldSetBit0AndBit2;
+  @nullable test_package.SimpleUnion shouldBeConstS1;
+  const int kZero = 0;
+  const int kOne = 1;
+  const int kOnes = -1;
+  const byte kByteOne = 1;
+  const long kLongOnes = -1;
+  const String kEmpty = "";
+  const String kFoo = "foo";
+  const int BIT0 = 1;
+  const int BIT1 = 2;
+  const int BIT2 = 4;
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/GenericBar.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/GenericBar.aidl
new file mode 100644
index 0000000..7cab936
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/GenericBar.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+parcelable GenericBar<T> {
+  int a;
+  test_package.GenericFoo<int,test_package.Bar,test_package.IntEnum> shouldBeGenericFoo;
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/GenericFoo.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/GenericFoo.aidl
new file mode 100644
index 0000000..8929c65
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/GenericFoo.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+parcelable GenericFoo<T, U, V> {
+  int a;
+  int b;
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/IEmpty.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/IEmpty.aidl
new file mode 100644
index 0000000..1717e58
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/IEmpty.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+interface IEmpty {
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ITest.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ITest.aidl
new file mode 100644
index 0000000..020c24f
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/ITest.aidl
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+interface ITest {
+  String GetName();
+  void TestVoidReturn();
+  oneway void TestOneway();
+  int GiveMeMyCallingPid();
+  int GiveMeMyCallingUid();
+  oneway void CacheCallingInfoFromOneway();
+  int GiveMeMyCallingPidFromOneway();
+  int GiveMeMyCallingUidFromOneway();
+  int RepeatInt(int value);
+  long RepeatLong(long value);
+  float RepeatFloat(float value);
+  double RepeatDouble(double value);
+  boolean RepeatBoolean(boolean value);
+  char RepeatChar(char value);
+  byte RepeatByte(byte value);
+  test_package.ByteEnum RepeatByteEnum(test_package.ByteEnum value);
+  test_package.IntEnum RepeatIntEnum(test_package.IntEnum value);
+  test_package.LongEnum RepeatLongEnum(test_package.LongEnum value);
+  IBinder RepeatBinder(IBinder value);
+  @nullable IBinder RepeatNullableBinder(@nullable IBinder value);
+  test_package.IEmpty RepeatInterface(test_package.IEmpty value);
+  @nullable test_package.IEmpty RepeatNullableInterface(@nullable test_package.IEmpty value);
+  ParcelFileDescriptor RepeatFd(in ParcelFileDescriptor fd);
+  @nullable ParcelFileDescriptor RepeatNullableFd(in @nullable ParcelFileDescriptor fd);
+  String RepeatString(String value);
+  @nullable String RepeatNullableString(@nullable String value);
+  test_package.RegularPolygon RepeatPolygon(in test_package.RegularPolygon value);
+  @nullable test_package.RegularPolygon RepeatNullablePolygon(in @nullable test_package.RegularPolygon value);
+  void RenamePolygon(inout test_package.RegularPolygon value, String newName);
+  boolean[] RepeatBooleanArray(in boolean[] input, out boolean[] repeated);
+  byte[] RepeatByteArray(in byte[] input, out byte[] repeated);
+  char[] RepeatCharArray(in char[] input, out char[] repeated);
+  int[] RepeatIntArray(in int[] input, out int[] repeated);
+  long[] RepeatLongArray(in long[] input, out long[] repeated);
+  float[] RepeatFloatArray(in float[] input, out float[] repeated);
+  double[] RepeatDoubleArray(in double[] input, out double[] repeated);
+  test_package.ByteEnum[] RepeatByteEnumArray(in test_package.ByteEnum[] input, out test_package.ByteEnum[] repeated);
+  test_package.IntEnum[] RepeatIntEnumArray(in test_package.IntEnum[] input, out test_package.IntEnum[] repeated);
+  test_package.LongEnum[] RepeatLongEnumArray(in test_package.LongEnum[] input, out test_package.LongEnum[] repeated);
+  String[] RepeatStringArray(in String[] input, out String[] repeated);
+  test_package.RegularPolygon[] RepeatRegularPolygonArray(in test_package.RegularPolygon[] input, out test_package.RegularPolygon[] repeated);
+  ParcelFileDescriptor[] RepeatFdArray(in ParcelFileDescriptor[] input, out ParcelFileDescriptor[] repeated);
+  List<String> Repeat2StringList(in List<String> input, out List<String> repeated);
+  List<test_package.RegularPolygon> Repeat2RegularPolygonList(in List<test_package.RegularPolygon> input, out List<test_package.RegularPolygon> repeated);
+  @nullable boolean[] RepeatNullableBooleanArray(in @nullable boolean[] input);
+  @nullable byte[] RepeatNullableByteArray(in @nullable byte[] input);
+  @nullable char[] RepeatNullableCharArray(in @nullable char[] input);
+  @nullable int[] RepeatNullableIntArray(in @nullable int[] input);
+  @nullable long[] RepeatNullableLongArray(in @nullable long[] input);
+  @nullable float[] RepeatNullableFloatArray(in @nullable float[] input);
+  @nullable double[] RepeatNullableDoubleArray(in @nullable double[] input);
+  @nullable test_package.ByteEnum[] RepeatNullableByteEnumArray(in @nullable test_package.ByteEnum[] input);
+  @nullable test_package.IntEnum[] RepeatNullableIntEnumArray(in @nullable test_package.IntEnum[] input);
+  @nullable test_package.LongEnum[] RepeatNullableLongEnumArray(in @nullable test_package.LongEnum[] input);
+  @nullable String[] RepeatNullableStringArray(in @nullable String[] input);
+  @nullable String[] DoubleRepeatNullableStringArray(in @nullable String[] input, out @nullable String[] repeated);
+  test_package.Foo repeatFoo(in test_package.Foo inFoo);
+  void renameFoo(inout test_package.Foo foo, String name);
+  void renameBar(inout test_package.Foo foo, String name);
+  int getF(in test_package.Foo foo);
+  test_package.GenericBar<int> repeatGenericBar(in test_package.GenericBar<int> bar);
+  void RepeatExtendableParcelable(in test_package.ExtendableParcelable input, out test_package.ExtendableParcelable output);
+  test_package.SimpleUnion RepeatSimpleUnion(in test_package.SimpleUnion u);
+  IBinder getICompatTest();
+  void RepeatExtendableParcelableWithoutExtension(in test_package.ExtendableParcelable input, out test_package.ExtendableParcelable output);
+  const int kZero = 0;
+  const int kOne = 1;
+  const int kOnes = -1;
+  const byte kByteOne = 1;
+  const long kLongOnes = -1;
+  const String kEmpty = "";
+  const String kFoo = "foo";
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/IntEnum.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/IntEnum.aidl
new file mode 100644
index 0000000..92ce575
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/IntEnum.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+@Backing(type="int")
+enum IntEnum {
+  FOO = 1000,
+  BAR = 2000,
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/LongEnum.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/LongEnum.aidl
new file mode 100644
index 0000000..4156557
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/LongEnum.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+@Backing(type="long")
+enum LongEnum {
+  FOO = 100000000000,
+  BAR = 200000000000,
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/MyExt.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/MyExt.aidl
new file mode 100644
index 0000000..c054eeb
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/MyExt.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+parcelable MyExt {
+  int a;
+  @utf8InCpp String b;
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/RegularPolygon.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/RegularPolygon.aidl
new file mode 100644
index 0000000..3eab12e
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/RegularPolygon.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+parcelable RegularPolygon {
+  String name = "square";
+  int numSides = 4;
+  float sideLength = 1.000000f;
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/SimpleUnion.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/SimpleUnion.aidl
new file mode 100644
index 0000000..767b5ae
--- /dev/null
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/test_package/SimpleUnion.aidl
@@ -0,0 +1,35 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package test_package;
+union SimpleUnion {
+  int a = 42;
+  int[] b;
+  String c;
+  test_package.ByteEnum d;
+  test_package.ByteEnum[] e;
+  @nullable test_package.Bar f;
+  const int kZero = 0;
+  const int kOne = 1;
+  const int kOnes = -1;
+  const byte kByteOne = 1;
+  const long kLongOnes = -1;
+  const String kEmpty = "";
+  const String kFoo = "foo";
+  const String S1 = "a string constant";
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/Bar.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/Bar.aidl
index 99ba6b5..2aaf974 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/Bar.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/Bar.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ByteEnum.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ByteEnum.aidl
index 16c6e1b..944573e 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ByteEnum.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ByteEnum.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ExtendableParcelable.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ExtendableParcelable.aidl
index 6646ba0..dbbb82c 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ExtendableParcelable.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ExtendableParcelable.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/FixedSize.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/FixedSize.aidl
index e7a32f2..f4908e2 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/FixedSize.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/FixedSize.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/Foo.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/Foo.aidl
index ddb6e8b..5e260ff 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/Foo.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/Foo.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/GenericBar.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/GenericBar.aidl
index 1d9103b..7cab936 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/GenericBar.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/GenericBar.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -16,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package test_package;
-parcelable GenericBar {
+parcelable GenericBar<T> {
   int a;
   test_package.GenericFoo<int,test_package.Bar,test_package.IntEnum> shouldBeGenericFoo;
 }
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/GenericFoo.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/GenericFoo.aidl
index 9bc86c1..8929c65 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/GenericFoo.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/GenericFoo.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
@@ -16,7 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package test_package;
-parcelable GenericFoo {
+parcelable GenericFoo<T, U, V> {
   int a;
   int b;
 }
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/IEmpty.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/IEmpty.aidl
index 5a27b19..1717e58 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/IEmpty.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/IEmpty.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ITest.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ITest.aidl
index 7cd58e7..020c24f 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ITest.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/ITest.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/IntEnum.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/IntEnum.aidl
index f889ec4..92ce575 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/IntEnum.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/IntEnum.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/LongEnum.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/LongEnum.aidl
index b03c85c..4156557 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/LongEnum.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/LongEnum.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/MyExt.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/MyExt.aidl
index 3525284..c054eeb 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/MyExt.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/MyExt.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/RegularPolygon.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/RegularPolygon.aidl
index 8fdd8c84b..3eab12e 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/RegularPolygon.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/RegularPolygon.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/SimpleUnion.aidl b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/SimpleUnion.aidl
index e7fc95c..767b5ae 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/SimpleUnion.aidl
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/current/test_package/SimpleUnion.aidl
@@ -2,13 +2,14 @@
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/tests/tests/binder_ndk/src/android/binder/cts/JavaClientTest.java b/tests/tests/binder_ndk/src/android/binder/cts/JavaClientTest.java
index d380647..e95f4dd 100644
--- a/tests/tests/binder_ndk/src/android/binder/cts/JavaClientTest.java
+++ b/tests/tests/binder_ndk/src/android/binder/cts/JavaClientTest.java
@@ -189,6 +189,15 @@
     }
 
     private static class Empty extends IEmpty.Stub {
+        @Override
+        public int getInterfaceVersion() {
+            return this.VERSION;
+        }
+
+        @Override
+        public String getInterfaceHash() {
+            return this.HASH;
+        }
     }
 
     @Test
diff --git a/tests/tests/binder_ndk/src/android/binder/cts/TestImpl.java b/tests/tests/binder_ndk/src/android/binder/cts/TestImpl.java
index 04f0b3e..32a01a2 100644
--- a/tests/tests/binder_ndk/src/android/binder/cts/TestImpl.java
+++ b/tests/tests/binder_ndk/src/android/binder/cts/TestImpl.java
@@ -38,6 +38,16 @@
 
 public class TestImpl extends ITest.Stub {
   @Override
+  public int getInterfaceVersion() {
+    return this.VERSION;
+  }
+
+  @Override
+  public String getInterfaceHash() {
+    return this.HASH;
+  }
+
+  @Override
   protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
     for (String arg : args) {
       pw.print(arg);
diff --git a/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java b/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java
index 5253cd0..648c500 100644
--- a/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java
+++ b/tests/tests/contactsprovider/src/android/provider/cts/contacts/CallLogProviderTest.java
@@ -76,6 +76,8 @@
         values.put(CallLog.Calls.DATE, Long.valueOf(0 /*start time*/));
         values.put(CallLog.Calls.DURATION, Long.valueOf(5 /*call duration*/));
         Uri uri = mContentResolver.insert(CallLog.Calls.CONTENT_URI, values);
+        // Get last modified prior to modification.
+        long lastModified = getLastModified(uri);
 
         CountDownLatch changeLatch = new CountDownLatch(1);
         mContentResolver.registerContentObserver(
@@ -99,6 +101,21 @@
             e.printStackTrace();
             fail("Expected update notification.");
         }
+
+        // Verify last modified is > than the original value.
+        long newLastModified = getLastModified(uri);
+        assertTrue(newLastModified > lastModified);
+    }
+
+    public long getLastModified(Uri uri) {
+        // Query the data base to get the last updated.
+        String[] projection = new String[] {
+                Calls.LAST_MODIFIED
+        };
+        Cursor results = mContentResolver.query(uri, projection, null, null, null, null);
+        results.moveToFirst();
+        assertEquals(1, results.getCount());
+        return results.getLong(results.getColumnIndex(Calls.LAST_MODIFIED));
     }
 
     public void testDelete() throws Exception {
diff --git a/tests/tests/content/Android.bp b/tests/tests/content/Android.bp
index 1d8d43f..7fb1863 100644
--- a/tests/tests/content/Android.bp
+++ b/tests/tests/content/Android.bp
@@ -50,6 +50,7 @@
         "cts-install-lib",
         "ShortcutManagerTestUtils",
         "libincfs-prebuilt",
+        "HelloWorldResHardeningLib",
     ],
     // Use multi-dex as the compatibility-common-util-devicesidelib dependency
     // on compatibility-device-util-axt pushes us beyond 64k methods.
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
index f3251c0..52d5fe0 100644
--- a/tests/tests/content/AndroidTest.xml
+++ b/tests/tests/content/AndroidTest.xml
@@ -96,6 +96,12 @@
         <option name="push-file" key="HelloWorld5_mdpi-v4.digests" value="/data/local/tmp/cts/content/HelloWorld5_mdpi-v4.digests" />
         <option name="push-file" key="HelloWorld5_mdpi-v4.digests.signature" value="/data/local/tmp/cts/content/HelloWorld5_mdpi-v4.digests.signature" />
         <option name="push-file" key="HelloWorld5.apk" value="/data/local/tmp/cts/content/malformed.apk" />
+        <option name="push-file" key="HelloWorldResHardening.apk" value="/data/local/tmp/cts/content/HelloWorldResHardening.apk" />
+        <option name="push-file" key="HelloWorldResHardening.apk.idsig" value="/data/local/tmp/cts/content/HelloWorldResHardening.apk.idsig" />
+        <option name="push-file" key="HelloWorldResHardening_hdpi-v4.apk" value="/data/local/tmp/cts/content/HelloWorldResHardening_hdpi-v4.apk" />
+        <option name="push-file" key="HelloWorldResHardening_hdpi-v4.apk.idsig" value="/data/local/tmp/cts/content/HelloWorldResHardening_hdpi-v4.apk.idsig" />
+        <option name="push-file" key="HelloWorldResHardening_mdpi-v4.apk" value="/data/local/tmp/cts/content/HelloWorldResHardening_mdpi-v4.apk" />
+        <option name="push-file" key="HelloWorldResHardening_mdpi-v4.apk.idsig" value="/data/local/tmp/cts/content/HelloWorldResHardening_mdpi-v4.apk.idsig" />
         <option name="push-file" key="malformed.apk.idsig" value="/data/local/tmp/cts/content/malformed.apk.idsig" />
         <option name="push-file" key="test-cert.x509.pem" value="/data/local/tmp/cts/content/test-cert.x509.pem" />
     </target_preparer>
diff --git a/tests/tests/content/HelloWorldApp/Android.bp b/tests/tests/content/HelloWorldApp/Android.bp
index 0cbb64a..e3c2de5 100644
--- a/tests/tests/content/HelloWorldApp/Android.bp
+++ b/tests/tests/content/HelloWorldApp/Android.bp
@@ -77,6 +77,42 @@
 }
 
 //-----------------------------------------------------------
+android_library {
+    name: "HelloWorldResHardeningLib",
+    defaults: ["cts_defaults"],
+    static_libs: [
+        "compatibility-device-util-axt",
+        "hamcrest-library",
+        "junit",
+        "testng",
+        "truth-prebuilt",
+    ],
+    srcs: ["src_res_hardening_lib/**/*.java"],
+    resource_dirs: [],
+    manifest: "AndroidManifestResHardeningLib.xml",
+    min_sdk_version: "24",
+    platform_apis: true,
+}
+
+//-----------------------------------------------------------
+android_test {
+    name: "HelloWorldResHardening",
+    defaults: ["hello_world_defaults"],
+    srcs: ["src_res_hardening/**/*.java"],
+    manifest: "AndroidManifestResHardening.xml",
+    static_libs: [
+        "HelloWorldResHardeningLib",
+    ],
+    // tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "general-tests",
+    ],
+    v4_signature: true,
+    platform_apis: true,
+}
+
+//-----------------------------------------------------------
 android_test {
     name: "HelloWorldShell",
     defaults: ["hello_world_defaults"],
diff --git a/tests/tests/content/HelloWorldApp/AndroidManifestResHardening.xml b/tests/tests/content/HelloWorldApp/AndroidManifestResHardening.xml
new file mode 100644
index 0000000..2849d3f
--- /dev/null
+++ b/tests/tests/content/HelloWorldApp/AndroidManifestResHardening.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.example.helloworld">
+
+    <application android:debuggable="true">
+        <activity android:name=".TestActivity" android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/tests/content/HelloWorldApp/AndroidManifestResHardeningLib.xml b/tests/tests/content/HelloWorldApp/AndroidManifestResHardeningLib.xml
new file mode 100644
index 0000000..4c1d1a0
--- /dev/null
+++ b/tests/tests/content/HelloWorldApp/AndroidManifestResHardeningLib.xml
@@ -0,0 +1,20 @@
+<?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.example.helloworld.lib">
+</manifest>
diff --git a/tests/tests/content/HelloWorldApp/res/xml/test_xml.xml b/tests/tests/content/HelloWorldApp/res/xml/test_xml.xml
index 3f225ee..65fc623 100644
--- a/tests/tests/content/HelloWorldApp/res/xml/test_xml.xml
+++ b/tests/tests/content/HelloWorldApp/res/xml/test_xml.xml
@@ -15,4 +15,203 @@
   ~ limitations under the License.
   -->
 
-<Test>true</Test>
\ No newline at end of file
+<Test>
+    <a>
+        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero.
+        Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis
+        sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa.
+        Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per
+        conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim
+        lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor.
+        Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor.
+        Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis
+        ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed,
+        euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora
+        torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non
+        tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla
+        facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet.
+        Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus
+        suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae
+        pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante
+        ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia
+        molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue
+        elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec,
+        blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices
+        enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi.
+        Integer lacinia sollicitudin massa. Cras metus. Sed aliquet risus a tortor. Integer id quam.
+        Morbi mi. Quisque nisl felis, venenatis tristique, dignissim in, ultrices sit amet, augue.
+        Proin sodales libero eget ante. Nulla quam. Aenean laoreet. Vestibulum nisi lectus, commodo
+        ac, facilisis ac, ultricies eu, pede. Ut orci risus, accumsan porttitor, cursus quis,
+        aliquet eget, justo. Sed pretium blandit orci. Ut eu diam at pede suscipit sodales. Aenean
+        lectus elit, fermentum non, convallis id, sagittis at, neque. Nullam mauris orci, aliquet
+        et, iaculis et, viverra vitae, ligula. Nulla ut felis in purus aliquam imperdiet. Maecenas
+        aliquet mollis lectus. Vivamus consectetuer risus et tortor. Lorem ipsum dolor sit amet,
+        consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus
+        diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent
+        mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget
+        nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
+        himenaeos. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor.
+        Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis
+        tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel,
+        suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum.
+        Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat
+        condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
+        inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque
+        adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse
+        potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam
+        ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus
+        luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum
+        magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices
+        posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In
+        vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet.
+        Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt
+        malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis
+        est pulvinar ullamcorper. Nulla facilisi. Integer lacinia sollicitudin massa. Cras metus.
+        Sed aliquet risus a tortor. Integer id quam. Morbi mi. Quisque nisl felis, venenatis
+        tristique, dignissim in, ultrices sit amet, augue. Proin sodales libero eget ante. Nulla
+        quam. Aenean laoreet. Vestibulum nisi lectus, commodo ac, facilisis ac, ultricies eu, pede.
+        Ut orci risus, accumsan porttitor, cursus quis, aliquet eget, justo. Sed pretium blandit
+        orci. Ut eu diam at pede suscipit sodales. Aenean lectus elit, fermentum non, convallis id,
+        sagittis at, neque. Nullam mauris orci, aliquet et, iaculis et, viverra vitae, ligula. Nulla
+        ut felis in purus aliquam imperdiet. Maecenas aliquet mollis lectus. Vivamus consectetuer
+        risus et tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio.
+        Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum
+        imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta.
+        Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora
+        torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed
+        dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem
+        at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas
+        porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac
+        turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel,
+        tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti
+        sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed
+        lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis
+        turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus
+        consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu
+        magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus
+        vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum
+        ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia
+        molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue
+        elementum. Morbi in ipsum si.
+    </a>
+    <a>
+        ez47HmHiHAzBvRptk3Og3b5sZMltJnYmSpeSmnobDlyRLvVsvm9umbkypggTJaM18KOl8aRCNW31xt8AUy2OulKrgvK3
+        VXXRHFJtWGmsM1IPAXeqx5cwxT4Pj8JGMXgnCPQ3aseoWTVdxkVHE9v3b8yt52obadKTZUfOgtw8K1Lu2p3JPzTbb9OK
+        Z8LiqLWr8B9QmYbuCUTojYViqxMjR2oP0Qjf4I85uKd7MUYaXWucnmQ5wbZhnNstEJBXAgMclWLZMWaKlCjxtHrpnON5
+        CLkdtOD4I3cNCoABydPXKZqoQ0zLinOYGo26VkLY3V7nN07WWe17ZZavMo0dyab9aVnSKlw6kVBidv8eqnWZ4Ngiu12K
+        sLIIKWG9jTPE03Nc9w0PdgHWjvGtsSLH6Z3988urdPvY7Rebj3WXRSTAUTvCXVY0qFhKqlQcNEvQfKvR6CDGoBUXJYmv
+        qfQnZfSLbyYuv1M1cWOiOmy4CKctAsHVvsXZiS4A2Kyu0XPvAMvNIotLV8VVxHb4mwvJSxtnc4iX6uyt5kZCvc6ep9WN
+        STLOeBZrALqPqwPSZQ9f4t4LUa8L2D3y9TcBFFgEFzDg9mPJfQYZOptnViOc0lL9oW2Kj2dXLKYKAxCfCOZy4E55BTy8
+        0uv0tRzDEBLvpQt81xtIYAL9yqEpQzJ5ymT7KUGdimRZdYATFDENgkoVl14eeMayuGYfl13wtG2k72l38uzQ3vFyBRaH
+        SUZUhKv1HS02qVnsZ9d5t8Yl9A6HzBfvubQY1Gwz336KZmp1garBtnW17KJ8rtSwvH2i1J1NIK4Ax6CrjafrSYUHkGWu
+        hTZbxBsUQbWyMrvOEs7AvNKgve87GPEGRhQcjpkAXBg9xKTc98ZeccOBuNMnOVdbAHKxBay4gWaMm8SCIKPOLs8LTXud
+        8hzYxdZAo7o5VAxAy5yIeWXtEOKbdrECi4nec2kO9z8tYq2GGilsISSVCwgtwfPfPI253aVsOJkKcdsU4jGDqOHy1JnG
+        hi6vPDDkBq1xIm518cCc0kToEhNc3LxCo8oYvSl1cbHuGJ2LZy63enYgwXo6gdFZBKrjE291Qi25RdqykjeLj01sUuhg
+        uz3feDHuHtv3sid47Xlv3FlUfLHYMrW7oFVCgT1NtbH2QaPAOESJN6floXAvNanB3dW8iTX9oHcFGyxv6OeJcnWXbB1o
+        drkgI9ZX3zRPG2oBSkRlVJJv3zFJbsMUUsk9zDZ1IBss8gddybpPNg4pE9Tk7jgShhC6TjcvKlZ82pIZvKQPppCIbMQG
+        Xn4rv8IAu7YJ87j0FAfPBfCfrPZnKPKtWvh7sTJmUwytFGoyh7Ci8aUoIL1i7Ojn0svUcVACFD1VxZkkOsVxiyVyztnv
+        KCuOXEqYjOsMdAeh1clGhO9XcPeVdieisNxuAW9yRA2ydRjqnPIEJxj9r5cytjEbVg2xK1ZuTfb9P4s9JZBdQBQN74Pj
+        ZO4RuGBkZt7WSZ6uPiWqD31QIBn2uCYxqzwi5B7jnDagaANmjk2AdwXUSX4TqSgjr8Y1kIXQWzirGWrmA3zpMI67BzFO
+        3jGcv3z5NQ4aC4aGO3QCu9MeWd3i8t19jSCGOhRhWrO6oQOLrxi0JGiCo50stpYjUGoK5tt8i26z1dzZAQcrSQmH96Mx
+        nkMkR0zaby6n2BNTtRukhXwk6laOPhOyFvBdTD6dYywWZRPNotOash1mjkrShHW2bTIUrBvWf2GdYNctCkkBpPviaSYw
+        8jz4YfO6d2i8GUaUegsfeujIUNvP78eSQb1H7uy3sPex7IEuggWxDFRtL0ly6XHZXGWpYIvDqZaTJl5H9vB2EFEWTlb0
+        SNXnCIYkAw0zBjPG1xq6MPNh0k8rPLVQSxUrd4j9EA5nPMoQDmNtYSg4wzruuZQDNzXgzXErVZif2h9g3FEoe7k2qhdc
+        TaETSP6hOvDVxPv6mqkTACPr9CPOsGCm69c3WN3sJXFyXIc76UhGRnqMsZlmHitiOfXY4HGPCNmp8rsf5Z9PWlL94tHE
+        JypQvFTV89HhB30yumxxQUqmXyEBu85r6eQaNETL06DbMJVz6u8GbshwQx1Q2clQJJnzjMazKqwy6we4gAZzyP0N797b
+        40gUjsyNcyKaG03TfsOhNdKdEZ2pHMmSANyRucGP17sMHlOU7cwJWmmFnXjeQuGuxiGJpmsB9NpwSHAQwNTgpEJIbMJV
+        vUOTLb1ZxwotgXSH7mCsSgCBH73qyVTcv4wSaC0J3SHLhnkvUo4gnQo9fhRiTExHUbkcczPFnMFY0iiIN8iTAfvNQxEH
+        9mq49izF05aQ3suciluj3bODVjR1fn1uhDA5JkDj3orEGFSGDDRM9eTxiwI7gixOFVDQDaDfLdSgfc9j8ezeeJ3HmQYw
+        s7Z8jInf3t2Vy4nWSakCyhvjoY1EJqQgCWnAGkqg7VtCc87jIEacyqZHQUiECCW2Xy0UYisrr3SuNZhI1eEUdpl8IpdC
+        c4JGekys17BC4ffM14NGCYvZ8R6xrTwOqCjWOVWffdhP80GzRZkwhyeigHrLnDMMA2VCqrvCkk0yczS9GxauCk9bsQW3
+        55R88kRNzWLgB5hOJQOxR0adZCLuFf1jd5CivE1uVqXFqsiCEayYEMS8hO985ByT7eKKmp4iYDBbC8SNNxP3FPsAsGvM
+        tB4viW1Tq7ugK1brb72k4qb68TLec19yS58I9Z0zkMdnfViYfZRhtTBPmJDR9F89UpZzvsMCpPsZqjH4kyuVzhZHuilL
+        oSWdC8uIqwLwemoOT5EkvOijmwxo7yRbw5FNIsqwBiXhlqwOPlixaovW4r2RgY7P9IiuKIVAJZJvqhlCXHr9efXmxriF
+        fE569OPv6m0lJ0NCrWVNZR9zgBCLnGHMjysPrAnjuDZYlQwPk0Jr2wBodtLMk5Lrmiog7KYWWPC39guC9PSkUp54Mjm4
+        coVqNhgbb1xwA8lTBYWUedL2pREVPoX2L0FFf8s1hZfS2GLAA47U9FkIRwxodQO2yFaF0w3cmcNm2nWmR7sz8Yqq7cwx
+        50njmKowgrTnwVMVtfEAvNaPcmcRDR7DAeqpOfFCr8VoWsAF5XNVFwzWJw8P99OK27yxVPafKtIzNuOaqkrxxjuWpiP6
+        zYOW4enPUcwcKt6ttjXYlQ7pmQbbtMAmnvY8NWhvtuPqopu46kxnIuas1KcDIqsqcyZJsaDrAKz4XUXiezW43ULtQrT5
+        azHS3jfcvqdUKkhzEJ7TifN0zEA1u90jqcl8D0StUBllBebquw1HDpLTyjMzlvu9BCgJVxY18S97XhaA0AAteGYHyQPw
+        TlffzXFwXkEjqXOfzFFmIe8XvvHetsW4ytkIms55nGPkYdoXq787zI432RZ8gcdfWu9gDvS1Cz3yHEwn5LxWWwybwQpJ
+        sYkhNd1OyEW8wzdG99RtP1QbFBpF4gm4RhZecYnRzU9ZCBb7bbbXGJIAZyLX7DprPN7DlLn42zpXE1hiUpOV7koTL12Z
+        W8cMMdNhY7GrpIrr8a91LpQJHq9ixV92Ei1dJxYHzLBYhbCe0L3ob04nMQFML5HxmvIG2fW4Sv4hciEWFKf1jG69rktZ
+        pIK9Uv6dWoHfcH5Semqn1MEIPhbB3nlWpfdkWAtrtUdDbJuWoM2gkISV7ilM1dY2YHmT65XAkDpxueCl9MpRNTmAaHOm
+        T7puyfzfAUTDEkE7hQHdn7FUvbj7rDHBK1Xtt41sNUkiqhwRK64YeYbTanCLS3X70PB6vU2VRyV84d1mSjrEy8tMOIcc
+        5Kx517POVALKNltCEcl9VF60JANv9LAmHLUUzWQIL0N3KK8a5uKUwCaeoPEdRC8JFbBgomKE3dyN2Rfm955Gsc6mQMMS
+        uTSctXtCoyu0CZ4WhssK35J1rwQtD64wZzshXHPeMOxjPkXS2EZ8X4fQvzvDBOMg5rwYgRvIVrvpACci9OUXzek9VSfj
+        W9XlPFXaeb6Lrhjli5fkAiENHSRgZwYrFMMfW3FzpS2CrdCkkPFKYbvL2VcvcqFmpF04a7JyMRl8soyPovVErwnWifNU
+        idzQ5rHE47s7dRS4jCQquCVaXmjYWamKXXuY8tEzTOvwuvYR9ZHpRQTD4gFN8oCC4aMbv5vVTEv0eQ0C1KKdv8J6UHgA
+        kEUy29DoC9NEMcBlms2kabJy08ZBeviRKu22r9SP1efiwKwCe8WlPnxiQT9K44GvPuKXga1AW7Uk20X5q5QxvGEme8rL
+        JyVRnkLiE5JZ8YWWtmMmnTixdkeP5CHPRFvvpWLIgc8E4Qr8nJznaqsQrU8UE1e3mk4yW4Ud5Zo3MwgeWWaUeMpOiZkB
+        kup4QHuTgruA6g4x4hKkeEx9Klv3HdKTTPpzDgz1kt3b4VOgnXCJnEjj2xFOGKDn6jYMzv6tOTuWjEBSMWD6Ug4ZtXiA
+        J0QXzADrJWQvfnJi3wNE2t8sJZcMXboVLMpFfD6hUbUigjJmp9eUxJrPWlUFTqSTJY8WQjRUResOwIJsu8r6OREnuIUS
+        kBvM5ItRdWUmx5lriGv7xyXRgHBTj0P4AA4VCGSUA0nxKM2eCopj8F8V4WymX8DrdpYpTKxdWWBDqkWMGSNyDwFbRqdA
+        JALeoksA8CNAaKAWSMFtb7qpeTgDrTOFdzLwXlxUoSmoxfxx9wpvYk5wOOvrmddSunACY35ABNYVa2FonRHriLsite1v
+        S2GPqwFmt4RwVxdheEVCtLrL95Akn7aiPueTvjEJB5fNwr85pDMiOuLL2DAAcNHyvrdHbSYyml9qG81SQEFMQFOjJOL6
+        5GzgdP5mfJvHZlnFUQvU9ynDtUmJdghdTNUxzG3D4UUZ7hVzh0MLO6MEavTXnvtEABHiijFW35KfoeLvAiqNEkejiZyV
+        yHgbbgDW85Z7x46XEsJfoXYF3rXtX3JJSCkeU2JkJoAyoyNPCzu8hr2roK4TTlP5j9SLrXgTd9e9QYFB78VFGvxxybiO
+        446riAf9S2asfmb0t0wWw6woGhGnhnRP
+    </a>
+    <a>
+        gQeWudOcpLpkDyeuVTikXTGu979qPoGp5VzVBoPdw36p25bfGtrCaxv3SngGUvmRC5nck6FT2kxZ7IdaQ9y04HefZhOw
+        JpTlRGRxOr8tacekbu6uCXCBkVMsJFv5LFHU5U2QNpw07JeGQ75b2CynUyuJ7B5bYpgKb9KLvNlqMESXMrVxI3zuy5Zd
+        xcLMkxBxjFBHCLuL0Tc8Xjqwwckr1ZNmxxq9mwY6Jz0UB02KKbkJpgoR5xOSSpYX7J3bQVxYwxZ33RPEtRkPPHvO7Cc5
+        HHpTcyXjJKMwMpnnaR7ErZhsA4UxP29hOGVoRkh5VZhhC01sn6v4tUlcLgJnerUpWGv6ZvfbpvnVUvQcVqzP38Xtiw3r
+        plWu038lW6zAWYu1n7A2rQCzgyFKUfgpltsS0eCADvg2888IYeFGIBuEMUKmceg2pDNoxCEsDo2zE0hYytKildAKJgWS
+        Hlblh5z4quHuk90cs0Mc689fNX8OufIIFGmITieqJD4tpCnieebW25PGfOvYeXjjSmnigBBhYOU7qGndl23xpZlJBqQD
+        vsGr6cGbty1kqE43LPE1UOQyOGTPFCApXSaWK46jP113aZllQd8PlkyaUhonWaWWEKLOrrLCfWbjUSaXtfsyaa3W6jfT
+        U8SZyMIMlOG01Fymyb3Xr8rAePYXB1n1YrnYbJcYMcz84PrpQpCTnOShT6nfrNS38wIjyEMr1cQycO3e7zaiHTT4WDwP
+        erwCa6t7R69oH2LelxuqIOEZKpLS1YfxqdpsfjMxMkUxty3OkCD1IZgcykn5WD4xtOah8oeaVOe7mdJQVTsEF7SiWCgr
+        OCoNQgnrY8hH4YjdNCoOMliBa5U4hjwkbr6D2u5ASmbuxARiFhx2QqzhCi6Js1uLyEuVxhmZCTAQWIeBT1rzEcCtThRE
+        VBOoU11j12J8GKOGchvAqzAHVc0k3m58bDXm3NH5x50P77m0XBWzPxsPHKlWVqg9fXxViOKZjNF7nOV1x3p8EQNVHMPR
+        HCD6NdNWodCA8YhsN83N3oakKb58nQfM16Eglscj8wcZql49rVvEx0l4YmmVqdRTFvPMPW8WBdu9g9YOmtjToahNPR58
+        KLIxZnFonU1LeF6NwBXii5uJwUqGxtiw98Zqyzv4R63FLvkysPmZjPgYse6emLyyZki4HGtitbFk6EivTWiXKjKhjWFw
+        T7qbNGy0ozmp6qfU9M4mFtlZim29AKm6uaiYsorMMvLmLoA70BhzSphs5x1E0z3GKPEH5jNVDrL8eQwQFbzWZ3eZegoI
+        xCfT2azc2jl7qgNTx5PrGOPyNrED0FBZpmmSdbtTK48vvIsIcHFskrB9OAtj0QbqcLinyQXR7yt1XoOAGRkP5J6koUwc
+        DVelDUubzbXskXB8SNqnE5TncmCewBtjmNzDCNPUc9BTnj2ZCjelb6X45mRGAnhBz3UCywVOwigEFFiO5GIu0fLI8ECN
+        Q3hqkM1Fuj6gWcX0o0jFuOdqI3WVieU8GxVGBguURWh5iV7UUMPmd1wW1nVfGvjxtsTAXREwD3VC5LIJrnCM29WFnpSv
+        WLiRaWj4dxI7C3IBuCfp3SNfvNNHIk74DUbNRMn3EbZLZxsu1KNKO9FhmNNGEv0JrR1r0sLYADQ17uNuLq1W77b3BIGK
+        4clNwE59W04oACRAto3wPeGyxgGxBaje76Wz1MzsPRLGLDRNxhIGr5wh3le4bBCD2G80rLFfovrF4IBTqkWVtX4OsrPm
+        jmVu5n7hCbzBtiyMSbMKQGOVUHScq09I96kPwviOF3hb4AaaYrvP7adWUdVAJF951ycnOU4Rr59BwzDLe1YOTVxc3PrI
+        F92od1ilX1Q6VhCnwboU92qaGDGBBAT8WDXWe53i88uK9sHPueZA2AL9aOjZNs9FkVPavbv0m1zs7lCBbkEwsQssIVXO
+        n0T9k1h9NtArCaqkzyZc1yc6hBBTz4bg81fcEhcygTiE4lqHQmzzPg88tti7jMHXfqZTPjaDZMH8z7PVJJflNYInZ0YI
+        DwDhEv5333kDU6MVerhWTfbvt5IxSIGTzPB5r9BI6olN0SAuOK7OJJug5AG5srpTMQCHHkBKat3USBA4k9gLPiUvKIq6
+        LEauOmx7Vq61BqeYDNkGr6oid523yWsFird8deRjkvrw043sBfrlqFO0jDcqBVdsGYztyUnFrrrAQH4Rq4ssYH56hW6e
+        D5NH2rPSw8SINcLiepnw7Qi8mAoiJPUwh5joAACGFjtjrIUMULgTqr5Ot3odSIwR5jp0A7LhM6aH32sMysvCdHwjTX0k
+        6SZ0guTOYqotHnVpZ9C4WKaReYYKu6gSUgm1sZbXZSbvtMlkcbsR10PSEY19M7hXYd4Rw1BII1CSguYkyYFxypeBUn7J
+        926HQk2vIatGIRTSSGVg92ZlL7DF78vKd5ySl0sdoCAG7lsByXotXXqSTQW9WPInoZLJcM9WxnOgrEiffQJQOP34ounj
+        qmCafBr3suXgjcXjMCs40ZbyPoYZFOsS1jYvtxtsCnsE6ssHRVdIP4GSdIzMqkvN7SMUdrpSxNWdyksCSIQ0cbkL5xpa
+        JE0dQm8PmOSo1b71BY282hck7PbDwpLjDPowQk8XLfqRTeJ4E9cZVx03e3z6SwUyujisSr9ffUs2ecnh9AxuykqLH2fm
+        W7be094eemuki5UnRacFUTSEA8B53q4Kk5YdIOj3SQ61KaoVSLWtjgOBB7EZFxwj4opISm4364HHuvz3yjz2TAc1na0f
+        L8X3YiW2gDkX9PY8SnN5B2Y8Qzl55cUwdiukBpnSDXdVjCU7igCI1KsC5cUOHAZJQiw4KijTdFMJb0RILQmzpoNdaSjb
+        itca8lWc7RemhpRqrmuj3qx4EUHFO8wngbuELpZS6lMj7qavYedFtrZRCKNFuYPRg4qpmStwi2Qd3OM2vOWuZGZxX1R6
+        2iOZdz1KjpxQqe3fSKKQsoIhmxya2kKh1lZvEH6WXsMaFycPtrJ7MdpxZznoccHQCostcsEpP6jcMW52jcjSovytNVRP
+        CigvgpIpciE5z9dfn5AjTOCc6rfKTMLVwj5UP7crubAAQTChUL6602Njovg8smbQT7GeC5lNwQbMLEPUOjnWdwqdTL5Y
+        OwqWMr6FAr8AdOMw5QJ2B4DPtOO24BHVzeOhyvb22kczjKetiNkWkICdZT4zoXzrcD7xwTBSwA3IDR4QrDjUSnDj0Jlq
+        M1uJdqHlG2kARd4686TGUqcYHkGKcIEhdqTevG7mmw2U7BrEVX8eaQXlQNFW7roRRCVyumzSmn2GQoCk2IEdIlYBbXYW
+        W0xHBXFJdZlYBf3Cj3zjJkgkke9jVrnbLTpJ0zeAnBWCXW9jywLhWeG9xHRo7kKeUxR3FvicSndXaFlYhWOJYTxfeCt9
+        jzWep7noL8ziZhCaDhITp5Q8rnIaNCK40sjrIHIUz5eZaDxgIOn8URKcN1zLg3mf0s8Zg6x5KpWSopLq9LNovbeIbsT0
+        YNUzYdrLku0dt7VUrEn7NUCz3nm51KujjAeHJd0gllVzBSE261T6suotPsWbE0GsE0i37Sheahgv4S4IMLgbjdILlwCo
+        fxxvVjnnc31qDZIRukTzHynPBju3avpBDogQoKxtY5Sd4kNamYiUZv2C70aCNhMtsL7vZnYyre2o2JYl4X9l49L2YEsu
+        Qd155xKdR9n1cFSUbg0FCBt38s6B8338vxaa2jgG0g3wk4RTnGAhfs2OPzdCOvE8q2JEgB2OY0LQ3ZP6KEEx6znmBi2H
+        1t2jcjx1ib8KDNPxEgtxYAVelxeHuLZELKIi5Bs8oPsVNLYQCVjPfhub8vHtXhZR4xRsMUHrQaYuWAfkPDwzN53BHz7T
+        lItvo0NlI2CeFPY2dcD4vGJrqCfr4uYzGJ7yQOik4Hu5ZoTXA1MSc3fyMVNImJbNzPy7dKU4JV0H6ww9b8yi2V4tALxV
+        d9AS9dOhF6l9oodAIS7NAVkh4wxWvBJ3U4rFcAzGFurM2M2UxWpnQVTHpYlw70FeillwjLx2EpjO9xY9dMTfljoCRX63
+        yAiEq3LfTMhnKbo3fhO66onKx4hC5e7010MTls8w771GYZ5kU6zz1lY3ZWcXMfdHrpRUs6JwSnxAleBGwE54LXVCPcZB
+        QVMpu17JeeANeHPKRR93mz3uIyYJAJIEXY2hUYI3KwLepQDB47EZMiN34D6ZfZSCGPNZZmz8qG2TBa37WmaMRlYj6Iko
+        qXIVzKKi9Vdf3dzbg7ESmVtnwldshNXatfP8nu4XTDQaGA9dDraYT35N2g8kRrXVpdBWy8RwPOeSn9FYnuFwc83l7GFV
+        CMb04fRmP4i1OfTyKRqEsnBYetqe3EeFecgIGxa6SfW0Xj5pgISt5QlYlmfooUAsNw9uqF5oCxwKvyhhNMYBrcE1NwBG
+        KvAYwerlnWP2e06SgqClD22YOT2PLANlayW6torCCV98AudopAy7oTZw1XzEg1g0e61WuHS0Gcwj3WGJVEI2AoXLYcc8
+        JynUQ9JGbkkcSrx8Jnwc4FTNPxIGXWn9c0d9F4eQlU9VE6F9JrSwYc9CZ7dYXxczG9xu563q1q9yYRw3RVTP74KjCaLV
+        LTUa8jsleEgLYYl2wLl0JKx6lXFGBO2O6tJXWVGGJ0EbuwQ4smyqdACYg5sthEniS9lPPpyP79jkFNcEvIsipTvPeRQl
+        m2oots2LGyz68WwJFGIy5bcAbhPvtRqBOmpJj0pUB7P9Un6OsBauIsJJLJPxvp5HDrew2pcsdDaDzWTk10QQQeSRSWv4
+        OMxJQl5TiWq4gjJeZIPENAAsDc5EReIUGwvkqOrzotlFQqNpwbchHr0cmF6ob780cqXp8P5dfl6TJHyi9yUoDtACKDGQ
+        ELeoj1krWeSrIU8uAFzc1p8htnCcS9pf0BQaLazCpyv7YFp9Ja7eGXDYCVvJ6lK6BxWGedWgGsOtvJBg6o0nT7NwYpwO
+        ozWqoeeNe2ET2eaRJsx8ZJ7mfXXMBkBa
+    </a>
+    <a>
+        BbLIdgLdNPh8l4u8VaOf6JSHWOTXV8WuDqgoxPx1z5MBCBkACih7n7mI2ExRttcafn9qVJtUEnPvSSQDRlkpcitusTop9fYz8m42WbdRdSh6UzvN4p58b5RRXkebgKdZOkK2QWAc1FajwqU7Kz6qW8lQp0xC6wdz1bbifwGirIkVGPp3ZJssrF4wcx6avzHkBf8kPoYhBBAYgTQpMW7NvXYuCXU6Vjw2hARRCx8V69LOFpY8e9pMjIU6kIOyib2DWTok0XQhrYWRBPMpjdYSmFYqhhNpgDUj94HrxQH4kqYGAzuGXGSSNVB0OeXPgGn4LEJNhyXtObk0sTORKorIg7LFkYO5u3X3lnNz5vE1Vq5tD2eLYCpBQbthzTnkmw7tD09JpIy4dG0jXYfVO6cUPg3iJpmJUHUsDxRFhPe9EJqtxOXUWn5CKEBM4JIUXZImd4XynKc9RivZ0VRcc1o46bABuSYtsAcjRgK5kCWHt7hr1NCvOcVAX9r9o8YF8qW0Kb72UmxoKLcJn6paEF5t9rm6mdZpAh4Ut0xS3laBoiGNPZUfeYT3yFgnLaANJtMh6nr0WGJgkd4TvA9M88tZ2rR5IIwCDiGpht0MfxzEN3m0kyAevBNbR8CF1IxNeCWuEKNHDQh42aY9o0DIs9muUDktM0AoOYBxGgZ7WodvXDW141v9UgGBOU0s5HQyYVltZtWeYgNl13zdGDdlX016boxZ6cjpTElPwSwBLDbDW78GsJdIdtMe3Qd4SPjNin9Mf3SJmqAj7xAaJYSUQJyY1bEsAxA5YBscbzFktNZPCcc2VEQVLN4z1ISx4bslVLhtKploEytzIUsuPOmuEFov1GOhsc71z0EAQd6tX4rN8VYLGGkXL4SWRcRczypiSsMEkTQvbqsravLiX6hEahMC6gehVHJksMDtBSPwqBx4J8dsHBXiHVmmtwhJJuNhAWoTCdGUW8Z05jzkFPH5nGDy1WyUp56d5EnwROzfezAHZqqDnunqjDMIAcfdRv9fSLgX1xMRrseWdNJL21Kcyk3JsD44EH6yvv9HxwT3xE5nFkpVnAX9ZBEu7Ksc2RBa3sgO6G2wJik55mzOYPpLGAwZOQsW9jSUNYCIDoXUyQz2WiH52PtmNNsnvhVf9vDMa8kfJ0gHGfGM1VjqFMfWiuph29lCIsUtD4I7Wo55q4TcGCHwEAUmjfi0DWNU8n7XdxSZFBvlb1hsVNFA6TqTCu0uFRQ400iBGCmuKlHBAFxVDDdmWJ5k5JwwB8vy0IqyVYrzZyIPSy9yWIibFzVl8nPx6vXaOYQOzkgMgx3z5U5wctunVRxbbvMJgPhXratRKywnsPQ9XKZ6d1PS7UtWXF3iksHCSwItQjAMoPBlmSvQqlHnPKqnQzTVkYHMSsRS2yVzAo8IQsD19zxOHOhS2zRRR0ri7FCVj51XQiy7s0keY5pYjfl5CFaK4fnnCIzH2q8r2pN66tl9Nbs7rOfYgQlUOchx7GYdJqwAyufGMCZKGrGTjV3PUwuaC3wPIxTeH1Ob0axD0Mwy38HnQYBV8TBuUTQQZb07UHpEDlPit1N6vBoenwHsGdVViUVmVoMHrz4qefiwKmwVKxf6iWg5rd2wByd8BKl5taUCvZbKS1HpCOAMzlec2psZD4Gwbos6V8YvPLz4XS8d6dW604ALEr2vVwddRvreUsFEi4gvt63DC87CsrXx6L0HndYR0Bu2V0KukOzSpWDfvJUvacoM51DZ4iIW953eONqCUeaLioaOOOIIPvu4FqmaMVIPAhsZFZ8PJdh973J10wqLRQdr37a1WgPqAQKKGxaTblVkouAnTr7ImgpF1xdVYDaD7mKolzYAbW4YJbfMDCz4VYWpqYo8iXc7e9CH6EVc5RPn5RzrTEyjroeOVzk6bvWPj8o54ObWZQNqZ6NmQXeB8CoeYN0vdJdybHX8rY85m5KvrQrjIEONFYyVd2MIyqSLou77jirC0YGFZxM4afdetykyJlE39OdljnbErxiGLgMHxo5eWsDmqWgNctgASkYIN75LgQWvd9xRPPlefjbClPjqW6rMCLnxHvFr3ObZWRSmmHTzApWIHFVZzTIRuvAq6XZu2OAO1LftaubpVlCbxOQV9zjEdLb3lISN7EdiQEIbHEYKILNRxHacP6i3KoEpeHqWPkB4SfSS0eZ75YGXbKQe8D00HLzprucGNC58SRAb3wO9wChojCae2sQHDN4h0UHZJ1perV9UXbhpM9Nv3h4Mt8SJAUkZCcGcNjuv450HIcuJjSFE1fjNvJQB10ZMRqOQ9WclCgnskaXjmJiGVfJhokzU9Z2MUGci19zE80WIzMebloy11bLW5XFyAm8l30hWcnURxJ5qM4ZCrfK4OCoEo74DSUtVOyrtNSmvKWIM2dQrj2hYfBssIcxLbzknJb5N9J4ZSgA30ZZqwJ3c7ppeqEUkq5V19kh3XSFbEFNruOPgfqQ3kwOGluWJcI1aZ0Nsa1C8ghorgg7FGAhwnHFQ7fc9ORkijt1OoToBKCTuvo2apXcMmjeyTnObOe7IkssHbIUetWfGZDcGQ4HI2l7nMXmjhQkzYFL15ooE6OokJWOO1KO3UoJgehZEg1XgcD4OZzP5p8hf0JmVNrOpZvF2xBijYV3bqqxvrT2AFUAhmtVdBmLaqmOpM55KjF1swC2zYihDweRspIrTDorn1tBh5YM2kTwaakD7iUcw9pfPzto5XtNqgltUHvufnIJDnIV8VzIPBPX2Hv72qjwseneKq0Q3lGsO1ReiAIMqrKUY7370qgEzAlERFDunckR8meFhgaZ2FYkZIVynLDjwHJIAGl30CdQxcjQkkrGZMZqZBHcOs5eTPz5vqs60n2i9qxBSJRx2FGntBXSGZHDygUWzzR2Nkt8eEiAde0aEwPwfzaNyGYP6fwV2FOL0mOOBlZ8HJZObyt5eS9QIms4Twhxr5WeSpeHx2MN4QqrfE7CFNx2RQBlZxS1OKGFdFsMXPYYj6sHDNcVrDNXCETak9wBOZDpNymKeaIZTGRUA3wvRDaV3kd8Gh5OFOKVMdn33qSdBc7Lr5RlHt2lxnyHoG2pPZ0LiY1hi72oUFZdgojC3PczwQaY9wS41dNrlCNCf99MwhfT6FSxMO6SUqyh2hNZWSpV7iJiRFso4hhe9i2zS9QIrazZhgY7x2vSUtbRvoCGS6BYd8ZCsPvK5o4KbKBxR2fohIlhfwShHG4LsjWKTW0wiURPNTYrOsgTUOHwWxagWosMZSoBOXdSJxDCIydZz64p6or6RXerVl9gqQHjmSaGZlWK7uFUrKmUq5TlYO5tW3Lin5GBDL4t9M2k4vnlpGPI8LThUGkOkegiBd5ZfPtxqPbqDxkW7iDR3oJvk3sVudSa1VEwaFRTaTByLPBcnnebxeEpkKPtQWSWVTh8Ew7Kt5qivQA2rQ60Asqj58DiolXor2kLbN0HdAo6wSOZiLQA7JOdX1CMmeJWVFXzYrGqJ8E1ricdkC9452TGJyDkaZymxqCloQOc5BFjN8lo6kEEwnHjzh5GIHcDnRhv2S0IkFIqaVIuqWHWTlvptYRondamIJTtNexb4hK3Qbam4T8VLLiSIllOCwGkbeRnO47eGb4iyXzbBctiLW15LMkr90WL1SS6ZfJ7Ht9KNFV0lCA1ObJ4wWyi5qxBZGdM1xbNf9nA4UiLyfBfe6zStyXdeNnV5CNokW8sLZqA3XQJ69GG2TfTBMTwefDwFIhXUMhc8W5xbGpQGPpiBqGcZtlhfNYnSH4zKXEV2dySYsxyxhgKats7meeqRsDHkDhLgVbPMa6CfWl2yDsuYQG82yCvsQjhGEtmkV33HAc5pySoxfA1LJFIQObCtbS9Q74y1ByqA7yiO4ocToitZfereTSuj0wUg4GwKiEuyNqT6KFu4wPzYv7rFa1rAmT0yjq2GsHoslygs9yzCLwT0HXDXGCTeMezmTJ7Oy56ooSnNsfpRtyBBN1eMB6NbyI4ZMy2bwKM7Yjojf95AdYTCbQGvAk13sPbRrfbgVIKSuiEIOOHquEkHK6CABI70TLHBIzQGmU0m4gVkeMSBDcFXO4ZMBuoYlxbtW4YyBFzQC9rPHY27blj1NXrwsxd8eSKK2odbW73f23zA7fE3CWPyNDYpkHC8lXsQjpw9kHEWzolMp3GzdAuSIjyQqVTLhJ8Kf86Gx4dXxRqGpcOe9fAwHCK7YnTrL4o9OYGpD8FuC9Xmg3g7dGBfsAeaKdB4ETknfILUxxfQoa1mE1LqA6lJ9oOcpmgkDIWpJfICZnqxHuvNN7FesSziFQ2Q0Z0Gsc8TifkiTARLghM17MyMKPzsEsptwaveU8vXtI21A6rCAXxqm4i5QMOj4oqH3lxc4cW56vL7PRzCID2hkBBW7TErEuj5fDtDOT9QrsrgkSzcdTfDzoz0v753MDB6wUrZF6iclxMqE9osoHn3Jw170BadxACmd26Egzg8CO1mDjTkMqICRBt2rXqSFXk8l002NyoHxO3UskaJipxwkkXya2OcC5Hr5IvEyiFbqRkdhxsby0tVh646gLE9Zzju6SGLnsebgOhqqDMEHxUPxqiWpiyyE5ZZ4r53m0JYBwMHwcWMtZa1yp4K4BcY8KtOQYzzr0jchzn4pU8lkfRqlF3HoVlmw5JhT8etbC6Yd0UykmPL75YoZYNxQjfOiTVAWBiahYWSRQf6ZB00UTRdx5w2QYm4MQxLdKobTvyGCj5CvtBTKeMulu0L6A1IgcIyxmKfR59StftY6bkyJ6gnyrAW5xBJg3H897UwUD5Xw6f5LkY07exayK3RUQfttLSjvvTF0mLztSkm6ubzJzq4dQQt4B9CQKKy6InrJmuoMLBWOQF8ow35MGM8eVNooIOIcqzWndwuYaoMqsWxeis7VVJCHSytcWoJcAxvIxdBt6buYc20RWfsMEbIb5duILw6rZ7FOGpXq3OFQ8DUOzvXnPichLLcyJ2Js4aLwsQ8fTN4Hiwo
+    </a>
+    <a>
+        ixF181Txv4vmFsdqVFW14Xqdf1rTcvrQiQR04lyaBQhug7EzKkRNNkWBpZ0Tcd4rtJFqzcNWT4UDP9Ty6785mlDO95rHROTxvL3KVp9ciXbPwnTwaverIRuhL149mAnSnamLzWxixBYBJryNFDMbOPWKhrgkiZZHFv1dBbR51TctICmLA5WF946K9btnq2giE1DPJTs5A14Wt0CJLGHwtc3WJQzK2OspZG3zyX9ghwP0OBlyF1tojLLvCNyKFgUFZQdcDisYnD935U9YENbpsEjvWNH4CyWbV7qtHCZRpzYkVEmcUlmYD1wWIwg3LzccmAW1FwpgFpQV4hHqlizuTyguqfGboOxfhfGq7SdBQgkSh2xImzB6tdVtAMLkrm8cmLllVSbsy1XtfcXfoVB8OdbPd0HwVaMGMzGRuTtQkBXx3KYKI9h6Pr8iYKwiRXF4zECXf8q0z3rPhYAId4GVQIpYhq4pqveHhdHmxm25DaCWIY3jOtlm02vUdfshuuaiUeVbT0j2x8pfFoUIpQLidZG0qRnT0HnxF7Ch9VBlWs3DgKz1JKB4JoT0FsOiQgPAJnNlydgHWShQMFhZGYBqjiRiUuXoMZ2N16q92PCsR3SESpeMVsDFrtoP1wx16xAPdZxExaIY9SoFWjWUHp00FnGkN7TPWtKjjUpPwpKS5Y5ak5hYtooiLCfeQkMz3DuxsLRjJ0gfTVdXLbxpVljDBdEzYLo1fBp3BHwwIaZwcIHtMDT3LJKiKITAkXBxhZdiOQ4dOXEuSbHV57rSfoVJjlSWUcjAL4sZnkpXbdPm7D5nDefUtQKWEuBGAffClcnbe29alojneuOZvBjk4IvFF1cNf7FfGJYS2HeCP3tBisGKYCM3BxDpTqlTShaPWD2CBRkdDQ8rbHbZQRDzXseCaSzpIwAKYqRxRWqefNIljQ2PLyqPuOvFV2m8lJmzIOh6J9RfDWcLK5TjRKFToguoRIJvShxar6qouSEsphKoIzEJ3iIr8Wan0RoK0jXGwb8HgWaYTIoJRu2Xy5jLFDcUuPqeUooCjFIDQMwRrUnsO4L13g8P8KBh3tUfi5GSo8SE356Gn68ZP8rNjY68DgYN3jRrFEG4uMsldgt5wOL8tsdfKI5JNc0K1ypjrKBaVHlCcykCJ1c1fjF29NFKxaFTWu5YZY3JTsCVdeXR9j5Gv8TU4IVqxinCgwWXd9E9LfvEFPtIqT337DjQNKGk4WcbPs6mG2wUAgb7iqksFBbv4ztgINv5vboGyJfZdtAr6epPQYS9LiGAOP9GAhe0dqJfjJxKBhxS654BIhbMKN9ZOUXUhwOYW6wKh28kUVHNdKrVz1mEk6HElCw7XmWlIUgc0fjElX5IM6BaGUCT5SIMm1pA1FutgdUzbX0sHQH3WeHqNOhx6U5ysQ4HUiN3MvXnOyKVQmIIAfJYTmawz3emxNVZNWWHnPiRDFwE8wrCtnd0iEB94OHPbkgF5xNc6yAiJzmhJyOjcIniFu4kYx7ZsRTA9mlK3isffPuQwCcT9Q1U4MqRB8wwiNxrC38H46emTAzruThEkKTeJ9zAJBxIOS0THQnB2tcDnZPy0eWlOifHWDdJS9Xvq0Sblp5wxk6Q1wcYILSaEHpT1PLo6AC3p409kDTMjWhyGkGmB9qU4g3ZnqVdSssx3tctEynVNgV0Pi7YOIL8oFhez2C0jYZjTNsNJKEcAuncA3NpR4FC7xPLbbXkwdwiLnhN6ojODvCPeIG10OlSUHYYRiyPpn2SF7upkHAO6GYplmO7Bgdm6HgKluZ7vo4TKOpFxIXJFwQHYUqd0DvhxkroX1CUIHqFj8WBYeu1e5pY3vXrZHZwqypC9Gh1sa1hcm3CimgaJ8eEutK6tKU4nWuXJSci6YiujuM6zwEzX04FcGBOM4OSpzjynJzXzQzuwhL7CKcAVogLfLDeINzmHyumgVIPSGUsbK55Uqg8YbZAEvLPfDe1sxRgT1IPZjrcLSXq4ekOXLQ6qQGBBjVJfX3nactWZvbllDKIGU3GXXJ2oj0JyXH3zq4FJFvol8Gh04MdCgDphLoNHuVxgvU8R7RyP518CR5EcGqf3TlfIZ7DIRHhkMgNED27fb6BAGFbitAPQOYwv6LIrk9elY8yckYql2Ke6j2kQGYCb5ISR1KQYTJVfXj3eUeVfzZ6NnbbvqWAbfMhcHu0vJlP6VKBSJB38FCwR6MrA1eyddmyetxH5imZpeb1lp12oaMOaBhl7FijE7rOVehvL6QbhIIrtCCjn6hB4fyVtA0sl7lvv92WkvGbbSLv0OAvtbR3anhtYoP5y1pbBOo5MU8aJlGQluiiUkKeZj9GpNBToNHe4dfewvPqJ3GnOgl1kknSYMoNGd7PWneBHYotchLsNTJygC5QOqL6CHdTX2n9KFPzDpuWWXkj5GCRBuIeKl3mrKwhAJomwJXQHyRYAiDwT0igrRwUiFU0wNGoYGWQAcrU2BoGlxtzKESXG1NRYoqnA8W3qEjLmGlruFvZYMkmHypDHykcmRmqFX9qFJlnhpZZXjEvfLKPzWe6IydTe9aZ40t7mHdYs2SGncCCBLzyNj6OHEnDMJB03T9BH2jTIQsn05R5Ll6DO3oIMLVFwlpLCUDGIwEoyHHnhVZz563MgDn9AARE5chxwcE3uewGZqdVQoaSTgASpQA8c1nH3ua6fz06TVSgIx2FeMOr8j1atdhphhJ9MPeqSm7RoxXRMuNbEO6IB3QLSH5bPwxZpWLuzePCn1CfwDCyBAttN0wmXiksGSQd1hSrsatZGgFsaU5OZO0yfj3qFXepLVOCOox1YnVJKOtWDU7ovLcW0ldycfE7kVBq6KRT9Msh2MPXdWANSCCjkGowgOjkBkJsQaMsStnBo3y1zHpSdwoWN18hRIunzqz8wii52XgiuO6iOIx4tppz7foIOHVSGQ4QFoMIqNpIvdamTxv8t0raRS7BIaDpvply9GJwClnI9xsY6ranpk8uUEVzYZmdQzKKNyQbWQwmre7EayjjNdA4jBuPj6NeCp4dW6LJHHWg2xuLcPTryKYAS6npOow6Gi8vtKiYfVf4vdILVDiBGWoNRqKuqsC7UlY6iu5jsGtbESdgMreKolMvlccFzMiBTe05RkHHaBk5imo11iICZfUvFmZfNsGJzTEtk0r1J8IEYOCVGgxHMKSTt2VzbvRTKKUa6Oa6GiLZArD7CyUqckvKcNKskKcC1d3zDQ5ELdxuZ83WTh0kjCnlKTa7ICE4zEW7EudhN5nWr67EfqAyVivmkz69rYbeS51v9AfMT00qS40ACo7wHoZC13zU5tBUE7NdgDpUX8xllaDmnHgysjqISpnnkatEOa2Pki16YZtQCpY5EDdHAomGZoOapGp0rBD40eq8P3W5CBixmbxe5xS8aGTZXyOPZJqrt7lSpKLbqZwsbGhXGYNvtm5poJgiBzJzTslCWbmARdF99H7RuPCeK0VhGswEE9KnDQlwUF5ygtlWgfQanfkLmSFp1gY3PMTzVlNQYznkIheyY73RXbjlW9WKkoKqWoBiP4t9jPwDF1JYdcXCs9BqvDyGvfha2LR7UzMf1dgAP5GppSHX2PBmYy8PtPwvT6YLEJJ5lnTY4K5p1X6BB9KBnCMQ2zlmFAWpwECY3ZP8gcdL6lXemiG2PKJFquwVqrUjnDOswPLPK87dp8Ju6IepDvvEpMpeIv8hD4vZEZRRpPK27BsQRtuMYiuXOQ9yKET9boooTmIGYYzKA3FIfM49mwKXT4AaGPcUVhJRfSed4QY1INNcP5lcsSQHWksEkbDMKxo0LN0oNvsZTSx7eEe5dlSDqsdhO811WDHtYZPR2i0MAyuHr6BkFOyo6cxvM2Co4l4j25vPKBqxhduJmGmd2DbuSlZfakMeUJ0fZJTT98e2OXVHyfYPMOoa0VM5egVU7sJ2c4G4XeR0tIFdQJTBe6Tzt7y0ohbd6lPlQbVyxAIgqqdBUCbxEADRZKo3UzEy77byi7gVWWs099ANUOx7ho3ibeow09PEW538GzBmy2Ct0q8NF7rRi7dJ0SOoroCwkBhnSIGwtsMWCeaglIJrnSbBPiRKQ8nYNMbjhKsWyRXszyF8zmt0a5DvteuHKDmRMtexarFUiUCntXrHLrpfgS2MLMliC8m59kWGH30fgXx8lF5bJr09Oa99zlbMS0flX8oxw3EJEvZ8k6gBkDxw9vSbuIw0MaFipKAy25r1yzmL8gwxW8WrgHAfxinUO0WSQY8xxEjOSV1APnVJve75vuEkKHhIaBz2Ybuii67EGyXCHY5WmbaUbxqi4IarAQfhXUQGFA00eEJLl6wPmIYcnrMMDC8vA046yq8p1UqLdbrA0saftiT9pmM77TD0ONCOalfq7fGYCie7x7yekhtWnEzoYUxOR0aDQkAPXKpj31mjLToDMtCGL7MLM4DiTyyF0rv2ScWFKARtZBrQaj6t1WonRQY0IzesHcSHgVTcj2bgdNH8ZiOiyDMVxmgrzVHDFj01qO3W5q4drvFN5dZEpcrBqb8ONMTh01CdsmkzlDNA5rnhYBvYeh5iinFpnXowkfUM88sXIQJWOR8P5DJnnfF2uYXJjGYtISqLzLGYWLEPODip8qlgN1DpOL1ZUsREQ5O1MDFGLQKJvtlXUYatqsEUTaNwKqPyQ7SPy7EvRUQSz8BzkNhhDlI9ABkfaMWkmmC6ZpjOapQvEwA9R6uPd8gentrZp4lO4bZBtrYxp6zH376cysIDU2GNuauN7MSAqvnKwT37YLYx4lhW9V4LQubo2Jn8Ibma3gwMfJE8V64cVRMjl2kG6fVNv7vGy8FUyu5JM5yV37pWQy2hBORmyXdPfbDBOWCYnWZeKqhLIGK7ONcuutHeIEGi7xJaDL82wSAgk4EqLEclMpQpeAWkJ1VvoikvgN9hWnoYGmupbCdLrbE2pqAdfVRBsIdQ5G0pox7UCGiV7XywHx5Idz8JDgayBR5emd9ogLJz7bJU
+    </a>
+</Test>
\ No newline at end of file
diff --git a/tests/tests/content/HelloWorldApp/res/xml/test_xml_attrs.xml b/tests/tests/content/HelloWorldApp/res/xml/test_xml_attrs.xml
index 28ce9bd..9e4c318 100644
--- a/tests/tests/content/HelloWorldApp/res/xml/test_xml_attrs.xml
+++ b/tests/tests/content/HelloWorldApp/res/xml/test_xml_attrs.xml
@@ -18,4 +18,119 @@
 <Test xmlns:app="http://schemas.android.com/apk/res-auto"
       app:inc_string_attr="@string/inc_string"
       app:inc_bool_attr="@bool/inc_bool"
-      app:inc_integer_attr="@integer/inc_integer" />
\ No newline at end of file
+      app:inc_integer_attr="@integer/inc_integer">
+    <a>
+        ez47HmHiHAzBvRptk3Og3b5sZMltJnYmSpeSmnobDlyRLvVsvm9umbkypggTJaM18KOl8aRCNW31xt8AUy2OulKrgvK3
+        VXXRHFJtWGmsM1IPAXeqx5cwxT4Pj8JGMXgnCPQ3aseoWTVdxkVHE9v3b8yt52obadKTZUfOgtw8K1Lu2p3JPzTbb9OK
+        Z8LiqLWr8B9QmYbuCUTojYViqxMjR2oP0Qjf4I85uKd7MUYaXWucnmQ5wbZhnNstEJBXAgMclWLZMWaKlCjxtHrpnON5
+        CLkdtOD4I3cNCoABydPXKZqoQ0zLinOYGo26VkLY3V7nN07WWe17ZZavMo0dyab9aVnSKlw6kVBidv8eqnWZ4Ngiu12K
+        sLIIKWG9jTPE03Nc9w0PdgHWjvGtsSLH6Z3988urdPvY7Rebj3WXRSTAUTvCXVY0qFhKqlQcNEvQfKvR6CDGoBUXJYmv
+        qfQnZfSLbyYuv1M1cWOiOmy4CKctAsHVvsXZiS4A2Kyu0XPvAMvNIotLV8VVxHb4mwvJSxtnc4iX6uyt5kZCvc6ep9WN
+        STLOeBZrALqPqwPSZQ9f4t4LUa8L2D3y9TcBFFgEFzDg9mPJfQYZOptnViOc0lL9oW2Kj2dXLKYKAxCfCOZy4E55BTy8
+        0uv0tRzDEBLvpQt81xtIYAL9yqEpQzJ5ymT7KUGdimRZdYATFDENgkoVl14eeMayuGYfl13wtG2k72l38uzQ3vFyBRaH
+        SUZUhKv1HS02qVnsZ9d5t8Yl9A6HzBfvubQY1Gwz336KZmp1garBtnW17KJ8rtSwvH2i1J1NIK4Ax6CrjafrSYUHkGWu
+        hTZbxBsUQbWyMrvOEs7AvNKgve87GPEGRhQcjpkAXBg9xKTc98ZeccOBuNMnOVdbAHKxBay4gWaMm8SCIKPOLs8LTXud
+        8hzYxdZAo7o5VAxAy5yIeWXtEOKbdrECi4nec2kO9z8tYq2GGilsISSVCwgtwfPfPI253aVsOJkKcdsU4jGDqOHy1JnG
+        hi6vPDDkBq1xIm518cCc0kToEhNc3LxCo8oYvSl1cbHuGJ2LZy63enYgwXo6gdFZBKrjE291Qi25RdqykjeLj01sUuhg
+        uz3feDHuHtv3sid47Xlv3FlUfLHYMrW7oFVCgT1NtbH2QaPAOESJN6floXAvNanB3dW8iTX9oHcFGyxv6OeJcnWXbB1o
+        drkgI9ZX3zRPG2oBSkRlVJJv3zFJbsMUUsk9zDZ1IBss8gddybpPNg4pE9Tk7jgShhC6TjcvKlZ82pIZvKQPppCIbMQG
+        Xn4rv8IAu7YJ87j0FAfPBfCfrPZnKPKtWvh7sTJmUwytFGoyh7Ci8aUoIL1i7Ojn0svUcVACFD1VxZkkOsVxiyVyztnv
+        KCuOXEqYjOsMdAeh1clGhO9XcPeVdieisNxuAW9yRA2ydRjqnPIEJxj9r5cytjEbVg2xK1ZuTfb9P4s9JZBdQBQN74Pj
+        ZO4RuGBkZt7WSZ6uPiWqD31QIBn2uCYxqzwi5B7jnDagaANmjk2AdwXUSX4TqSgjr8Y1kIXQWzirGWrmA3zpMI67BzFO
+        3jGcv3z5NQ4aC4aGO3QCu9MeWd3i8t19jSCGOhRhWrO6oQOLrxi0JGiCo50stpYjUGoK5tt8i26z1dzZAQcrSQmH96Mx
+        nkMkR0zaby6n2BNTtRukhXwk6laOPhOyFvBdTD6dYywWZRPNotOash1mjkrShHW2bTIUrBvWf2GdYNctCkkBpPviaSYw
+        8jz4YfO6d2i8GUaUegsfeujIUNvP78eSQb1H7uy3sPex7IEuggWxDFRtL0ly6XHZXGWpYIvDqZaTJl5H9vB2EFEWTlb0
+        SNXnCIYkAw0zBjPG1xq6MPNh0k8rPLVQSxUrd4j9EA5nPMoQDmNtYSg4wzruuZQDNzXgzXErVZif2h9g3FEoe7k2qhdc
+        TaETSP6hOvDVxPv6mqkTACPr9CPOsGCm69c3WN3sJXFyXIc76UhGRnqMsZlmHitiOfXY4HGPCNmp8rsf5Z9PWlL94tHE
+        JypQvFTV89HhB30yumxxQUqmXyEBu85r6eQaNETL06DbMJVz6u8GbshwQx1Q2clQJJnzjMazKqwy6we4gAZzyP0N797b
+        40gUjsyNcyKaG03TfsOhNdKdEZ2pHMmSANyRucGP17sMHlOU7cwJWmmFnXjeQuGuxiGJpmsB9NpwSHAQwNTgpEJIbMJV
+        vUOTLb1ZxwotgXSH7mCsSgCBH73qyVTcv4wSaC0J3SHLhnkvUo4gnQo9fhRiTExHUbkcczPFnMFY0iiIN8iTAfvNQxEH
+        9mq49izF05aQ3suciluj3bODVjR1fn1uhDA5JkDj3orEGFSGDDRM9eTxiwI7gixOFVDQDaDfLdSgfc9j8ezeeJ3HmQYw
+        s7Z8jInf3t2Vy4nWSakCyhvjoY1EJqQgCWnAGkqg7VtCc87jIEacyqZHQUiECCW2Xy0UYisrr3SuNZhI1eEUdpl8IpdC
+        c4JGekys17BC4ffM14NGCYvZ8R6xrTwOqCjWOVWffdhP80GzRZkwhyeigHrLnDMMA2VCqrvCkk0yczS9GxauCk9bsQW3
+        55R88kRNzWLgB5hOJQOxR0adZCLuFf1jd5CivE1uVqXFqsiCEayYEMS8hO985ByT7eKKmp4iYDBbC8SNNxP3FPsAsGvM
+        tB4viW1Tq7ugK1brb72k4qb68TLec19yS58I9Z0zkMdnfViYfZRhtTBPmJDR9F89UpZzvsMCpPsZqjH4kyuVzhZHuilL
+        oSWdC8uIqwLwemoOT5EkvOijmwxo7yRbw5FNIsqwBiXhlqwOPlixaovW4r2RgY7P9IiuKIVAJZJvqhlCXHr9efXmxriF
+        fE569OPv6m0lJ0NCrWVNZR9zgBCLnGHMjysPrAnjuDZYlQwPk0Jr2wBodtLMk5Lrmiog7KYWWPC39guC9PSkUp54Mjm4
+        coVqNhgbb1xwA8lTBYWUedL2pREVPoX2L0FFf8s1hZfS2GLAA47U9FkIRwxodQO2yFaF0w3cmcNm2nWmR7sz8Yqq7cwx
+        50njmKowgrTnwVMVtfEAvNaPcmcRDR7DAeqpOfFCr8VoWsAF5XNVFwzWJw8P99OK27yxVPafKtIzNuOaqkrxxjuWpiP6
+        zYOW4enPUcwcKt6ttjXYlQ7pmQbbtMAmnvY8NWhvtuPqopu46kxnIuas1KcDIqsqcyZJsaDrAKz4XUXiezW43ULtQrT5
+        azHS3jfcvqdUKkhzEJ7TifN0zEA1u90jqcl8D0StUBllBebquw1HDpLTyjMzlvu9BCgJVxY18S97XhaA0AAteGYHyQPw
+        TlffzXFwXkEjqXOfzFFmIe8XvvHetsW4ytkIms55nGPkYdoXq787zI432RZ8gcdfWu9gDvS1Cz3yHEwn5LxWWwybwQpJ
+        sYkhNd1OyEW8wzdG99RtP1QbFBpF4gm4RhZecYnRzU9ZCBb7bbbXGJIAZyLX7DprPN7DlLn42zpXE1hiUpOV7koTL12Z
+        W8cMMdNhY7GrpIrr8a91LpQJHq9ixV92Ei1dJxYHzLBYhbCe0L3ob04nMQFML5HxmvIG2fW4Sv4hciEWFKf1jG69rktZ
+        pIK9Uv6dWoHfcH5Semqn1MEIPhbB3nlWpfdkWAtrtUdDbJuWoM2gkISV7ilM1dY2YHmT65XAkDpxueCl9MpRNTmAaHOm
+        T7puyfzfAUTDEkE7hQHdn7FUvbj7rDHBK1Xtt41sNUkiqhwRK64YeYbTanCLS3X70PB6vU2VRyV84d1mSjrEy8tMOIcc
+        5Kx517POVALKNltCEcl9VF60JANv9LAmHLUUzWQIL0N3KK8a5uKUwCaeoPEdRC8JFbBgomKE3dyN2Rfm955Gsc6mQMMS
+        uTSctXtCoyu0CZ4WhssK35J1rwQtD64wZzshXHPeMOxjPkXS2EZ8X4fQvzvDBOMg5rwYgRvIVrvpACci9OUXzek9VSfj
+        W9XlPFXaeb6Lrhjli5fkAiENHSRgZwYrFMMfW3FzpS2CrdCkkPFKYbvL2VcvcqFmpF04a7JyMRl8soyPovVErwnWifNU
+        idzQ5rHE47s7dRS4jCQquCVaXmjYWamKXXuY8tEzTOvwuvYR9ZHpRQTD4gFN8oCC4aMbv5vVTEv0eQ0C1KKdv8J6UHgA
+        kEUy29DoC9NEMcBlms2kabJy08ZBeviRKu22r9SP1efiwKwCe8WlPnxiQT9K44GvPuKXga1AW7Uk20X5q5QxvGEme8rL
+        JyVRnkLiE5JZ8YWWtmMmnTixdkeP5CHPRFvvpWLIgc8E4Qr8nJznaqsQrU8UE1e3mk4yW4Ud5Zo3MwgeWWaUeMpOiZkB
+        kup4QHuTgruA6g4x4hKkeEx9Klv3HdKTTPpzDgz1kt3b4VOgnXCJnEjj2xFOGKDn6jYMzv6tOTuWjEBSMWD6Ug4ZtXiA
+        J0QXzADrJWQvfnJi3wNE2t8sJZcMXboVLMpFfD6hUbUigjJmp9eUxJrPWlUFTqSTJY8WQjRUResOwIJsu8r6OREnuIUS
+        kBvM5ItRdWUmx5lriGv7xyXRgHBTj0P4AA4VCGSUA0nxKM2eCopj8F8V4WymX8DrdpYpTKxdWWBDqkWMGSNyDwFbRqdA
+        JALeoksA8CNAaKAWSMFtb7qpeTgDrTOFdzLwXlxUoSmoxfxx9wpvYk5wOOvrmddSunACY35ABNYVa2FonRHriLsite1v
+        S2GPqwFmt4RwVxdheEVCtLrL95Akn7aiPueTvjEJB5fNwr85pDMiOuLL2DAAcNHyvrdHbSYyml9qG81SQEFMQFOjJOL6
+        5GzgdP5mfJvHZlnFUQvU9ynDtUmJdghdTNUxzG3D4UUZ7hVzh0MLO6MEavTXnvtEABHiijFW35KfoeLvAiqNEkejiZyV
+        yHgbbgDW85Z7x46XEsJfoXYF3rXtX3JJSCkeU2JkJoAyoyNPCzu8hr2roK4TTlP5j9SLrXgTd9e9QYFB78VFGvxxybiO
+        446riAf9S2asfmb0t0wWw6woGhGnhnRP
+    </a>
+    <a>
+        gQeWudOcpLpkDyeuVTikXTGu979qPoGp5VzVBoPdw36p25bfGtrCaxv3SngGUvmRC5nck6FT2kxZ7IdaQ9y04HefZhOw
+        JpTlRGRxOr8tacekbu6uCXCBkVMsJFv5LFHU5U2QNpw07JeGQ75b2CynUyuJ7B5bYpgKb9KLvNlqMESXMrVxI3zuy5Zd
+        xcLMkxBxjFBHCLuL0Tc8Xjqwwckr1ZNmxxq9mwY6Jz0UB02KKbkJpgoR5xOSSpYX7J3bQVxYwxZ33RPEtRkPPHvO7Cc5
+        HHpTcyXjJKMwMpnnaR7ErZhsA4UxP29hOGVoRkh5VZhhC01sn6v4tUlcLgJnerUpWGv6ZvfbpvnVUvQcVqzP38Xtiw3r
+        plWu038lW6zAWYu1n7A2rQCzgyFKUfgpltsS0eCADvg2888IYeFGIBuEMUKmceg2pDNoxCEsDo2zE0hYytKildAKJgWS
+        Hlblh5z4quHuk90cs0Mc689fNX8OufIIFGmITieqJD4tpCnieebW25PGfOvYeXjjSmnigBBhYOU7qGndl23xpZlJBqQD
+        vsGr6cGbty1kqE43LPE1UOQyOGTPFCApXSaWK46jP113aZllQd8PlkyaUhonWaWWEKLOrrLCfWbjUSaXtfsyaa3W6jfT
+        U8SZyMIMlOG01Fymyb3Xr8rAePYXB1n1YrnYbJcYMcz84PrpQpCTnOShT6nfrNS38wIjyEMr1cQycO3e7zaiHTT4WDwP
+        erwCa6t7R69oH2LelxuqIOEZKpLS1YfxqdpsfjMxMkUxty3OkCD1IZgcykn5WD4xtOah8oeaVOe7mdJQVTsEF7SiWCgr
+        OCoNQgnrY8hH4YjdNCoOMliBa5U4hjwkbr6D2u5ASmbuxARiFhx2QqzhCi6Js1uLyEuVxhmZCTAQWIeBT1rzEcCtThRE
+        VBOoU11j12J8GKOGchvAqzAHVc0k3m58bDXm3NH5x50P77m0XBWzPxsPHKlWVqg9fXxViOKZjNF7nOV1x3p8EQNVHMPR
+        HCD6NdNWodCA8YhsN83N3oakKb58nQfM16Eglscj8wcZql49rVvEx0l4YmmVqdRTFvPMPW8WBdu9g9YOmtjToahNPR58
+        KLIxZnFonU1LeF6NwBXii5uJwUqGxtiw98Zqyzv4R63FLvkysPmZjPgYse6emLyyZki4HGtitbFk6EivTWiXKjKhjWFw
+        T7qbNGy0ozmp6qfU9M4mFtlZim29AKm6uaiYsorMMvLmLoA70BhzSphs5x1E0z3GKPEH5jNVDrL8eQwQFbzWZ3eZegoI
+        xCfT2azc2jl7qgNTx5PrGOPyNrED0FBZpmmSdbtTK48vvIsIcHFskrB9OAtj0QbqcLinyQXR7yt1XoOAGRkP5J6koUwc
+        DVelDUubzbXskXB8SNqnE5TncmCewBtjmNzDCNPUc9BTnj2ZCjelb6X45mRGAnhBz3UCywVOwigEFFiO5GIu0fLI8ECN
+        Q3hqkM1Fuj6gWcX0o0jFuOdqI3WVieU8GxVGBguURWh5iV7UUMPmd1wW1nVfGvjxtsTAXREwD3VC5LIJrnCM29WFnpSv
+        WLiRaWj4dxI7C3IBuCfp3SNfvNNHIk74DUbNRMn3EbZLZxsu1KNKO9FhmNNGEv0JrR1r0sLYADQ17uNuLq1W77b3BIGK
+        4clNwE59W04oACRAto3wPeGyxgGxBaje76Wz1MzsPRLGLDRNxhIGr5wh3le4bBCD2G80rLFfovrF4IBTqkWVtX4OsrPm
+        jmVu5n7hCbzBtiyMSbMKQGOVUHScq09I96kPwviOF3hb4AaaYrvP7adWUdVAJF951ycnOU4Rr59BwzDLe1YOTVxc3PrI
+        F92od1ilX1Q6VhCnwboU92qaGDGBBAT8WDXWe53i88uK9sHPueZA2AL9aOjZNs9FkVPavbv0m1zs7lCBbkEwsQssIVXO
+        n0T9k1h9NtArCaqkzyZc1yc6hBBTz4bg81fcEhcygTiE4lqHQmzzPg88tti7jMHXfqZTPjaDZMH8z7PVJJflNYInZ0YI
+        DwDhEv5333kDU6MVerhWTfbvt5IxSIGTzPB5r9BI6olN0SAuOK7OJJug5AG5srpTMQCHHkBKat3USBA4k9gLPiUvKIq6
+        LEauOmx7Vq61BqeYDNkGr6oid523yWsFird8deRjkvrw043sBfrlqFO0jDcqBVdsGYztyUnFrrrAQH4Rq4ssYH56hW6e
+        D5NH2rPSw8SINcLiepnw7Qi8mAoiJPUwh5joAACGFjtjrIUMULgTqr5Ot3odSIwR5jp0A7LhM6aH32sMysvCdHwjTX0k
+        6SZ0guTOYqotHnVpZ9C4WKaReYYKu6gSUgm1sZbXZSbvtMlkcbsR10PSEY19M7hXYd4Rw1BII1CSguYkyYFxypeBUn7J
+        926HQk2vIatGIRTSSGVg92ZlL7DF78vKd5ySl0sdoCAG7lsByXotXXqSTQW9WPInoZLJcM9WxnOgrEiffQJQOP34ounj
+        qmCafBr3suXgjcXjMCs40ZbyPoYZFOsS1jYvtxtsCnsE6ssHRVdIP4GSdIzMqkvN7SMUdrpSxNWdyksCSIQ0cbkL5xpa
+        JE0dQm8PmOSo1b71BY282hck7PbDwpLjDPowQk8XLfqRTeJ4E9cZVx03e3z6SwUyujisSr9ffUs2ecnh9AxuykqLH2fm
+        W7be094eemuki5UnRacFUTSEA8B53q4Kk5YdIOj3SQ61KaoVSLWtjgOBB7EZFxwj4opISm4364HHuvz3yjz2TAc1na0f
+        L8X3YiW2gDkX9PY8SnN5B2Y8Qzl55cUwdiukBpnSDXdVjCU7igCI1KsC5cUOHAZJQiw4KijTdFMJb0RILQmzpoNdaSjb
+        itca8lWc7RemhpRqrmuj3qx4EUHFO8wngbuELpZS6lMj7qavYedFtrZRCKNFuYPRg4qpmStwi2Qd3OM2vOWuZGZxX1R6
+        2iOZdz1KjpxQqe3fSKKQsoIhmxya2kKh1lZvEH6WXsMaFycPtrJ7MdpxZznoccHQCostcsEpP6jcMW52jcjSovytNVRP
+        CigvgpIpciE5z9dfn5AjTOCc6rfKTMLVwj5UP7crubAAQTChUL6602Njovg8smbQT7GeC5lNwQbMLEPUOjnWdwqdTL5Y
+        OwqWMr6FAr8AdOMw5QJ2B4DPtOO24BHVzeOhyvb22kczjKetiNkWkICdZT4zoXzrcD7xwTBSwA3IDR4QrDjUSnDj0Jlq
+        M1uJdqHlG2kARd4686TGUqcYHkGKcIEhdqTevG7mmw2U7BrEVX8eaQXlQNFW7roRRCVyumzSmn2GQoCk2IEdIlYBbXYW
+        W0xHBXFJdZlYBf3Cj3zjJkgkke9jVrnbLTpJ0zeAnBWCXW9jywLhWeG9xHRo7kKeUxR3FvicSndXaFlYhWOJYTxfeCt9
+        jzWep7noL8ziZhCaDhITp5Q8rnIaNCK40sjrIHIUz5eZaDxgIOn8URKcN1zLg3mf0s8Zg6x5KpWSopLq9LNovbeIbsT0
+        YNUzYdrLku0dt7VUrEn7NUCz3nm51KujjAeHJd0gllVzBSE261T6suotPsWbE0GsE0i37Sheahgv4S4IMLgbjdILlwCo
+        fxxvVjnnc31qDZIRukTzHynPBju3avpBDogQoKxtY5Sd4kNamYiUZv2C70aCNhMtsL7vZnYyre2o2JYl4X9l49L2YEsu
+        Qd155xKdR9n1cFSUbg0FCBt38s6B8338vxaa2jgG0g3wk4RTnGAhfs2OPzdCOvE8q2JEgB2OY0LQ3ZP6KEEx6znmBi2H
+        1t2jcjx1ib8KDNPxEgtxYAVelxeHuLZELKIi5Bs8oPsVNLYQCVjPfhub8vHtXhZR4xRsMUHrQaYuWAfkPDwzN53BHz7T
+        lItvo0NlI2CeFPY2dcD4vGJrqCfr4uYzGJ7yQOik4Hu5ZoTXA1MSc3fyMVNImJbNzPy7dKU4JV0H6ww9b8yi2V4tALxV
+        d9AS9dOhF6l9oodAIS7NAVkh4wxWvBJ3U4rFcAzGFurM2M2UxWpnQVTHpYlw70FeillwjLx2EpjO9xY9dMTfljoCRX63
+        yAiEq3LfTMhnKbo3fhO66onKx4hC5e7010MTls8w771GYZ5kU6zz1lY3ZWcXMfdHrpRUs6JwSnxAleBGwE54LXVCPcZB
+        QVMpu17JeeANeHPKRR93mz3uIyYJAJIEXY2hUYI3KwLepQDB47EZMiN34D6ZfZSCGPNZZmz8qG2TBa37WmaMRlYj6Iko
+        qXIVzKKi9Vdf3dzbg7ESmVtnwldshNXatfP8nu4XTDQaGA9dDraYT35N2g8kRrXVpdBWy8RwPOeSn9FYnuFwc83l7GFV
+        CMb04fRmP4i1OfTyKRqEsnBYetqe3EeFecgIGxa6SfW0Xj5pgISt5QlYlmfooUAsNw9uqF5oCxwKvyhhNMYBrcE1NwBG
+        KvAYwerlnWP2e06SgqClD22YOT2PLANlayW6torCCV98AudopAy7oTZw1XzEg1g0e61WuHS0Gcwj3WGJVEI2AoXLYcc8
+        JynUQ9JGbkkcSrx8Jnwc4FTNPxIGXWn9c0d9F4eQlU9VE6F9JrSwYc9CZ7dYXxczG9xu563q1q9yYRw3RVTP74KjCaLV
+        LTUa8jsleEgLYYl2wLl0JKx6lXFGBO2O6tJXWVGGJ0EbuwQ4smyqdACYg5sthEniS9lPPpyP79jkFNcEvIsipTvPeRQl
+        m2oots2LGyz68WwJFGIy5bcAbhPvtRqBOmpJj0pUB7P9Un6OsBauIsJJLJPxvp5HDrew2pcsdDaDzWTk10QQQeSRSWv4
+        OMxJQl5TiWq4gjJeZIPENAAsDc5EReIUGwvkqOrzotlFQqNpwbchHr0cmF6ob780cqXp8P5dfl6TJHyi9yUoDtACKDGQ
+        ELeoj1krWeSrIU8uAFzc1p8htnCcS9pf0BQaLazCpyv7YFp9Ja7eGXDYCVvJ6lK6BxWGedWgGsOtvJBg6o0nT7NwYpwO
+        ozWqoeeNe2ET2eaRJsx8ZJ7mfXXMBkBa
+    </a>
+</Test>
\ No newline at end of file
diff --git a/tests/tests/content/HelloWorldApp/src_res_hardening/com/example/helloworld/TestActivity.java b/tests/tests/content/HelloWorldApp/src_res_hardening/com/example/helloworld/TestActivity.java
new file mode 100644
index 0000000..c1ed1ad
--- /dev/null
+++ b/tests/tests/content/HelloWorldApp/src_res_hardening/com/example/helloworld/TestActivity.java
@@ -0,0 +1,82 @@
+/*
+ * 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.example.helloworld;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Process;
+
+import androidx.annotation.Nullable;
+
+import com.example.helloworld.lib.TestUtils;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+public class TestActivity extends Activity {
+    private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // Respond to the test with the pid of this application.
+        final Intent pidResponse = new Intent(TestUtils.TEST_STATUS_ACTION);
+        pidResponse.putExtra(TestUtils.PID_STATUS_PID_KEY, Process.myPid());
+        sendBroadcast(pidResponse);
+
+        // Run the test in a separate thread so that onCreate can finish.
+        mExecutorService.execute(this::runTest);
+    }
+
+    private void runTest() {
+        try {
+            final Intent intent = getIntent();
+            final String testName = intent.getStringExtra(TestUtils.TEST_NAME_EXTRA_KEY);
+            final boolean assertionType = intent.getBooleanExtra(
+                    TestUtils.TEST_ASSERT_SUCCESS_EXTRA_KEY, true);
+
+            final Method testMethod = TestUtils.class.getMethod(testName, Resources.class,
+                    TestUtils.AssertionType.class);
+            testMethod.invoke(null, getResources(),
+                    assertionType ? TestUtils.AssertionType.ASSERT_SUCCESS
+                            : TestUtils.AssertionType.ASSERT_READ_FAILURE);
+        } catch (AssertionError | Exception e) {
+            final Throwable t = (e instanceof InvocationTargetException) ? e.getCause() : e;
+            final Intent failureMessage = new Intent(TestUtils.TEST_STATUS_ACTION);
+            failureMessage.putExtra(TestUtils.TEST_STATUS_RESULT_KEY,
+                    String.format("%s: %s\n%s",
+                            t.getClass().getName(),
+                            t.getMessage(),
+                            Arrays.stream(t.getStackTrace())
+                                    .map(Object::toString).collect(Collectors.joining("\n"))));
+            sendBroadcast(failureMessage);
+            return;
+        }
+
+        // Report that the test finished without crashing.
+        final Intent successMessage = new Intent(TestUtils.TEST_STATUS_ACTION);
+        successMessage.putExtra(TestUtils.TEST_STATUS_RESULT_KEY,
+                TestUtils.TEST_STATUS_RESULT_SUCCESS);
+        sendBroadcast(successMessage);
+    }
+}
diff --git a/tests/tests/content/HelloWorldApp/src_res_hardening_lib/com/example/helloworld/lib/TestUtils.java b/tests/tests/content/HelloWorldApp/src_res_hardening_lib/com/example/helloworld/lib/TestUtils.java
new file mode 100644
index 0000000..cc62324
--- /dev/null
+++ b/tests/tests/content/HelloWorldApp/src_res_hardening_lib/com/example/helloworld/lib/TestUtils.java
@@ -0,0 +1,325 @@
+/*
+ * 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.example.helloworld.lib;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.junit.Assert.assertEquals;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Process;
+
+import com.android.compatibility.common.util.MatcherUtils;
+import com.android.internal.util.XmlUtils;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.hamcrest.core.StringStartsWith;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class TestUtils {
+    public static final String TEST_APP_PACKAGE = "com.example.helloworld";
+    public static final String TEST_ACTIVITY_NAME = "com.example.helloworld.TestActivity";
+
+    public static final String TEST_NAME_EXTRA_KEY = "TEST_NAME";
+    public static final String TEST_ASSERT_SUCCESS_EXTRA_KEY = "ASSERT_SUCCESS";
+
+    public static final String TEST_STATUS_ACTION = "android.content.pm.cts.TEST_STATUS_UPDATE";
+
+    public static final String PID_STATUS_PID_KEY = "TEST_PID";
+    public static final String TEST_STATUS_RESULT_KEY = "TEST_RESULT";
+    public static final String TEST_STATUS_RESULT_SUCCESS = "Success";
+
+    public static final String RES_XML_PATH = "res/xml/test_xml.xml";
+    public static final String RES_XML_ATTRS_PATH = "res/xml/test_xml_attrs.xml";
+    public static final String RES_DRAWABLE_HDPI_PATH = "res/drawable-hdpi-v4/background.jpg";
+    public static final String RES_DRAWABLE_MDPI_PATH = "res/drawable-mdpi-v4/background.jpg";
+
+    public static final String RES_IDENTIFIER = TEST_APP_PACKAGE + ":string/inc_string";
+
+    public static final int RES_STRING = 0x7f021000;
+    public static final int RES_ARRAY = 0x7f051000;
+    public static final int RES_STYLE = 0x7f061000;
+    public static final int[] RES_STYLEABLE = {0x7f011000, 0x7f011001, 0x7f011002};
+
+    public enum AssertionType {
+        ASSERT_SUCCESS,
+        ASSERT_READ_FAILURE,
+    }
+
+    public static final String TEST_GET_IDENTIFIER = "checkGetIdentifier";
+
+    public static void checkGetIdentifier(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailure(type,
+                () -> res.getIdentifier(RES_IDENTIFIER, "", ""),
+                Matchers.not(equalTo(0)), equalTo(0));
+    }
+
+    public static final String TEST_GET_RESOURCE_NAME = "checkGetResourceName";
+
+    public static void checkGetResourceName(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailureException(type,
+                () -> res.getResourceName(RES_STRING),
+                equalTo(RES_IDENTIFIER), instanceOf(Resources.NotFoundException.class));
+    }
+
+    public static final String TEST_GET_STRING = "checkGetString";
+
+    public static void checkGetString(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailureException(type,
+                () -> res.getString(RES_STRING),
+                equalTo("true"), instanceOf(Resources.NotFoundException.class));
+    }
+
+    public static final String TEST_GET_STRING_ARRAY = "checkGetStringArray";
+
+    public static void checkGetStringArray(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailureException(type,
+                () -> res.getStringArray(RES_ARRAY),
+                equalTo(new String[]{"true"}), instanceOf(Resources.NotFoundException.class));
+    }
+
+    public static final String TEST_OPEN_XML = "checkOpenXmlResourceParser";
+
+    public static void checkOpenXmlResourceParser(Resources res, AssertionType type)
+            throws Exception {
+        testReadSuccessAndFailureException(type,
+                () -> {
+                    final AssetManager assets = res.getAssets();
+                    try (XmlResourceParser p = assets.openXmlResourceParser(RES_XML_PATH)) {
+                        XmlUtils.beginDocument(p, "Test");
+                        assertEquals(XmlPullParser.START_TAG, p.next());
+                        final String text = p.nextText();
+                        return text == null ? "" : text.trim();
+                    }
+                },
+                StringStartsWith.startsWith("Lorem ipsum dolor"),
+                instanceOf(FileNotFoundException.class));
+    }
+
+    public static final String TEST_APPLY_STYLE = "checkApplyStyle";
+
+    public static void checkApplyStyle(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailure(type,
+                () -> {
+                    final Resources.Theme theme = res.newTheme();
+                    theme.applyStyle(RES_STYLE, true);
+                    final TypedArray values = theme.obtainStyledAttributes(RES_STYLEABLE);
+                    return new String[]{
+                            values.getString(0),
+                            values.getString(1),
+                            values.getString(2),
+                    };
+                },
+                equalTo(new String[]{"true", "true", "1"}),
+                equalTo(new String[]{null, null, null}));
+    }
+
+    public static final String TEST_XML_ATTRIBUTES = "checkXmlAttributes";
+
+    public static void checkXmlAttributes(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailure(type,
+                () -> {
+                    final AssetManager assets = res.getAssets();
+                    try (XmlResourceParser p = assets.openXmlResourceParser(RES_XML_ATTRS_PATH)) {
+                        XmlUtils.beginDocument(p, "Test");
+                        final TypedArray values = res.obtainAttributes(p, RES_STYLEABLE);
+                        final String[] results = {
+                                values.getString(0),
+                                values.getString(1),
+                                values.getString(2),
+                        };
+                        values.recycle();
+                        return results;
+                    }
+                },
+                equalTo(new String[]{"true", "true", "1"}),
+                equalTo(new String[]{null, null, null}));
+    }
+
+    public static final String TEST_OPEN_FILE_MISSING = "checkOpenMissingFile";
+
+    public static void checkOpenMissingFile(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailureException(type,
+                () -> {
+                    final AssetManager assets = res.getAssets();
+                    try (InputStream is = assets.openNonAsset(RES_DRAWABLE_HDPI_PATH)) {
+                        return true;
+                    }
+                },
+                equalTo(true), instanceOf(FileNotFoundException.class));
+    }
+
+    public static final String TEST_OPEN_FILE_FD_MISSING = "checkOpenMissingFdFile";
+
+    public static void checkOpenMissingFdFile(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailureException(type,
+                () -> {
+                    final AssetManager assets = res.getAssets();
+                    try (AssetFileDescriptor is = assets.openNonAssetFd(RES_DRAWABLE_HDPI_PATH)) {
+                        return true;
+                    }
+                },
+                equalTo(true), instanceOf(FileNotFoundException.class));
+    }
+
+    private static class FailedWhileReadingException extends Exception {
+    }
+
+    public static final String TEST_OPEN_FILE = "checkOpen";
+
+    public static void checkOpen(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailureException(type,
+                () -> {
+                    final AssetManager assets = res.getAssets();
+                    try (InputStream is = assets.openNonAsset(RES_DRAWABLE_MDPI_PATH)) {
+                        try {
+                            readFullStream(is);
+                        } catch (IOException e) {
+                            throw new FailedWhileReadingException();
+                        }
+                        return true;
+                    }
+                }, equalTo(true), instanceOf(FailedWhileReadingException.class));
+    }
+
+    public static final String TEST_OPEN_FILE_FD = "checkOpenFd";
+
+    public static void checkOpenFd(Resources res, AssertionType type) throws Exception {
+        testReadSuccessAndFailureException(type,
+                () -> {
+                    final AssetManager assets = res.getAssets();
+                    try (AssetFileDescriptor fd = assets.openNonAssetFd(RES_DRAWABLE_MDPI_PATH)) {
+                        try {
+                            readFullStream(fd.createInputStream());
+                        } catch (IOException e) {
+                            throw new FailedWhileReadingException();
+                        }
+                        return true;
+                    }
+                }, equalTo(true), instanceOf(FailedWhileReadingException.class));
+    }
+
+    /**
+     * Used to wait for the process to wait for a particular broadcast to be received.
+     */
+    public static class BroadcastDetector implements AutoCloseable {
+        private final Context mContext;
+        private final HandlerThread mThread;
+        private final Handler mHandler;
+        private final BroadcastReceiver mReceiver;
+        private final Semaphore mLatch = new Semaphore(0);
+        private volatile Exception mException;
+
+        public BroadcastDetector(Context context, IntentFilter intentFilter,
+                IBroadcastCallback callback) {
+            mContext = context;
+            mThread = new HandlerThread(callback.toString(), Process.THREAD_PRIORITY_FOREGROUND);
+            mThread.start();
+            mHandler = new Handler(mThread.getLooper());
+            mReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    try {
+                        if (callback.onReceive(context, intent)) {
+                            mLatch.release();
+                        }
+                    } catch (Exception e) {
+                        mException = e;
+                        mLatch.release();
+                    }
+                }
+            };
+            context.registerReceiver(mReceiver, intentFilter, null, mHandler);
+        }
+
+        /**
+         * Returns true if the broadcast was received and
+         * {@link IBroadcastCallback#onReceive(Context, Intent)} returned true.
+         */
+        public boolean waitForBroadcast(long timeout, TimeUnit unit)
+                throws Exception {
+            if (!mLatch.tryAcquire(timeout, unit)) {
+                return false;
+            }
+            if (mException != null) {
+                throw mException;
+            }
+            return true;
+        }
+
+        @Override
+        public void close() {
+            mContext.unregisterReceiver(mReceiver);
+            mThread.quit();
+        }
+    }
+
+    public interface IBroadcastCallback {
+        boolean onReceive(Context context, Intent intent) throws Exception;
+    }
+
+    private interface ThrowingFunction<R> {
+        R apply() throws Exception;
+    }
+
+    private static <T> void testReadSuccessAndFailure(AssertionType assertType,
+            ThrowingFunction<T> getValue,
+            Matcher<? super T> checkSuccess,
+            Matcher<? super T> checkFailure) throws Exception {
+        final T value = getValue.apply();
+        if (assertType == AssertionType.ASSERT_SUCCESS) {
+            assertThat(value, checkSuccess);
+        } else {
+            assertThat(value, checkFailure);
+        }
+    }
+
+    private static <T> void testReadSuccessAndFailureException(AssertionType assertType,
+            ThrowingFunction<T> getValue,
+            Matcher<? super T> checkSuccess,
+            Matcher<Throwable> checkFailure) throws Exception {
+        if (assertType == AssertionType.ASSERT_SUCCESS) {
+            assertThat(getValue.apply(), checkSuccess);
+        } else {
+            MatcherUtils.assertThrows(checkFailure, getValue::apply);
+        }
+    }
+
+    private static void readFullStream(InputStream is) throws IOException {
+        final byte[] buffer = new byte[1024];
+        while (is.read(buffer) != -1) {
+        }
+    }
+}
diff --git a/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java b/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java
index 8280877..0cb98f4 100644
--- a/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ResourcesHardeningTest.java
@@ -19,23 +19,20 @@
 import static android.content.pm.cts.PackageManagerShellCommandIncrementalTest.checkIncrementalDeliveryFeature;
 import static android.content.pm.cts.PackageManagerShellCommandIncrementalTest.isAppInstalled;
 import static android.content.pm.cts.PackageManagerShellCommandIncrementalTest.uninstallPackageSilently;
-import static android.content.pm.cts.PackageManagerShellCommandIncrementalTest.writeFullStream;
 
-import static org.hamcrest.core.IsEqual.equalTo;
 import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.app.ActivityManager;
 import android.app.UiAutomation;
 import android.content.Context;
-import android.content.cts.util.XmlUtils;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.content.res.AssetFileDescriptor;
-import android.content.res.AssetManager;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
 import android.platform.test.annotations.AppModeFull;
+import android.util.ArrayMap;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
@@ -46,220 +43,332 @@
 import com.android.incfs.install.IncrementalInstallSession;
 import com.android.incfs.install.PendingBlock;
 
-import org.hamcrest.Matcher;
-import org.hamcrest.MatcherAssert;
+import com.example.helloworld.lib.TestUtils;
+
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 @RunWith(AndroidJUnit4.class)
 @AppModeFull
 @LargeTest
 public class ResourcesHardeningTest {
     private static final String TEST_APK_PATH = "/data/local/tmp/cts/content/";
-    private static final String[] TEST_APKS = {"HelloWorld5.apk", "HelloWorld5_mdpi-v4.apk"};
-    private static final String TEST_APP_PACKAGE = "com.example.helloworld";
+    private static final String[] TEST_APKS = {
+            "HelloWorldResHardening.apk",
+            "HelloWorldResHardening_mdpi-v4.apk",
+            "HelloWorldResHardening_hdpi-v4.apk"
+    };
 
-    private static final String RES_IDENTIFIER = TEST_APP_PACKAGE + ":string/inc_string";
-    private static final String RES_XML_PATH = "res/xml/test_xml.xml";
-    private static final String RES_XML_LARGE_PATH = "res/xml/test_xml_attrs.xml";
-    private static final String RES_DRAWABLE_PATH = "res/drawable-mdpi-v4/background.jpg";
-    private static final int RES_STRING = 0x7f021000;
-    private static final int RES_ARRAY = 0x7f051000;
-    private static final int RES_STYLE = 0x7f061000;
-    private static final int[] RES_STYLEABLE = {0x7f011000, 0x7f011001, 0x7f011002};
+    private static final String RES_TABLE_PATH = "resources.arsc";
+    private static final int INCFS_BLOCK_SIZE = 4096;
+
+    private final Map<String, List<RestrictedBlockRange>> mRestrictedRanges = new ArrayMap<>();
 
     @Before
     public void onBefore() throws Exception {
         checkIncrementalDeliveryFeature();
+
+        // Set up the blocks that need to be restricted in order to test resource hardening.
+        if (!mRestrictedRanges.isEmpty()) {
+            return;
+        }
+        for (final String apk : TEST_APKS) {
+            try (ZipFile zip = new ZipFile(TEST_APK_PATH + apk)) {
+                final List<RestrictedBlockRange> infos = new ArrayList<>();
+                RestrictedBlockRange info;
+                info = restrictZipEntry(zip, RES_TABLE_PATH);
+                if (info != null) {
+                    infos.add(info);
+                }
+                // Restrict only the middle block of the compiled xml to test that the whole
+                // file needs to be present just to open the xml file.
+                info = restrictOnlyMiddleBlock(restrictZipEntry(zip, TestUtils.RES_XML_PATH));
+                if (info != null) {
+                    infos.add(info);
+                }
+                // Restrict only the middle block of this file to test that the whole file does
+                // NOT need to be present just to create an input stream or fd.
+                info = restrictOnlyMiddleBlock(
+                        restrictZipEntry(zip, TestUtils.RES_DRAWABLE_MDPI_PATH));
+                if (info != null) {
+                    infos.add(info);
+                }
+                // Test that FileNotFoundExceptions are thrown when the file is missing.
+                info = restrictZipEntry(zip, TestUtils.RES_DRAWABLE_HDPI_PATH);
+                if (info != null) {
+                    infos.add(info);
+                }
+                assertFalse(infos.isEmpty());
+                mRestrictedRanges.put(apk, infos);
+            }
+        }
     }
 
     @Test
     public void checkGetIdentifier() throws Exception {
-        testReadSuccessAndFailure(
-                (res, filter) -> {
-                    filter.stopSendingBlocks();
-                    return res.getIdentifier(RES_IDENTIFIER, "", "");
-                },
-                not(equalTo(0)), equalTo(0));
+        testIncrementalForeignPackageResources(TestUtils::checkGetIdentifier);
     }
 
     @Test
     public void checkGetResourceName() throws Exception {
-        testReadSuccessAndFailureException(
-                (res, filter) -> {
-                    filter.stopSendingBlocks();
-                    return res.getResourceName(RES_STRING);
-                },
-                equalTo(RES_IDENTIFIER), instanceOf(Resources.NotFoundException.class));
+        testIncrementalForeignPackageResources(TestUtils::checkGetResourceName);
     }
 
     @Test
     public void checkGetString() throws Exception {
-        testReadSuccessAndFailureException(
-                (res, filter) -> {
-                    filter.stopSendingBlocks();
-                    return res.getString(RES_STRING);
-                },
-                equalTo("true"), instanceOf(Resources.NotFoundException.class));
+        testIncrementalForeignPackageResources(TestUtils::checkGetString);
     }
 
     @Test
     public void checkGetStringArray() throws Exception {
-        testReadSuccessAndFailureException(
-                (res, filter) -> {
-                    filter.stopSendingBlocks();
-                    return res.getStringArray(RES_ARRAY);
-                },
-                equalTo(new String[]{"true"}), instanceOf(Resources.NotFoundException.class));
+        testIncrementalForeignPackageResources(TestUtils::checkGetStringArray);
     }
 
     @Test
     public void checkOpenXmlResourceParser() throws Exception {
-        testReadSuccessAndFailureException(
-                (res, filter) -> {
-                    filter.stopSendingBlocks();
-                    final AssetManager assets = res.getAssets();
-                    try (XmlResourceParser p = assets.openXmlResourceParser(RES_XML_PATH)) {
-                        XmlUtils.beginDocument(p, "Test");
-                        return p.nextText();
-                    }
-                },
-                equalTo("true"), instanceOf(FileNotFoundException.class));
+        testIncrementalForeignPackageResources(TestUtils::checkOpenXmlResourceParser);
     }
 
     @Test
     public void checkApplyStyle() throws Exception {
-        testReadSuccessAndFailure(
-                (res, filter) -> {
-                    filter.stopSendingBlocks();
-                    final Resources.Theme theme = res.newTheme();
-                    theme.applyStyle(RES_STYLE, true);
-                    final TypedArray values = theme.obtainStyledAttributes(RES_STYLEABLE);
-                    return new String[]{
-                            values.getString(0),
-                            values.getString(1),
-                            values.getString(2),
-                    };
-                },
-                equalTo(new String[]{"true", "true", "1"}),
-                equalTo(new String[]{null, null, null}));
+        testIncrementalForeignPackageResources(TestUtils::checkApplyStyle);
     }
 
     @Test
     public void checkXmlAttributes() throws Exception {
-        testReadSuccessAndFailure(
-                (res, filter) -> {
-                    final AssetManager assets = res.getAssets();
-                    try (XmlResourceParser p = assets.openXmlResourceParser(RES_XML_LARGE_PATH)) {
-                        XmlUtils.beginDocument(p, "Test");
-                        filter.stopSendingBlocks();
-                        final TypedArray values = res.obtainAttributes(p, RES_STYLEABLE);
-                        return new String[]{
-                                values.getString(0),
-                                values.getString(1),
-                                values.getString(2),
-                        };
-                    }
-                },
-                equalTo(new String[]{"true", "true", "1"}),
-                equalTo(new String[]{null, null, null}));
+        testIncrementalForeignPackageResources(TestUtils::checkXmlAttributes);
+    }
+
+    @Test
+    public void checkOpenMissingFile() throws Exception {
+        testIncrementalForeignPackageResources(TestUtils::checkOpenMissingFile);
+    }
+
+    @Test
+    public void checkOpenMissingFdFile() throws Exception {
+        testIncrementalForeignPackageResources(TestUtils::checkOpenMissingFdFile);
     }
 
     @Test
     public void checkOpen() throws Exception {
-        testReadSuccessAndFailureException(
-                (res, filter) -> {
-                    final AssetManager assets = res.getAssets();
-                    try (InputStream is = assets.openNonAsset(RES_DRAWABLE_PATH)) {
-                        filter.stopSendingBlocks();
-                        ByteArrayOutputStream result = new ByteArrayOutputStream();
-                        writeFullStream(is, result, AssetFileDescriptor.UNKNOWN_LENGTH);
-                        return true;
-                    }
-                }, equalTo(true), instanceOf(IOException.class));
+        testIncrementalForeignPackageResources(TestUtils::checkOpen);
     }
 
     @Test
     public void checkOpenFd() throws Exception {
-        testReadSuccessAndFailureException(
-                (res, filter) -> {
-                    final AssetManager assets = res.getAssets();
-                    try (AssetFileDescriptor fd = assets.openNonAssetFd(RES_DRAWABLE_PATH)) {
-                        filter.stopSendingBlocks();
-                        final ByteArrayOutputStream result = new ByteArrayOutputStream();
-                        writeFullStream(fd.createInputStream(), result,
-                                AssetFileDescriptor.UNKNOWN_LENGTH);
-                        return true;
-                    }
-                }, equalTo(true), instanceOf(IOException.class));
+        testIncrementalForeignPackageResources(TestUtils::checkOpenFd);
     }
 
-    private interface ThrowingFunction<R> {
-        R apply(Resources res, BlockFilterController filter) throws Exception;
+    @Test
+    public void checkGetIdentifierRemote() throws Exception {
+        testIncrementalOwnPackageResources(TestUtils.TEST_GET_IDENTIFIER);
+    }
+
+    @Test
+    public void checkGetResourceNameRemote() throws Exception {
+        testIncrementalOwnPackageResources(TestUtils.TEST_GET_RESOURCE_NAME);
+    }
+
+    @Test
+    public void checkGetStringRemote() throws Exception {
+        testIncrementalOwnPackageResources(TestUtils.TEST_GET_STRING);
+    }
+
+    @Test
+    public void checkGetStringArrayRemote() throws Exception {
+        testIncrementalOwnPackageResources(TestUtils.TEST_GET_STRING_ARRAY);
+    }
+
+    @Test
+    public void checkOpenXmlResourceParserRemote() throws Exception {
+        testIncrementalOwnPackageResources(TestUtils.TEST_OPEN_XML);
+    }
+
+    @Test
+    public void checkApplyStyleRemote() throws Exception {
+        testIncrementalOwnPackageResources(TestUtils.TEST_APPLY_STYLE);
+    }
+
+    @Test
+    public void checkXmlAttributesRemote() throws Exception {
+        testIncrementalOwnPackageResources(TestUtils.TEST_XML_ATTRIBUTES);
+    }
+
+    @Test
+    public void checkOpenMissingFileRemote() throws Exception {
+        // If a zip entry local header is missing, libziparchive hardening causes a
+        // FileNotFoundException to be thrown regardless of whether a process queries its own
+        // resources or the resources of another package.
+        testIncrementalOwnPackageResources(TestUtils.TEST_OPEN_FILE_MISSING,
+                false /* expectCrash */);
+    }
+
+    @Test
+    public void checkOpenMissingFdFileRemote() throws Exception {
+        // If a zip entry local header is missing, libziparchive hardening causes a
+        // FileNotFoundException to be thrown regardless of whether a process queries its own
+        // resources or the resources of another package.
+        testIncrementalOwnPackageResources(TestUtils.TEST_OPEN_FILE_FD_MISSING,
+                false /* expectCrash */);
+    }
+
+    @Test
+    public void checkOpenRemote() throws Exception {
+        testIncrementalOwnPackageResources(TestUtils.TEST_OPEN_FILE);
+    }
+
+    @Test
+    public void checkOpenFdRemote() throws Exception {
+        // Failing to read missing blocks through a file descriptor using read/pread causes an
+        // IOException to be thrown.
+        testIncrementalOwnPackageResources(TestUtils.TEST_OPEN_FILE_FD, false /* expectCrash */);
+    }
+
+    private interface TestFunction {
+        void apply(Resources res, TestUtils.AssertionType type) throws Exception;
     }
 
     /**
-     * Runs the test twice to test resource resolution when all necessary blocks are available and
-     * when some necessary blocks are missing due to incremental installation.
-     *
-     * During the test of the failure path {@link TestBlockFilter#stopSendingBlocks()} will be
-     * invoked when {@link BlockFilterController#stopSendingBlocks()} is invoked; preventing any
-     * blocks that have not been served from being served during the test of the failure path.
-     *
-     * @param getValue executes resource resolution and returns a T object
-     * @param checkSuccess the matcher that represents the value when all pages are available
-     * @param checkFailure the matcher that represents the value when all pages are missing
-     * @param <T> the expected return type of the resource resolution
+     * Installs a package incrementally and tests that retrieval of that package's resources from
+     * within this process does not crash this process and instead falls back to some default
+     * behavior.
      */
-    private <T> void testReadSuccessAndFailure(ThrowingFunction<T> getValue,
-            Matcher<? super T> checkSuccess, Matcher<? super T> checkFailure) throws Exception {
+    private void testIncrementalForeignPackageResources(TestFunction test) throws Exception {
         try (ShellInstallSession session = startInstallSession()) {
-            final T value = getValue.apply(session.getPackageResources(),
-                    BlockFilterController.noop());
-            MatcherAssert.assertThat(value, checkSuccess);
+            test.apply(session.getPackageResources(), TestUtils.AssertionType.ASSERT_SUCCESS);
         }
         try (ShellInstallSession session = startInstallSession()) {
-            final T value = getValue.apply(session.getPackageResources(),
-                    BlockFilterController.allowDisable(session));
-            MatcherAssert.assertThat(value, checkFailure);
+            session.enableBlockRestrictions();
+            test.apply(session.getPackageResources(), TestUtils.AssertionType.ASSERT_READ_FAILURE);
         }
     }
 
     /**
-     * Variant of {@link #testReadSuccessAndFailure(ThrowingFunction, Matcher, Matcher)} that
-     * expects an exception to be thrown during the failure path.
+     * Installs a package incrementally and tests that the package crashes when it fails to retrieve
+     * its own resources due to incremental installation.
      */
-    private <T> void testReadSuccessAndFailureException(ThrowingFunction<T> getValue,
-            Matcher<? super T> checkSuccess, Matcher<Throwable> checkFailure)
+    private void testIncrementalOwnPackageResources(String testName, boolean expectCrash)
             throws Exception {
-        try (ShellInstallSession session = startInstallSession()) {
-            final T value = getValue.apply(session.getPackageResources(),
-                    BlockFilterController.noop());
-            MatcherAssert.assertThat(value, checkSuccess);
+        try (RemoteTest session = new RemoteTest(startInstallSession(), testName)) {
+            session.mSession.getPackageResources();
+            session.start(true /* assertSuccess */);
         }
-        try (ShellInstallSession session = startInstallSession()) {
-            MatcherUtils.assertThrows(checkFailure,
-                    () -> getValue.apply(session.getPackageResources(),
-                            BlockFilterController.allowDisable(session)));
+
+        try (RemoteTest session = new RemoteTest(startInstallSession(), testName)) {
+            session.mSession.getPackageResources();
+            session.mSession.enableBlockRestrictions();
+            if (expectCrash) {
+                MatcherUtils.assertThrows(instanceOf(RemoteProcessCrashedException.class),
+                        () -> session.start(false /* assertSuccess */));
+            } else {
+                session.start(false /* assertSuccess */);
+            }
         }
     }
 
-    private static ShellInstallSession startInstallSession() throws IOException,
+    private void testIncrementalOwnPackageResources(String testName) throws Exception {
+        testIncrementalOwnPackageResources(testName, true /* expectCrash */);
+    }
+
+    private static class RemoteProcessCrashedException extends RuntimeException {
+    }
+
+    private static class RemoteTest implements AutoCloseable {
+        private static final int SPIN_SLEEP_MS = 500;
+        private static final long RESPONSE_TIMEOUT_MS = 60 * 1000;
+
+        private final ShellInstallSession mSession;
+        private final String mTestName;
+
+        RemoteTest(ShellInstallSession session, String testName) {
+            mSession = session;
+            mTestName = testName;
+        }
+
+        public void start(boolean assertSuccess) throws Exception {
+            final AtomicInteger pid = new AtomicInteger();
+            final IntentFilter statusFilter = new IntentFilter(TestUtils.TEST_STATUS_ACTION);
+
+            final TestUtils.BroadcastDetector pidDetector = new TestUtils.BroadcastDetector(
+                    getContext(), statusFilter, (Context context, Intent intent) -> {
+                if (intent.hasExtra(TestUtils.PID_STATUS_PID_KEY)) {
+                    pid.set(intent.getIntExtra(TestUtils.PID_STATUS_PID_KEY, -1));
+                    return true;
+                }
+                return false;
+            });
+
+            final TestUtils.BroadcastDetector finishDetector = new TestUtils.BroadcastDetector(
+                    getContext(), statusFilter, (Context context, Intent intent) -> {
+                if (intent.hasExtra(TestUtils.TEST_STATUS_RESULT_KEY)) {
+                    final String reason = intent.getStringExtra(TestUtils.TEST_STATUS_RESULT_KEY);
+                    if (!reason.equals(TestUtils.TEST_STATUS_RESULT_SUCCESS)) {
+                        throw new IllegalStateException("Remote test failed: " + reason);
+                    }
+                    return true;
+                }
+                return false;
+            });
+
+            // Start the test app and indicate which test to run.
+            try (pidDetector; finishDetector) {
+                final Intent launchIntent = new Intent(Intent.ACTION_VIEW);
+                launchIntent.setClassName(TestUtils.TEST_APP_PACKAGE, TestUtils.TEST_ACTIVITY_NAME);
+                launchIntent.putExtra(TestUtils.TEST_NAME_EXTRA_KEY, mTestName);
+                launchIntent.putExtra(TestUtils.TEST_ASSERT_SUCCESS_EXTRA_KEY, assertSuccess);
+                launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+
+                getContext().startActivity(launchIntent);
+
+                // The test app must respond with a broadcast containing its pid so this test can
+                // check if the test app crashes.
+                assertTrue("Timed out while waiting for pid",
+                        pidDetector.waitForBroadcast(RESPONSE_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+                // Wait for the test app to finish testing or crash.
+                final ActivityManager am = getActivityManager();
+                final int remotePid = pid.get();
+                for (int i = 0; i < (RESPONSE_TIMEOUT_MS / SPIN_SLEEP_MS); i++) {
+                    if (am.getRunningAppProcesses().stream().noneMatch(
+                            info -> info.pid == remotePid)) {
+                        throw new RemoteProcessCrashedException();
+                    }
+                    if (finishDetector.waitForBroadcast(SPIN_SLEEP_MS, TimeUnit.MILLISECONDS)) {
+                        return;
+                    }
+                }
+                throw new TimeoutException("Timed out while waiting for remote test to finish");
+            }
+        }
+
+        @Override
+        public void close() throws Exception {
+            mSession.close();
+        }
+    }
+
+    private ShellInstallSession startInstallSession() throws IOException,
             InterruptedException {
-        return startInstallSession(TEST_APKS, TEST_APP_PACKAGE);
+        return startInstallSession(TEST_APKS, TestUtils.TEST_APP_PACKAGE);
     }
 
-    private static ShellInstallSession startInstallSession(String[] apks, String packageName)
+    private ShellInstallSession startInstallSession(String[] apks, String packageName)
             throws IOException, InterruptedException {
         final String v4SignatureSuffix = ".idsig";
         final TestBlockFilter filter = new TestBlockFilter();
@@ -281,24 +390,6 @@
         return session;
     }
 
-    private static class BlockFilterController {
-        private final ShellInstallSession mSession;
-        BlockFilterController(ShellInstallSession session) {
-            mSession = session;
-        }
-        public static BlockFilterController allowDisable(ShellInstallSession session) {
-            return new BlockFilterController(session);
-        }
-        public static BlockFilterController noop() {
-            return new BlockFilterController(null);
-        }
-        public void stopSendingBlocks() {
-            if (mSession != null) {
-                mSession.stopSendingBlocks();
-            }
-        }
-    }
-
     /**
      * A wrapper for {@link IncrementalInstallSession} that uninstalls the installed package when
      * testing is finished.
@@ -307,6 +398,7 @@
         public final IncrementalInstallSession session;
         private final TestBlockFilter mFilter;
         private final String mPackageName;
+
         private ShellInstallSession(IncrementalInstallSession session,
                 TestBlockFilter filter, String packageName) {
             this.session = session;
@@ -315,8 +407,8 @@
             getUiAutomation().adoptShellPermissionIdentity();
         }
 
-        public void stopSendingBlocks() {
-            mFilter.stopSendingBlocks();
+        public void enableBlockRestrictions() {
+            mFilter.enableBlockRestrictions();
         }
 
         public Resources getPackageResources() throws PackageManager.NameNotFoundException {
@@ -331,17 +423,59 @@
         }
     }
 
-    private static class TestBlockFilter implements IBlockFilter {
-        private final AtomicBoolean mDisabled = new AtomicBoolean();
+    private class TestBlockFilter implements IBlockFilter {
+        private final AtomicBoolean mRestrictBlocks = new AtomicBoolean(false);
+
         @Override
         public boolean shouldServeBlock(PendingBlock block) {
-            return !mDisabled.get();
+            if (!mRestrictBlocks.get() || block.getType() == PendingBlock.Type.SIGNATURE_TREE) {
+                // Always send signature blocks and always send blocks when enableBlockRestrictions
+                // has not been called.
+                return true;
+            }
+
+            // Allow the block to be served if it does not reside in a restricted range.
+            final String apkFileName = block.getPath().getFileName().toString();
+            return mRestrictedRanges.get(apkFileName).stream().noneMatch(
+                    info -> info.dataStartBlockIndex <= block.getBlockIndex()
+                            && block.getBlockIndex() <= info.dataEndBlockIndex);
         }
-        public void stopSendingBlocks() {
-            mDisabled.set(true);
+
+        public void enableBlockRestrictions() {
+            mRestrictBlocks.set(true);
         }
     }
 
+    private static class RestrictedBlockRange {
+        public final String entryName;
+        public final int dataStartBlockIndex;
+        public final int dataEndBlockIndex;
+
+        RestrictedBlockRange(String zipEntryName, int dataStartBlockIndex,
+                int dataEndBlockIndex) {
+            this.entryName = zipEntryName;
+            this.dataStartBlockIndex = dataStartBlockIndex;
+            this.dataEndBlockIndex = dataEndBlockIndex;
+        }
+    }
+
+    private static RestrictedBlockRange restrictZipEntry(ZipFile file, String entryFileName) {
+        final ZipArchiveEntry info = file.getEntry(entryFileName);
+        if (info == null) return null;
+        final long headerSize = entryFileName.getBytes(StandardCharsets.UTF_8).length + 30;
+        final int dataStartBlock = (int) (info.getDataOffset() - headerSize) / INCFS_BLOCK_SIZE;
+        final int dataEndBlock = (int) (info.getDataOffset() + info.getCompressedSize())
+                / INCFS_BLOCK_SIZE;
+        return new RestrictedBlockRange(entryFileName, dataStartBlock, dataEndBlock);
+    }
+
+    private static RestrictedBlockRange restrictOnlyMiddleBlock(RestrictedBlockRange info) {
+        if (info == null) return null;
+        assertTrue(info.dataEndBlockIndex - info.dataStartBlockIndex > 2);
+        final int middleBlock = (info.dataStartBlockIndex + info.dataEndBlockIndex) / 2;
+        return new RestrictedBlockRange(info.entryName, middleBlock, middleBlock);
+    }
+
     private static Context getContext() {
         return InstrumentationRegistry.getInstrumentation().getContext();
     }
@@ -349,4 +483,8 @@
     private static UiAutomation getUiAutomation() {
         return InstrumentationRegistry.getInstrumentation().getUiAutomation();
     }
+
+    private static ActivityManager getActivityManager() {
+        return (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
+    }
 }
diff --git a/tests/tests/display/src/android/display/cts/DisplayTest.java b/tests/tests/display/src/android/display/cts/DisplayTest.java
index c4ce26c..16b630c2 100644
--- a/tests/tests/display/src/android/display/cts/DisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayTest.java
@@ -877,6 +877,9 @@
         // of VESA EDID STANDARD Version 1, Revision 4
         assertTrue(year >= 1990);
 
+        int week = deviceProductInfo.getManufactureWeek();
+        assertTrue(week == -1 || (week >= 1 && week <= 53));
+
         List<Integer> allowedConnectionToSinkValues = List.of(
                 DeviceProductInfo.CONNECTION_TO_SINK_UNKNOWN,
                 DeviceProductInfo.CONNECTION_TO_SINK_BUILT_IN,
diff --git a/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java b/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
index 1ade371..2a796f9 100644
--- a/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
+++ b/tests/tests/graphics/src/android/graphics/cts/FrameRateCtsActivity.java
@@ -391,7 +391,11 @@
         }
     }
 
-    private boolean isAlternative(Display.Mode mode, Display.Mode other) {
+    private boolean isSeamless(Display.Mode mode, Display.Mode other) {
+        if (mode.getModeId() == other.getModeId()) {
+            return true;
+        }
+
         if (!hasSameResolution(mode, other)) {
             return false;
         }
@@ -430,7 +434,7 @@
         List<Float> seamedRefreshRates = new ArrayList<>();
         Display.Mode[] modes = display.getSupportedModes();
         for (Display.Mode otherMode : modes) {
-            if (hasSameResolution(mode, otherMode) && !isAlternative(mode, otherMode)) {
+            if (!isSeamless(mode, otherMode)) {
                 seamedRefreshRates.add(otherMode.getRefreshRate());
             }
         }
@@ -609,7 +613,7 @@
             Display.Mode toMode = mModeChangedEvents.get(eventId);
             assertTrue("Non-seamless mode switch was not expected, but there was a "
                             + "non-seamless switch from from " + fromMode + " to " + toMode + ".",
-                    isAlternative(fromMode, toMode));
+                    isSeamless(fromMode, toMode));
         }
     }
 
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/RippleDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/RippleDrawableTest.java
index 6993ddc..d3906e9 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/RippleDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/RippleDrawableTest.java
@@ -47,7 +47,7 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class RippleDrawableTest {
-    private static final ColorStateList DEFAULT_EFFECT_COLOR = ColorStateList.valueOf(0x80ffffff);
+    private static final ColorStateList DEFAULT_EFFECT_COLOR = ColorStateList.valueOf(0x8dffffff);
     private Context mContext;
 
     @Before
diff --git a/tests/tests/hardware/res/raw/sony_dualsense_bluetooth_vibratortests.json b/tests/tests/hardware/res/raw/sony_dualsense_bluetooth_vibratortests.json
new file mode 100644
index 0000000..da5eaeb
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualsense_bluetooth_vibratortests.json
@@ -0,0 +1,44 @@
+// Refer to
+//  - struct dualsense_output_report_bt
+//  - dualsense_init_output_report()
+//  - dualsense_output_worker()
+// in drivers/hid/hid-playstation.c
+[
+  {
+    "id": 1,
+    "durations" : [1000],
+    "amplitudes" : [192],
+    "leftFfIndex" : 6,
+    "rightFfIndex" : 5,
+    "output" :
+        [
+            {"index" : 0,
+            "data" : 0x31},   // DS_OUTPUT_REPORT_BT
+
+            {"index" : 3,
+             // DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT |
+             // DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION
+             "data" : 0x03}
+        ]
+  },
+
+  {
+    "id": 1,
+    "durations" : [2000, 2000, 2000, 2000, 2000],
+    "amplitudes" : [16, 32, 64, 128, 255],
+    "leftFfIndex" : 6,
+    "rightFfIndex" : 5,
+    "output" :
+        [
+            {"index" : 0,
+            "data" : 0x31},   // DS_OUTPUT_REPORT_BT
+
+            {"index" : 3,
+             // DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT |
+             // DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION
+             "data" : 0x03}
+        ]
+  }
+
+]
+
diff --git a/tests/tests/hardware/res/raw/sony_dualsense_usb_vibratortests.json b/tests/tests/hardware/res/raw/sony_dualsense_usb_vibratortests.json
new file mode 100644
index 0000000..2e30ccb
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualsense_usb_vibratortests.json
@@ -0,0 +1,44 @@
+// Refer to
+//  - struct dualsense_output_report_usb
+//  - dualsense_init_output_report()
+//  - dualsense_output_worker()
+// in drivers/hid/hid-playstation.c
+[
+  {
+    "id": 1,
+    "durations" : [1000],
+    "amplitudes" : [192],
+    "leftFfIndex" : 4,
+    "rightFfIndex" : 3,
+    "output" :
+        [
+            {"index" : 0,
+            "data" : 0x02},   // DS_OUTPUT_REPORT_USB
+
+            {"index" : 1,
+             // DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT |
+             // DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION
+             "data" : 0x03}
+        ]
+  },
+
+  {
+    "id": 1,
+    "durations" : [2000, 2000, 2000, 2000, 2000],
+    "amplitudes" : [16, 32, 64, 128, 255],
+    "leftFfIndex" : 4,
+    "rightFfIndex" : 3,
+    "output" :
+        [
+            {"index" : 0,
+            "data" : 0x02},   // DS_OUTPUT_REPORT_USB
+
+            {"index" : 1,
+             // DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT |
+             // DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION
+             "data" : 0x03}
+        ]
+  }
+
+]
+
diff --git a/tests/tests/hardware/res/raw/sony_dualshock3_usb_lighttests.json b/tests/tests/hardware/res/raw/sony_dualshock3_usb_lighttests.json
index ec88ed8..c9cc22a 100644
--- a/tests/tests/hardware/res/raw/sony_dualshock3_usb_lighttests.json
+++ b/tests/tests/hardware/res/raw/sony_dualshock3_usb_lighttests.json
@@ -2,10 +2,11 @@
 [
     {
         "id": 1,
-        "lightType": "INPUT_PLAYER_ID",
-        "lightName": "sony",
-        "lightColor": 0x00000000,
-        "lightPlayerId": 4,
+        "type": "PLAYER_ID",
+        "capabilities": "NONE",
+        "name": "sony",
+        "color": 0x00000000,
+        "playerId": 4,
         "hidEventType": "UHID_SET_REPORT",
         "ledsHidOutput":   // LED Bitmask data index of HID SET_REPORT packet.
             [ { "index": 10,  "data": 16 }
diff --git a/tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_lighttests.json b/tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_lighttests.json
index 26e1ebb..86db368 100644
--- a/tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_lighttests.json
+++ b/tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_lighttests.json
@@ -2,11 +2,12 @@
 [
   {
     "id": 1,
-    "lightType": "INPUT_RGB",
-    "lightName": "RGB",
+    "type": "INPUT",
+    "capabilities": "RGB | BRIGHTNESS",
+    "name": "RGB",
     "report": [],
-    "lightColor": 0xff446688,
-    "lightPlayerId": 0,
+    "color": 0xff446688,
+    "playerId": 0,
     "hidEventType": "UHID_OUTPUT",
     "ledsHidOutput":   // RGB leds brightness
         [ { "index": 8, "data": 0x44 },
@@ -17,11 +18,12 @@
 
   {
     "id": 1,
-    "lightType": "INPUT_RGB",
-    "lightName": "RGB",
+    "type": "INPUT",
+    "capabilities": "RGB | BRIGHTNESS",
+    "name": "RGB",
     "report": [],
-    "lightColor": 0x7f446688,
-    "lightPlayerId": 0,
+    "color": 0x7f446688,
+    "playerId": 0,
     "hidEventType": "UHID_OUTPUT",
     "ledsHidOutput":   // RGB leds brightness
         [ { "index": 8, "data": 0x22 },
@@ -32,11 +34,12 @@
 
   {
     "id": 1,
-    "lightType": "INPUT_RGB",
-    "lightName": "RGB",
+    "type": "INPUT",
+    "capabilities": "RGB | BRIGHTNESS",
+    "name": "RGB",
     "report": [],
-    "lightColor": 0x00000000,
-    "lightPlayerId": 0,
+    "color": 0x00000000,
+    "playerId": 0,
     "hidEventType": "UHID_OUTPUT",
     "ledsHidOutput":   // RGB leds brightness
         [ { "index": 8, "data": 0x0 },
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseBluetoothTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseBluetoothTest.java
index 08a98b8..a6206db 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseBluetoothTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseBluetoothTest.java
@@ -42,4 +42,9 @@
     public void testAllMotions() {
         testInputEvents(R.raw.sony_dualsense_bluetooth_motioneventtests);
     }
+
+    @Test
+    public void testVibrator() throws Exception {
+        testInputVibratorEvents(R.raw.sony_dualsense_bluetooth_vibratortests);
+    }
 }
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseUsbTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseUsbTest.java
index 8baf254..7f046eed 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseUsbTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualSenseUsbTest.java
@@ -42,4 +42,9 @@
     public void testAllMotions() {
         testInputEvents(R.raw.sony_dualsense_usb_motioneventtests);
     }
+
+    @Test
+    public void testVibrator() throws Exception {
+        testInputVibratorEvents(R.raw.sony_dualsense_usb_vibratortests);
+    }
 }
diff --git a/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java b/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
index 0803da3..1f6d3dd 100644
--- a/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
@@ -60,7 +60,13 @@
     private static final String KEY_ALLOW_FRAME_DROP = "allow-frame-drop";
 
     // movie length, in frames
-    private static final int NUM_FRAMES = 30;               // two seconds of video
+    private static final int NUM_FRAMES = FRAME_RATE * 3;   // three seconds of video
+
+    // since encoders are lossy, we'll skip the first 2 seconds and
+    // then verify rest of the video for the desired behavior.
+    // Expectation is encoders will drop Qp low enough after some frames to
+    // ensure that there are no significant encoding losses
+    private final int FIRST_FRAME_TO_VALIDATE = FRAME_RATE * 2;
 
     private static final int TEST_R0 = 0;                   // dull green background
     private static final int TEST_G0 = 136;
@@ -733,9 +739,12 @@
                                 info.presentationTimeUs);
                         surface.awaitNewImage();
                         surface.drawImage();
-                        if (!checkSurfaceFrame(checkIndex++)) {
+                        // Start checking after FIRST_FRAME_TO_VALIDATE number of frames
+                        if (checkIndex > FIRST_FRAME_TO_VALIDATE &&
+                                !checkSurfaceFrame(checkIndex)) {
                             badFrames++;
                         }
+                        checkIndex++;
                     }
                 }
             }
diff --git a/tests/tests/neuralnetworks/Android.mk b/tests/tests/neuralnetworks/Android.mk
index 01cf38f..7ac51ea 100644
--- a/tests/tests/neuralnetworks/Android.mk
+++ b/tests/tests/neuralnetworks/Android.mk
@@ -29,7 +29,7 @@
 
 LOCAL_WHOLE_STATIC_LIBRARIES := CtsNNAPITests_static
 
-LOCAL_SHARED_LIBRARIES := libandroid liblog libneuralnetworks
+LOCAL_SHARED_LIBRARIES := libandroid liblog libneuralnetworks libvulkan
 LOCAL_STATIC_LIBRARIES := libbase_ndk libgtest_ndk_c++ libgmock_ndk
 LOCAL_CTS_TEST_PACKAGE := android.neuralnetworks
 
diff --git a/tests/tests/neuralnetworks/java_test/Android.bp b/tests/tests/neuralnetworks/java_test/Android.bp
index 599f650..cfa2782 100644
--- a/tests/tests/neuralnetworks/java_test/Android.bp
+++ b/tests/tests/neuralnetworks/java_test/Android.bp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 android_test {
     name: "CtsNNAPIJavaTestCases",
     defaults: ["cts_defaults"],
diff --git a/tests/tests/neuralnetworks/java_test/jni/Android.bp b/tests/tests/neuralnetworks/java_test/jni/Android.bp
index a4c8a45..8e80f28 100644
--- a/tests/tests/neuralnetworks/java_test/jni/Android.bp
+++ b/tests/tests/neuralnetworks/java_test/jni/Android.bp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
 cc_test_library {
     name: "libctsneuralnetworks_jni",
     gtest: false,
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java
index c55edc4..193b029 100644
--- a/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcPreferredPaymentTest.java
@@ -116,4 +116,33 @@
         }
     }
 
+    /** Tests getSelectionModeForCategory API
+     *  CardEmulation.CATEGORY_PAYMENT */
+    @Test
+    public void testGetSelectionModeForCategoryPayment() {
+        try {
+            int mode = mCardEmulation.getSelectionModeForCategory(CardEmulation.CATEGORY_PAYMENT);
+            Log.i(mTag, "getSelectionModeForCategory for Payment: " + mode);
+
+            assertTrue("Retrieve incorrect SelectionMode for Payment",
+                    CardEmulation.SELECTION_MODE_PREFER_DEFAULT == mode);
+        } catch (Exception e) {
+            fail("Unexpected Exception " + e);
+        }
+    }
+
+    /** Tests getSelectionModeForCategory API
+     *  CardEmulation.CATEGORY_OTHER */
+    @Test
+    public void testGetSelectionModeForCategoryOther() {
+        try {
+            int mode = mCardEmulation.getSelectionModeForCategory(CardEmulation.CATEGORY_OTHER);
+            Log.i(mTag, "getSelectionModeForCategory for Other: " + mode);
+
+            assertTrue("Retrieve incorrect SelectionMode for Other",
+                    CardEmulation.SELECTION_MODE_ASK_IF_CONFLICT == mode);
+        } catch (Exception e) {
+            fail("Unexpected Exception " + e);
+        }
+    }
 }
diff --git a/tests/tests/os/CtsOsTestCases.xml b/tests/tests/os/CtsOsTestCases.xml
index cf17162..812e2ea8 100644
--- a/tests/tests/os/CtsOsTestCases.xml
+++ b/tests/tests/os/CtsOsTestCases.xml
@@ -38,6 +38,7 @@
     <!-- Create Place to store apks -->
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command" value="mkdir -p /data/local/tmp/cts/os" />
+        <option name="run-command" value="am wait-for-broadcast-idle" />
         <option name="teardown-command" value="rm -rf /data/local/tmp/cts/os" />
     </target_preparer>
     <!-- Load additional APKs onto device -->
diff --git a/tests/tests/os/OWNERS b/tests/tests/os/OWNERS
index 3429892..c748b28 100644
--- a/tests/tests/os/OWNERS
+++ b/tests/tests/os/OWNERS
@@ -1,4 +1,5 @@
-per-file *AutoRevoke* = eugenesusla@google.com
-per-file *Companion* = eugenesusla@google.com
-per-file *AndroidManifest.xml = eugenesusla@google.com
-per-file *CtsOsTestCases.xml = eugenesusla@google.com
+per-file *AutoRevoke* = file:platform/frameworks/base:/core/java/android/permission/OWNERS
+per-file *AppHibernation* = file:platform/frameworks/base:/core/java/android/permission/OWNERS
+per-file *Companion* = file:platform/frameworks/base:/core/java/android/permission/OWNERS
+per-file *AndroidManifest.xml = file:platform/frameworks/base:/core/java/android/permission/OWNERS
+per-file *CtsOsTestCases.xml = file:platform/frameworks/base:/core/java/android/permission/OWNERS
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
index 72b98cf..3432250 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationIntegrationTest.kt
@@ -34,6 +34,7 @@
 import androidx.test.InstrumentationRegistry
 import androidx.test.filters.SdkSuppress
 import androidx.test.runner.AndroidJUnit4
+import com.android.compatibility.common.util.DisableAnimationRule
 import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
 import com.android.compatibility.common.util.UiAutomatorUtils
 import org.hamcrest.CoreMatchers
@@ -41,6 +42,7 @@
 import org.junit.Assert.assertThat
 import org.junit.Assert.assertTrue
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -62,6 +64,9 @@
 
     private lateinit var packageManager: PackageManager
 
+    @get:Rule
+    val disableAnimationRule = DisableAnimationRule()
+
     @Before
     fun setup() {
         packageManager = context.packageManager
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
index c2bd254..0f27184 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
@@ -84,6 +84,21 @@
     }
 }
 
+inline fun withAppNoUninstallAssertion(
+    apk: String,
+    packageName: String,
+    action: () -> Unit
+) {
+    installApk(apk)
+    try {
+        // Try to reduce flakiness caused by new package update not propagating in time
+        Thread.sleep(1000)
+        action()
+    } finally {
+        uninstallAppWithoutAssertion(packageName)
+    }
+}
+
 inline fun <T> withDeviceConfig(
     namespace: String,
     name: String,
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index 35b56ce..897ef5f 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -33,8 +33,6 @@
 import android.support.test.uiautomator.BySelector
 import android.support.test.uiautomator.UiDevice
 import android.support.test.uiautomator.UiObject2
-import android.support.test.uiautomator.UiScrollable
-import android.support.test.uiautomator.UiSelector
 import android.view.accessibility.AccessibilityNodeInfo
 import android.view.accessibility.AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
 import android.widget.Switch
@@ -42,8 +40,9 @@
 import androidx.test.InstrumentationRegistry
 import androidx.test.filters.SdkSuppress
 import androidx.test.runner.AndroidJUnit4
-import com.android.compatibility.common.util.MatcherUtils.hasTextThat
+import com.android.compatibility.common.util.DisableAnimationRule
 import com.android.compatibility.common.util.SystemUtil
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
 import com.android.compatibility.common.util.SystemUtil.eventually
 import com.android.compatibility.common.util.SystemUtil.getEventually
 import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
@@ -55,7 +54,6 @@
 import com.android.compatibility.common.util.textAsString
 import com.android.compatibility.common.util.uiDump
 import org.hamcrest.CoreMatchers.containsString
-import org.hamcrest.CoreMatchers.containsStringIgnoringCase
 import org.hamcrest.CoreMatchers.equalTo
 import org.hamcrest.Matcher
 import org.hamcrest.Matchers.greaterThan
@@ -65,6 +63,7 @@
 import org.junit.Assert.assertTrue
 import org.junit.Assume.assumeFalse
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import java.lang.reflect.Modifier
@@ -97,6 +96,9 @@
         const val LOG_TAG = "AutoRevokeTest"
     }
 
+    @get:Rule
+    val disableAnimationRule = DisableAnimationRule()
+
     @Before
     fun setup() {
         // Collapse notifications
@@ -127,30 +129,50 @@
         withUnusedThresholdMs(3L) {
             withDummyApp {
                 // Setup
-                startApp()
-                clickPermissionAllow()
-                assertPermission(PERMISSION_GRANTED)
+                startAppAndAcceptPermission()
                 killDummyApp()
-                Thread.sleep(5)
+                Thread.sleep(5) // wait longer than the unused threshold
 
                 // Run
                 runAppHibernationJob(context, LOG_TAG)
 
                 // Verify
                 assertPermission(PERMISSION_DENIED)
-                if (hasFeatureWatch()) {
-                    expandNotificationsWatch()
-                } else {
-                    runShellCommandOrThrow("cmd statusbar expand-notifications")
-                }
-                waitFindObject(By.textContains("unused app"))
-                        .click()
-                if (hasFeatureWatch()) {
-                    // In wear os, notification has one additional button to open it
-                    waitFindObject(By.text("Open")).click();
-                }
+                openUnusedAppsNotification()
+
                 waitFindObject(By.text(supportedAppPackageName))
                 waitFindObject(By.text("Calendar permission removed"))
+                goBack()
+            }
+        }
+    }
+
+    @AppModeFull(reason = "Uses separate apps for testing")
+    @Test
+    fun testUnusedApp_uninstallApp() {
+        withUnusedThresholdMs(3L) {
+            withDummyAppNoUninstallAssertion {
+                // Setup
+                startAppAndAcceptPermission()
+                killDummyApp()
+                Thread.sleep(5) // wait longer than the unused threshold
+
+                // Run
+                runAppHibernationJob(context, LOG_TAG)
+
+                // Verify
+                openUnusedAppsNotification()
+                waitFindObject(By.text(supportedAppPackageName))
+
+                assertTrue(isPackageInstalled(supportedAppPackageName))
+                clickUninstallIcon()
+                clickUninstallOk()
+
+                eventually {
+                    assertFalse(isPackageInstalled(supportedAppPackageName))
+                }
+
+                goBack()
             }
         }
     }
@@ -330,6 +352,19 @@
         installApk(supportedApkPath)
     }
 
+    private fun isPackageInstalled(packageName: String): Boolean {
+        val pm = context.packageManager
+
+        return callWithShellPermissionIdentity {
+            try {
+                pm.getPackageInfo(packageName, 0)
+                true
+            } catch (e: PackageManager.NameNotFoundException) {
+                false
+            }
+        }
+    }
+
     private fun uninstallApp() {
         uninstallApp(supportedAppPackageName)
     }
@@ -338,6 +373,25 @@
         startApp(supportedAppPackageName)
     }
 
+    private fun startAppAndAcceptPermission() {
+        startApp()
+        clickPermissionAllow()
+        assertPermission(PERMISSION_GRANTED)
+    }
+
+    private fun openUnusedAppsNotification() {
+        if (hasFeatureWatch()) {
+            expandNotificationsWatch()
+        } else {
+            runShellCommandOrThrow("cmd statusbar expand-notifications")
+        }
+        waitFindObject(By.textContains("unused app")).click()
+        if (hasFeatureWatch()) {
+            // In wear os, notification has one additional button to open it
+            waitFindObject(By.text("Open")).click()
+        }
+    }
+
     private fun goHome() {
         runShellCommandOrThrow("input keyevent KEYCODE_HOME")
     }
@@ -373,6 +427,23 @@
         }
     }
 
+    private fun clickUninstallIcon() {
+        val rowSelector = By.text(supportedAppPackageName)
+        val rowItem = waitFindObject(rowSelector).parent.parent
+
+        val uninstallSelector = if (isAutomotiveDevice()) {
+            By.res("com.android.permissioncontroller:id/car_ui_secondary_action")
+        } else {
+            By.desc("Uninstall or disable")
+        }
+
+        rowItem.findObject(uninstallSelector).click()
+    }
+
+    private fun clickUninstallOk() {
+        waitFindObject(By.text("OK")).click()
+    }
+
     private inline fun withDummyApp(
         apk: String = supportedApkPath,
         packageName: String = supportedAppPackageName,
@@ -381,6 +452,14 @@
         withApp(apk, packageName, action)
     }
 
+    private inline fun withDummyAppNoUninstallAssertion(
+        apk: String = supportedApkPath,
+        packageName: String = supportedAppPackageName,
+        action: () -> Unit
+    ) {
+        withAppNoUninstallAssertion(apk, packageName, action)
+    }
+
     private fun assertPermission(
         state: Int,
         packageName: String = supportedAppPackageName,
@@ -396,17 +475,11 @@
 
         waitForIdle()
 
-        if (hasFeatureWatch()) {
-            // WearOS need to scroll down to find the Permission item to click
-            UiScrollable(UiSelector().scrollable(true))
-                    .getChildByText(UiSelector(), "Permissions")
-        }
-
         click("Permissions")
     }
 
     private fun click(label: String) {
-        waitFindNode(hasTextThat(containsStringIgnoringCase(label))).click()
+        waitFindObject(byTextIgnoreCase(label)).click()
         waitForIdle()
     }
 
@@ -507,6 +580,10 @@
     assertThat(runShellCommandOrThrow("pm uninstall $packageName"), containsString("Success"))
 }
 
+fun uninstallAppWithoutAssertion(packageName: String) {
+    runShellCommandOrThrow("pm uninstall $packageName")
+}
+
 fun installApk(apk: String) {
     assertThat(runShellCommandOrThrow("pm install -r $apk"), containsString("Success"))
 }
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/OWNERS b/tests/tests/packageinstaller/adminpackageinstaller/OWNERS
index 0ab0d04..7455e48 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/OWNERS
+++ b/tests/tests/packageinstaller/adminpackageinstaller/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 36137
 toddke@google.com
 sunnygoyal@google.com
+patb@google.com
diff --git a/tests/tests/permission/Android.bp b/tests/tests/permission/Android.bp
index e22d39c..b78b6c0 100644
--- a/tests/tests/permission/Android.bp
+++ b/tests/tests/permission/Android.bp
@@ -46,6 +46,7 @@
         // TODO(b/175251166): remove once Android migrates to JUnit 4.12,
         // which provides assertThrows
         "testng",
+        "bluetooth-test-util-lib",
     ],
     jni_libs: [
         "libctspermission_jni",
diff --git a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
index e30cc37..c93d0cd 100644
--- a/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
@@ -25,12 +25,19 @@
 import static android.permission.cts.PermissionUtils.revokePermission;
 import static android.permission.cts.PermissionUtils.uninstallApp;
 
-import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
 
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.cts.BTAdapterUtils;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.platform.test.annotations.AppModeFull;
 
@@ -38,8 +45,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -68,16 +74,26 @@
         UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
     }
 
-    @BeforeClass
-    public static void enableTestMode() {
-        runShellCommand("dumpsys activity service"
-                + " com.android.bluetooth/.btservice.AdapterService set-test-mode enabled");
+    private Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+    private BluetoothAdapter mBluetoothAdapter;
+    private boolean mBluetoothAdapterWasEnabled;
+
+    @Before
+    public void enableBluetooth() {
+        assumeTrue(supportsBluetooth());
+        mBluetoothAdapter = mContext.getSystemService(BluetoothManager.class).getAdapter();
+        mBluetoothAdapterWasEnabled = mBluetoothAdapter.isEnabled();
+        assertTrue(BTAdapterUtils.enableAdapter(mBluetoothAdapter, mContext));
+        enableTestMode();
     }
 
-    @AfterClass
-    public static void disableTestMode() {
-        runShellCommand("dumpsys activity service"
-                + " com.android.bluetooth/.btservice.AdapterService set-test-mode disabled");
+    @After
+    public void disableBluetooth() {
+        assumeTrue(supportsBluetooth());
+        disableTestMode();
+        if (!mBluetoothAdapterWasEnabled) {
+            assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
+        }
     }
 
     @After
@@ -216,4 +232,18 @@
         final Bundle res = resolver.call(TEST_APP_AUTHORITY, METHOD_SCAN_BLUETOOTH, null, null);
         assertEquals(expected, Result.values()[res.getInt(Intent.EXTRA_INDEX)]);
     }
+
+    private boolean supportsBluetooth() {
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+    }
+
+    private void enableTestMode() {
+        runShellCommandOrThrow("dumpsys activity service"
+                + " com.android.bluetooth/.btservice.AdapterService set-test-mode enabled");
+    }
+
+    private void disableTestMode() {
+        runShellCommandOrThrow("dumpsys activity service"
+                + " com.android.bluetooth/.btservice.AdapterService set-test-mode disabled");
+    }
 }
diff --git a/tests/tests/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java b/tests/tests/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
index e76e760..9b4b9ae 100644
--- a/tests/tests/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
@@ -35,6 +35,7 @@
 import android.content.Context;
 import android.content.ContextParams;
 import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
 import android.util.ArraySet;
 import android.util.Base64;
 import android.util.Log;
@@ -117,6 +118,7 @@
         mScanNoteCount = 0;
     }
 
+    @AppModeFull
     @Test
     public void scanWithoutRenouncingNotesBluetoothAndLocation() {
         clearNoteCounts();
@@ -125,6 +127,7 @@
         assertThat(mScanNoteCount).isGreaterThan(0);
     }
 
+    @AppModeFull
     @Test
     public void scanRenouncingLocationNotesBluetoothButNotLocation() {
         clearNoteCounts();
diff --git a/tests/tests/permission/src/android/permission/cts/PlatformPermissionGroupMappingTest.kt b/tests/tests/permission/src/android/permission/cts/PlatformPermissionGroupMappingTest.kt
new file mode 100644
index 0000000..7f84722
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/PlatformPermissionGroupMappingTest.kt
@@ -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 android.permission.cts
+
+import android.os.Build
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+import org.junit.Test
+
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+class PlatformPermissionGroupMappingTest {
+    private val instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val context = instrumentation.context
+    private val packageManager = context.packageManager
+
+    @Test
+    fun platformPermissionHasPermissionGroup() {
+        val future = CompletableFuture<String>()
+        packageManager.getGroupOfPlatformPermission(
+            android.Manifest.permission.READ_CALENDAR, context.mainExecutor
+        ) { future.complete(it) }
+        val permissionGroupName = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+        assertThat(permissionGroupName).isEqualTo(android.Manifest.permission_group.CALENDAR)
+    }
+
+    @Test
+    fun platformPermissionGroupHasPermission() {
+        val future = CompletableFuture<List<String>>()
+        packageManager.getPlatformPermissionsForGroup(
+            android.Manifest.permission_group.CALENDAR, context.mainExecutor
+        ) { future.complete(it) }
+        val permissionNames = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+        assertThat(permissionNames).contains(android.Manifest.permission.READ_CALENDAR)
+    }
+
+    companion object {
+        private const val TIMEOUT_MILLIS = 15 * 1000L
+    }
+}
diff --git a/tests/tests/permission2/res/raw/OWNERS b/tests/tests/permission2/res/raw/OWNERS
index a67ff98..04895ff 100644
--- a/tests/tests/permission2/res/raw/OWNERS
+++ b/tests/tests/permission2/res/raw/OWNERS
@@ -2,6 +2,7 @@
 cbrubaker@google.com
 hackbod@google.com
 toddke@google.com
+patb@google.com
 yamasani@google.com
 michaelwr@google.com
 narayan@google.com
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index bb409db..084d4d1 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -4232,11 +4232,6 @@
     <permission android:name="android.permission.GET_RUNTIME_PERMISSIONS"
                 android:protectionLevel="signature" />
 
-    <!-- @SystemApi Allows the system to read the mapping between permission and permission group.
-        @hide -->
-    <permission android:name="android.permission.GET_RUNTIME_PERMISSION_GROUP_MAPPING"
-                android:protectionLevel="signature|privileged" />
-
     <!-- @SystemApi Allows the system to restore runtime permission state. This might grant
     permissions, hence this is a more scoped, less powerful variant of GRANT_RUNTIME_PERMISSIONS.
     Among other restrictions this cannot override user choices.
diff --git a/tests/tests/permission3/Android.bp b/tests/tests/permission3/Android.bp
index fa0cea5..d60c44e 100644
--- a/tests/tests/permission3/Android.bp
+++ b/tests/tests/permission3/Android.bp
@@ -32,6 +32,7 @@
         "androidx.test.rules",
         "compatibility-device-util-axt",
         "ctstestrunner-axt",
+        "bluetooth-test-util-lib",
     ],
     data: [
         ":CtsPermissionPolicyApp25",
diff --git a/tests/tests/permission3/AndroidManifest.xml b/tests/tests/permission3/AndroidManifest.xml
index 31e7e71..2192d13 100644
--- a/tests/tests/permission3/AndroidManifest.xml
+++ b/tests/tests/permission3/AndroidManifest.xml
@@ -22,6 +22,7 @@
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
 
     <application>
 
diff --git a/tests/tests/permission3/res/values/strings.xml b/tests/tests/permission3/res/values/strings.xml
index d6d368b..194f203 100755
--- a/tests/tests/permission3/res/values/strings.xml
+++ b/tests/tests/permission3/res/values/strings.xml
@@ -18,9 +18,6 @@
 
 <resources>
     <string name="permissions">Permissions</string>
-    <string name="deny">Don\u2019t allow</string>
-    <string name="ask">Ask every time</string>
-    <string name="allow">Allow</string>
     <string name="allow_foreground">Allow only while using the app</string>
     <string name="allow_media_storage">Allow access to media only</string>
     <string name="allow_external_storage">Allow management of all files</string>
diff --git a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
index a7b4709..b74d502 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
@@ -29,6 +29,7 @@
 import android.support.test.uiautomator.UiObject2
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.rule.ActivityTestRule
+import com.android.compatibility.common.util.DisableAnimationRule
 import com.android.compatibility.common.util.SystemUtil.runShellCommand
 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
 import com.android.compatibility.common.util.UiAutomatorUtils
@@ -58,6 +59,9 @@
             context.packageManager.permissionControllerPackageName, 0).resources
 
     @get:Rule
+    val disableAnimationRule = DisableAnimationRule()
+
+    @get:Rule
     val activityRule = ActivityTestRule(StartForFutureActivity::class.java, false, false)
 
     private var screenTimeoutBeforeTest: Long = 0L
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index 07245ec..6c693b7 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -74,6 +74,12 @@
                 "com.android.permissioncontroller:" +
                         "id/permission_no_upgrade_and_dont_ask_again_button"
 
+        const val ALLOW_RADIO_BUTTON = "com.android.permissioncontroller:id/allow_radio_button"
+        const val ALLOW_FOREGROUND_RADIO_BUTTON =
+                "com.android.permissioncontroller:id/allow_foreground_only_radio_button"
+        const val ASK_RADIO_BUTTON = "com.android.permissioncontroller:id/ask_radio_button"
+        const val DENY_RADIO_BUTTON = "com.android.permissioncontroller:id/deny_radio_button"
+
         const val ALLOW_BUTTON_TEXT = "grant_dialog_button_allow"
         const val ALLOW_FOREGROUND_BUTTON_TEXT = "grant_dialog_button_allow_foreground"
         const val DENY_BUTTON_TEXT = "grant_dialog_button_deny"
@@ -444,53 +450,53 @@
             val wasGranted = if (isAutomotive) {
                 // Automotive doesn't support one time permissions, and thus
                 // won't show an "Ask every time" message
-                !waitFindObject(byTextRes(R.string.deny)).isChecked
+                !waitFindObject(By.res(DENY_RADIO_BUTTON)).isChecked
             } else {
                 if (isWatch) {
                     click(By.text("Deny"))
                 }
-                !(waitFindObject(byTextRes(R.string.deny)).isChecked ||
+                !(waitFindObject(By.res(DENY_RADIO_BUTTON)).isChecked ||
                     (!isLegacyApp && hasAskButton(permission) &&
-                        waitFindObject(byTextRes(R.string.ask)).isChecked))
+                        waitFindObject(By.res(ASK_RADIO_BUTTON)).isChecked))
             }
             var alreadyChecked = false
             val button = waitFindObject(
-                byTextRes(
-                    if (isAutomotive) {
-                        // Automotive doesn't support one time permissions, and thus
-                        // won't show an "Ask every time" message
-                        when (state) {
-                            PermissionState.ALLOWED ->
-                                if (showsForegroundOnlyButton(permission)) {
-                                    R.string.allow_foreground
-                                } else {
-                                    R.string.allow
-                                }
-                            PermissionState.DENIED -> R.string.deny
-                            PermissionState.DENIED_WITH_PREJUDICE -> R.string.deny
-                        }
-                    } else {
-                        when (state) {
-                            PermissionState.ALLOWED ->
-                                if (showsForegroundOnlyButton(permission)) {
-                                    R.string.allow_foreground
-                                } else if (isMediaStorageButton(permission, targetSdk)) {
-                                    R.string.allow_media_storage
-                                } else if (isAllStorageButton(permission, targetSdk)) {
-                                    R.string.allow_external_storage
-                                } else {
-                                    R.string.allow
-                                }
-                            PermissionState.DENIED ->
-                                if (!isLegacyApp && hasAskButton(permission)) {
-                                    R.string.ask
-                                } else {
-                                    R.string.deny
-                                }
-                            PermissionState.DENIED_WITH_PREJUDICE -> R.string.deny
-                        }
+                if (isAutomotive) {
+                    // Automotive doesn't support one time permissions, and thus
+                    // won't show an "Ask every time" message
+                    when (state) {
+                        PermissionState.ALLOWED ->
+                            if (showsForegroundOnlyButton(permission)) {
+                                By.res(ALLOW_FOREGROUND_RADIO_BUTTON)
+                            } else {
+                                By.res(ALLOW_RADIO_BUTTON)
+                            }
+                        PermissionState.DENIED -> By.res(DENY_RADIO_BUTTON)
+                        PermissionState.DENIED_WITH_PREJUDICE -> By.res(DENY_RADIO_BUTTON)
                     }
-                )
+                } else {
+                    when (state) {
+                        PermissionState.ALLOWED ->
+                            if (showsForegroundOnlyButton(permission)) {
+                                By.res(ALLOW_FOREGROUND_RADIO_BUTTON)
+                            } else if (isMediaStorageButton(permission, targetSdk)) {
+                                // Uses "allow_foreground_only_radio_button" as id
+                                byTextRes(R.string.allow_media_storage)
+                            } else if (isAllStorageButton(permission, targetSdk)) {
+                                // Uses "allow_always_radio_button" as id
+                                byTextRes(R.string.allow_external_storage)
+                            } else {
+                                By.res(ALLOW_RADIO_BUTTON)
+                            }
+                        PermissionState.DENIED ->
+                            if (!isLegacyApp && hasAskButton(permission)) {
+                                By.res(ASK_RADIO_BUTTON)
+                            } else {
+                                By.res(DENY_RADIO_BUTTON)
+                            }
+                        PermissionState.DENIED_WITH_PREJUDICE -> By.res(DENY_RADIO_BUTTON)
+                    }
+                }
             )
             alreadyChecked = button.isChecked
             if (!alreadyChecked) {
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt
index 1bed5e9..b88246b 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTest30WithBluetooth.kt
@@ -16,10 +16,17 @@
 
 package android.permission3.cts
 
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothManager
+import android.bluetooth.cts.BTAdapterUtils
 import android.content.Intent
+import android.content.pm.PackageManager
 import androidx.core.os.BuildCompat
 import androidx.test.InstrumentationRegistry
+import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
 import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertTrue
+import org.junit.After
 import org.junit.Assume.assumeTrue
 import org.junit.Before
 import org.junit.Test
@@ -30,6 +37,8 @@
 class PermissionTest30WithBluetooth : BaseUsePermissionTest() {
 
     val AUTHORITY = "android.permission3.cts.usepermission.AccessBluetoothOnCommand"
+    private lateinit var bluetoothAdapter: BluetoothAdapter
+    private var bluetoothAdapterWasEnabled: Boolean = false
 
     private enum class BluetoothScanResult {
         UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
@@ -40,6 +49,25 @@
         installPackage(APP_APK_PATH_30_WITH_BLUETOOTH)
     }
 
+    @Before
+    fun enableBluetooth() {
+        assumeTrue(supportsBluetooth())
+        bluetoothAdapter = context.getSystemService(BluetoothManager::class.java).adapter
+        bluetoothAdapterWasEnabled = bluetoothAdapter.isEnabled()
+        assertTrue(BTAdapterUtils.enableAdapter(bluetoothAdapter, context))
+        runShellCommandOrThrow("dumpsys activity service" +
+                " com.android.bluetooth/.btservice.AdapterService set-test-mode enabled")
+    }
+
+    @After
+    fun disableBluetooth() {
+        assumeTrue(supportsBluetooth())
+        runShellCommandOrThrow("dumpsys activity service" +
+                " com.android.bluetooth/.btservice.AdapterService set-test-mode disabled")
+        if (!bluetoothAdapterWasEnabled)
+            assertTrue(BTAdapterUtils.disableAdapter(bluetoothAdapter, context))
+    }
+
     @Test
     fun testGivenBluetoothIsDeniedWhenScanIsAttemptedThenThenGetEmptyScanResult() {
         assumeTrue(BuildCompat.isAtLeastS())
@@ -52,4 +80,7 @@
         val result = resolver.call(AUTHORITY, "", null, null)
         return BluetoothScanResult.values()[result!!.getInt(Intent.EXTRA_INDEX)]
     }
+
+    private fun supportsBluetooth(): Boolean =
+            context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
 }
diff --git a/tests/tests/resourcesloader/OWNERS b/tests/tests/resourcesloader/OWNERS
index d2cb9ad..57228c7 100644
--- a/tests/tests/resourcesloader/OWNERS
+++ b/tests/tests/resourcesloader/OWNERS
@@ -1,4 +1,5 @@
  # Bug component: 568761
 rtmitchell@google.com
 chiuwinson@google.com
-toddke@google.com
\ No newline at end of file
+toddke@google.com
+patb@google.com
diff --git a/tests/tests/role/src/android/app/role/cts/RoleManagerTest.java b/tests/tests/role/src/android/app/role/cts/RoleManagerTest.java
index 98fd59e..7d9ce89 100644
--- a/tests/tests/role/src/android/app/role/cts/RoleManagerTest.java
+++ b/tests/tests/role/src/android/app/role/cts/RoleManagerTest.java
@@ -52,6 +52,7 @@
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.DisableAnimationRule;
 import com.android.compatibility.common.util.TestUtils;
 import com.android.compatibility.common.util.ThrowingRunnable;
 import com.android.compatibility.common.util.UiAutomatorUtils;
@@ -116,6 +117,9 @@
     private static final RoleManager sRoleManager = sContext.getSystemService(RoleManager.class);
 
     @Rule
+    public DisableAnimationRule mDisableAnimationRule = new DisableAnimationRule();
+
+    @Rule
     public ActivityTestRule<WaitForResultActivity> mActivityRule =
             new ActivityTestRule<>(WaitForResultActivity.class);
 
diff --git a/tests/tests/sensorprivacy/OWNERS b/tests/tests/sensorprivacy/OWNERS
index c74393b..da10897 100644
--- a/tests/tests/sensorprivacy/OWNERS
+++ b/tests/tests/sensorprivacy/OWNERS
@@ -1,3 +1,3 @@
 # Bug component: 137825
 
-file:platform/frameworks/native:/libs/sensorprivacy/OWNERS
+include platform/frameworks/native:/libs/sensorprivacy/OWNERS
\ No newline at end of file
diff --git a/tests/tests/telephony/current/permissions/src/android/telephony/cts/telephonypermission/TelephonyManagerReadPhoneStatePermissionTest.java b/tests/tests/telephony/current/permissions/src/android/telephony/cts/telephonypermission/TelephonyManagerReadPhoneStatePermissionTest.java
index 8f4922c..7d164d4 100644
--- a/tests/tests/telephony/current/permissions/src/android/telephony/cts/telephonypermission/TelephonyManagerReadPhoneStatePermissionTest.java
+++ b/tests/tests/telephony/current/permissions/src/android/telephony/cts/telephonypermission/TelephonyManagerReadPhoneStatePermissionTest.java
@@ -19,7 +19,6 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
-import android.app.UiAutomation;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.platform.test.annotations.AppModeFull;
@@ -33,6 +32,8 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.ShellIdentityUtils;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -68,18 +69,6 @@
                 TelephonyUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
     }
 
-    public static void grantUserReadPhoneStatePermission() {
-        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
-        uiAutomation.grantRuntimePermission(getContext().getPackageName(),
-                android.Manifest.permission.READ_PHONE_STATE);
-    }
-
-    public static void revokeUserReadPhoneStatePermission() {
-        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
-        uiAutomation.revokeRuntimePermission(getContext().getPackageName(),
-                android.Manifest.permission.READ_PHONE_STATE);
-    }
-
     /**
      * Verify that TelephonyManager APIs requiring READ_PHONE_STATE Permission must work.
      * <p>
@@ -116,15 +105,15 @@
             return;
         }
 
-        grantUserReadPhoneStatePermission();
-
         try {
             // We must ensure that compat fwk enables READ_PHONE_STATE enforcement
             TelephonyUtils.enableCompatCommand(InstrumentationRegistry.getInstrumentation(),
                     TelephonyUtils.CTS_APP_PACKAGE,
                     TelephonyUtils.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION_STRING);
-            mTelephonyManager.getCallState();
-            mTelephonyManager.getCallStateForSubscription();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getCallState());
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getCallStateForSubscription());
         } catch (SecurityException e) {
             fail("TelephonyManager#getCallState and TelephonyManager#getCallStateForSubscription "
                     + "must not throw a SecurityException because READ_PHONE_STATE permission is "
@@ -135,128 +124,148 @@
         int subId = mTelephonyManager.getSubscriptionId();
 
         try {
-            mTelephonyManager.getNetworkType();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getNetworkType());
         } catch (SecurityException e) {
             fail("getNetworkType() must not throw a SecurityException with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getDeviceSoftwareVersion();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getDeviceSoftwareVersion());
         } catch (SecurityException e) {
             fail("getDeviceSoftwareVersion() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getCarrierConfig();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getCarrierConfig());
         } catch (SecurityException e) {
             fail("getCarrierConfig() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getDataNetworkType();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getDataNetworkType());
         } catch (SecurityException e) {
             fail("getDataNetworkType() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getVoiceNetworkType();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getVoiceNetworkType());
         } catch (SecurityException e) {
             fail("getVoiceNetworkType() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getGroupIdLevel1();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getGroupIdLevel1());
         } catch (SecurityException e) {
             fail("getGroupIdLevel1() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getLine1AlphaTag();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getLine1AlphaTag());
         } catch (SecurityException e) {
             fail("getLine1AlphaTag() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getVoiceMailNumber();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getVoiceMailNumber());
         } catch (SecurityException e) {
             fail("getVoiceMailNumber() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getVisualVoicemailPackageName();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getVisualVoicemailPackageName());
         } catch (SecurityException e) {
             fail("getVisualVoicemailPackageName() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getVoiceMailAlphaTag();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getVoiceMailAlphaTag());
         } catch (SecurityException e) {
             fail("getVoiceMailAlphaTag() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getForbiddenPlmns();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getForbiddenPlmns());
         } catch (SecurityException e) {
             fail("getForbiddenPlmns() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.isDataRoamingEnabled();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.isDataRoamingEnabled());
         } catch (SecurityException e) {
             fail("isDataRoamingEnabled() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getSubscriptionId(
-                    mTelecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL));
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getSubscriptionId(
+                            mTelecomManager.getDefaultOutgoingPhoneAccount(
+                                    PhoneAccount.SCHEME_TEL)));
         } catch (SecurityException e) {
             fail("getSubscriptionId(phoneAccountHandle) must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getServiceState();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getServiceState());
         } catch (SecurityException e) {
             fail("getServiceState() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getEmergencyNumberList();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getEmergencyNumberList());
         } catch (SecurityException e) {
             fail("getEmergencyNumberList() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getEmergencyNumberList(
-                    EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getEmergencyNumberList(
+                            EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE));
         } catch (SecurityException e) {
             fail("getEmergencyNumberList(EMERGENCY_SERVICE_CATEGORY_POLICE) must"
                     + " not throw a SecurityException with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.getPreferredOpportunisticDataSubscription();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.getPreferredOpportunisticDataSubscription());
         } catch (SecurityException e) {
             fail("getPreferredOpportunisticDataSubscription() must not throw"
                     + " a SecurityException with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.isModemEnabledForSlot(SubscriptionManager.getSlotIndex(subId));
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.isModemEnabledForSlot(
+                            SubscriptionManager.getSlotIndex(subId)));
         } catch (SecurityException e) {
             fail("isModemEnabledForSlot(slotIndex) must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.isMultiSimSupported();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.isMultiSimSupported());
         } catch (SecurityException e) {
             fail("isMultiSimSupported() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
         try {
-            mTelephonyManager.doesSwitchMultiSimConfigTriggerReboot();
+            ShellIdentityUtils.invokeMethodWithShellPermissions(
+                    mTelephonyManager, (tm) -> tm.doesSwitchMultiSimConfigTriggerReboot());
         } catch (SecurityException e) {
             fail("doesSwitchMultiSimConfigTriggerReboot() must not throw a SecurityException"
                     + " with READ_PHONE_STATE" + e);
         }
-
-        revokeUserReadPhoneStatePermission();
     }
 
     private static Context getContext() {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/ModemActivityInfoTest.java b/tests/tests/telephony/current/src/android/telephony/cts/ModemActivityInfoTest.java
index 2e4471b..d6f336d 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/ModemActivityInfoTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/ModemActivityInfoTest.java
@@ -21,6 +21,7 @@
 
 import android.os.SystemClock;
 import android.telephony.ModemActivityInfo;
+import android.util.Range;
 
 import org.junit.Test;
 
@@ -32,6 +33,12 @@
 public class ModemActivityInfoTest {
     private static final String TAG = "ModemActivityInfoTest";
 
+    private static final Range RANGE_FOR_TX_POWER_LEVEL_0 = new Range<>(Integer.MIN_VALUE, 0);
+    private static final Range RANGE_FOR_TX_POWER_LEVEL_1 = new Range<>(0, 5);
+    private static final Range RANGE_FOR_TX_POWER_LEVEL_2 = new Range<>(5, 15);
+    private static final Range RANGE_FOR_TX_POWER_LEVEL_3 = new Range<>(15, 20);
+    private static final Range RANGE_FOR_TX_POWER_LEVEL_4 = new Range<>(20, Integer.MAX_VALUE);
+
     private static final int VALID_SLEEP_TIME_MS = 1;
     private static final int VALID_IDLE_TIME_MS = 1;
     private static final int VALID_RX_TIME_MS = 1;
@@ -80,6 +87,16 @@
         IntStream.range(0, ModemActivityInfo.getNumTxPowerLevels()).forEach(
                 (x) -> assertEquals(VALID_TX_TIME_MS[x],
                         info.getTransmitDurationMillisAtPowerLevel(x)));
+        assertEquals(RANGE_FOR_TX_POWER_LEVEL_0, info.getTransmitPowerRange(
+                ModemActivityInfo.TX_POWER_LEVEL_0));
+        assertEquals(RANGE_FOR_TX_POWER_LEVEL_1, info.getTransmitPowerRange(
+                ModemActivityInfo.TX_POWER_LEVEL_1));
+        assertEquals(RANGE_FOR_TX_POWER_LEVEL_2, info.getTransmitPowerRange(
+                ModemActivityInfo.TX_POWER_LEVEL_2));
+        assertEquals(RANGE_FOR_TX_POWER_LEVEL_3, info.getTransmitPowerRange(
+                ModemActivityInfo.TX_POWER_LEVEL_3));
+        assertEquals(RANGE_FOR_TX_POWER_LEVEL_4, info.getTransmitPowerRange(
+                ModemActivityInfo.TX_POWER_LEVEL_4));
     }
 
     @Test
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/QualifiedNetworksServiceTest.java b/tests/tests/telephony/current/src/android/telephony/cts/QualifiedNetworksServiceTest.java
new file mode 100644
index 0000000..e1187da
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/cts/QualifiedNetworksServiceTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.telephony.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import android.telephony.data.QualifiedNetworksService;
+
+import org.junit.Test;
+
+import java.util.Collections;
+
+public class QualifiedNetworksServiceTest {
+    private static final int SLOT_INDEX = 0;
+    private static final int APN_TYPES = 0;
+
+    private class TestQns extends QualifiedNetworksService {
+        TestQns() {
+            super();
+        }
+
+        public TestNap onCreateNetworkAvailabilityProvider(int slotIndex) {
+            return new TestNap(slotIndex);
+        }
+
+        public class TestNap extends QualifiedNetworksService.NetworkAvailabilityProvider {
+            TestNap(int slotIndex) {
+                super(slotIndex);
+            }
+
+            public void close() {
+                // Do nothing
+            }
+        }
+    }
+
+    @Test
+    public void testConstructorsAndGetters() {
+        QualifiedNetworksService qns = new TestQns();
+        QualifiedNetworksService.NetworkAvailabilityProvider nap =
+                qns.onCreateNetworkAvailabilityProvider(SLOT_INDEX);
+        assertEquals(SLOT_INDEX, nap.getSlotIndex());
+    }
+
+    @Test
+    public void testNetworkAvailabilityProvider() {
+        QualifiedNetworksService qns = new TestQns();
+        QualifiedNetworksService.NetworkAvailabilityProvider nap =
+                qns.onCreateNetworkAvailabilityProvider(SLOT_INDEX);
+        nap.updateQualifiedNetworkTypes(APN_TYPES, Collections.emptyList());
+        nap.reportThrottleStatusChanged(Collections.emptyList());
+    }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index c14c6dc..e58bef4 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -1282,6 +1282,8 @@
         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
                 tp -> tp.setSystemSelectionChannels(Collections.emptyList()));
 
+        // TODO (b/189255895): Uncomment once getSystemSelection channels is functional in S QPR
+        /**
         // getSystemSelectionChannels was added in IRadio 1.6, so ensure it returns
         // the value that was set by setSystemSelectionChannels.
         if (mRadioVersion >= RADIO_HAL_VERSION_1_6) {
@@ -1289,6 +1291,7 @@
                     ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
                     TelephonyManager::getSystemSelectionChannels));
         }
+         **/
     }
 
     @Test
@@ -1647,7 +1650,7 @@
         synchronized (mLock) {
             // reboot takes longer time
             if (!mRadioRebootTriggered) {
-                mLock.wait(15000);
+                mLock.wait(20000);
             }
         }
         assertThat(mTelephonyManager.getRadioPowerState()).isEqualTo(
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java b/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java
index 2286b090..31ba58f 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java
@@ -18,6 +18,8 @@
 
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
+import static junit.framework.Assert.assertNotNull;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -101,7 +103,9 @@
             TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
             mPhoneAccountHandle = telecomManager
                     .getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
+            assertNotNull(mPhoneAccountHandle);
             mPhoneNumber = telecomManager.getLine1Number(mPhoneAccountHandle);
+            assertNotNull(mPhoneNumber, "Tests require a line1 number for the active SIM.");
 
             mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
                     .createForPhoneAccountHandle(mPhoneAccountHandle);
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
index 4767ad7..d27d857 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
@@ -76,6 +76,8 @@
     private static final String COMMAND_SET_UCE_ENABLED = "uce set-device-enabled ";
     private static final String COMMAND_REMOVE_UCE_REQUEST_DISALLOWED_STATUS =
             "uce remove-request-disallowed-status ";
+    private static final String COMMAND_SET_CAPABILITY_REQUEST_TIMEOUT =
+            "uce set-capabilities-request-timeout ";
     private static final String COMMAND_SET_TEST_MODE_ENABLED = "src set-test-enabled ";
     private static final String COMMAND_SET_D2D_ENABLED = "d2d set-device-support ";
 
@@ -630,6 +632,13 @@
         TelephonyUtils.executeShellCommand(mInstrumentation, cmdBuilder.toString());
     }
 
+    void setCapabilitiesRequestTimeout(int slotId, long timeoutAfterMs) throws Exception {
+        StringBuilder cmdBuilder = new StringBuilder();
+        cmdBuilder.append(COMMAND_BASE).append(COMMAND_SET_CAPABILITY_REQUEST_TIMEOUT)
+                .append(COMMAND_SLOT_IDENTIFIER).append(slotId).append(" ").append(timeoutAfterMs);
+        TelephonyUtils.executeShellCommand(mInstrumentation, cmdBuilder.toString());
+    }
+
     void setDeviceToDeviceCommunicationEnabled(boolean enabled) throws Exception {
         TelephonyUtils.executeShellCommand(mInstrumentation, COMMAND_BASE
                 + COMMAND_SET_D2D_ENABLED  + (enabled ? "true" : "default"));
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java
index c3e1a91..372301a 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java
@@ -693,7 +693,7 @@
                 assertEquals(expectedCallbackResult.intValue(), waitForIntResult(errorQueue));
                 assertEquals(0L, waitForLongResult(retryAfterQueue));
             } catch (Exception e) {
-                fail("requestCapabilities with command error failed: " + e);
+                fail("requestAvailability with command error failed: " + e);
             } finally {
                 errorQueue.clear();
                 retryAfterQueue.clear();
@@ -2079,9 +2079,9 @@
         terminatedMap.put(emptyReasonArgs, emptyReasonExpectedArgs);
 
         // Verify each subscription terminated and the expected result
-        terminatedMap.forEach((deactivated, expectedResult) -> {
-            String terminatedReason = (String) deactivated.arg1;
-            Long terminatedRetryAfterMillis = (Long) deactivated.arg2;
+        terminatedMap.forEach((reason, expectedResult) -> {
+            String terminatedReason = (String) reason.arg1;
+            Long terminatedRetryAfterMillis = (Long) reason.arg2;
             capabilityExchangeImpl.setSubscribeOperation((uris, cb) -> {
                 cb.onNetworkResponse(networkRespCode, networkRespReason);
                 cb.onNotifyCapabilitiesUpdate(pidfXmlList);
@@ -2106,7 +2106,7 @@
                 fail("Unexpected exception " + e);
             }
 
-            deactivated.recycle();
+            reason.recycle();
             expectedResult.recycle();
             errorQueue.clear();
             errorRetryQueue.clear();
@@ -2115,9 +2115,11 @@
             removeTestContactFromEab();
         });
 
-        // Verify the subscribe request is sccessful when the terminated is timeout and the
-        // retryAfter is 0L
-        String terminatedReason = "timemout";
+        /*
+         * Verify the subscribe request is successful when: A) The terminated is timeout and
+         * B) The retryAfter is 0L and C) All the capabilities have been received.
+         */
+        String terminatedReason = "timeout";
         long terminatedRetryAfterMillis = 0L;
         capabilityExchangeImpl.setSubscribeOperation((uris, cb) -> {
             cb.onNetworkResponse(networkRespCode, networkRespReason);
@@ -2140,6 +2142,195 @@
         capabilityQueue.clear();
         removeTestContactFromEab();
 
+        /*
+         * Set the subscribe request is failed because NOT all of the capabilities have been
+         * received.
+         */
+        capabilityExchangeImpl.setSubscribeOperation((uris, cb) -> {
+            cb.onNetworkResponse(networkRespCode, networkRespReason);
+            cb.onTerminated(terminatedReason, terminatedRetryAfterMillis);
+        });
+
+        requestCapabilities(uceAdapter, numbers, callback);
+
+        /*
+         * Verify the request is failed because NOT all of the capabilities have been received.
+         */
+        assertEquals(RcsUceAdapter.ERROR_REQUEST_TIMEOUT, waitForIntResult(errorQueue));
+        assertEquals(0L, (waitForLongResult(errorRetryQueue)));
+
+        errorQueue.clear();
+        errorRetryQueue.clear();
+        completeQueue.clear();
+        capabilityQueue.clear();
+        removeTestContactFromEab();
+        overrideCarrierConfig(null);
+    }
+
+    @Test
+    public void testTimeoutToRequestCapabilitiesWithPresenceMechanism() throws Exception {
+        if (!ImsUtils.shouldTestImsService()) {
+            return;
+        }
+        ImsManager imsManager = getContext().getSystemService(ImsManager.class);
+        RcsUceAdapter uceAdapter = imsManager.getImsRcsManager(sTestSub).getUceAdapter();
+        assertNotNull("UCE adapter should not be null!", uceAdapter);
+
+        // Remove the test contact capabilities
+        removeTestContactFromEab();
+
+        // Connect to the ImsService
+        setupTestImsService(uceAdapter, true, true /* presence cap */, false /* OPTIONS */);
+
+        TestRcsCapabilityExchangeImpl capabilityExchangeImpl = sServiceConnector
+                .getCarrierService().getRcsFeature().getRcsCapabilityExchangeImpl();
+
+        BlockingQueue<Integer> errorQueue = new LinkedBlockingQueue<>();
+        BlockingQueue<Long> errorRetryQueue = new LinkedBlockingQueue<>();
+        BlockingQueue<Boolean> completeQueue = new LinkedBlockingQueue<>();
+        BlockingQueue<RcsContactUceCapability> capabilityQueue = new LinkedBlockingQueue<>();
+        RcsUceAdapter.CapabilitiesCallback callback = new RcsUceAdapter.CapabilitiesCallback() {
+            @Override
+            public void onCapabilitiesReceived(List<RcsContactUceCapability> capabilities) {
+                capabilities.forEach(c -> capabilityQueue.offer(c));
+            }
+            @Override
+            public void onComplete() {
+                completeQueue.offer(true);
+            }
+            @Override
+            public void onError(int errorCode, long retryAfterMilliseconds) {
+                errorQueue.offer(errorCode);
+                errorRetryQueue.offer(retryAfterMilliseconds);
+            }
+        };
+
+        // Prepare three contacts
+        final Uri contact1 = sTestNumberUri;
+        final Uri contact2 = sTestContact2Uri;
+        final Uri contact3 = sTestContact3Uri;
+
+        Collection<Uri> contacts = new ArrayList<>(3);
+        contacts.add(contact1);
+        contacts.add(contact2);
+        contacts.add(contact3);
+
+        // Setup the ImsService doesn't trigger any callbacks.
+        capabilityExchangeImpl.setSubscribeOperation((uris, cb) -> {
+            // It won't trigger any callbacks.
+        });
+
+        try {
+            setCapabilitiesRequestTimeout(3000L);
+
+            requestCapabilities(uceAdapter, contacts, callback);
+
+            // Verify that the clients receive the TIMEOUT error code.
+            assertEquals(RcsUceAdapter.ERROR_REQUEST_TIMEOUT, waitForIntResult(errorQueue));
+            assertEquals(0L, (waitForLongResult(errorRetryQueue)));
+        } finally {
+            errorQueue.clear();
+            errorRetryQueue.clear();
+            completeQueue.clear();
+            capabilityQueue.clear();
+            removeTestContactFromEab();
+            setCapabilitiesRequestTimeout(-1L);
+        }
+
+        // Setup the ImsService only trigger the network response callback. However it doesn't
+        // trigger the onTerminated callback
+        int networkRespCode = 200;
+        String networkRespReason = "OK";
+        capabilityExchangeImpl.setSubscribeOperation((uris, cb) -> {
+            cb.onNetworkResponse(networkRespCode, networkRespReason);
+        });
+
+        try {
+            setCapabilitiesRequestTimeout(3000L);
+
+            requestCapabilities(uceAdapter, contacts, callback);
+
+            // Verify that the clients receive the TIMEOUT error code.
+            assertEquals(RcsUceAdapter.ERROR_REQUEST_TIMEOUT, waitForIntResult(errorQueue));
+            assertEquals(0L, (waitForLongResult(errorRetryQueue)));
+        } finally {
+            errorQueue.clear();
+            errorRetryQueue.clear();
+            completeQueue.clear();
+            capabilityQueue.clear();
+            removeTestContactFromEab();
+            setCapabilitiesRequestTimeout(-1L);
+        }
+
+        overrideCarrierConfig(null);
+    }
+
+
+    @Test
+    public void testTimeoutToRequestCapabilitiesWithOptionsMechanism() throws Exception {
+        if (!ImsUtils.shouldTestImsService()) {
+            return;
+        }
+        ImsManager imsManager = getContext().getSystemService(ImsManager.class);
+        RcsUceAdapter uceAdapter = imsManager.getImsRcsManager(sTestSub).getUceAdapter();
+        assertNotNull("UCE adapter should not be null!", uceAdapter);
+
+        // Remove the test contact capabilities
+        removeTestContactFromEab();
+
+        // Connect to the ImsService
+        setupTestImsService(uceAdapter, true, false, true /* OPTIONS enabled */);
+
+        TestRcsCapabilityExchangeImpl capabilityExchangeImpl = sServiceConnector
+                .getCarrierService().getRcsFeature().getRcsCapabilityExchangeImpl();
+
+        // The test contact
+        Collection<Uri> contacts = new ArrayList<>(3);
+        contacts.add(sTestNumberUri);
+
+        // The result callback
+        BlockingQueue<Integer> errorQueue = new LinkedBlockingQueue<>();
+        BlockingQueue<Long> errorRetryQueue = new LinkedBlockingQueue<>();
+        BlockingQueue<Boolean> completeQueue = new LinkedBlockingQueue<>();
+        BlockingQueue<RcsContactUceCapability> capabilityQueue = new LinkedBlockingQueue<>();
+        RcsUceAdapter.CapabilitiesCallback callback = new RcsUceAdapter.CapabilitiesCallback() {
+            @Override
+            public void onCapabilitiesReceived(List<RcsContactUceCapability> capabilities) {
+                capabilities.forEach(c -> capabilityQueue.offer(c));
+            }
+            @Override
+            public void onComplete() {
+                completeQueue.offer(true);
+            }
+            @Override
+            public void onError(int errorCode, long retryAfterMilliseconds) {
+                errorQueue.offer(errorCode);
+                errorRetryQueue.offer(retryAfterMilliseconds);
+            }
+        };
+
+        // Setup the ImsService doesn't trigger any callbacks.
+        capabilityExchangeImpl.setOptionsOperation((contact, myCapabilities, optionsCallback) -> {
+            // It won't trigger any callbacks.
+        });
+
+        try {
+            setCapabilitiesRequestTimeout(3000L);
+
+            requestCapabilities(uceAdapter, contacts, callback);
+
+            // Verify that the clients receive the TIMEOUT error code.
+            assertEquals(RcsUceAdapter.ERROR_REQUEST_TIMEOUT, waitForIntResult(errorQueue));
+            assertEquals(0L, (waitForLongResult(errorRetryQueue)));
+        } finally {
+            errorQueue.clear();
+            errorRetryQueue.clear();
+            completeQueue.clear();
+            capabilityQueue.clear();
+            removeTestContactFromEab();
+            setCapabilitiesRequestTimeout(-1L);
+        }
+
         overrideCarrierConfig(null);
     }
 
@@ -2360,6 +2551,14 @@
         }
     }
 
+    private static void setCapabilitiesRequestTimeout(long timeoutAfterMillis) {
+        try {
+            sServiceConnector.setCapabilitiesRequestTimeout(sTestSlot, timeoutAfterMillis);
+        } catch (Exception e) {
+            Log.w("RcsUceAdapterTest", "Cannot set capabilities request timeout: " + e);
+        }
+    }
+
     private void requestCapabilities(RcsUceAdapter uceAdapter, Collection<Uri> numbers,
             RcsUceAdapter.CapabilitiesCallback callback) {
         try {
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
index 6df20fb..13e9a33 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/SipDelegateManagerTest.java
@@ -44,7 +44,6 @@
 import android.telephony.ims.ImsManager;
 import android.telephony.ims.ImsService;
 import android.telephony.ims.SipDelegateConfiguration;
-import android.telephony.ims.SipDelegateImsConfiguration;
 import android.telephony.ims.SipDelegateManager;
 import android.telephony.ims.SipMessage;
 import android.telephony.ims.feature.ImsFeature;
@@ -648,33 +647,6 @@
     }
 
     @Test
-    public void testDeprecatedConfig() throws Exception {
-        if (!ImsUtils.shouldTestImsService()) {
-            return;
-        }
-        assertTrue(sServiceConnector.setDefaultSmsApp());
-        connectTestImsServiceWithSipTransportAndConfig();
-
-        TestSipTransport transportImpl = sServiceConnector.getCarrierService().getSipTransport();
-        TestImsRegistration regImpl = sServiceConnector.getCarrierService().getImsRegistration();
-        SipDelegateManager manager = getSipDelegateManager();
-        DelegateRequest request = getDefaultRequest();
-        TestSipDelegateConnection delegateConn = new TestSipDelegateConnection(request);
-
-        TestSipDelegate delegate = createSipDelegateConnectionAndVerify(manager, delegateConn,
-                transportImpl, Collections.emptySet(), 0);
-        assertNotNull(delegate);
-        verifyUpdateRegistrationCalled(regImpl);
-        verifyRegisteredAndSendOldSipConfig(delegateConn, delegate, request.getFeatureTags(),
-                Collections.emptySet());
-
-        destroySipDelegateAndVerifyConnDestroyed(manager, transportImpl, delegateConn, delegate);
-        assertEquals("There should be no more delegates", 0,
-                transportImpl.getDelegates().size());
-        verifyUpdateRegistrationCalled(regImpl);
-    }
-
-    @Test
     public void testDelegateRegistrationChanges() throws Exception {
         if (!ImsUtils.shouldTestImsService()) {
             return;
@@ -948,6 +920,17 @@
         assertEquals("uri", configInc.getSipAssociatedUriHeader());
         Uri gruuUri = Uri.parse("sip:blah@gruu.net");
         assertEquals(gruuUri, configInc.getPublicGruuUri());
+        SipDelegateConfiguration.IpSecConfiguration ipSecConfig = configInc.getIpSecConfiguration();
+        assertEquals(123, ipSecConfig.getLocalTxPort());
+        assertEquals(124, ipSecConfig.getLocalRxPort());
+        assertEquals(125, ipSecConfig.getLastLocalTxPort());
+        assertEquals(126, ipSecConfig.getRemoteTxPort());
+        assertEquals(127, ipSecConfig.getRemoteRxPort());
+        assertEquals(128, ipSecConfig.getLastRemoteTxPort());
+        assertEquals("secverify", ipSecConfig.getSipSecurityVerifyHeader());
+        InetSocketAddress natAddr = configInc.getNatSocketAddress();
+        assertEquals("3.3.3.3", natAddr.getAddress().getHostAddress());
+        assertEquals(129, natAddr.getPort());
     }
 
     @Test
@@ -1857,25 +1840,6 @@
         sendConfigChange(sipConfig, delegateConn, delegate);
     }
 
-    private void verifyRegisteredAndSendOldSipConfig(TestSipDelegateConnection delegateConn,
-            TestSipDelegate delegate, Set<String> registeredTags,
-            Set<FeatureTagState> deniedTags) {
-        // wait for reg change to be called
-        delegateConn.setOperationCountDownLatch(1);
-        DelegateRegistrationState s = getRegisteredRegistrationState(registeredTags);
-        delegate.notifyImsRegistrationUpdate(s);
-        delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
-        delegateConn.verifyRegistrationStateRegistered(registeredTags);
-        delegateConn.verifyDenied(deniedTags);
-
-        delegateConn.setOperationCountDownLatch(1);
-        // Use the old config here and ensure a equivalent version of the new config is received
-        // by app.
-        delegate.notifyImsConfigurationUpdate(generateOldConfig());
-        delegateConn.waitForCountDown(ImsUtils.TEST_TIMEOUT_MS);
-        delegateConn.verifyConfigEquals(generateNewTestConfig());
-    }
-
     private Set<FeatureTagState> generateDeniedSetFromRequest(Set<String> grantedTags,
             Set<String> newTags, int reason) {
         // Deny features from newTags that are already granted in grantedTags.
@@ -2038,77 +2002,6 @@
         return b.build();
     }
 
-
-    /**
-     * @return A instance of the deprecated SipDelegateImConfiguration, which has the same
-     * equivalent configuration as {@link #generateNewTestConfig()}.
-     */
-    private SipDelegateImsConfiguration generateOldConfig() {
-        return new SipDelegateImsConfiguration.Builder(1)
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING,
-                        SipDelegateImsConfiguration.SIP_TRANSPORT_TCP)
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING,
-                        "1.1.1.1")
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT, 80)
-                .addString(SipDelegateImsConfiguration
-                                .KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING,
-                        "2.2.2.2")
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT, 81)
-                .addBoolean(SipDelegateImsConfiguration.KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL,
-                        true)
-                .addBoolean(SipDelegateImsConfiguration.KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL,
-                        true)
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT,
-                        508)
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING,
-                        "test1")
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING,
-                        "test2")
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_HOME_DOMAIN_STRING,
-                        "test.domain")
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_IMEI_STRING, "testImei")
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING,
-                        "sipauth")
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING,
-                        "sipnonce")
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING,
-                        "srvroute")
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_PATH_HEADER_STRING, "path")
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_USER_AGENT_HEADER_STRING,
-                        "ua")
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_URI_USER_PART_STRING, "user")
-                .addString(SipDelegateImsConfiguration
-                        .KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING, "pani")
-                .addString(SipDelegateImsConfiguration
-                        .KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING, "plani")
-                .addString(SipDelegateImsConfiguration
-                        .KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING, "cni")
-                .addString(
-                        SipDelegateImsConfiguration.KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING,
-                        "uri")
-                .addBoolean(SipDelegateImsConfiguration.KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL, true)
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING,
-                        "sip:blah@gruu.net")
-                .addBoolean(SipDelegateImsConfiguration.KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL, true)
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT, 123)
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT, 124)
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT,
-                        125)
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT,
-                        126)
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT,
-                        127)
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT,
-                        128)
-                .addString(SipDelegateImsConfiguration.KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING,
-                        "secverify")
-                .addBoolean(SipDelegateImsConfiguration.KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL, true)
-                .addString(SipDelegateImsConfiguration
-                        .KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING, "3.3.3.3")
-                .addInt(SipDelegateImsConfiguration.KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT, 129)
-                .build();
-    }
-
     private DelegateRegistrationState getRegisteredRegistrationState(Set<String> registered) {
         return new DelegateRegistrationState.Builder().addRegisteredFeatureTags(registered).build();
     }
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java
index 5040dcf..d0d41f4 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipDelegate.java
@@ -27,7 +27,6 @@
 import android.telephony.ims.DelegateStateCallback;
 import android.telephony.ims.FeatureTagState;
 import android.telephony.ims.SipDelegateConfiguration;
-import android.telephony.ims.SipDelegateImsConfiguration;
 import android.telephony.ims.SipMessage;
 import android.telephony.ims.stub.SipDelegate;
 import android.util.ArraySet;
@@ -141,10 +140,6 @@
         mStateCallback.onConfigurationChanged(config);
     }
 
-    public void notifyImsConfigurationUpdate(SipDelegateImsConfiguration config) {
-        mStateCallback.onImsConfigurationChanged(config);
-    }
-
     public void notifyOnCreated(Set<FeatureTagState> deniedTags) {
         mStateCallback.onCreated(this, deniedTags);
     }
diff --git a/tests/tests/text/resourceApk/Android.bp b/tests/tests/text/resourceApk/Android.bp
index 3f4d4c9..c29d648 100644
--- a/tests/tests/text/resourceApk/Android.bp
+++ b/tests/tests/text/resourceApk/Android.bp
@@ -29,5 +29,6 @@
         "cts",
         "general-tests",
         "mts",
+        "sts",
     ],
 }
diff --git a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextViewIntegrationTest.java b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextViewIntegrationTest.java
index 9d3b0d6..4e71d2a 100644
--- a/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextViewIntegrationTest.java
+++ b/tests/tests/textclassifier/src/android/view/textclassifier/cts/TextViewIntegrationTest.java
@@ -69,6 +69,7 @@
 import org.junit.Assume;
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -197,6 +198,7 @@
     }
 
     @Test
+    @Ignore  // Enable the test once b/187862341 is fixed.
     public void smartSelection_cancelSelectionDoesNotInvokeClassifyText() throws Exception {
         Assume.assumeTrue(BuildCompat.isAtLeastS());
         smartSelectionInternal();
diff --git a/tests/tests/time/src/android/app/time/cts/TimeManagerTest.java b/tests/tests/time/src/android/app/time/cts/TimeManagerTest.java
index 1b43e58..ee69fc1 100644
--- a/tests/tests/time/src/android/app/time/cts/TimeManagerTest.java
+++ b/tests/tests/time/src/android/app/time/cts/TimeManagerTest.java
@@ -239,7 +239,6 @@
      * Registers a {@link android.app.time.TimeManager.TimeZoneDetectorListener}, makes changes
      * to the "location enabled" setting and checks that the listener is called.
      */
-    @Ignore("http://b/171953500")
     @Test
     public void testLocationManagerAffectsCapabilities() throws Exception {
         Context context = InstrumentationRegistry.getInstrumentation().getContext();
@@ -256,16 +255,28 @@
         ExecutorService executor = Executors.newSingleThreadExecutor();
         try {
             timeManager.addTimeZoneDetectorListener(executor, listener);
-            waitForListenerCallbackCount(0, listenerTriggerCount);
+
+            // This test does not use waitForListenerCallbackCount() because changing the location
+            // enabled setting triggers more than one callback when there's a work profile, so it's
+            // easier just to sleep and confirm >= 1 callbacks have been received.
+            sleepForAsyncOperation();
+            int newCallbackCount = listenerTriggerCount.get();
+            assertEquals(0, newCallbackCount);
+            int previousCallbackCount = 0;
 
             UserHandle userHandle = android.os.Process.myUserHandle();
             boolean locationEnabled = locationManager.isLocationEnabledForUser(userHandle);
 
             locationManager.setLocationEnabledForUser(!locationEnabled, userHandle);
-            waitForListenerCallbackCount(1, listenerTriggerCount);
+            sleepForAsyncOperation();
+            newCallbackCount = listenerTriggerCount.get();
+            assertTrue(newCallbackCount > previousCallbackCount);
+            previousCallbackCount = newCallbackCount;
 
             locationManager.setLocationEnabledForUser(locationEnabled, userHandle);
-            waitForListenerCallbackCount(2, listenerTriggerCount);
+            sleepForAsyncOperation();
+            newCallbackCount = listenerTriggerCount.get();
+            assertTrue(newCallbackCount > previousCallbackCount);
         } finally {
             // Remove the listener. Required otherwise the fuzzy equality rules of lambdas causes
             // problems for later tests.
diff --git a/tests/tests/toast/OWNERS b/tests/tests/toast/OWNERS
index 9363c1a..47186b7 100644
--- a/tests/tests/toast/OWNERS
+++ b/tests/tests/toast/OWNERS
@@ -1,3 +1,4 @@
 # Bug component: 137825
 svetoslavganov@google.com
 toddke@google.com
+patb@google.com
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
index 6b0a5c2..a6d6611 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
@@ -193,6 +193,31 @@
         assertEquals(0f, effect.getDistance(), 0.001f);
     }
 
+    @Test
+    public void testPullToZeroReleases() {
+        EdgeEffect edgeEffect = new EdgeEffect(getContext());
+        edgeEffect.setSize(200, 200);
+        assertEquals(0.5f, edgeEffect.onPullDistance(0.5f, 0.5f), 0f);
+        assertFalse(edgeEffect.isFinished());
+        assertEquals(-0.5f, edgeEffect.onPullDistance(-0.5f, 0.5f), 0f);
+        assertTrue(edgeEffect.isFinished());
+    }
+
+    @Test
+    public void testFlingNegativeReleases() throws Throwable {
+        MockVsyncHelper.runOnVsyncThread(() -> {
+            EdgeEffect edgeEffect = new EdgeEffect(getContext());
+            edgeEffect.setSize(WIDTH, HEIGHT);
+            assertEquals(0.01f, edgeEffect.onPullDistance(0.01f, 0.5f), 0f);
+            assertFalse(edgeEffect.isFinished());
+            edgeEffect.onAbsorb(-10000);
+            nextFrame();
+            drawEdgeEffect(edgeEffect, 0f, 0f);
+            // It should have flung past 0 in one frame
+            assertTrue(edgeEffect.isFinished());
+        });
+    }
+
     private RenderNode drawStretchEffect(float rotation) {
         EdgeEffect edgeEffect = new EdgeEffect(getContext());
         edgeEffect.setSize(WIDTH, HEIGHT);
@@ -426,33 +451,35 @@
     @Test
     @LargeTest
     public void testStretchPullAndHold() throws Exception {
-        EdgeEffect edgeEffect = createEdgeEffectWithPull();
-        assertEquals(0.25f, edgeEffect.getDistance(), 0.001f);
+        MockVsyncHelper.runOnVsyncThread(() -> {
+            EdgeEffect edgeEffect = createEdgeEffectWithPull();
+            assertEquals(0.25f, edgeEffect.getDistance(), 0.001f);
 
-        // We must wait until the EdgeEffect would normally start receding (167 ms)
-        sleepAnimationTime(200);
+            // We must wait until the EdgeEffect would normally start receding (167 ms)
+            sleepAnimationTime(200);
 
-        // Drawing will cause updates of the distance if it is animating
-        RenderNode renderNode = new RenderNode(null);
-        Canvas canvas = renderNode.beginRecording();
-        edgeEffect.draw(canvas);
+            // Drawing will cause updates of the distance if it is animating
+            RenderNode renderNode = new RenderNode(null);
+            Canvas canvas = renderNode.beginRecording();
+            edgeEffect.draw(canvas);
 
-        // A glow effect would start receding now, so let's be sure it doesn't:
-        sleepAnimationTime(200);
-        edgeEffect.draw(canvas);
+            // A glow effect would start receding now, so let's be sure it doesn't:
+            sleepAnimationTime(200);
+            edgeEffect.draw(canvas);
 
-        // It should not be updating now
-        assertEquals(0.25f, edgeEffect.getDistance(), 0.001f);
+            // It should not be updating now
+            assertEquals(0.25f, edgeEffect.getDistance(), 0.001f);
 
-        // Now let's release it and it should start animating
-        edgeEffect.onRelease();
+            // Now let's release it and it should start animating
+            edgeEffect.onRelease();
 
-        sleepAnimationTime(20);
+            sleepAnimationTime(20);
 
-        // Now that it should be animating, the draw should update the distance
-        edgeEffect.draw(canvas);
+            // Now that it should be animating, the draw should update the distance
+            edgeEffect.draw(canvas);
 
-        assertTrue(edgeEffect.getDistance() < 0.25f);
+            assertTrue(edgeEffect.getDistance() < 0.25f);
+        });
     }
 
     /**
@@ -461,32 +488,32 @@
     @Test
     @LargeTest
     public void testCatchStretchDuringAnimation() throws Exception {
-        EdgeEffect edgeEffect = createEdgeEffectWithPull();
-        assertEquals(0.25f, edgeEffect.getDistance(), 0.001f);
-        edgeEffect.onRelease();
+        MockVsyncHelper.runOnVsyncThread(() -> {
+            EdgeEffect edgeEffect = createEdgeEffectWithPull();
+            assertEquals(0.25f, edgeEffect.getDistance(), 0.001f);
+            edgeEffect.onRelease();
 
-        // Wait some time to be sure it is animating away.
-        long startTime = AnimationUtils.currentAnimationTimeMillis();
-        sleepAnimationTime(20);
+            // Wait some time to be sure it is animating away.
+            sleepAnimationTime(20);
 
-        // Drawing will cause updates of the distance if it is animating
-        RenderNode renderNode = new RenderNode(null);
-        Canvas canvas = renderNode.beginRecording();
-        edgeEffect.draw(canvas);
+            // Drawing will cause updates of the distance if it is animating
+            RenderNode renderNode = new RenderNode(null);
+            Canvas canvas = renderNode.beginRecording();
+            edgeEffect.draw(canvas);
 
-        // It should have started retracting. Now catch it.
-        float consumed = edgeEffect.onPullDistance(0f, 0.5f);
-        assertEquals(0f, consumed, 0f);
+            // It should have started retracting. Now catch it.
+            float consumed = edgeEffect.onPullDistance(0f, 0.5f);
+            assertEquals(0f, consumed, 0f);
 
-        float distanceAfterAnimation = edgeEffect.getDistance();
-        assertTrue(distanceAfterAnimation < 0.25f);
+            float distanceAfterAnimation = edgeEffect.getDistance();
+            assertTrue(distanceAfterAnimation < 0.25f);
 
+            sleepAnimationTime(50);
 
-        sleepAnimationTime(50);
-
-        // There should be no change once it has been caught.
-        edgeEffect.draw(canvas);
-        assertEquals(distanceAfterAnimation, edgeEffect.getDistance(), 0f);
+            // There should be no change once it has been caught.
+            edgeEffect.draw(canvas);
+            assertEquals(distanceAfterAnimation, edgeEffect.getDistance(), 0f);
+        });
     }
 
     /**
@@ -524,16 +551,13 @@
      * by at least <code>durationMillis</code> milliseconds. This is useful for EdgeEffect because
      * it uses that mechanism to determine the animation duration.
      *
+     * Must be in a {@link MockVsyncHelper#runOnVsyncThread(MockVsyncHelper.CallableVoid)}
+     *
      * @param durationMillis The time to sleep in milliseconds.
      */
-    private void sleepAnimationTime(long durationMillis) throws Exception {
-        final long startTime = AnimationUtils.currentAnimationTimeMillis();
-        long currentTime = startTime;
-        final long endTime = startTime + durationMillis;
-        do {
-            Thread.sleep(endTime - currentTime);
-            currentTime = AnimationUtils.currentAnimationTimeMillis();
-        } while (currentTime < endTime);
+    private void sleepAnimationTime(long durationMillis) {
+        AnimationUtils.lockAnimationClock(
+                AnimationUtils.currentAnimationTimeMillis() + durationMillis);
     }
 
     private interface StretchVerifier {
@@ -541,7 +565,11 @@
     }
 
     // validates changes to the stretch over the course of an animation
-    private void verifyStretch(EdgeEffectInitializer initializer, StretchVerifier stretchVerifier) {
+    private void verifyStretch(
+            long timeBetweenFrames,
+            EdgeEffectInitializer initializer,
+            StretchVerifier stretchVerifier
+    ) {
         MockVsyncHelper.runOnVsyncThread(() -> {
             EdgeEffect edgeEffect = new EdgeEffect(getContext());
             edgeEffect.setSize(WIDTH, HEIGHT);
@@ -549,7 +577,7 @@
             RenderNode renderNode1 = drawEdgeEffect(edgeEffect, 0, 0);
             float oldStretch = getStretchDownPixelCount(renderNode1);
             for (int i = 0; i < 3; i++) {
-                nextFrame();
+                sleepAnimationTime(timeBetweenFrames);
                 RenderNode renderNode2 = drawEdgeEffect(edgeEffect, 0, 0);
                 float newStretch = getStretchDownPixelCount(renderNode2);
                 stretchVerifier.verify(oldStretch, newStretch);
@@ -561,15 +589,19 @@
     @Test
     public void testOnAbsorb() {
         verifyStretch(
+                8, // The spring will bounce back very quickly
                 edgeEffect -> edgeEffect.onAbsorb(300),
-                (oldStretch, newStretch) -> assertTrue("Stretch should grow",
-                        oldStretch < newStretch)
+                (oldStretch, newStretch) -> {
+                    assertTrue("Stretch should grow",
+                            oldStretch < newStretch);
+                }
         );
     }
 
     @Test
     public void testOnRelease() {
         verifyStretch(
+                16,
                 edgeEffect -> {
                     edgeEffect.onPull(1);
                     edgeEffect.onRelease();
diff --git a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
index 0513230..0df6b25 100644
--- a/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
+++ b/tests/tests/voiceinteraction/common/src/android/voiceinteraction/common/Utils.java
@@ -52,12 +52,18 @@
     public static final int HOTWORD_DETECTION_SERVICE_WITHOUT_ISOLATED_PROCESS = 3;
     public static final int HOTWORD_DETECTION_SERVICE_WITHIN_ISOLATED_PROCESS = 4;
 
-    /** Indicate which test event for testing. */
-    public static final int VOICE_INTERACTION_SERVICE_NORMAL_TEST = 0;
-    public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_TEST = 1;
-    public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_WITHOUT_PERMISSION_TEST = 2;
-    public static final int HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST = 3;
-    public static final int HOTWORD_DETECTION_SERVICE_EXTERNAL_SOURCE_ONDETECT_TEST = 4;
+    /**
+     * Indicate which test event for testing.
+     *
+     * Note: The VIS is the abbreviation of VoiceInteractionService
+     */
+    public static final int VIS_NORMAL_TEST = 0;
+    public static final int VIS_WITHOUT_MANAGE_HOTWORD_DETECTION_PERMISSION_TEST = 1;
+    public static final int VIS_HOLD_BIND_HOTWORD_DETECTION_PERMISSION_TEST = 2;
+
+    public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_TEST = 100;
+    public static final int HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST = 101;
+    public static final int HOTWORD_DETECTION_SERVICE_EXTERNAL_SOURCE_ONDETECT_TEST = 102;
 
     public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS = 1;
     public static final int HOTWORD_DETECTION_SERVICE_TRIGGER_ILLEGAL_STATE_EXCEPTION = 2;
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
index e5e7c20..12d7fd0 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/BasicVoiceInteractionService.java
@@ -18,6 +18,7 @@
 
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
+import android.Manifest;
 import android.content.Intent;
 import android.media.AudioFormat;
 import android.os.ParcelFileDescriptor;
@@ -73,9 +74,12 @@
         if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST) {
             runWithShellPermissionIdentity(() -> {
                 mAlwaysOnHotwordDetector = callCreateAlwaysOnHotwordDetector();
-            });
-        } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_WITHOUT_PERMISSION_TEST) {
-            callCreateAlwaysOnHotwordDetector();
+            }, Manifest.permission.MANAGE_HOTWORD_DETECTION);
+        } else if (testEvent == Utils.VIS_WITHOUT_MANAGE_HOTWORD_DETECTION_PERMISSION_TEST) {
+            runWithShellPermissionIdentity(() -> callCreateAlwaysOnHotwordDetector(),
+                    Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE);
+        } else if (testEvent == Utils.VIS_HOLD_BIND_HOTWORD_DETECTION_PERMISSION_TEST) {
+            runWithShellPermissionIdentity(() -> callCreateAlwaysOnHotwordDetector());
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST) {
             runWithShellPermissionIdentity(() -> {
                 if (mAlwaysOnHotwordDetector != null) {
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainInteractionService.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainInteractionService.java
index 2165854..415ac8d 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainInteractionService.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/MainInteractionService.java
@@ -55,7 +55,7 @@
         }
 
         final int testEvent = mIntent.getIntExtra(Utils.KEY_TEST_EVENT, -1);
-        if (testEvent == Utils.VOICE_INTERACTION_SERVICE_NORMAL_TEST) {
+        if (testEvent == Utils.VIS_NORMAL_TEST) {
             maybeStart();
         } else if (testEvent == Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST) {
             runWithShellPermissionIdentity(() -> {
diff --git a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/VoiceInteractionMain.java b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/VoiceInteractionMain.java
index 37bb775..4a0b775 100644
--- a/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/VoiceInteractionMain.java
+++ b/tests/tests/voiceinteraction/service/src/android/voiceinteraction/service/VoiceInteractionMain.java
@@ -31,7 +31,7 @@
         super.onCreate(savedInstanceState);
         Intent intent = new Intent();
         intent.setComponent(new ComponentName(this, MainInteractionService.class));
-        intent.putExtra(Utils.KEY_TEST_EVENT, Utils.VOICE_INTERACTION_SERVICE_NORMAL_TEST);
+        intent.putExtra(Utils.KEY_TEST_EVENT, Utils.VIS_NORMAL_TEST);
         final Bundle intentExtras = getIntent().getExtras();
         if (intentExtras != null) {
             intent.putExtras(intentExtras);
diff --git a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
index 4636dbc..a347e01 100644
--- a/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
+++ b/tests/tests/voiceinteraction/src/android/voiceinteraction/cts/HotwordDetectionServiceBasicTest.java
@@ -48,74 +48,67 @@
     @Test
     public void testHotwordDetectionService_validHotwordDetectionComponentName_triggerSuccess()
             throws Throwable {
-        createAndVerifyHotwordDetectionServiceBindSuccess();
+        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
+                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
     }
 
     @Test
-    public void testHotwordDetectionService_withoutAllowTriggerPermission_triggerFailure()
+    public void testVoiceInteractionService_withoutManageHotwordDetectionPermission_triggerFailure()
             throws Throwable {
-        final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(mContext,
-                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT);
-        receiver.register();
-
-        mActivityTestRule.getScenario().onActivity(activity -> {
-            activity.triggerHotwordDetectionServiceTest(
-                    Utils.HOTWORD_DETECTION_SERVICE_BASIC,
-                    Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_WITHOUT_PERMISSION_TEST);
-        });
-
-        final Intent intent = receiver.awaitForBroadcast(TIMEOUT_MS);
-        assertThat(intent).isNotNull();
-        assertThat(intent.getIntExtra(Utils.KEY_TEST_RESULT, -1)).isEqualTo(
+        testHotwordDetection(Utils.VIS_WITHOUT_MANAGE_HOTWORD_DETECTION_PERMISSION_TEST,
+                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
                 Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SECURITY_EXCEPTION);
+    }
 
-        receiver.unregisterQuietly();
+    @Test
+    public void testVoiceInteractionService_holdBindHotwordDetectionPermission_triggerFailure()
+            throws Throwable {
+        testHotwordDetection(Utils.VIS_HOLD_BIND_HOTWORD_DETECTION_PERMISSION_TEST,
+                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SECURITY_EXCEPTION);
     }
 
     @Test
     public void testHotwordDetectionService_onDetectFromDsp_success()
             throws Throwable {
         // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
-        createAndVerifyHotwordDetectionServiceBindSuccess();
+        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
+                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
 
         // Use AlwaysOnHotwordDetector to test the onDetect function of HotwordDetectionService
-        testOnDetect(Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST);
+        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_DSP_ONDETECT_TEST,
+                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_ONDETECT_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_ONDETECT_SUCCESS);
     }
 
     @Test
     public void testHotwordDetectionService_onDetectFromExternalSource_success()
             throws Throwable {
         // Create AlwaysOnHotwordDetector and wait the HotwordDetectionService ready
-        createAndVerifyHotwordDetectionServiceBindSuccess();
+        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST,
+                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
 
         // Use AlwaysOnHotwordDetector to test the external source function of
         // HotwordDetectionService
-        testOnDetect(Utils.HOTWORD_DETECTION_SERVICE_EXTERNAL_SOURCE_ONDETECT_TEST);
+        testHotwordDetection(Utils.HOTWORD_DETECTION_SERVICE_EXTERNAL_SOURCE_ONDETECT_TEST,
+                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_ONDETECT_RESULT_INTENT,
+                Utils.HOTWORD_DETECTION_SERVICE_ONDETECT_SUCCESS);
     }
 
-    private void createAndVerifyHotwordDetectionServiceBindSuccess() {
-        final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(mContext,
-                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_TRIGGER_RESULT_INTENT);
-        receiver.register();
-
-        mActivityTestRule.getScenario().onActivity(activity -> {
-            activity.triggerHotwordDetectionServiceTest(
-                    Utils.HOTWORD_DETECTION_SERVICE_BASIC,
-                    Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_TEST);
-        });
-
-        final Intent intent = receiver.awaitForBroadcast(TIMEOUT_MS);
+    private static void assertIntentExtraValueAsExpectation(Intent intent, int expectedResult) {
         assertThat(intent).isNotNull();
-        assertThat(intent.getIntExtra(Utils.KEY_TEST_RESULT, -1)).isEqualTo(
-                Utils.HOTWORD_DETECTION_SERVICE_TRIGGER_SUCCESS);
 
-        receiver.unregisterQuietly();
+        int result = intent.getIntExtra(Utils.KEY_TEST_RESULT, -1);
+        assertThat(result).isEqualTo(expectedResult);
     }
 
-    private void testOnDetect(int testType) {
-        final BlockingBroadcastReceiver onDetectReceiver = new BlockingBroadcastReceiver(mContext,
-                Utils.BROADCAST_HOTWORD_DETECTION_SERVICE_ONDETECT_RESULT_INTENT);
-        onDetectReceiver.register();
+    private void testHotwordDetection(int testType, String expectedIntent, int expectedResult) {
+        final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(mContext,
+                expectedIntent);
+        receiver.register();
 
         mActivityTestRule.getScenario().onActivity(activity -> {
             activity.triggerHotwordDetectionServiceTest(
@@ -123,12 +116,10 @@
                     testType);
         });
 
-        final Intent intent = onDetectReceiver.awaitForBroadcast(TIMEOUT_MS);
-        assertThat(intent).isNotNull();
-        assertThat(intent.getIntExtra(Utils.KEY_TEST_RESULT, -1)).isEqualTo(
-                Utils.HOTWORD_DETECTION_SERVICE_ONDETECT_SUCCESS);
+        final Intent intent = receiver.awaitForBroadcast(TIMEOUT_MS);
+        receiver.unregisterQuietly();
 
-        onDetectReceiver.unregisterQuietly();
+        assertIntentExtraValueAsExpectation(intent, expectedResult);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListView_ScrollTest.java b/tests/tests/widget/src/android/widget/cts/AbsListView_ScrollTest.java
index d63bb04..15ba71b 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListView_ScrollTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListView_ScrollTest.java
@@ -517,7 +517,7 @@
         // Note that due to asynchronous nature of the moving pieces, we might still get one
         // more scroll frame as the injected motion events that constitute an emulated tap
         // are being processed by our list view.
-        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mListView);
+        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mListView, false);
 
         // Sleep for a second
         SystemClock.sleep(1000);
@@ -549,7 +549,7 @@
         final CountDownLatch flingLatch = new CountDownLatch(1);
         mListView.setOnScrollListener(new ScrollIdleListListener(flingLatch));
         CtsTouchUtils.emulateFlingGesture(mInstrumentation, mActivityRule, mListView,
-                isDownwardsFlingGesture);
+                isDownwardsFlingGesture, false, null);
 
         assertTrue("Timed out while waiting for the fling to complete",
                 flingLatch.await(5, TimeUnit.SECONDS));
diff --git a/tests/tests/wifi/Android.bp b/tests/tests/wifi/Android.bp
index 4349126..850c89b 100644
--- a/tests/tests/wifi/Android.bp
+++ b/tests/tests/wifi/Android.bp
@@ -19,7 +19,8 @@
 
 java_defaults {
     name: "CtsWifiLastStableSdkDefaults",
-    target_sdk_version: "30",
+    // TODO(b/167575586): Wait for S SDK finalization to change target sdk to 31.
+    target_sdk_version: "10000",
     min_sdk_version: "30",
 }
 
diff --git a/tests/tests/wifi/OWNERS b/tests/tests/wifi/OWNERS
index 7d9d0f9..a0ab9e6 100644
--- a/tests/tests/wifi/OWNERS
+++ b/tests/tests/wifi/OWNERS
@@ -1,4 +1,2 @@
 # Bug component: 33618
-dysu@google.com
-etancohen@google.com
-satk@google.com
+include platform/packages/modules/Wifi:/WIFI_OWNERS
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 2647aa2..a0919af 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
@@ -22,6 +22,7 @@
 import static android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
+import static android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats;
 import static android.net.wifi.WifiUsabilityStatsEntry.RadioStats;
 import static android.net.wifi.WifiUsabilityStatsEntry.RateStats;
 import static android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE;
@@ -278,6 +279,12 @@
                             WME_ACCESS_CATEGORY_VO).getContentionTimeAvgMicros()).isAtLeast(0);
                     assertThat(statsEntry.getContentionTimeStats(
                             WME_ACCESS_CATEGORY_VO).getContentionNumSamples()).isAtLeast(0);
+                    // This is to add CTS test for the constructor function.
+                    ContentionTimeStats contentionStats = new ContentionTimeStats(2, 1, 4, 10);
+                    assertEquals(2, contentionStats.getContentionTimeMinMicros());
+                    assertEquals(1, contentionStats.getContentionTimeMaxMicros());
+                    assertEquals(4, contentionStats.getContentionTimeAvgMicros());
+                    assertEquals(10, contentionStats.getContentionNumSamples());
                     assertThat(statsEntry.getChannelUtilizationRatio()).isIn(Range.closed(0, 255));
                     if (mTelephonyManager != null) {
                         boolean isCellularDataAvailable =
@@ -552,6 +559,15 @@
             assertThat(countDownLatchScorer.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
             assertThat(connectedNetworkScorer.stopSessionId)
                     .isEqualTo(connectedNetworkScorer.startSessionId);
+            // Verify that onStart() and onStop() set internal variables correctly.
+            connectedNetworkScorer.onStart(
+                    new WifiConnectedSessionInfo.Builder(100)
+                            .setUserSelected(false)
+                            .build());
+            assertEquals(100, connectedNetworkScorer.startSessionId.intValue());
+            assertEquals(false, connectedNetworkScorer.isUserSelected);
+            connectedNetworkScorer.onStop(200);
+            assertEquals(200, connectedNetworkScorer.stopSessionId.intValue());
         } finally {
             mWifiManager.removeOnWifiUsabilityStatsListener(usabilityStatsListener);
             mWifiManager.clearWifiConnectedNetworkScorer();
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/TestHelper.java b/tests/tests/wifi/src/android/net/wifi/cts/TestHelper.java
index c21432c..7bc6baf 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/TestHelper.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/TestHelper.java
@@ -499,6 +499,17 @@
                 assertThat(testNetworkCallback.onAvailableCalled).isTrue();
                 final WifiInfo wifiInfo = getWifiInfo(testNetworkCallback.networkCapabilities);
                 assertConnectionEquals(network, wifiInfo);
+                if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) {
+                    assertThat(wifiInfo.isTrusted()).isTrue();
+                    WifiInfo redact = wifiInfo
+                            .makeCopy(NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION);
+                    assertThat(wifiInfo.getInformationElements()).isNotNull();
+                    assertThat(redact.getInformationElements()).isNull();
+                    assertThat(redact.getApplicableRedactions()).isEqualTo(
+                            NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION
+                            | NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS
+                            | NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS);
+                }
                 if (BuildCompat.isAtLeastS()) {
                     // If STA concurrency for restricted connection is supported, this should not
                     // be the primary connection.
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiBuildCompat.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiBuildCompat.java
index 46e5a78..0968b1c2 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiBuildCompat.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiBuildCompat.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.ModuleInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.util.Log;
 
@@ -54,23 +55,17 @@
     private static long getWifiApexVersionCode(@NonNull Context ctx) {
         PackageManager packageManager = ctx.getPackageManager();
         long wifiStackVersion = 0;
-        try {
-            String wifiPackageName = null;
-            for (ModuleInfo moduleInfo : packageManager.getInstalledModules(0)) {
-                if (moduleInfo.getPackageName().endsWith(WIFI_PACKAGE_NAME_SUFFIX)) {
-                    wifiPackageName = moduleInfo.getPackageName();
-                    break;
-                }
+        String wifiPackageName = null;
+        for (PackageInfo packageInfo : packageManager
+                .getInstalledPackages(PackageManager.MATCH_APEX)) {
+            if (packageInfo.packageName.endsWith(WIFI_PACKAGE_NAME_SUFFIX)) {
+                wifiPackageName = packageInfo.packageName;
+                wifiStackVersion = packageInfo.getLongVersionCode();
+                break;
             }
-            if (wifiPackageName != null) {
-                wifiStackVersion = packageManager.getPackageInfo(
-                        wifiPackageName, PackageManager.MATCH_APEX).getLongVersionCode();
-            }
-            Log.v(TAG, "Wifi Module package name is " + wifiPackageName
-                    + ", version is " + wifiStackVersion);
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, "Wifi Module is missing! Exception: " + e.getMessage());
         }
+        Log.v(TAG, "Wifi Module package name is " + wifiPackageName
+                + ", version is " + wifiStackVersion);
         return wifiStackVersion;
     }
 
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index f37b62c..4daa179 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -18,6 +18,7 @@
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.wifi.WifiAvailableChannel.OP_MODE_SAP;
 import static android.net.wifi.WifiAvailableChannel.OP_MODE_STA;
 import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
 import static android.net.wifi.WifiManager.COEX_RESTRICTION_SOFTAP;
@@ -552,11 +553,11 @@
      */
     @SdkSuppress(minSdkVersion = 31, codeName = "S")
     public void testRestartWifiSubsystem() throws Exception {
-        mSubsystemRestartStatus = 0; // 0: uninitialized
         if (!WifiFeature.isWifiSupported(getContext())) {
             // skip the test if WiFi is not supported
             return;
         }
+        mSubsystemRestartStatus = 0; // 0: uninitialized
         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         try {
             uiAutomation.adoptShellPermissionIdentity();
@@ -1120,6 +1121,61 @@
     }
 
     /**
+     * Test the WifiManager APIs that return whether a feature is supported.
+     */
+    public void testGetSupportedFeatures() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) {
+            // Skip the test if wifi module version is older than S.
+            return;
+        }
+        mWifiManager.isMakeBeforeBreakWifiSwitchingSupported();
+        mWifiManager.isStaBridgedApConcurrencySupported();
+    }
+
+    /**
+     * Verify non DO apps cannot call removeNonCallerConfiguredNetworks.
+     */
+    public void testRemoveNonCallerConfiguredNetworksNotAllowed() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) {
+            // Skip the test if wifi module version is older than S.
+            return;
+        }
+        try {
+            mWifiManager.removeNonCallerConfiguredNetworks();
+            fail("Expected security exception for non DO app");
+        } catch (SecurityException e) {
+        }
+    }
+
+    /**
+     * Test coverage for the constructor of AddNetworkResult.
+     */
+    public void testAddNetworkResultCreation() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) {
+            // Skip the test if wifi module version is older than S.
+            return;
+        }
+        int statusCode = WifiManager.AddNetworkResult.STATUS_NO_PERMISSION;
+        int networkId = 5;
+        WifiManager.AddNetworkResult result = new WifiManager.AddNetworkResult(
+            statusCode, networkId);
+        assertEquals("statusCode should match", statusCode, result.statusCode);
+        assertEquals("networkId should match", networkId, result.networkId);
+    }
+
+    /**
      * Verify that {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} throws a
      * SecurityException when called by a normal app.
      */
@@ -2321,6 +2377,12 @@
                 softApConfigBuilder.setIeee80211axEnabled(true);
                 verifySetGetSoftApConfig(softApConfigBuilder.build());
             }
+
+            if (BuildCompat.isAtLeastS()) {
+                softApConfigBuilder.setBridgedModeOpportunisticShutdownEnabled(false);
+                verifySetGetSoftApConfig(softApConfigBuilder.build());
+            }
+
         } finally {
             mWifiManager.unregisterSoftApCallback(callback);
             uiAutomation.dropShellPermissionIdentity();
@@ -2407,6 +2469,10 @@
                 assertNotEquals(callback.getCurrentSoftApInfo().getWifiStandard(),
                         ScanResult.WIFI_STANDARD_UNKNOWN);
             }
+
+            if (callback.getOnSoftapInfoChangedCalledCount() > 1) {
+                assertTrue(callback.getCurrentSoftApInfo().getAutoShutdownTimeoutMillis() > 0);
+            }
         } finally {
             // stop tethering which used to verify stopSoftAp
             mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
@@ -4278,14 +4344,16 @@
 
     /**
      * Tests {@link WifiManager#isPasspointTermsAndConditionsSupported)} does not crash.
-     * TODO(b/167575586): Wait for S SDK finalization to determine the final minSdkVersion.
      */
-    @SdkSuppress(minSdkVersion = 31, codeName = "S")
     public void testIsPasspointTermsAndConditionsSupported() throws Exception {
         if (!WifiFeature.isWifiSupported(getContext())) {
             // skip the test if WiFi is not supported
             return;
         }
+        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
+            // Skip the test if wifi module version is older than S.
+            return;
+        }
         mWifiManager.isPasspointTermsAndConditionsSupported();
     }
 
@@ -4294,16 +4362,15 @@
      * {@link WifiManager#clearOverrideCountryCode()} and
      * {@link WifiManager#setDefaultCountryCode()} need privileged permission
      * and the permission is not even given to shell user.
+     *
+     * TODO(b/167575586): Wait for S SDK finalization to determine the final minSdkVersion.
      */
+    @SdkSuppress(minSdkVersion = 31, codeName = "S")
     public void testManageCountryCodeMethodsFailWithoutPermissions() throws Exception {
         if (!WifiFeature.isWifiSupported(getContext())) {
             // skip the test if WiFi is not supported
             return;
         }
-        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(mContext)) {
-            // Skip the test if wifi module version is older than S.
-            return;
-        }
         ShellIdentityUtils.invokeWithShellPermissions(() -> {
             try {
                 mWifiManager.setOverrideCountryCode(TEST_COUNTRY_CODE);
@@ -4330,14 +4397,16 @@
 
     /**
      * Tests {@link WifiManager#flushPasspointAnqpCache)} does not crash.
-     * TODO(b/167575586): Wait for S SDK finalization to determine the final minSdkVersion.
      */
-    @SdkSuppress(minSdkVersion = 31, codeName = "S")
     public void testFlushPasspointAnqpCache() throws Exception {
         if (!WifiFeature.isWifiSupported(getContext())) {
             // skip the test if WiFi is not supported
             return;
         }
+        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
+            // Skip the test if wifi module version is older than S.
+            return;
+        }
         // The below API only works with privileged permissions (obtained via shell identity
         // for test)
         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
@@ -4351,14 +4420,16 @@
 
     /**
      * Tests {@link WifiManager#isDecoratedIdentitySupported)} does not crash.
-     * TODO(b/167575586): Wait for S SDK finalization to determine the final minSdkVersion.
      */
-    @SdkSuppress(minSdkVersion = 31, codeName = "S")
     public void testIsDecoratedIdentitySupported() throws Exception {
         if (!WifiFeature.isWifiSupported(getContext())) {
             // skip the test if WiFi is not supported
             return;
         }
+        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
+            // Skip the test if wifi module version is older than S.
+            return;
+        }
         mWifiManager.isDecoratedIdentitySupported();
     }
 
@@ -4425,6 +4496,10 @@
         // for test)
         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         try {
+
+            WifiAvailableChannel channel = new WifiAvailableChannel(2412, OP_MODE_SAP);
+            assertEquals(channel.getFrequencyMhz(), 2412);
+            assertEquals(channel.getOperationalModes(), OP_MODE_SAP);
             final List<Integer> valid24GhzFreqs = Arrays.asList(
                 2412, 2417, 2422, 2427, 2432, 2437, 2442,
                 2447, 2452, 2457, 2462, 2467, 2472, 2484);
diff --git a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
index 65b2f8b..fca5cbc 100644
--- a/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -88,8 +88,15 @@
         builder.addAccessPoint(testAp);
         if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
             builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize());
+            assertTrue(RangingRequest.getDefaultRttBurstSize()
+                    >= RangingRequest.getMinRttBurstSize());
+            assertTrue(RangingRequest.getDefaultRttBurstSize()
+                    <= RangingRequest.getMaxRttBurstSize());
         }
         RangingRequest request = builder.build();
+        if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
+            assertEquals(1, request.getRttResponders().size());
+        }
 
         List<RangingResult> allResults = new ArrayList<>();
         int numFailures = 0;
diff --git a/tests/translation/Android.bp b/tests/translation/Android.bp
index d6c2886..5656e99 100644
--- a/tests/translation/Android.bp
+++ b/tests/translation/Android.bp
@@ -39,5 +39,7 @@
         "src/**/*.java",
     ],
     sdk_version: "test_current",
+    // set target sdk 30 that can use for test
+    target_sdk_version: "30",
     min_sdk_version: "30",
 }
diff --git a/tests/translation/AndroidManifest.xml b/tests/translation/AndroidManifest.xml
index c8fe37e..779cf6c 100644
--- a/tests/translation/AndroidManifest.xml
+++ b/tests/translation/AndroidManifest.xml
@@ -29,6 +29,10 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+        <activity android:name=".VirtualContainerViewActivity"
+                  android:label="VirtualContainerViewActivity"
+                  android:exported="true">
+        </activity>
 
         <service android:name=".CtsTranslationService"
                  android:label="CtsTranslationService"
diff --git a/tests/translation/res/layout/virtual_container_view_activity.xml b/tests/translation/res/layout/virtual_container_view_activity.xml
new file mode 100644
index 0000000..c28c064
--- /dev/null
+++ b/tests/translation/res/layout/virtual_container_view_activity.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:id="@+id/root_view"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:focusable="true"
+              android:focusableInTouchMode="true"
+              android:orientation="vertical" >
+
+    <!-- Custom View -->
+    <android.translation.cts.VirtualContainerView
+        android:id="@+id/virtual_container_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/translation/src/android/translation/cts/CtsTestIme.java b/tests/translation/src/android/translation/cts/CtsTestIme.java
index b875c3c..b07be05 100644
--- a/tests/translation/src/android/translation/cts/CtsTestIme.java
+++ b/tests/translation/src/android/translation/cts/CtsTestIme.java
@@ -56,7 +56,7 @@
     static String IME_SERVICE_PACKAGE = "android.translation.cts";
 
     private Context mContext;
-    private UiTranslationManagerTest.TestTranslationStateCallback mCallback;
+    private FakeTranslationStateCallback mCallback;
     private CommandReceiver mReceiver;
 
     @Override
@@ -85,7 +85,7 @@
 
     void registerUiTranslationStateCallback(Intent intent) {
         final UiTranslationManager manager = mContext.getSystemService(UiTranslationManager.class);
-        mCallback = new UiTranslationManagerTest.TestTranslationStateCallback();
+        mCallback = new FakeTranslationStateCallback();
         final Executor executor = Executors.newSingleThreadExecutor();
         manager.registerUiTranslationStateCallback(executor, mCallback);
 
diff --git a/tests/translation/src/android/translation/cts/FakeTranslationStateCallback.java b/tests/translation/src/android/translation/cts/FakeTranslationStateCallback.java
new file mode 100644
index 0000000..6f414ee
--- /dev/null
+++ b/tests/translation/src/android/translation/cts/FakeTranslationStateCallback.java
@@ -0,0 +1,99 @@
+/*
+ * 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.translation.cts;
+
+import android.icu.util.ULocale;
+import android.util.Log;
+import android.util.Pair;
+import android.view.View;
+import android.view.translation.UiTranslationStateCallback;
+
+/**
+ * The test implementation for {@link UiTranslationStateCallback}.
+ */
+public class FakeTranslationStateCallback implements UiTranslationStateCallback {
+
+    private static final String TAG = "MockTranslationStateCallback";
+
+    private boolean mStartCalled;
+    private boolean mFinishCalled;
+    private boolean mPausedCalled;
+    private boolean mResumedCalled;
+    private ULocale mSourceLocale;
+    private ULocale mTargetLocale;
+
+    FakeTranslationStateCallback() {
+        resetStates();
+    }
+
+    void resetStates() {
+        mStartCalled = false;
+        mFinishCalled = false;
+        mPausedCalled = false;
+        mResumedCalled = false;
+        mSourceLocale = null;
+        mTargetLocale = null;
+    }
+
+    Pair<ULocale, ULocale> getStartedLanguagePair() {
+        return new Pair<>(mSourceLocale, mTargetLocale);
+    }
+
+    boolean isOnStartedCalled() {
+        return mStartCalled;
+    }
+
+    boolean isOnFinishedCalled() {
+        return mFinishCalled;
+    }
+
+    boolean isOnPausedCalled() {
+        return mPausedCalled;
+    }
+
+    boolean isOnResumedCalled() {
+        return mResumedCalled;
+    }
+
+    @Override
+    public void onStarted(ULocale sourceLocale, ULocale targetLocale) {
+        Log.d(TAG, "onStarted, source=" + sourceLocale.getLanguage() + " targetLocale="
+                + targetLocale.getLanguage());
+        mStartCalled = true;
+        mSourceLocale = sourceLocale;
+        mTargetLocale = targetLocale;
+    }
+
+    @Override
+    public void onResumed(ULocale sourceLocale, ULocale targetLocale) {
+        Log.d(TAG, "onResumed, source=" + sourceLocale.getLanguage() + " targetLocale="
+                + targetLocale.getLanguage());
+        mResumedCalled = true;
+    }
+
+    @Override
+    public void onPaused() {
+        Log.d(TAG, "onPaused");
+        mPausedCalled = true;
+    }
+
+    @Override
+    public void onFinished() {
+        Log.d(TAG, "onFinished");
+        mFinishCalled = true;
+    }
+}
diff --git a/tests/translation/src/android/translation/cts/Helper.java b/tests/translation/src/android/translation/cts/Helper.java
index 66a4a91..cda9e37 100644
--- a/tests/translation/src/android/translation/cts/Helper.java
+++ b/tests/translation/src/android/translation/cts/Helper.java
@@ -140,21 +140,4 @@
                         Until.findObject(By.res(resourcePackage, resourceId)), 5_000L);
         return foundObj;
     }
-
-    static class Triple<T, U, V> {
-
-        private final T first;
-        private final U second;
-        private final V third;
-
-        public Triple(T first, U second, V third) {
-            this.first = first;
-            this.second = second;
-            this.third = third;
-        }
-
-        public T getFirst() { return first; }
-        public U getSecond() { return second; }
-        public V getThird() { return third; }
-    }
 }
\ No newline at end of file
diff --git a/tests/translation/src/android/translation/cts/TranslationManagerTest.java b/tests/translation/src/android/translation/cts/TranslationManagerTest.java
index e9800fe..325713cc 100644
--- a/tests/translation/src/android/translation/cts/TranslationManagerTest.java
+++ b/tests/translation/src/android/translation/cts/TranslationManagerTest.java
@@ -271,7 +271,7 @@
 
         final TranslationResponseValue value = response.getTranslationResponseValues().get(0);
         assertThat(value.getStatusCode()).isEqualTo(TranslationResponseValue.STATUS_SUCCESS);
-        assertThat(value.getText()).isEqualTo("success");
+        assertThat(value.getText().toString()).isEqualTo("success");
         assertThat(value.getTransliteration()).isNull();
         assertThat(value.getExtras()).isEqualTo(Bundle.EMPTY);
     }
diff --git a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
index 6239716..82c4e71 100644
--- a/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
+++ b/tests/translation/src/android/translation/cts/UiTranslationManagerTest.java
@@ -18,8 +18,6 @@
 
 import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
 import static android.content.Context.TRANSLATION_MANAGER_SERVICE;
-import static android.view.translation.TranslationResponseValue.STATUS_SUCCESS;
-import static android.provider.Settings.Secure.ENABLED_INPUT_METHODS;
 import static android.translation.cts.Helper.ACTION_ASSERT_UI_TRANSLATION_CALLBACK_ON_FINISH;
 import static android.translation.cts.Helper.ACTION_ASSERT_UI_TRANSLATION_CALLBACK_ON_PAUSE;
 import static android.translation.cts.Helper.ACTION_ASSERT_UI_TRANSLATION_CALLBACK_ON_RESUME;
@@ -30,13 +28,15 @@
 import static android.translation.cts.Helper.EXTRA_SOURCE_LOCALE;
 import static android.translation.cts.Helper.EXTRA_TARGET_LOCALE;
 import static android.translation.cts.Helper.EXTRA_VERIFY_RESULT;
-import static android.translation.cts.Helper.Triple;
+import static android.view.translation.TranslationResponseValue.STATUS_SUCCESS;
 
 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -48,11 +48,12 @@
 import android.service.contentcapture.ContentCaptureService;
 import android.service.translation.TranslationService;
 import android.util.Log;
+import android.util.LongSparseArray;
 import android.util.Pair;
+import android.view.View;
 import android.view.autofill.AutofillId;
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.inputmethod.InputMethodManager;
-import android.view.translation.TranslationManager;
 import android.view.translation.TranslationRequest;
 import android.view.translation.TranslationResponse;
 import android.view.translation.TranslationResponseValue;
@@ -60,8 +61,10 @@
 import android.view.translation.UiTranslationManager;
 import android.view.translation.UiTranslationSpec;
 import android.view.translation.UiTranslationStateCallback;
+import android.view.translation.ViewTranslationCallback;
 import android.view.translation.ViewTranslationRequest;
 import android.view.translation.ViewTranslationResponse;
+import android.widget.TextView;
 
 import androidx.lifecycle.Lifecycle;
 import androidx.test.core.app.ActivityScenario;
@@ -80,13 +83,14 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
+import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
-import java.util.List;
-import java.util.Locale;
+
 
 /**
  * Tests for {@link UiTranslationManager} related APIs.
@@ -107,12 +111,20 @@
 
     private static final long UI_WAIT_TIMEOUT = 2000;
 
+    // TODO: Use fw definition when it becomes public or testapi
+    private static final String ID_CONTENT_DESCRIPTION = "android:content_description";
+
     private static Context sContext;
     private static CtsTranslationService.TranslationReplier sTranslationReplier;
 
     private CtsContentCaptureService.ServiceWatcher mContentCaptureServiceWatcher;
     private CtsTranslationService.ServiceWatcher mTranslationServiceServiceWatcher;
     private ActivityScenario<SimpleActivity> mActivityScenario;
+    private ActivityScenario<VirtualContainerViewActivity> mVirtualContainerViewActivityScenario;
+
+    private VirtualContainerView mVirtualContainerView;
+
+    private TextView mTextView;
 
     @Rule
     public final RequiredServiceRule mContentCaptureServiceRule =
@@ -139,36 +151,30 @@
 
     @Before
     public void setup() throws Exception {
-        prepareDevice();
         CtsContentCaptureService.resetStaticState();
         CtsTranslationService.resetStaticState();
     }
 
     @After
     public void cleanup() throws Exception {
-        mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
-
+        if (mActivityScenario != null) {
+            mActivityScenario.moveToState(Lifecycle.State.DESTROYED);
+        }
+        if (mVirtualContainerViewActivityScenario != null) {
+            mVirtualContainerViewActivityScenario.moveToState(Lifecycle.State.DESTROYED);
+        }
         Helper.resetTemporaryContentCaptureService();
         Helper.resetTemporaryTranslationService();
     }
 
-    private void prepareDevice() throws Exception {
-        // Unlock screen.
-        runShellCommand("input keyevent KEYCODE_WAKEUP");
-        // Dismiss keyguard, in case it's set as "Swipe to unlock".
-        runShellCommand("wm dismiss-keyguard");
-        // Collapse notifications.
-        runShellCommand("cmd statusbar collapse");
-    }
-
     @Test
     public void testUiTranslation() throws Throwable {
-        final Triple<CharSequence, List<AutofillId>, ContentCaptureContext> result =
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
                 enableServicesAndStartActivityForTranslation();
 
-        final CharSequence originalText = result.getFirst();
-        final List<AutofillId> views = result.getSecond();
-        final ContentCaptureContext contentCaptureContext = result.getThird();
+        final CharSequence originalText = mTextView.getText();
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
 
         final String translatedText = "success";
         final UiTranslationManager manager = sContext.getSystemService(UiTranslationManager.class);
@@ -186,7 +192,7 @@
                     new TranslationSpec(ULocale.FRENCH,
                             TranslationSpec.DATA_FORMAT_TEXT),
                     views, contentCaptureContext.getActivityId(),
-                    new UiTranslationSpec.Builder().setShouldPadContentForCompat(true).build());
+                    new UiTranslationSpec.Builder().build());
 
             // Check request
             final TranslationRequest request = sTranslationReplier.getNextTranslationRequest();
@@ -196,28 +202,28 @@
             assertThat(viewRequest.getKeys().size()).isEqualTo(1);
             assertThat(viewRequest.getKeys()).containsExactly(ViewTranslationRequest.ID_TEXT);
             assertThat(viewRequest.getValue(ViewTranslationRequest.ID_TEXT).getText())
-                    .isEqualTo(originalText);
+                    .isEqualTo(originalText.toString());
 
             SystemClock.sleep(UI_WAIT_TIMEOUT);
-            assertThat(helloText.getText()).isEqualTo(translatedText);
+            assertThat(helloText.getText().toString()).isEqualTo(translatedText);
 
             // Call pauseTranslation API
             manager.pauseTranslation(contentCaptureContext.getActivityId());
 
             SystemClock.sleep(UI_WAIT_TIMEOUT);
-            assertThat(helloText.getText()).isEqualTo(originalText);
+            assertThat(helloText.getText().toString()).isEqualTo(originalText.toString());
 
             // Call resumeTranslation API
             manager.resumeTranslation(contentCaptureContext.getActivityId());
 
             SystemClock.sleep(UI_WAIT_TIMEOUT);
-            assertThat(helloText.getText()).isEqualTo(translatedText);
+            assertThat(helloText.getText().toString()).isEqualTo(translatedText);
 
             // Call finishTranslation API
             manager.finishTranslation(contentCaptureContext.getActivityId());
 
             SystemClock.sleep(UI_WAIT_TIMEOUT);
-            assertThat(helloText.getText()).isEqualTo(originalText);
+            assertThat(helloText.getText().toString()).isEqualTo(originalText.toString());
 
             // Check the Translation session is destroyed after calling finishTranslation()
             CtsTranslationService translationService =
@@ -227,14 +233,198 @@
     }
 
     @Test
+    public void testUiTranslation_CustomViewTranslationCallback() throws Throwable {
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
+                enableServicesAndStartActivityForTranslation();
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
+
+        // Set ViewTranslationCallback
+        ViewTranslationCallback mockCallback = Mockito.mock(ViewTranslationCallback.class);
+        mTextView.setViewTranslationCallback(mockCallback);
+        // Set response
+        sTranslationReplier.addResponse(createViewsTranslationResponse(views, "success"));
+        final UiTranslationManager manager = sContext.getSystemService(UiTranslationManager.class);
+        runWithShellPermissionIdentity(() -> {
+            // Call startTranslation API
+            manager.startTranslation(
+                    new TranslationSpec(ULocale.ENGLISH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    new TranslationSpec(ULocale.FRENCH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    views, contentCaptureContext.getActivityId(),
+                    new UiTranslationSpec.Builder().build());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        ArgumentCaptor<View> viewArgumentCaptor = ArgumentCaptor.forClass(View.class);
+        Mockito.verify(mockCallback, Mockito.times(1)).onShowTranslation(viewArgumentCaptor.capture());
+        TextView capturedView = (TextView) viewArgumentCaptor.getValue();
+        assertThat(capturedView.getAutofillId()).isEqualTo(mTextView.getAutofillId());
+
+        runWithShellPermissionIdentity(() -> {
+            // Call pauseTranslation API
+            manager.pauseTranslation(contentCaptureContext.getActivityId());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        Mockito.verify(mockCallback, Mockito.times(1)).onHideTranslation(viewArgumentCaptor.capture());
+        capturedView = (TextView) viewArgumentCaptor.getValue();
+        assertThat(capturedView.getAutofillId()).isEqualTo(mTextView.getAutofillId());
+
+        runWithShellPermissionIdentity(() -> {
+            // Call resumeTranslation API
+            manager.resumeTranslation(contentCaptureContext.getActivityId());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        Mockito.verify(mockCallback, Mockito.times(2)).onShowTranslation(viewArgumentCaptor.capture());
+        capturedView = (TextView) viewArgumentCaptor.getValue();
+        assertThat(capturedView.getAutofillId()).isEqualTo(mTextView.getAutofillId());
+
+        // Clear callback
+        mTextView.clearViewTranslationCallback();
+        runWithShellPermissionIdentity(() -> {
+            // Call finishTranslation API
+            manager.finishTranslation(contentCaptureContext.getActivityId());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        // Verify callback does not be called, keep the latest state
+        Mockito.verify(mockCallback, Mockito.never()).onClearTranslation(any(View.class));
+
+        // Finally, verify that no unexpected interactions occurred. We cannot use
+        // verifyNoMoreInteractions as the callback has some hidden methods.
+        Mockito.verify(mockCallback, Mockito.times(2)).onShowTranslation(any());
+        Mockito.verify(mockCallback, Mockito.times(1)).onHideTranslation(any());
+    }
+
+    @Test
+    public void testUiTranslation_ViewTranslationCallback_paddingText() throws Throwable {
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
+                enableServicesAndStartActivityForTranslation();
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
+
+        // Set response
+        final CharSequence originalText = mTextView.getText();
+        final CharSequence translatedText = "Translated World";
+        sTranslationReplier.addResponse(
+                createViewsTranslationResponse(views, translatedText.toString()));
+        final UiTranslationManager manager = sContext.getSystemService(UiTranslationManager.class);
+
+        // Use TextView default ViewTranslationCallback implementation
+        runWithShellPermissionIdentity(() -> {
+            // Call startTranslation API
+            manager.startTranslation(
+                    new TranslationSpec(ULocale.ENGLISH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    new TranslationSpec(ULocale.FRENCH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    views, contentCaptureContext.getActivityId(),
+                    new UiTranslationSpec.Builder().setShouldPadContentForCompat(true).build());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        CharSequence currentText = mTextView.getText();
+        assertThat(currentText.length()).isNotEqualTo(originalText.length());
+        assertThat(currentText.length()).isEqualTo(translatedText.length());
+
+        runWithShellPermissionIdentity(() -> {
+            // Call finishTranslation API
+            manager.finishTranslation(contentCaptureContext.getActivityId());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+
+        // Set Customized ViewTranslationCallback
+        ViewTranslationCallback mockCallback = Mockito.mock(ViewTranslationCallback.class);
+        mTextView.setViewTranslationCallback(mockCallback);
+        runWithShellPermissionIdentity(() -> {
+            // Call startTranslation API
+            manager.startTranslation(
+                    new TranslationSpec(ULocale.ENGLISH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    new TranslationSpec(ULocale.FRENCH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    views, contentCaptureContext.getActivityId(),
+                    new UiTranslationSpec.Builder().setShouldPadContentForCompat(true).build());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        assertThat(mTextView.getText().length()).isEqualTo(originalText.length());
+    }
+
+    @Test
+    public void testUiTranslation_hasContentDescription() throws Throwable {
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
+                enableServicesAndStartActivityForTranslation();
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
+
+        // Set response
+        final CharSequence translatedText = "Translated World";
+        final CharSequence originalDescription = "Hello Description";
+        mActivityScenario.onActivity(activity -> {
+            mTextView.setContentDescription(originalDescription);
+        });
+        sTranslationReplier.addResponse(
+                createViewsTranslationResponse(views, translatedText.toString()));
+        final UiTranslationManager manager = sContext.getSystemService(UiTranslationManager.class);
+
+        // Use TextView default ViewTranslationCallback implementation
+        runWithShellPermissionIdentity(() -> {
+            // Call startTranslation API
+            manager.startTranslation(
+                    new TranslationSpec(ULocale.ENGLISH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    new TranslationSpec(ULocale.FRENCH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    views, contentCaptureContext.getActivityId(),
+                    new UiTranslationSpec.Builder().build());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        assertThat(mTextView.getContentDescription().toString())
+                .isEqualTo(translatedText.toString());
+
+        // Check request to make sure the content description key doesn't be changed
+        final TranslationRequest request = sTranslationReplier.getNextTranslationRequest();
+        final List<ViewTranslationRequest> requests = request.getViewTranslationRequests();
+        final ViewTranslationRequest viewRequest = requests.get(0);
+        assertThat(viewRequest.getAutofillId()).isEqualTo(views.get(0));
+        assertThat(viewRequest.getKeys().size()).isEqualTo(2);
+        assertThat(viewRequest.getKeys()).containsExactly(ID_CONTENT_DESCRIPTION,
+                ViewTranslationRequest.ID_TEXT);
+        assertThat(viewRequest.getValue(ID_CONTENT_DESCRIPTION).getText())
+                .isEqualTo(originalDescription);
+
+        runWithShellPermissionIdentity(() -> {
+            // Call pauseTranslation API
+            manager.pauseTranslation(contentCaptureContext.getActivityId());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        assertThat(mTextView.getContentDescription().toString())
+                .isEqualTo(originalDescription.toString());
+
+        runWithShellPermissionIdentity(() -> {
+            // Call resumeTranslation API
+            manager.resumeTranslation(contentCaptureContext.getActivityId());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        assertThat(mTextView.getContentDescription().toString())
+                .isEqualTo(translatedText.toString());
+
+        runWithShellPermissionIdentity(() -> {
+            // Call finishTranslation API
+            manager.finishTranslation(contentCaptureContext.getActivityId());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        assertThat(mTextView.getContentDescription().toString())
+                .isEqualTo(originalDescription.toString());
+    }
+
+    @Test
     public void testIMEUiTranslationStateCallback() throws Throwable {
         try (ImeSession imeSession = new ImeSession(
                 new ComponentName(CtsTestIme.IME_SERVICE_PACKAGE, CtsTestIme.class.getName()))) {
 
-            final Triple<CharSequence, List<AutofillId>, ContentCaptureContext> result =
+            final Pair<List<AutofillId>, ContentCaptureContext> result =
                     enableServicesAndStartActivityForTranslation();
-            final List<AutofillId> views = result.getSecond();
-            final ContentCaptureContext contentCaptureContext = result.getThird();
+            final List<AutofillId> views = result.first;
+            final ContentCaptureContext contentCaptureContext = result.second;
             final UiTranslationManager manager =
                     sContext.getSystemService(UiTranslationManager.class);
             sTranslationReplier.addResponse(createViewsTranslationResponse(views, "success"));
@@ -254,7 +444,7 @@
                         new TranslationSpec(ULocale.FRENCH,
                                 TranslationSpec.DATA_FORMAT_TEXT),
                         views, contentCaptureContext.getActivityId(),
-                        new UiTranslationSpec.Builder().setShouldPadContentForCompat(true).build());
+                        new UiTranslationSpec.Builder().build());
                 SystemClock.sleep(UI_WAIT_TIMEOUT);
             });
             // Send broadcat to request IME to check the onStarted() result
@@ -324,11 +514,11 @@
 
     @Test
     public void testNonIMEUiTranslationStateCallback() throws Throwable {
-        final Triple<CharSequence, List<AutofillId>, ContentCaptureContext> result =
+        final Pair<List<AutofillId>, ContentCaptureContext> result =
                 enableServicesAndStartActivityForTranslation();
 
-        final List<AutofillId> views = result.getSecond();
-        final ContentCaptureContext contentCaptureContext = result.getThird();
+        final List<AutofillId> views = result.first;
+        final ContentCaptureContext contentCaptureContext = result.second;
 
         UiTranslationManager manager =
                 sContext.getSystemService(UiTranslationManager.class);
@@ -337,8 +527,8 @@
 
         // Register callback
         final Executor executor = Executors.newSingleThreadExecutor();
-        final TestTranslationStateCallback callback = new TestTranslationStateCallback();
-        manager.registerUiTranslationStateCallback(executor, callback);
+        UiTranslationStateCallback mockCallback = Mockito.mock(UiTranslationStateCallback.class);
+        manager.registerUiTranslationStateCallback(executor, mockCallback);
         runWithShellPermissionIdentity(() -> {
             // Call startTranslation API
             manager.startTranslation(
@@ -347,13 +537,114 @@
                     new TranslationSpec(ULocale.FRENCH,
                             TranslationSpec.DATA_FORMAT_TEXT),
                     views, contentCaptureContext.getActivityId(),
-                    new UiTranslationSpec.Builder().setShouldPadContentForCompat(true).build());
+                    new UiTranslationSpec.Builder().build());
             SystemClock.sleep(UI_WAIT_TIMEOUT);
 
-            assertThat(callback.isOnStartedCalled()).isFalse();
+            Mockito.verify(mockCallback, Mockito.never())
+                    .onStarted(any(ULocale.class), any(ULocale.class));
         });
     }
 
+    @Test
+    public void testVirtualViewUiTranslation() throws Throwable {
+        // Enable CTS ContentCaptureService
+        CtsContentCaptureService contentcaptureService = enableContentCaptureService();
+
+        // Start Activity and get needed information
+        final List<AutofillId> views = startVirtualContainerViewActivityAndGetViewsForTranslation();
+        ViewTranslationCallback mockCallback = Mockito.mock(ViewTranslationCallback.class);
+        mVirtualContainerView.setViewTranslationCallback(mockCallback);
+
+        // Wait session created and get the ConttCaptureContext from ContentCaptureService
+        final ContentCaptureContext contentCaptureContext =
+                getContentCaptureContextFromContentCaptureService(contentcaptureService);
+
+        // enable CTS TranslationService
+        mTranslationServiceServiceWatcher = CtsTranslationService.setServiceWatcher();
+        Helper.setTemporaryTranslationService(CtsTranslationService.SERVICE_NAME);
+
+        final String translatedText = "success";
+        final UiTranslationManager manager = sContext.getSystemService(UiTranslationManager.class);
+        // Set response
+        final TranslationResponse expectedResponse =
+                createViewsTranslationResponse(views, translatedText);
+        sTranslationReplier.addResponse(expectedResponse);
+
+        runWithShellPermissionIdentity(() -> {
+            // Call startTranslation API
+            manager.startTranslation(
+                    new TranslationSpec(ULocale.ENGLISH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    new TranslationSpec(ULocale.FRENCH,
+                            TranslationSpec.DATA_FORMAT_TEXT),
+                    views, contentCaptureContext.getActivityId(),
+                    new UiTranslationSpec.Builder().build());
+
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        // Check request
+        final TranslationRequest request = sTranslationReplier.getNextTranslationRequest();
+        final List<ViewTranslationRequest> requests = request.getViewTranslationRequests();
+        assertThat(requests.size()).isEqualTo(views.size());
+        // 1st virtual child in container
+        final ViewTranslationRequest viewRequest1 = requests.get(0);
+        assertThat(viewRequest1.getAutofillId()).isEqualTo(views.get(0));
+        assertThat(viewRequest1.getKeys()).containsExactly(ViewTranslationRequest.ID_TEXT);
+        assertThat(viewRequest1.getValue(ViewTranslationRequest.ID_TEXT).getText().toString())
+                .isEqualTo("Hello 0");
+        // 2nd virtual child in container
+        final ViewTranslationRequest viewRequest2 = requests.get(1);
+        assertThat(viewRequest2.getAutofillId()).isEqualTo(views.get(1));
+        assertThat(viewRequest2.getKeys()).containsExactly(ViewTranslationRequest.ID_TEXT);
+        assertThat(viewRequest2.getValue(ViewTranslationRequest.ID_TEXT).getText().toString())
+                .isEqualTo("Hello 1");
+
+        // Check responses
+        final LongSparseArray<ViewTranslationResponse> responses
+                = mVirtualContainerView.getViewTranslationResponseForCustomView();
+        assertThat(responses).isNotNull();
+        assertThat(responses.size()).isEqualTo(2);
+        assertThat(responses.valueAt(0))
+                .isEqualTo(expectedResponse.getViewTranslationResponses().valueAt(0));
+        assertThat(responses.valueAt(1))
+                .isEqualTo(expectedResponse.getViewTranslationResponses().valueAt(1));
+
+        ArgumentCaptor<View> viewArgumentCaptor = ArgumentCaptor.forClass(View.class);
+        Mockito.verify(mockCallback, Mockito.times(1))
+                .onShowTranslation(viewArgumentCaptor.capture());
+        VirtualContainerView capturedView = (VirtualContainerView) viewArgumentCaptor.getValue();
+        assertThat(capturedView.getAutofillId()).isEqualTo(mVirtualContainerView.getAutofillId());
+
+        runWithShellPermissionIdentity(() -> {
+            // Call pauseTranslation API
+            manager.pauseTranslation(contentCaptureContext.getActivityId());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        Mockito.verify(mockCallback, Mockito.times(1)).onHideTranslation(any(View.class));
+
+        runWithShellPermissionIdentity(() -> {
+            // Call finishTranslation API
+            manager.finishTranslation(contentCaptureContext.getActivityId());
+            SystemClock.sleep(UI_WAIT_TIMEOUT);
+        });
+        Mockito.verify(mockCallback, Mockito.times(1)).onClearTranslation(any(View.class));
+    }
+
+    private List<AutofillId> startVirtualContainerViewActivityAndGetViewsForTranslation() {
+        // Start VirtualContainerViewActivity and get needed information
+        Intent intent = new Intent(sContext, VirtualContainerViewActivity.class)
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        AtomicReference<List<AutofillId>> viewAutofillIdsRef = new AtomicReference<>();
+
+        mVirtualContainerViewActivityScenario = ActivityScenario.launch(intent);
+        mVirtualContainerViewActivityScenario.onActivity(activity -> {
+            mVirtualContainerView = activity.getVirtualContainerView();
+            // Get the views that need to be translated.
+            viewAutofillIdsRef.set(activity.getViewsForTranslation());
+        });
+        return viewAutofillIdsRef.get();
+    }
+
     private BlockingBroadcastReceiver sendCommandToIme(String action, boolean mutable) {
         final String actionImeServiceCommandDone = action + "_" + SystemClock.uptimeMillis();
         final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(sContext,
@@ -399,13 +690,16 @@
                     new ViewTranslationResponse.Builder(viewAutofillIds.get(i))
                             .setValue(ViewTranslationRequest.ID_TEXT,
                                     new TranslationResponseValue.Builder(STATUS_SUCCESS)
+                                            .setText(translatedText).build())
+                            .setValue(ID_CONTENT_DESCRIPTION,
+                                    new TranslationResponseValue.Builder(STATUS_SUCCESS)
                                             .setText(translatedText).build());
             responseBuilder.setViewTranslationResponse(i, responseDataBuilder.build());
         }
         return responseBuilder.build();
     }
 
-    private Triple<CharSequence, List<AutofillId>, ContentCaptureContext>
+    private Pair<List<AutofillId>, ContentCaptureContext>
             enableServicesAndStartActivityForTranslation() throws Exception {
         // Enable CTS ContentCaptureService
         CtsContentCaptureService contentcaptureService = enableContentCaptureService();
@@ -418,6 +712,7 @@
 
         mActivityScenario = ActivityScenario.launch(intent);
         mActivityScenario.onActivity(activity -> {
+            mTextView = activity.getHelloText();
             originalTextRef.set(activity.getHelloText().getText());
             viewAutofillIdsRef.set(activity.getViewsForTranslation());
         });
@@ -433,72 +728,8 @@
         mTranslationServiceServiceWatcher = CtsTranslationService.setServiceWatcher();
         Helper.setTemporaryTranslationService(CtsTranslationService.SERVICE_NAME);
 
-        // TODO(b/184617863): use separate methods not use Triple here.
-        return new Triple(originalText, views, contentCaptureContext);
-    }
-
-    static class TestTranslationStateCallback implements UiTranslationStateCallback {
-        private boolean mStartCalled;
-        private boolean mFinishCalled;
-        private boolean mPausedCalled;
-        private boolean mResumedCalled;
-        private ULocale mSourceLocale;
-        private ULocale mTargetLocale;
-
-        TestTranslationStateCallback() {
-            resetStates();
-        }
-
-        void resetStates() {
-            mStartCalled = false;
-            mFinishCalled = false;
-            mPausedCalled = false;
-            mResumedCalled = false;
-            mSourceLocale = null;
-            mTargetLocale = null;
-        }
-
-        Pair<ULocale, ULocale> getStartedLanguagePair() {
-            return new Pair<>(mSourceLocale, mTargetLocale);
-        }
-
-        boolean isOnStartedCalled() {
-            return mStartCalled;
-        }
-
-        boolean isOnFinishedCalled() {
-            return mFinishCalled;
-        }
-
-        boolean isOnPausedCalled() {
-            return mPausedCalled;
-        }
-
-        boolean isOnResumedCalled() {
-            return mResumedCalled;
-        }
-
-        @Override
-        public void onStarted(ULocale sourceLocale, ULocale targetLocale) {
-            mStartCalled = true;
-            mSourceLocale = sourceLocale;
-            mTargetLocale = targetLocale;
-        }
-
-        @Override
-        public void onResumed(ULocale sourceLocale, ULocale targetLocale) {
-            mResumedCalled = true;
-        }
-
-        @Override
-        public void onPaused() {
-            mPausedCalled = true;
-        }
-
-        @Override
-        public void onFinished() {
-            mFinishCalled = true;
-        }
+        // TODO(b/184617863): use separate methods not use Pair here.
+        return new Pair(views, contentCaptureContext);
     }
 
     private static class ImeSession implements AutoCloseable {
diff --git a/tests/translation/src/android/translation/cts/VirtualContainerView.java b/tests/translation/src/android/translation/cts/VirtualContainerView.java
new file mode 100644
index 0000000..196e9c6
--- /dev/null
+++ b/tests/translation/src/android/translation/cts/VirtualContainerView.java
@@ -0,0 +1,67 @@
+/*
+ * 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.translation.cts;
+
+import android.content.Context;
+import android.icu.util.ULocale;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.LongSparseArray;
+import android.view.View;
+import android.view.autofill.AutofillId;
+import android.view.translation.TranslationRequestValue;
+import android.view.translation.TranslationSpec;
+import android.view.translation.ViewTranslationCallback;
+import android.view.translation.ViewTranslationRequest;
+import android.view.translation.ViewTranslationResponse;
+import android.view.translation.TranslationResponseValue;
+import java.util.function.Consumer;
+
+public class VirtualContainerView extends View {
+
+    private static final String TAG = "VirtualContainerView";
+
+    private LongSparseArray<ViewTranslationResponse> mResponse;
+
+    public VirtualContainerView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void onCreateVirtualViewTranslationRequests(long[] virtualIds, int[] supportedFormats,
+            Consumer<ViewTranslationRequest> requestsCollector) {
+        AutofillId hostViewAutofillId = getAutofillId();
+        int virtualIdCount = virtualIds.length;
+        for (int i=0; i< virtualIdCount; i++) {
+            ViewTranslationRequest.Builder requestBuilder =
+                    new ViewTranslationRequest.Builder(hostViewAutofillId, virtualIds[i]);
+            ViewTranslationRequest request = requestBuilder.setValue(ViewTranslationRequest.ID_TEXT,
+                    TranslationRequestValue.forText("Hello " + i)).build();
+            requestsCollector.accept(request);
+        }
+    }
+
+    @Override
+    public void onVirtualViewTranslationResponses(
+            LongSparseArray<ViewTranslationResponse> response) {
+        mResponse = response;
+    }
+
+    LongSparseArray<ViewTranslationResponse> getViewTranslationResponseForCustomView() {
+        return mResponse;
+    }
+}
diff --git a/tests/translation/src/android/translation/cts/VirtualContainerViewActivity.java b/tests/translation/src/android/translation/cts/VirtualContainerViewActivity.java
new file mode 100644
index 0000000..2a57d68
--- /dev/null
+++ b/tests/translation/src/android/translation/cts/VirtualContainerViewActivity.java
@@ -0,0 +1,55 @@
+/*
+ * 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.translation.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.autofill.AutofillId;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A activity that contains a VirtualContainerView used for translation testing.
+ */
+public class VirtualContainerViewActivity extends Activity {
+
+    VirtualContainerView mVirtualContainerView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.virtual_container_view_activity);
+
+        mVirtualContainerView = findViewById(R.id.virtual_container_view);
+    }
+
+    List<AutofillId> getViewsForTranslation() {
+        AutofillId autofillId = mVirtualContainerView.getAutofillId();
+        final List<AutofillId> views = new ArrayList<>();
+        // TODO: get from Content Capture
+        AutofillId virtualChild1 = new AutofillId(autofillId, 12345L, 0);
+        AutofillId virtualChild2 = new AutofillId(autofillId, 12346L, 0);
+        views.add(virtualChild1);
+        views.add(virtualChild2);
+        return views;
+    }
+
+    VirtualContainerView getVirtualContainerView() {
+        return mVirtualContainerView;
+    }
+}
\ No newline at end of file
diff --git a/tests/translation/src/android/translation/cts/unittests/TextViewTranslationTest.java b/tests/translation/src/android/translation/cts/unittests/TextViewTranslationTest.java
index 1c79192..5b6da3f 100644
--- a/tests/translation/src/android/translation/cts/unittests/TextViewTranslationTest.java
+++ b/tests/translation/src/android/translation/cts/unittests/TextViewTranslationTest.java
@@ -89,8 +89,8 @@
 
         assertThat(request).isNotNull();
         assertThat(request.getAutofillId()).isEqualTo(mTestTextView.getAutofillId());
-        assertThat(request.getValue(ViewTranslationRequest.ID_TEXT).getText())
-                .isEqualTo(mTestTextView.getText());
+        assertThat(request.getValue(ViewTranslationRequest.ID_TEXT).getText().toString())
+                .isEqualTo(mTestTextView.getText().toString());
     }
 
     @Test
diff --git a/tests/translation/src/android/translation/cts/unittests/TranslationRequestTest.java b/tests/translation/src/android/translation/cts/unittests/TranslationRequestTest.java
index a36db64..3752499 100644
--- a/tests/translation/src/android/translation/cts/unittests/TranslationRequestTest.java
+++ b/tests/translation/src/android/translation/cts/unittests/TranslationRequestTest.java
@@ -36,15 +36,17 @@
 
     private final TranslationRequestValue mValue = TranslationRequestValue.forText("hello");
 
-    private final ViewTranslationRequest mRequest = new ViewTranslationRequest
+    private final ViewTranslationRequest mViewRequest = new ViewTranslationRequest
             .Builder(new AutofillId(17))
             .setValue("sample id", TranslationRequestValue.forText("sample text"))
             .build();
 
     @Test
     public void testBuilder_validViewTranslationRequest() {
+        final ArrayList<ViewTranslationRequest> viewRequests = new ArrayList<>();
+        viewRequests.add(mViewRequest);
         final TranslationRequest request = new TranslationRequest.Builder()
-                .addViewTranslationRequest(mRequest)
+                .setViewTranslationRequests(viewRequests)
                 .build();
 
         assertThat(request.getTranslationRequestValues().size()).isEqualTo(0);
@@ -55,13 +57,15 @@
         assertThat(viewRequest.getAutofillId()).isEqualTo(new AutofillId(17));
         assertThat(viewRequest.getKeys().size()).isEqualTo(1);
         assertThat(viewRequest.getKeys()).containsExactly("sample id");
-        assertThat(viewRequest.getValue("sample id").getText()).isEqualTo("sample text");
+        assertThat(viewRequest.getValue("sample id").getText().toString()).isEqualTo("sample text");
     }
 
     @Test
     public void testBuilder_validTranslationRequestValue() {
+        final ArrayList<TranslationRequestValue> values = new ArrayList<>();
+        values.add(mValue);
         final TranslationRequest request = new TranslationRequest.Builder()
-                .addTranslationRequestValue(mValue)
+                .setTranslationRequestValues(values)
                 .build();
 
         assertThat(request.getTranslationRequestValues().size()).isEqualTo(1);
@@ -69,7 +73,7 @@
 
         final TranslationRequestValue value =
                 request.getTranslationRequestValues().get(0);
-        assertThat(value.getText()).isEqualTo("hello");
+        assertThat(value.getText().toString()).isEqualTo("hello");
     }
 
     @Test
@@ -87,12 +91,12 @@
     public void testBuilder_mixingSetters() {
         final ArrayList<TranslationRequestValue> values = new ArrayList<>();
         values.add(mValue);
-        final ArrayList<ViewTranslationRequest> requests = new ArrayList<>();
-        requests.add(mRequest);
+        final ArrayList<ViewTranslationRequest> viewRequests = new ArrayList<>();
+        viewRequests.add(mViewRequest);
 
         final TranslationRequest request = new TranslationRequest.Builder()
                 .setTranslationRequestValues(values)
-                .setViewTranslationRequests(requests)
+                .setViewTranslationRequests(viewRequests)
                 .build();
 
         assertThat(request.getTranslationRequestValues().size()).isEqualTo(1);
@@ -103,18 +107,20 @@
         assertThat(viewRequest.getAutofillId()).isEqualTo(new AutofillId(17));
         assertThat(viewRequest.getKeys().size()).isEqualTo(1);
         assertThat(viewRequest.getKeys()).containsExactly("sample id");
-        assertThat(viewRequest.getValue("sample id").getText()).isEqualTo("sample text");
+        assertThat(viewRequest.getValue("sample id").getText().toString()).isEqualTo("sample text");
 
         final TranslationRequestValue value =
                 request.getTranslationRequestValues().get(0);
-        assertThat(value.getText()).isEqualTo("hello");
+        assertThat(value.getText().toString()).isEqualTo("hello");
     }
 
     @Test
     public void testParceledRequest_validTranslationRequestValues() {
+        final ArrayList<TranslationRequestValue> values = new ArrayList<>();
+        values.add(mValue);
+        values.add(TranslationRequestValue.forText("world"));
         final TranslationRequest request = new TranslationRequest.Builder()
-                .addTranslationRequestValue(mValue)
-                .addTranslationRequestValue(TranslationRequestValue.forText("world"))
+                .setTranslationRequestValues(values)
                 .build();
 
         final Parcel parcel = Parcel.obtain();
@@ -128,21 +134,22 @@
 
         final TranslationRequestValue value1 =
                 parceledRequest.getTranslationRequestValues().get(0);
-        assertThat(value1.getText()).isEqualTo("hello");
+        assertThat(value1.getText().toString()).isEqualTo("hello");
 
         final TranslationRequestValue value2 =
                 parceledRequest.getTranslationRequestValues().get(1);
-        assertThat(value2.getText()).isEqualTo("world");
+        assertThat(value2.getText().toString()).isEqualTo("world");
     }
 
     @Test
     public void testBuilder_sameAutofillIdViewTranslationRequests() {
+        final ArrayList<ViewTranslationRequest> viewRequests = new ArrayList<>();
+        viewRequests.add(mViewRequest);
+        viewRequests.add(new ViewTranslationRequest.Builder(new AutofillId(17))
+                .setValue("id2", TranslationRequestValue.forText("text2"))
+                .build());
         final TranslationRequest request = new TranslationRequest.Builder()
-                .addViewTranslationRequest(mRequest)
-                .addViewTranslationRequest(
-                        new ViewTranslationRequest.Builder(new AutofillId(17))
-                                .setValue("id2", TranslationRequestValue.forText("text2"))
-                                .build())
+                .setViewTranslationRequests(viewRequests)
                 .build();
 
         assertThat(request.getTranslationRequestValues().size()).isEqualTo(0);
@@ -153,45 +160,25 @@
         assertThat(viewRequest.getAutofillId()).isEqualTo(new AutofillId(17));
         assertThat(viewRequest.getKeys().size()).isEqualTo(1);
         assertThat(viewRequest.getKeys()).containsExactly("sample id");
-        assertThat(viewRequest.getValue("sample id").getText()).isEqualTo("sample text");
+        assertThat(viewRequest.getValue("sample id").getText().toString()).isEqualTo("sample text");
 
         final ViewTranslationRequest viewRequest2 =
                 request.getViewTranslationRequests().get(1);
         assertThat(viewRequest2.getAutofillId()).isEqualTo(new AutofillId(17));
         assertThat(viewRequest2.getKeys().size()).isEqualTo(1);
         assertThat(viewRequest2.getKeys()).containsExactly("id2");
-        assertThat(viewRequest2.getValue("id2").getText()).isEqualTo("text2");
-    }
-
-    @Test
-    public void testBuilder_mixingAdders() {
-        final TranslationRequest request = new TranslationRequest.Builder()
-                .addViewTranslationRequest(mRequest)
-                .addTranslationRequestValue(mValue)
-                .build();
-
-        assertThat(request.getTranslationRequestValues().size()).isEqualTo(1);
-        assertThat(request.getViewTranslationRequests().size()).isEqualTo(1);
-
-        final ViewTranslationRequest viewRequest =
-                request.getViewTranslationRequests().get(0);
-        assertThat(viewRequest.getAutofillId()).isEqualTo(new AutofillId(17));
-        assertThat(viewRequest.getKeys().size()).isEqualTo(1);
-        assertThat(viewRequest.getKeys()).containsExactly("sample id");
-        assertThat(viewRequest.getValue("sample id").getText()).isEqualTo("sample text");
-
-        final TranslationRequestValue value =
-                request.getTranslationRequestValues().get(0);
-        assertThat(value.getText()).isEqualTo("hello");
+        assertThat(viewRequest2.getValue("id2").getText().toString()).isEqualTo("text2");
     }
 
     @Test
     public void testParceledRequest_validViewTranslationRequests() {
+        final ArrayList<ViewTranslationRequest> viewRequests = new ArrayList<>();
+        viewRequests.add(mViewRequest);
+        viewRequests.add(new ViewTranslationRequest.Builder(new AutofillId(42))
+                .setValue("id2", TranslationRequestValue.forText("test"))
+                .build());
         final TranslationRequest request = new TranslationRequest.Builder()
-                .addViewTranslationRequest(mRequest)
-                .addViewTranslationRequest(new ViewTranslationRequest.Builder(new AutofillId(42))
-                        .setValue("id2", TranslationRequestValue.forText("test"))
-                        .build())
+                .setViewTranslationRequests(viewRequests)
                 .build();
 
         final Parcel parcel = Parcel.obtain();
@@ -208,13 +195,13 @@
         assertThat(request1.getAutofillId()).isEqualTo(new AutofillId(17));
         assertThat(request1.getKeys().size()).isEqualTo(1);
         assertThat(request1.getKeys()).containsExactly("sample id");
-        assertThat(request1.getValue("sample id").getText()).isEqualTo("sample text");
+        assertThat(request1.getValue("sample id").getText().toString()).isEqualTo("sample text");
 
         final ViewTranslationRequest request2 =
                 parceledRequest.getViewTranslationRequests().get(1);
         assertThat(request2.getAutofillId()).isEqualTo(new AutofillId(42));
         assertThat(request2.getKeys().size()).isEqualTo(1);
         assertThat(request2.getKeys()).containsExactly("id2");
-        assertThat(request2.getValue("id2").getText()).isEqualTo("test");
+        assertThat(request2.getValue("id2").getText().toString()).isEqualTo("test");
     }
 }
\ No newline at end of file
diff --git a/tests/translation/src/android/translation/cts/unittests/TranslationValueTest.java b/tests/translation/src/android/translation/cts/unittests/TranslationValueTest.java
index 45512bb..c07ec0d 100644
--- a/tests/translation/src/android/translation/cts/unittests/TranslationValueTest.java
+++ b/tests/translation/src/android/translation/cts/unittests/TranslationValueTest.java
@@ -20,8 +20,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.testng.Assert.assertThrows;
-
 import android.os.Bundle;
 import android.view.translation.TranslationRequestValue;
 import android.view.translation.TranslationResponseValue;
@@ -93,6 +91,40 @@
     }
 
     @Test
+    public void testTranslationResponseValue_extrasEqualityWhenSameInstance() {
+        final Bundle extras = new Bundle();
+        final TranslationResponseValue extras1 =
+                new TranslationResponseValue.Builder(STATUS_SUCCESS).setExtras(extras).build();
+        final TranslationResponseValue extras2 =
+                new TranslationResponseValue.Builder(STATUS_SUCCESS).setExtras(extras).build();
+
+        assertThat(extras1).isEqualTo(extras2);
+    }
+
+    @Test
+    public void testTranslationResponseValue_extrasEqualityWhenEmpty() {
+        final TranslationResponseValue defaultValue =
+                new TranslationResponseValue.Builder(STATUS_SUCCESS).build();
+        final Bundle extras = new Bundle();
+        final TranslationResponseValue valueWithEmptyExtras =
+                new TranslationResponseValue.Builder(STATUS_SUCCESS).setExtras(extras).build();
+
+        assertThat(defaultValue).isEqualTo(valueWithEmptyExtras);
+    }
+
+    @Test
+    public void testTranslationResponseValue_extrasEqualityWhenUnequal() {
+        final TranslationResponseValue extras1 =
+                new TranslationResponseValue.Builder(STATUS_SUCCESS).build();
+        final Bundle extras = new Bundle();
+        extras.putString("k", "v");
+        final TranslationResponseValue extras2 =
+                new TranslationResponseValue.Builder(STATUS_SUCCESS).setExtras(extras).build();
+
+        assertThat(extras1).isNotEqualTo(extras2);
+    }
+
+    @Test
     public void testTranslationResponseValue_validTransliteration() {
         final TranslationResponseValue value = new TranslationResponseValue.Builder(STATUS_SUCCESS)
                 .setTransliteration("pronunciation")
diff --git a/tests/translation/src/android/translation/cts/unittests/UiTranslationSpecTest.java b/tests/translation/src/android/translation/cts/unittests/UiTranslationSpecTest.java
new file mode 100644
index 0000000..782cdb0
--- /dev/null
+++ b/tests/translation/src/android/translation/cts/unittests/UiTranslationSpecTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.translation.cts.unittests;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+import android.view.translation.UiTranslationSpec;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link UiTranslationSpec} related APIs.
+ */
+@RunWith(AndroidJUnit4.class)
+public class UiTranslationSpecTest {
+
+    @Test
+    public void testUiTranslationSpec_defaultBuilder() {
+        final UiTranslationSpec uiSpec = new UiTranslationSpec.Builder().build();
+
+        assertThat(uiSpec.shouldPadContentForCompat()).isFalse();
+    }
+
+    @Test
+    public void testUiTranslationSpec_builder_setShouldPadContentForCompat() {
+        final UiTranslationSpec uiSpec = new UiTranslationSpec.Builder()
+                .setShouldPadContentForCompat(true).build();
+
+        assertThat(uiSpec.shouldPadContentForCompat()).isTrue();
+    }
+
+    @Test
+    public void testParceledUiTranslationSpec() {
+        final UiTranslationSpec uiSpec = new UiTranslationSpec.Builder()
+                .setShouldPadContentForCompat(true).build();
+
+        final Parcel parcel = Parcel.obtain();
+        uiSpec.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        final UiTranslationSpec parceledSpec = UiTranslationSpec.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+
+        assertThat(parceledSpec).isEqualTo(uiSpec);
+    }
+}
diff --git a/tests/translation/src/android/translation/cts/unittests/ViewTranslationResponseTest.java b/tests/translation/src/android/translation/cts/unittests/ViewTranslationResponseTest.java
index c3a9516..5e8015a 100644
--- a/tests/translation/src/android/translation/cts/unittests/ViewTranslationResponseTest.java
+++ b/tests/translation/src/android/translation/cts/unittests/ViewTranslationResponseTest.java
@@ -78,7 +78,7 @@
 
         assertThat(request.getAutofillId()).isEqualTo(new AutofillId(17));
         assertThat(request.getKeys().size()).isEqualTo(1);
-        assertThat(request.getValue("sample id").getText()).isEqualTo("sample text");
+        assertThat(request.getValue("sample id").getText().toString()).isEqualTo("sample text");
 
         assertThrows(IllegalArgumentException.class, () -> request.getValue("something"));
         assertThrows(NullPointerException.class, () -> request.getValue(null));
@@ -100,8 +100,8 @@
 
         assertThat(request.getAutofillId()).isEqualTo(new AutofillId(17));
         assertThat(request.getKeys().size()).isEqualTo(3);
-        assertThat(request.getValue("sample id").getText()).isEqualTo("sample text");
-        assertThat(request.getValue("id2").getText()).isEqualTo("text2");
+        assertThat(request.getValue("sample id").getText().toString()).isEqualTo("sample text");
+        assertThat(request.getValue("id2").getText().toString()).isEqualTo("text2");
         assertThat(request.getValue("id3").getStatusCode())
                 .isEqualTo(TranslationResponseValue.STATUS_ERROR);
     }