Merge "ITS: Enable hidden physical camera ITS test" into qt-dev
diff --git a/apps/CameraITS/tests/scene1/test_raw_exposure.py b/apps/CameraITS/tests/scene1/test_raw_exposure.py
index fa3c9ff..437b63f 100644
--- a/apps/CameraITS/tests/scene1/test_raw_exposure.py
+++ b/apps/CameraITS/tests/scene1/test_raw_exposure.py
@@ -26,8 +26,9 @@
 NUM_ISO_STEPS = 5
 SATURATION_TOL = 0.01
 BLK_LVL_TOL = 0.1
-# Test 3 steps per 2x exposure
-EXP_MULT = pow(2, 1.0/3)
+EXP_MULT_SHORT = pow(2, 1.0/3)  # Test 3 steps per 2x exposure
+EXP_MULT_LONG = pow(10, 1.0/3)  # Test 3 steps per 10x exposure
+EXP_LONG = 1E6  # 1ms
 INCREASING_THR = 0.99
 # slice captures into burst of SLICE_LEN requests
 SLICE_LEN = 10
@@ -67,7 +68,10 @@
         mult = 1.0
         while exp_min*mult < exp_max:
             e_test.append(int(exp_min*mult))
-            mult *= EXP_MULT
+            if exp_min*mult < EXP_LONG:
+                mult *= EXP_MULT_SHORT
+            else:
+                mult *= EXP_MULT_LONG
         if e_test[-1] < exp_max * INCREASING_THR:
             e_test.append(int(exp_max))
         e_test_ms = [e / 1000000.0 for e in e_test]
@@ -78,22 +82,21 @@
             reqs = [its.objects.manual_capture_request(s, e, 0) for e in e_test]
             # Capture raw in debug mode, rawStats otherwise
             caps = []
-            for i in range(len(reqs) / SLICE_LEN):
+            slice_len = SLICE_LEN
+            # Eliminate cap burst of 1: returns [[]], not [{}, ...]
+            while len(reqs) % slice_len == 1:
+                slice_len -= 1
+            # Break caps into smaller bursts
+            for i in range(len(reqs) / slice_len):
                 if debug:
-                    caps += cam.do_capture(reqs[i*SLICE_LEN:(i+1)*SLICE_LEN], cam.CAP_RAW)
+                    caps += cam.do_capture(reqs[i*slice_len:(i+1)*slice_len], cam.CAP_RAW)
                 else:
-                    caps += cam.do_capture(reqs[i*SLICE_LEN:(i+1)*SLICE_LEN], raw_stat_fmt)
-            last_n = len(reqs) % SLICE_LEN
-            if last_n == 1:
-                if debug:
-                    caps += [cam.do_capture(reqs[-last_n:], cam.CAP_RAW)]
-                else:
-                    caps += [cam.do_capture(reqs[-last_n:], raw_stat_fmt)]
-            elif last_n > 0:
-                if debug:
-                    caps += cam.do_capture(reqs[-last_n:], cam.CAP_RAW)
-                else:
-                    caps += cam.do_capture(reqs[-last_n:], raw_stat_fmt)
+                    caps += cam.do_capture(reqs[i*slice_len:(i+1)*slice_len], raw_stat_fmt)
+            last_n = len(reqs) % slice_len
+            if debug:
+                caps += cam.do_capture(reqs[-last_n:], cam.CAP_RAW)
+            else:
+                caps += cam.do_capture(reqs[-last_n:], raw_stat_fmt)
 
             # Measure the mean of each channel.
             # Each shot should be brighter (except underexposed/overexposed scene)
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
index 043a280..a679c41 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
@@ -49,7 +49,7 @@
             "<ProfileList Version=\"1.0.0\">" +
             "<PeripheralProfile ProfileName=\"AudioBox USB 96\" ProfileDescription=\"PreSonus AudioBox USB 96\" ProductName=\"USB-Audio - AudioBox USB 96\">" +
                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000,88200,96000\"/>" +
-                "<InputDevInfo ChanCounts=\"1, 2\" ChanPosMasks=\"12, 16\" ChanIndexMasks=\"1,3\" Encodings=\"4\" SampleRates=\"44100,48000,88200,96000\"/>" +
+                "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"4\" SampleRates=\"44100,48000,88200,96000\"/>" +
             "</PeripheralProfile>" +
             "<PeripheralProfile ProfileName=\"AudioBox 44VSL\" ProfileDescription=\"Presonus AudioBox 44VSL\" ProductName=\"USB-Audio - AudioBox 44 VSL\">" +
                 "<OutputDevInfo ChanCounts=\"2,3,4\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15\" Encodings=\"4\" SampleRates=\"44100,48000,88200,96000\" />" +
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
index 3421f65..07c598f 100755
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
@@ -110,29 +110,34 @@
     private static final int MENU_ID_PROGRESS = Menu.FIRST + 1;
 
     private class CameraCombination {
-        private final int cameraIndex;
-        private final int resolutionIndex;
-        private final int formatIndex;
+        private final int mCameraIndex;
+        private final int mResolutionIndex;
+        private final int mFormatIndex;
+        private final int mResolutionWidth;
+        private final int mResolutionHeight;
+        private final String mFormatName;
 
-        private CameraCombination(int cameraIndex, int resolutionIndex, int formatIndex) {
-            this.cameraIndex = cameraIndex;
-            this.resolutionIndex = resolutionIndex;
-            this.formatIndex = formatIndex;
+        private CameraCombination(int cameraIndex, int resolutionIndex, int formatIndex,
+            int resolutionWidth, int resolutionHeight, String formatName) {
+            this.mCameraIndex = cameraIndex;
+            this.mResolutionIndex = resolutionIndex;
+            this.mFormatIndex = formatIndex;
+            this.mResolutionWidth = resolutionWidth;
+            this.mResolutionHeight = resolutionHeight;
+            this.mFormatName = formatName;
         }
 
         @Override
         public String toString() {
-            return String.format("Camera %d, %dx%d, %s", cameraIndex,
-                mPreviewSizes.get(resolutionIndex).width,
-                mPreviewSizes.get(resolutionIndex).height,
-                mPreviewFormatNames.get(mPreviewFormats.get(formatIndex)));
+            return String.format("Camera %d, %dx%d, %s",
+                mCameraIndex, mResolutionWidth, mResolutionHeight, mFormatName);
         }
     }
 
     private static final Comparator<CameraCombination> COMPARATOR =
-        Comparator.<CameraCombination, Integer>comparing(c -> c.cameraIndex)
-            .thenComparing(c -> c.resolutionIndex)
-            .thenComparing(c -> c.formatIndex);
+        Comparator.<CameraCombination, Integer>comparing(c -> c.mCameraIndex)
+            .thenComparing(c -> c.mResolutionIndex)
+            .thenComparing(c -> c.mFormatIndex);
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -211,7 +216,7 @@
      */
     private void setUntestedCombination() {
         Optional<CameraCombination> combination = mUntestedCombinations.stream().filter(
-            c -> c.cameraIndex == mCurrentCameraId).findFirst();
+            c -> c.mCameraIndex == mCurrentCameraId).findFirst();
         if (!combination.isPresent()) {
             Toast.makeText(this, "All Camera " + mCurrentCameraId + " tests are done.",
                 Toast.LENGTH_SHORT).show();
@@ -219,13 +224,13 @@
         }
 
         // There is untested combination for the current camera, set the next untested combination.
-        int mResolutionIndex = combination.get().resolutionIndex;
-        int mFormatIndex = combination.get().formatIndex;
+        int mNextResolutionIndex = combination.get().mResolutionIndex;
+        int mNextFormatIndex = combination.get().mFormatIndex;
 
-        mNextPreviewSize = mPreviewSizes.get(mResolutionIndex);
-        mResolutionSpinner.setSelection(mResolutionIndex);
-        mNextPreviewFormat = mPreviewFormats.get(mFormatIndex);
-        mFormatSpinner.setSelection(mFormatIndex);
+        mNextPreviewSize = mPreviewSizes.get(mNextResolutionIndex);
+        mResolutionSpinner.setSelection(mNextResolutionIndex);
+        mNextPreviewFormat = mPreviewFormats.get(mNextFormatIndex);
+        mFormatSpinner.setSelection(mNextFormatIndex);
     }
 
     @Override
@@ -423,7 +428,10 @@
         for (int resolutionIndex = 0; resolutionIndex < mPreviewSizes.size(); resolutionIndex++) {
             for (int formatIndex = 0; formatIndex < mPreviewFormats.size(); formatIndex++) {
                 CameraCombination combination = new CameraCombination(
-                    id, resolutionIndex, formatIndex);
+                    id, resolutionIndex, formatIndex,
+                    mPreviewSizes.get(resolutionIndex).width,
+                    mPreviewSizes.get(resolutionIndex).height,
+                    mPreviewFormatNames.get(mPreviewFormats.get(formatIndex)));
 
                 if (!mTestedCombinations.contains(combination)) {
                     mUntestedCombinations.add(combination);
@@ -628,7 +636,11 @@
                     CameraCombination combination = new CameraCombination(
                         mCurrentCameraId,
                         mResolutionSpinner.getSelectedItemPosition(),
-                        mFormatSpinner.getSelectedItemPosition());
+                        mFormatSpinner.getSelectedItemPosition(),
+                        mPreviewSizes.get(mResolutionSpinner.getSelectedItemPosition()).width,
+                        mPreviewSizes.get(mResolutionSpinner.getSelectedItemPosition()).height,
+                        mPreviewFormatNames.get(
+                            mPreviewFormats.get(mFormatSpinner.getSelectedItemPosition())));
 
                     mUntestedCombinations.remove(combination);
                     mTestedCombinations.add(combination);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index 911e08a..93bb6a5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -186,17 +186,20 @@
         }
 
         // DISALLOW_AMBIENT_DISPLAY.
-        adapter.add(createInteractiveTestItem(this, DISALLOW_AMBIENT_DISPLAY_ID,
-                R.string.device_owner_disallow_ambient_display,
-                R.string.device_owner_disallow_ambient_display_info,
-                new ButtonInfo[] {
-                        new ButtonInfo(
-                                R.string.device_owner_user_restriction_set,
-                                CommandReceiverActivity.createSetUserRestrictionIntent(
-                                        UserManager.DISALLOW_AMBIENT_DISPLAY, true)),
-                        new ButtonInfo(
-                                R.string.device_owner_settings_go,
-                                new Intent(Settings.ACTION_DISPLAY_SETTINGS))}));
+        // TODO: After the ambient display feature flag is added in PackageManager (b/135591614),
+        // uncomment this test and run it only when ambient display is supported by the device.
+
+        // adapter.add(createInteractiveTestItem(this, DISALLOW_AMBIENT_DISPLAY_ID,
+        //         R.string.device_owner_disallow_ambient_display,
+        //         R.string.device_owner_disallow_ambient_display_info,
+        //         new ButtonInfo[] {
+        //                 new ButtonInfo(
+        //                         R.string.device_owner_user_restriction_set,
+        //                         CommandReceiverActivity.createSetUserRestrictionIntent(
+        //                                 UserManager.DISALLOW_AMBIENT_DISPLAY, true)),
+        //                 new ButtonInfo(
+        //                         R.string.device_owner_settings_go,
+        //                         new Intent(Settings.ACTION_DISPLAY_SETTINGS))}));
 
         // DISALLOW_CONFIG_VPN
         adapter.add(createInteractiveTestItem(this, DISALLOW_CONFIG_VPN_ID,
diff --git a/hostsidetests/appbinding/hostside/src/com/android/cts/appbinding/AppBindingHostTest.java b/hostsidetests/appbinding/hostside/src/com/android/cts/appbinding/AppBindingHostTest.java
old mode 100644
new mode 100755
index 327c9ab..87d90a3
--- a/hostsidetests/appbinding/hostside/src/com/android/cts/appbinding/AppBindingHostTest.java
+++ b/hostsidetests/appbinding/hostside/src/com/android/cts/appbinding/AppBindingHostTest.java
@@ -489,6 +489,11 @@
             return;
         }
 
+        if (!getDevice().isMultiUserSupported()) {
+            // device do not support multi-user.
+            return;
+        }
+
         installAndCheckBound(APK_1, PACKAGE_A, SERVICE_1, USER_SYSTEM);
 
         final int userId = getDevice().createUser("test-user");
diff --git a/hostsidetests/incident/src/com/android/server/cts/JobSchedulerIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/JobSchedulerIncidentTest.java
index 0430e58..9c8363c 100644
--- a/hostsidetests/incident/src/com/android/server/cts/JobSchedulerIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/JobSchedulerIncidentTest.java
@@ -185,7 +185,8 @@
         assertTrue(0 <= ji.getTriggerContentUpdateDelayMs());
         assertTrue(0 <= ji.getTriggerContentMaxDelayMs());
         testNetworkRequestProto(ji.getRequiredNetwork());
-        assertTrue(0 <= ji.getTotalNetworkBytes());
+        // JobInfo.NETWORK_BYTES_UNKNOWN (= -1) is a valid value.
+        assertTrue(-1 <= ji.getTotalNetworkBytes());
         assertTrue(0 <= ji.getMinLatencyMs());
         assertTrue(0 <= ji.getMaxExecutionDelayMs());
         JobStatusDumpProto.JobInfo.Backoff bp = ji.getBackoffPolicy();
diff --git a/hostsidetests/securitybulletin/AndroidTest.xml b/hostsidetests/securitybulletin/AndroidTest.xml
index b8d5799..38d8eaf 100644
--- a/hostsidetests/securitybulletin/AndroidTest.xml
+++ b/hostsidetests/securitybulletin/AndroidTest.xml
@@ -69,6 +69,7 @@
         <!--__________________-->
         <!-- Bulletin 2016-10 -->
         <!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+        <option name="push" value="CVE-2016-3913->/data/local/tmp/CVE-2016-3913" />
 
         <!--__________________-->
         <!-- Bulletin 2016-11 -->
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/Android.mk
new file mode 100644
index 0000000..e21a08e
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-3913
+LOCAL_SRC_FILES := poc.cpp
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libutils \
+    libmedia \
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CPPFLAGS += -Wall -Werror -Wno-unused-parameter
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/poc.cpp
new file mode 100644
index 0000000..5d45862
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-3913/poc.cpp
@@ -0,0 +1,167 @@
+/**
+ * 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.
+ */
+
+#include <binder/IServiceManager.h>
+#include <media/IMediaHTTPService.h>
+#include <media/IMediaPlayer.h>
+#include <media/IMediaPlayerService.h>
+#include <media/VolumeShaper.h>
+#include <media/mediaplayer.h>
+
+using namespace android;
+using namespace android::media;
+
+class MyMediaPlayer : public BnInterface<IMediaPlayer> {
+ public:
+  status_t onTransact(uint32_t code, const Parcel &data, Parcel *reply,
+                      uint32_t flags = 0) {
+    return OK;
+  }
+  void disconnect() {}
+
+  status_t setDataSource(const sp<IMediaHTTPService> &httpService,
+                         const char *url,
+                         const KeyedVector<String8, String8> *headers) {
+    return OK;
+  }
+
+  status_t setDataSource(int fd, int64_t offset, int64_t length) { return OK; }
+
+  status_t setDataSource(const sp<IStreamSource> &source) { return OK; }
+
+  status_t setDataSource(const sp<IDataSource> &source) { return OK; }
+
+  status_t setVideoSurfaceTexture(
+      const sp<IGraphicBufferProducer> &bufferProducer) {
+    return OK;
+  }
+
+  status_t getBufferingSettings(BufferingSettings *buffering) {
+    return OK;
+  }
+
+  status_t setBufferingSettings(const BufferingSettings &buffering) {
+    return OK;
+  }
+
+  status_t prepareAsync() { return OK; }
+
+  status_t start() { return OK; }
+
+  status_t stop() { return OK; }
+
+  status_t pause() { return OK; }
+
+  status_t isPlaying(bool *state) { return OK; }
+
+  status_t setPlaybackSettings(const AudioPlaybackRate &rate) { return OK; }
+
+  status_t getPlaybackSettings(AudioPlaybackRate *rate) { return OK; }
+
+  status_t setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
+    return OK;
+  }
+
+  status_t getSyncSettings(AVSyncSettings *sync, float *videoFps) { return OK; }
+
+  status_t seekTo(int msec, MediaPlayerSeekMode mode) { return OK; }
+
+  status_t getCurrentPosition(int *msec) { return OK; }
+
+  status_t getDuration(int *msec) { return OK; }
+
+  status_t notifyAt(int64_t mediaTimeUs) { return OK; }
+
+  status_t reset() { return OK; }
+
+  status_t setAudioStreamType(audio_stream_type_t stream) { return OK; }
+
+  status_t setLooping(int loop) { return OK; }
+
+  status_t setVolume(float leftVolume, float rightVolume) { return OK; }
+
+  status_t setAuxEffectSendLevel(float level) { return OK; }
+
+  status_t attachAuxEffect(int effectId) { return OK; }
+
+  status_t setParameter(int key, const Parcel &request) { return OK; }
+
+  status_t getParameter(int key, Parcel *reply) { return OK; }
+
+  status_t setRetransmitEndpoint(const struct sockaddr_in *endpoint) {
+    return OK;
+  }
+
+  status_t getRetransmitEndpoint(struct sockaddr_in *endpoint) { return OK; }
+
+  status_t setNextPlayer(const sp<IMediaPlayer> &player) { return OK; }
+
+  VolumeShaper::Status applyVolumeShaper(
+      const sp<VolumeShaper::Configuration> &configuration,
+      const sp<VolumeShaper::Operation> &operation) {
+    return (VolumeShaper::Status)OK;
+  }
+  sp<VolumeShaper::State> getVolumeShaperState(int id) { return NULL; }
+
+  status_t prepareDrm(const uint8_t uuid[16],
+                      const Vector<uint8_t> &drmSessionId) {
+    return OK;
+  }
+
+  status_t releaseDrm() { return OK; }
+
+  status_t invoke(const Parcel &request, Parcel *reply) { return OK; }
+
+  status_t setMetadataFilter(const Parcel &request) { return OK; }
+
+  status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply) {
+    return OK;
+  }
+
+  status_t setOutputDevice(audio_port_handle_t deviceId) { return OK; }
+
+  status_t getRoutedDeviceId(audio_port_handle_t *deviceId) { return OK; }
+
+  status_t enableAudioDeviceCallback(bool enabled) { return OK; }
+};
+
+int main() {
+  sp<IBinder> binder =
+      defaultServiceManager()->getService(String16("media.player"));
+  sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+  sp<IMediaPlayer> player = service->create(
+      new MediaPlayer(), (audio_session_t)AUDIO_SESSION_ALLOCATE);
+
+  if (player == NULL) {
+    return EXIT_FAILURE;
+  }
+
+  sp<IMediaPlayer> localPlayer = new MyMediaPlayer();
+  if (localPlayer == NULL) {
+    return EXIT_FAILURE;
+  }
+
+  // set the data source to initialize mPlayer
+  player->setDataSource(NULL, "file:///test", NULL);
+
+  // Set the next player to a local instance of BnMediaPlayer.
+  // The remote side will construct a BpMediaPlayer object, and then
+  // unsafely cast it to a MediaPlayerService::Client.
+  // This will an out-of-bounds access on class members.
+  player->setNextPlayer(localPlayer);
+
+  return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
new file mode 100644
index 0000000..98994e1
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/Poc16_10.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc16_10 extends SecurityTestCase {
+
+    /**
+     *  b/30204103
+     */
+    @SecurityTest(minPatchLevel = "2016-10")
+    public void testPocCVE_2016_3913() throws Exception {
+        AdbUtils.runCommandLine("logcat -c",getDevice());
+        AdbUtils.runPoc("CVE-2016-3913", getDevice(), 60);
+        String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+        assertNotMatchesMultiLine("Fatal signal 11.*?/system/bin/mediaserver",logcat);
+    }
+}
diff --git a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml b/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
index 6398bd9..6f3a6e9 100644
--- a/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
+++ b/hostsidetests/statsd/apps/statsdapp/AndroidManifest.xml
@@ -56,13 +56,6 @@
             </intent-filter>
         </activity>
 
-        <activity
-            android:name=".LmkActivity"
-            android:label="Lmk Test Activity"
-            android:launchMode="singleInstance"
-            android:process=":LmkProcess"
-            android:exported="true"
-            />
         <activity android:name=".DaveyActivity" android:exported="true" />
         <activity android:name=".HiddenApiUsedActivity" android:exported="true" />
         <activity
diff --git a/hostsidetests/statsd/apps/statsdapp/jni/alloc_stress_activity.cpp b/hostsidetests/statsd/apps/statsdapp/jni/alloc_stress_activity.cpp
index 463efe6..d207479 100644
--- a/hostsidetests/statsd/apps/statsdapp/jni/alloc_stress_activity.cpp
+++ b/hostsidetests/statsd/apps/statsdapp/jni/alloc_stress_activity.cpp
@@ -33,7 +33,7 @@
 size_t s = 4 * (1 << 20); // 4 MB
 extern "C"
 JNIEXPORT void JNICALL
-Java_com_android_server_cts_device_statsd_LmkActivity_cmain(JNIEnv* , jobject /* this */)
+Java_com_android_server_cts_device_statsd_StatsdCtsBackgroundService_cmain(JNIEnv* , jobject /* this */)
 {
     long long allocCount = 0;
     while (1) {
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/LmkActivity.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/LmkActivity.java
deleted file mode 100644
index c3600a1..0000000
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/LmkActivity.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.cts.device.statsd;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class LmkActivity extends Activity {
-
-    static {
-        System.loadLibrary("lmkhelper");
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        new Thread(new Runnable() {
-            public void run() {
-                cmain();
-            }
-        }).start();
-
-    }
-
-    /**
-     *  Keep allocating memory until the process is killed by LMKD.
-     **/
-    public native void cmain();
-
-}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsBackgroundService.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsBackgroundService.java
index fc1c472..ad018f9 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsBackgroundService.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/StatsdCtsBackgroundService.java
@@ -29,9 +29,14 @@
     public static final String KEY_ACTION = "action";
     public static final String ACTION_BACKGROUND_SLEEP = "action.background_sleep";
     public static final String ACTION_END_IMMEDIATELY = "action.end_immediately";
+    public static final String ACTION_LMK = "action.lmk";
 
     public static final int SLEEP_OF_ACTION_BACKGROUND_SLEEP = 2_000;
 
+    static {
+        System.loadLibrary("lmkhelper");
+    }
+
     public StatsdCtsBackgroundService() {
         super(StatsdCtsBackgroundService.class.getName());
     }
@@ -47,8 +52,16 @@
                 break;
             case ACTION_END_IMMEDIATELY:
                 break;
+            case ACTION_LMK:
+                new Thread(this::cmain).start();
+                break;
             default:
                 Log.e(TAG, "Intent had invalid action");
         }
     }
+
+    /**
+     *  Keep allocating memory until the process is killed by LMKD.
+     **/
+    public native void cmain();
 }
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
index d09175e..ec6291d 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/DeviceAtomTestCase.java
@@ -35,9 +35,15 @@
             "com.android.server.cts.device.statsd";
     public static final String DEVICE_SIDE_TEST_FOREGROUND_SERVICE_NAME =
             "com.android.server.cts.device.statsd.StatsdCtsForegroundService";
+    private static final String DEVICE_SIDE_BG_SERVICE_COMPONENT =
+            "com.android.server.cts.device.statsd/.StatsdCtsBackgroundService";
     public static final long DEVICE_SIDE_TEST_PKG_HASH =
             Long.parseUnsignedLong("15694052924544098582");
 
+    // Constants from device side tests (not directly accessible here).
+    public static final String KEY_ACTION = "action";
+    public static final String ACTION_LMK = "action.lmk";
+
     public static final String CONFIG_NAME = "cts_config";
 
     @Override
@@ -189,6 +195,19 @@
                 "cmd deviceidle tempwhitelist %s", DEVICE_SIDE_TEST_PACKAGE));
     }
 
+    /**
+     * Runs a (background) service to perform the given action.
+     * @param actionValue the action code constants indicating the desired action to perform.
+     */
+    protected void executeBackgroundService(String actionValue) throws Exception {
+        allowBackgroundServices();
+        getDevice().executeShellCommand(String.format(
+                "am startservice -n '%s' -e %s %s",
+                DEVICE_SIDE_BG_SERVICE_COMPONENT,
+                KEY_ACTION, actionValue));
+    }
+
+
     /** Make the test app standby-active so it can run syncs and jobs immediately. */
     protected void allowImmediateSyncs() throws Exception {
         getDevice().executeShellCommand("am set-standby-bucket "
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateTestCase.java
index cd65a37..2fa4233 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateTestCase.java
@@ -35,15 +35,12 @@
 
   private static final String TAG = "Statsd.ProcStateTestCase";
 
-  private static final String DEVICE_SIDE_BG_SERVICE_COMPONENT
-          = "com.android.server.cts.device.statsd/.StatsdCtsBackgroundService";
   private static final String DEVICE_SIDE_FG_ACTIVITY_COMPONENT
           = "com.android.server.cts.device.statsd/.StatsdCtsForegroundActivity";
   private static final String DEVICE_SIDE_FG_SERVICE_COMPONENT
           = "com.android.server.cts.device.statsd/.StatsdCtsForegroundService";
 
   // Constants from the device-side tests (not directly accessible here).
-  public static final String KEY_ACTION = "action";
   public static final String ACTION_END_IMMEDIATELY = "action.end_immediately";
   public static final String ACTION_BACKGROUND_SLEEP = "action.background_sleep";
   public static final String ACTION_SLEEP_WHILE_TOP = "action.sleep_top";
@@ -56,17 +53,6 @@
   public static final int SLEEP_OF_ACTION_BACKGROUND_SLEEP = 2_000;
   public static final int SLEEP_OF_FOREGROUND_SERVICE = 2_000;
 
-  /**
-   * Runs a (background) service to perform the given action.
-   * @param actionValue the action code constants indicating the desired action to perform.
-   */
-  protected void executeBackgroundService(String actionValue) throws Exception {
-    allowBackgroundServices();
-    getDevice().executeShellCommand(String.format(
-            "am startservice -n '%s' -e %s %s",
-            DEVICE_SIDE_BG_SERVICE_COMPONENT,
-            KEY_ACTION, actionValue));
-  }
 
   /**
    * Runs an activity (in the foreground) to perform the given action.
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index 80d36a9..918f794 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -98,7 +98,8 @@
 
         Thread.sleep(WAIT_TIME_SHORT);
 
-        runActivity("LmkActivity", null, null, 5_000);
+        executeBackgroundService(ACTION_LMK);
+        Thread.sleep(5_000);
 
         // Sorted list of events in order in which they occurred.
         List<EventMetricData> data = getEventMetricDataList();
@@ -107,8 +108,8 @@
         assertTrue(data.get(0).getAtom().hasLmkKillOccurred());
         LmkKillOccurred atom = data.get(0).getAtom().getLmkKillOccurred();
         assertEquals(getUid(), atom.getUid());
-        assertEquals(DEVICE_SIDE_TEST_PACKAGE + ":LmkProcess", atom.getProcessName());
-        assertEquals(0, atom.getOomAdjScore());
+        assertEquals(DEVICE_SIDE_TEST_PACKAGE, atom.getProcessName());
+        assertTrue(500 <= atom.getOomAdjScore());
     }
 
     public void testAppCrashOccurred() throws Exception {
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java
index bd94615..fc069b1 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java
@@ -46,34 +46,13 @@
     private final int metric3MatcherId = 3;
 
     private final int act1MatcherId = 10;
-    private final int act1TtlSecs = 40;
     private final int act1CancelMatcherId = -10;
 
     private final int act2MatcherId = 20;
-    private final int act2TtlSecs = 60;
     private final int act2CancelMatcherId = -20;
 
 
-    /**
-     * Metric 1:
-     *     Activation 1:
-     *         - Ttl: 40 seconds
-     *         - Type: IMMEDIATE
-     *     Activation 2:
-     *         - Ttl: 60 seconds
-     *         - Type: ON_BOOT
-     *
-     * Metric 2:
-     *     Activation 1:
-     *         - Ttl: 40 seconds
-     *         - Type: ON_BOOT
-     *     Activation 2:
-     *         - Ttl: 60 seconds
-     *         - Type: IMMEDIATE
-     *
-     * Metric 3: No activations; always active
-     **/
-    private StatsdConfig.Builder createConfig() {
+    private StatsdConfig.Builder createConfig(final int act1TtlSecs, final int act2TtlSecs) {
         AtomMatcher metric1Matcher =
                 MetricsUtils.simpleAtomMatcher(metric1MatcherId, metric1MatcherId);
         AtomMatcher metric2Matcher =
@@ -151,17 +130,34 @@
                 .addMetricActivation(metric2Activation);
     }
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        uploadConfig(createConfig());
-    }
-
+    /**
+     * Metric 1:
+     *     Activation 1:
+     *         - Ttl: 5 seconds
+     *         - Type: IMMEDIATE
+     *     Activation 2:
+     *         - Ttl: 8 seconds
+     *         - Type: ON_BOOT
+     *
+     * Metric 2:
+     *     Activation 1:
+     *         - Ttl: 5 seconds
+     *         - Type: ON_BOOT
+     *     Activation 2:
+     *         - Ttl: 8 seconds
+     *         - Type: IMMEDIATE
+     *
+     * Metric 3: No activations; always active
+     **/
     public void testCancellation() throws Exception {
         if (statsdDisabled()) {
             return;
         }
 
+        final int act1TtlSecs = 5;
+        final int act2TtlSecs = 8;
+        uploadConfig(createConfig(act1TtlSecs, act2TtlSecs));
+
         // Ignored, metric not active.
         doAppBreadcrumbReported(metric1MatcherId);
         Thread.sleep(10L);
@@ -235,14 +231,37 @@
         verifyMetrics(report, 4, 0, 1);
     }
 
+    /**
+     * Metric 1:
+     *     Activation 1:
+     *         - Ttl: 100 seconds
+     *         - Type: IMMEDIATE
+     *     Activation 2:
+     *         - Ttl: 200 seconds
+     *         - Type: ON_BOOT
+     *
+     * Metric 2:
+     *     Activation 1:
+     *         - Ttl: 100 seconds
+     *         - Type: ON_BOOT
+     *     Activation 2:
+     *         - Ttl: 200 seconds
+     *         - Type: IMMEDIATE
+     *
+     * Metric 3: No activations; always active
+     **/
     public void testRestart() throws Exception {
         if (statsdDisabled()) {
             return;
         }
 
+        final int act1TtlSecs = 100;
+        final int act2TtlSecs = 200;
+        uploadConfig(createConfig(act1TtlSecs, act2TtlSecs));
+
         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
         // Time remaining:
-        // Metric 1 Activation 1: 30 seconds
+        // Metric 1 Activation 1: 100 seconds
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds (will activate after boot)
         // Metric 2 Activation 2: 0 seconds
@@ -255,9 +274,9 @@
         logAllMetrics();
 
         // Time remaining:
-        // Metric 1 Activation 1: 30 seconds
+        // Metric 1 Activation 1: 100 seconds
         // Metric 1 Activation 2: 0 seconds
-        // Metric 2 Activation 1: 30 seconds
+        // Metric 2 Activation 1: 100 seconds
         // Metric 2 Activation 2: 0 seconds
         rebootDeviceAndWaitUntilReady();
 
@@ -271,7 +290,7 @@
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds
         // Metric 2 Activation 2: 0 seconds
-        Thread.sleep(30_000L);
+        Thread.sleep(act1TtlSecs * 1000L);
 
         // Metric 1 event ignored, Activation 1 expired.
         // Metric 2 event ignored, Activation 1 expired.
@@ -283,7 +302,7 @@
         // Metric 1 Activation 1: 0 seconds
         // Metric 1 Activation 2: 0 seconds (will activate after boot)
         // Metric 2 Activation 1: 0 seconds
-        // Metric 2 Activation 2: 50 seconds
+        // Metric 2 Activation 2: 200 seconds
         doAppBreadcrumbReported(act2MatcherId);
         Thread.sleep(10L);
 
@@ -294,10 +313,10 @@
 
         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
         // Time remaining:
-        // Metric 1 Activation 1: 30 seconds
+        // Metric 1 Activation 1: 100 seconds
         // Metric 1 Activation 2: 0 seconds (will activate after boot)
         // Metric 2 Activation 1: 0 seconds (will activate after boot)
-        // Metric 2 Activation 2: 50 seconds
+        // Metric 2 Activation 2: 200 seconds
         doAppBreadcrumbReported(act1MatcherId);
         Thread.sleep(10L);
 
@@ -307,17 +326,17 @@
         logAllMetrics();
 
         // Time remaining:
-        // Metric 1 Activation 1: 20 seconds
+        // Metric 1 Activation 1: 50 seconds
         // Metric 1 Activation 2: 0 seconds (will activate after boot)
         // Metric 2 Activation 1: 0 seconds (will activate after boot)
-        // Metric 2 Activation 2: 40 seconds
-        Thread.sleep(10_000L);
+        // Metric 2 Activation 2: 150 seconds
+        Thread.sleep(act1TtlSecs * 1000L / 2);
 
         // Time remaining:
-        // Metric 1 Activation 1: 20 seconds
-        // Metric 1 Activation 2: 50 seconds
-        // Metric 2 Activation 1: 30 seconds
-        // Metric 2 Activation 2: 40 seconds
+        // Metric 1 Activation 1: 50 seconds
+        // Metric 1 Activation 2: 200 seconds
+        // Metric 2 Activation 1: 100 seconds
+        // Metric 2 Activation 2: 150 seconds
         rebootDeviceAndWaitUntilReady();
 
         // Fourth logged event for Metric 1.
@@ -328,10 +347,10 @@
         // Expire Metric 1 Activation 1.
         // Time remaining:
         // Metric 1 Activation 1: 0 seconds
-        // Metric 1 Activation 2: 30 seconds
-        // Metric 2 Activation 1: 10 seconds
-        // Metric 2 Activation 2: 20 seconds
-        Thread.sleep(20_000L);
+        // Metric 1 Activation 2: 150 seconds
+        // Metric 2 Activation 1: 50 seconds
+        // Metric 2 Activation 2: 100 seconds
+        Thread.sleep(act1TtlSecs * 1000L / 2);
 
         // Fifth logged event for Metric 1.
         // Fifth logged event for Metric 2.
@@ -344,7 +363,7 @@
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds
         // Metric 2 Activation 2: 0 seconds
-        Thread.sleep(30_000L);
+        Thread.sleep(act2TtlSecs * 1000L);
 
         // Metric 1 event ignored.
         // Metric 2 event ignored.
@@ -367,14 +386,37 @@
         verifyMetrics(report, 2, 2, 3);
     }
 
+    /**
+     * Metric 1:
+     *     Activation 1:
+     *         - Ttl: 100 seconds
+     *         - Type: IMMEDIATE
+     *     Activation 2:
+     *         - Ttl: 200 seconds
+     *         - Type: ON_BOOT
+     *
+     * Metric 2:
+     *     Activation 1:
+     *         - Ttl: 100 seconds
+     *         - Type: ON_BOOT
+     *     Activation 2:
+     *         - Ttl: 200 seconds
+     *         - Type: IMMEDIATE
+     *
+     * Metric 3: No activations; always active
+     **/
     public void testMultipleActivations() throws Exception {
         if (statsdDisabled()) {
             return;
         }
 
+        final int act1TtlSecs = 100;
+        final int act2TtlSecs = 200;
+        uploadConfig(createConfig(act1TtlSecs, act2TtlSecs));
+
         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
         // Time remaining:
-        // Metric 1 Activation 1: 40 seconds
+        // Metric 1 Activation 1: 100 seconds
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds (will activate after boot)
         // Metric 2 Activation 2: 0 seconds
@@ -387,11 +429,11 @@
         logAllMetrics();
 
         // Time remaining:
-        // Metric 1 Activation 1: 30 seconds
+        // Metric 1 Activation 1: 50 seconds
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds (will activate after boot)
         // Metric 2 Activation 2: 0 seconds
-        Thread.sleep(10_000L);
+        Thread.sleep(act1TtlSecs * 1000L / 2);
 
         // Second logged event for Metric 1.
         // Metric 2 event ignored, will activate after boot.
@@ -400,7 +442,7 @@
 
         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
         // Time remaining:
-        // Metric 1 Activation 1: 30 seconds
+        // Metric 1 Activation 1: 100 seconds
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds (will activate after boot)
         // Metric 2 Activation 2: 0 seconds
@@ -413,9 +455,9 @@
         logAllMetrics();
 
         // Time remaining:
-        // Metric 1 Activation 1: 40 seconds
+        // Metric 1 Activation 1: 100 seconds
         // Metric 1 Activation 2: 0 seconds
-        // Metric 2 Activation 1: 40 seconds
+        // Metric 2 Activation 1: 100 seconds
         // Metric 2 Activation 2: 0 seconds
         rebootDeviceAndWaitUntilReady();
 
@@ -426,9 +468,9 @@
 
         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
         // Time remaining:
-        // Metric 1 Activation 1: 40 seconds
+        // Metric 1 Activation 1: 100 seconds
         // Metric 1 Activation 2: 0 seconds
-        // Metric 2 Activation 1: 40 seconds
+        // Metric 2 Activation 1: 100 seconds
         // Metric 2 Activation 2: 0 seconds
         doAppBreadcrumbReported(act1MatcherId);
         Thread.sleep(10L);
@@ -444,7 +486,7 @@
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds
         // Metric 2 Activation 2: 0 seconds
-        Thread.sleep(40_000);
+        Thread.sleep(act1TtlSecs * 1000L);
 
         // Metric 1 event ignored.
         // Metric 2 event ignored.
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
index aa7eafe..8051d83 100644
--- a/tests/app/Android.mk
+++ b/tests/app/Android.mk
@@ -32,6 +32,7 @@
     ctstestserver \
     mockito-target-minus-junit4 \
     androidx.test.rules \
+    androidx.test.ext.junit \
     platform-test-annotations \
     cts-wm-util \
     androidx.test.rules \
diff --git a/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
index a4808ed..a49f4a5 100644
--- a/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
@@ -75,8 +75,10 @@
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_400, 56);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_420, 64);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_440, 88);
+            expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_450, 88);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XXHIGH, 88);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_560, 112);
+            expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_600, 138);
             expectedMemorySizeForWatch.put(DisplayMetrics.DENSITY_XXXHIGH, 154);
         }
 
@@ -98,8 +100,10 @@
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_400, 96);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_420, 112);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_440, 128);
+            expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_450, 128);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXHIGH, 128);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_560, 192);
+            expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_600, 228);
             expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 256);
         }
 
@@ -121,8 +125,10 @@
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_400, 192);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_420, 228);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_440, 256);
+            expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_450, 256);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 256);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_560, 384);
+            expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_600, 448);
             expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 512);
         }
 
@@ -144,8 +150,10 @@
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_400, 288);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_420, 336);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_440, 384);
+            expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_450, 384);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 384);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_560, 576);
+            expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_600, 672);
             expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 768);
         }
 
diff --git a/tests/app/src/android/app/cts/DialogTest.java b/tests/app/src/android/app/cts/DialogTest.java
index 6cf088e..00837f6 100755
--- a/tests/app/src/android/app/cts/DialogTest.java
+++ b/tests/app/src/android/app/cts/DialogTest.java
@@ -57,11 +57,13 @@
 import android.view.WindowManager;
 import android.widget.LinearLayout;
 
-import androidx.test.InstrumentationRegistry;
+
 import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.FlakyTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
+
 
 import com.android.compatibility.common.util.PollingCheck;
 
@@ -474,7 +476,6 @@
         return event;
     }
 
-    @FlakyTest(bugId = 133760851)
     @Test
     public void testTouchEvent() {
         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
@@ -491,18 +492,14 @@
         assertNull(d.touchEvent);
         assertFalse(d.isOnTouchEventCalled);
 
-        // Send a touch event outside the dialog window.  Expect the event to be ignored
+        // Tap outside the dialog window.  Expect the event to be ignored
         // because closeOnTouchOutside is false.
         d.setCanceledOnTouchOutside(false);
 
-        long now = SystemClock.uptimeMillis();
-        MotionEvent touchMotionEvent = sendTouchEvent(now, MotionEvent.ACTION_DOWN, x, y);
+        long downTime = SystemClock.uptimeMillis();
 
-        new PollingCheck(TEST_TIMEOUT) {
-            protected boolean check() {
-                return !d.dispatchTouchEventResult;
-            }
-        }.run();
+        sendTouchEvent(downTime, MotionEvent.ACTION_DOWN, x, y).recycle();
+        MotionEvent touchMotionEvent = sendTouchEvent(downTime, MotionEvent.ACTION_UP, x, y);
 
         assertMotionEventEquals(touchMotionEvent, d.touchEvent);
         assertTrue(d.isOnTouchEventCalled);
@@ -510,8 +507,6 @@
         d.isOnTouchEventCalled = false;
         assertTrue(d.isShowing());
         touchMotionEvent.recycle();
-        // Send ACTION_UP to keep the event stream consistent
-        sendTouchEvent(now, MotionEvent.ACTION_UP, x, y).recycle();
 
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
             // Watch activities cover the entire screen, so there is no way to touch outside.
@@ -520,23 +515,17 @@
 
         // Send a touch event outside the dialog window. Expect the dialog to be dismissed
         // because closeOnTouchOutside is true.
-
         d.setCanceledOnTouchOutside(true);
-        now = SystemClock.uptimeMillis();
-        touchMotionEvent = sendTouchEvent(now, MotionEvent.ACTION_DOWN, x, y);
+        downTime = SystemClock.uptimeMillis();
 
-        new PollingCheck(TEST_TIMEOUT) {
-            protected boolean check() {
-                return d.dispatchTouchEventResult;
-            }
-        }.run();
+        sendTouchEvent(downTime, MotionEvent.ACTION_DOWN, x, y).recycle();
+        touchMotionEvent = sendTouchEvent(downTime, MotionEvent.ACTION_UP, x, y);
 
         assertMotionEventEquals(touchMotionEvent, d.touchEvent);
         assertTrue(d.isOnTouchEventCalled);
         assertMotionEventEquals(touchMotionEvent, d.onTouchEvent);
         assertFalse(d.isShowing());
         touchMotionEvent.recycle();
-        sendTouchEvent(now, MotionEvent.ACTION_UP, x, y).recycle();
     }
 
     @Test
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index e555a17..e408cb5 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -2014,6 +2014,7 @@
             } else {
                 Size effectivePlaneSize = getEffectivePlaneSizeForImage(src, i);
                 int srcRowByteCount = srcRowStride;
+                int dstRowByteCount = dstRowStride;
                 byte[] srcDataRow = new byte[srcRowByteCount];
 
                 if (srcPixStride == dstPixStride) {
@@ -2029,11 +2030,11 @@
                             }
                         }
                         srcBuffer.get(srcDataRow, /*offset*/0, srcRowByteCount);
-                        dstBuffer.put(srcDataRow, /*offset*/0, srcRowByteCount);
+                        dstBuffer.put(srcDataRow, /*offset*/0,
+                                Math.min(srcRowByteCount, dstRowByteCount));
                     }
                 } else {
                     // Row by row per pixel copy case
-                    int dstRowByteCount = dstRowStride;
                     byte[] dstDataRow = new byte[dstRowByteCount];
                     for (int row = 0; row < effectivePlaneSize.getHeight(); row++) {
                         if (row == effectivePlaneSize.getHeight() - 1) {
@@ -2152,12 +2153,12 @@
             rhsBuffer = rhsPlanes[i].getBuffer();
             lhsBuffer.rewind();
             rhsBuffer.rewind();
-            // Special case for YUV420_888 buffer with different chroma layout
-            if (lhsImg.getFormat() == ImageFormat.YUV_420_888 && (i != 0) &&
+            // Special case for YUV420_888 buffer with different layout
+            if (lhsImg.getFormat() == ImageFormat.YUV_420_888 &&
                     (lhsPlanes[i].getPixelStride() != rhsPlanes[i].getPixelStride() ||
                      lhsPlanes[i].getRowStride() != rhsPlanes[i].getRowStride())) {
-                int width = lhsImg.getWidth() / 2;
-                int height = lhsImg.getHeight() / 2;
+                int width = getEffectivePlaneSizeForImage(lhsImg, i).getWidth();
+                int height = getEffectivePlaneSizeForImage(lhsImg, i).getHeight();
                 int rowSizeL = lhsPlanes[i].getRowStride();
                 int rowSizeR = rhsPlanes[i].getRowStride();
                 byte[] lhsRow = new byte[rowSizeL];
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 7cab036..32a20ae 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
@@ -242,10 +242,6 @@
     protected void tapOnDisplayCenter(int displayId) {
         final Rect bounds = mAmWmState.getWmState().getDisplay(displayId).getDisplayRect();
         tapOnDisplay(bounds.centerX(), bounds.centerY(), displayId);
-        // This is needed after a tap in multi-display to ensure that the display focus has really
-        // changed, if needed. The call to syncInputTransaction will wait until focus change has
-        // propagated from WMS to native input before returning.
-        getInstrumentation().getUiAutomation().syncInputTransactions();
     }
 
     /**
diff --git a/tests/inputmethod/mockime/Android.mk b/tests/inputmethod/mockime/Android.mk
index d0b1eec..346e316 100644
--- a/tests/inputmethod/mockime/Android.mk
+++ b/tests/inputmethod/mockime/Android.mk
@@ -19,7 +19,7 @@
 LOCAL_MODULE := CtsMockInputMethodLib
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
 
 # TODO: ideally we should split MockIme source files into three categories
 #       1) common, 2) common + IME-only, and 3) common + client-only.
@@ -47,7 +47,7 @@
 
 LOCAL_PROGUARD_ENABLED := disabled
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
 LOCAL_MIN_SDK_VERSION := 19
 
 # tag this module as a cts test artifact
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
index 2608be2..8ad306b 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
@@ -18,6 +18,8 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
+import static org.junit.Assume.assumeFalse;
+
 import android.app.UiAutomation;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -38,6 +40,7 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputContentInfo;
 import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSystemProperty;
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
@@ -235,6 +238,11 @@
             @NonNull Context context,
             @NonNull UiAutomation uiAutomation,
             @Nullable ImeSettings.Builder imeSettings) throws Exception {
+        // Currently, MockIme doesn't fully support multi-client IME. Skip tests until it does.
+        // TODO: Re-enable when MockIme supports multi-client IME.
+        assumeFalse("MockIme session doesn't support Multi-Client IME, skip it",
+                InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED);
+
         final MockImeSession client = new MockImeSession(context, uiAutomation);
         client.initialize(imeSettings);
         return client;
diff --git a/tests/tests/assist/AndroidTest.xml b/tests/tests/assist/AndroidTest.xml
index 60cbbe6..3c08038 100644
--- a/tests/tests/assist/AndroidTest.xml
+++ b/tests/tests/assist/AndroidTest.xml
@@ -18,9 +18,15 @@
     <option name="config-descriptor:metadata" key="component" value="framework" />
     <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+
+    <!-- Force service to be installed as non-instant mode, always -->
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true"/>
+        <option name="force-install-mode" value="FULL"/>
+        <option name="test-file-name" value="CtsAssistService.apk" />
+    </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsAssistService.apk" />
         <option name="test-file-name" value="CtsAssistApp.apk" />
         <option name="test-file-name" value="CtsAssistTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/assist/OWNERS b/tests/tests/assist/OWNERS
index d924ccc..77c59df 100644
--- a/tests/tests/assist/OWNERS
+++ b/tests/tests/assist/OWNERS
@@ -1,2 +1 @@
 # Bug component: 351486
-felipeal@google.com
diff --git a/tests/tests/assist/common/Android.bp b/tests/tests/assist/common/Android.bp
new file mode 100644
index 0000000..35bfbb1
--- /dev/null
+++ b/tests/tests/assist/common/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2015 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.
+
+java_library {
+    name: "CtsAssistCommon",
+    srcs: ["src/**/*.java"],
+    sdk_version: "test_current",
+}
diff --git a/tests/tests/assist/common/Android.mk b/tests/tests/assist/common/Android.mk
deleted file mode 100644
index 88c90ee..0000000
--- a/tests/tests/assist/common/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := CtsAssistCommon
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/assist/common/src/android/assist/common/AutoResetLatch.java b/tests/tests/assist/common/src/android/assist/common/AutoResetLatch.java
new file mode 100644
index 0000000..f358120
--- /dev/null
+++ b/tests/tests/assist/common/src/android/assist/common/AutoResetLatch.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.assist.common;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A [CountDownLatch] that resets itself to [mCount] after every await call.
+ */
+public class AutoResetLatch {
+
+    private final int mCount;
+    private CountDownLatch mLatch;
+
+    public AutoResetLatch() {
+        this(1);
+    }
+
+    public AutoResetLatch(int count) {
+        mCount = count;
+        mLatch = new CountDownLatch(count);
+    }
+
+    public void await() throws InterruptedException {
+        try {
+            mLatch.await();
+        } finally {
+            mLatch = new CountDownLatch(mCount);
+        }
+    }
+
+    public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
+        try {
+            return mLatch.await(timeout, unit);
+        } finally {
+            mLatch = new CountDownLatch(mCount);
+        }
+    }
+
+    public void countDown() {
+        mLatch.countDown();
+    }
+}
diff --git a/tests/tests/assist/common/src/android/assist/common/BaseRemoteCallbackActivity.java b/tests/tests/assist/common/src/android/assist/common/BaseRemoteCallbackActivity.java
new file mode 100644
index 0000000..8f9e9d3
--- /dev/null
+++ b/tests/tests/assist/common/src/android/assist/common/BaseRemoteCallbackActivity.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.assist.common;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteCallback;
+
+public class BaseRemoteCallbackActivity extends Activity {
+
+    private RemoteCallback mRemoteCallback;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        registerReceivingCallback();
+    }
+
+    protected void notify(String action) {
+        RemoteCallback callback = getIntent().getParcelableExtra(Utils.EXTRA_REMOTE_CALLBACK);
+
+        if (callback == null) {
+            throw new IllegalStateException("Test ran expecting " + action
+                    + " but did not register callback");
+        } else {
+            Bundle bundle = new Bundle();
+            bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, action);
+            callback.sendResult(bundle);
+        }
+    }
+
+    protected void registerReceivingCallback() {
+        RemoteCallback remoteCallback = getIntent().getParcelableExtra(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING);
+        if (remoteCallback == null) {
+            return;
+
+        }
+
+        mRemoteCallback = new RemoteCallback((results) -> {
+            String action = results.getString(Utils.EXTRA_REMOTE_CALLBACK_ACTION);
+            if (action.equals(Utils.ACTION_END_OF_TEST)) {
+                if (!isFinishing()) {
+                    finish();
+                }
+            } else {
+                onReceivedEventFromCaller(results, action);
+            }
+        }, new Handler(Looper.getMainLooper()));
+
+        Bundle bundle = new Bundle();
+        bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.EXTRA_REMOTE_CALLBACK_RECEIVING_ACTION);
+        bundle.putParcelable(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING, mRemoteCallback);
+        remoteCallback.sendResult(bundle);
+    }
+
+    /**
+     * React to events from the calling test. Called from the main thread.
+     */
+    protected void onReceivedEventFromCaller(Bundle results, String action) {
+    }
+}
diff --git a/tests/tests/assist/common/src/android/assist/common/Utils.java b/tests/tests/assist/common/src/android/assist/common/Utils.java
index 349574b..50e4d42 100755
--- a/tests/tests/assist/common/src/android/assist/common/Utils.java
+++ b/tests/tests/assist/common/src/android/assist/common/Utils.java
@@ -36,6 +36,7 @@
     public static final String BROADCAST_ASSIST_DATA_INTENT = ACTION_PREFIX + "ASSIST_DATA";
     public static final String BROADCAST_INTENT_START_ASSIST = ACTION_PREFIX + "START_ASSIST";
     public static final String ASSIST_RECEIVER_REGISTERED = ACTION_PREFIX + "ASSIST_READY";
+    public static final String ACTION_END_OF_TEST = ACTION_PREFIX + "END_OF_TEST";
 
     public static final String ACTION_INVALIDATE = "invalidate_action";
     public static final String GET_CONTENT_VIEW_HEIGHT = ACTION_PREFIX + "GET_CONTENT_VIEW_HEIGHT";
@@ -68,11 +69,10 @@
     public static final String GAINED_FOCUS = ACTION_PREFIX + "focus_changed";
     public static final String LOST_FOCUS = ACTION_PREFIX + "lost_focus";
 
-    /** Flag Secure Test intent constants */
-    public static final String FLAG_SECURE_HASRESUMED = ACTION_PREFIX + "flag_secure_hasResumed";
     public static final String APP_3P_HASRESUMED = ACTION_PREFIX + "app_3p_hasResumed";
     public static final String APP_3P_HASDRAWED = ACTION_PREFIX + "app_3p_hasDrawed";
-    public static final String TEST_ACTIVITY_LOADED = ACTION_PREFIX + "test_activity_hasResumed";
+    public static final String TEST_ACTIVITY_DESTROY = ACTION_PREFIX + "test_activity_destroy";
+    public static final String TEST_ACTIVITY_WEBVIEW_LOADED = ACTION_PREFIX + "test_activity_webview_hasResumed";
 
     // Notice: timeout belows have to be long because some devices / form factors (like car) are
     // slower.
@@ -93,9 +93,11 @@
      * Extras used to pass RemoteCallback objects responsible for IPC between test, app, and
      * service.
      */
-    public static final String EXTRA_CALLBACK_CONTEXT_READY = "extra_callback_context_ready";
-    public static final String EXTRA_CALLBACK_ACTIVITY_RESUMED = "extra_callback_activity_resumed";
-    public static final String EXTRA_CALLBACK_ACTIVITY_DRAWED = "extra_callback_activity_drawed";
+    public static final String EXTRA_REMOTE_CALLBACK = "extra_remote_callback";
+    public static final String EXTRA_REMOTE_CALLBACK_ACTION = "extra_remote_callback_action";
+
+    public static final String EXTRA_REMOTE_CALLBACK_RECEIVING = "extra_remote_callback_receiving";
+    public static final String EXTRA_REMOTE_CALLBACK_RECEIVING_ACTION = "extra_remote_callback_receiving_action";
 
     /** Test name suffixes */
     public static final String ASSIST_STRUCTURE = "ASSIST_STRUCTURE";
@@ -113,6 +115,7 @@
 
     /** Session intent constants */
     public static final String HIDE_SESSION = "android.intent.action.hide_session";
+    public static final String HIDE_SESSION_COMPLETE = "android.intent.action.hide_session_complete";
 
     /** Lifecycle activity intent constants */
     /** Session intent constants */
@@ -176,30 +179,6 @@
         }
     }
 
-    /** The shim activity that starts the service associated with each test. */
-    public static final String getTestActivity(String testCaseType) {
-        switch (testCaseType) {
-            case DISABLE_CONTEXT:
-                // doesn't need to wait for activity to resume
-                // can be activated on top of any non-secure activity.
-                return "service.DisableContextActivity";
-            case ASSIST_STRUCTURE:
-            case FLAG_SECURE:
-            case LIFECYCLE:
-            case LIFECYCLE_NOUI:
-            case SCREENSHOT:
-            case EXTRA_ASSIST:
-            case VERIFY_CONTENT_VIEW:
-            case TEXTVIEW:
-            case LARGE_VIEW_HIERARCHY:
-            case WEBVIEW:
-            case FOCUS_CHANGE:
-                return "service.DelayedAssistantActivity";
-            default:
-                return "";
-        }
-    }
-
     /**
      * The test app associated with each test.
      */
@@ -207,8 +186,6 @@
         switch (testCaseType) {
             case ASSIST_STRUCTURE:
             case LARGE_VIEW_HIERARCHY:
-                return new ComponentName(
-                        "android.assist.testapp", "android.assist.testapp.TestApp");
             case DISABLE_CONTEXT:
                 return new ComponentName(
                         "android.assist.testapp", "android.assist.testapp.TestApp");
@@ -240,6 +217,14 @@
     }
 
     /**
+     * Sets the proper action used to launch an activity in the testapp package.
+     */
+    public static void setTestAppAction(Intent intent, String testCaseName) {
+        intent.putExtra(Utils.TESTCASE_TYPE, testCaseName);
+        intent.setAction("android.intent.action.TEST_APP_" + testCaseName);
+    }
+
+    /**
      * Returns the amount of time to wait for assist data.
      */
     public static final int getAssistDataTimeout(String testCaseType) {
@@ -278,4 +263,10 @@
     public static int getExpectedUid(Bundle extras) {
         return extras.getInt(MY_UID_EXTRA);
     }
+
+    public static Bundle bundleOfRemoteAction(String action) {
+        Bundle bundle = new Bundle();
+        bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, action);
+        return bundle;
+    }
 }
diff --git a/tests/tests/assist/service/AndroidManifest.xml b/tests/tests/assist/service/AndroidManifest.xml
index 6f01d3d..05da5fd 100644
--- a/tests/tests/assist/service/AndroidManifest.xml
+++ b/tests/tests/assist/service/AndroidManifest.xml
@@ -23,24 +23,28 @@
     <application>
       <uses-library android:name="android.test.runner" />
       <service android:name=".MainInteractionService"
-              android:label="CTS test voice interaction service"
-              android:permission="android.permission.BIND_VOICE_INTERACTION"
-              android:process=":interactor"
-              android:exported="true">
+               android:label="CTS test voice interaction service"
+               android:permission="android.permission.BIND_VOICE_INTERACTION"
+               android:process=":interactor"
+               android:exported="true"
+               android:visibleToInstantApps="true">
           <meta-data android:name="android.voice_interaction"
                      android:resource="@xml/interaction_service" />
           <intent-filter>
               <action android:name="android.service.voice.VoiceInteractionService" />
           </intent-filter>
       </service>
-      <activity android:name=".DisableContextActivity" >
+      <activity android:name=".DisableContextActivity"
+                android:visibleToInstantApps="true">
           <intent-filter>
               <action android:name="android.intent.action.START_TEST_DISABLE_CONTEXT" />
               <category android:name="android.intent.category.DEFAULT" />
           </intent-filter>
       </activity>
       <activity android:name=".DelayedAssistantActivity"
-                android:label="Delay Assistant Start Activity">
+                android:label="Delay Assistant Start Activity"
+                android:exported="true"
+                android:visibleToInstantApps="true">
           <intent-filter>
               <action android:name="android.intent.action.START_TEST_ASSIST_STRUCTURE" />
               <action android:name="android.intent.action.START_TEST_LIFECYCLE" />
@@ -50,6 +54,9 @@
               <action android:name="android.intent.action.START_TEST_EXTRA_ASSIST" />
               <action android:name="android.intent.action.START_TEST_TEXTVIEW" />
               <action android:name="android.intent.action.START_TEST_LARGE_VIEW_HIERARCHY" />
+              <action android:name="android.intent.action.START_TEST_VERIFY_CONTENT_VIEW" />
+              <action android:name="android.intent.action.START_TEST_FOCUS_CHANGE" />
+              <action android:name="android.intent.action.START_TEST_WEBVIEW" />
               <category android:name="android.intent.category.DEFAULT" />
           </intent-filter>
       </activity>
diff --git a/tests/tests/assist/service/src/android/assist/service/DelayedAssistantActivity.java b/tests/tests/assist/service/src/android/assist/service/DelayedAssistantActivity.java
index ddf43bd..d68106a 100644
--- a/tests/tests/assist/service/src/android/assist/service/DelayedAssistantActivity.java
+++ b/tests/tests/assist/service/src/android/assist/service/DelayedAssistantActivity.java
@@ -16,19 +16,22 @@
 
 package android.assist.service;
 
-import android.app.Activity;
+import android.assist.common.BaseRemoteCallbackActivity;
 import android.assist.common.Utils;
-import android.content.Intent;
 import android.content.ComponentName;
+import android.content.Intent;
 import android.os.Bundle;
+import android.os.RemoteCallback;
 import android.util.Log;
 
-public class DelayedAssistantActivity extends Activity {
+public class DelayedAssistantActivity extends BaseRemoteCallbackActivity {
     static final String TAG = "DelayedAssistantActivity";
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        RemoteCallback remoteCallback = getIntent().getParcelableExtra(Utils.EXTRA_REMOTE_CALLBACK);
+
         Intent intent = new Intent();
         intent.setComponent(new ComponentName(this, MainInteractionService.class));
         intent.putExtra(Utils.EXTRA_REGISTER_RECEIVER, true);
@@ -37,8 +40,15 @@
                 getIntent().getIntExtra(Utils.DISPLAY_WIDTH_KEY, 0));
         intent.putExtra(Utils.DISPLAY_HEIGHT_KEY,
                 getIntent().getIntExtra(Utils.DISPLAY_HEIGHT_KEY, 0));
+        intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK, remoteCallback);
         finish();
         ComponentName serviceName = startService(intent);
         Log.i(TAG, "Started service: " + serviceName);
     }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        notify(Utils.TEST_ACTIVITY_DESTROY);
+    }
 }
diff --git a/tests/tests/assist/service/src/android/assist/service/DisableContextActivity.java b/tests/tests/assist/service/src/android/assist/service/DisableContextActivity.java
index 2fd540b..c02370e 100644
--- a/tests/tests/assist/service/src/android/assist/service/DisableContextActivity.java
+++ b/tests/tests/assist/service/src/android/assist/service/DisableContextActivity.java
@@ -16,27 +16,32 @@
 
 package android.assist.service;
 
-import android.app.Activity;
-import android.content.Intent;
+import android.assist.common.BaseRemoteCallbackActivity;
+import android.assist.common.Utils;
 import android.content.ComponentName;
-import android.os.Bundle;
+import android.content.Intent;
+import android.os.RemoteCallback;
 import android.util.Log;
 
-public class DisableContextActivity extends Activity {
+public class DisableContextActivity extends BaseRemoteCallbackActivity {
     static final String TAG = "DisableContextActivity";
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
-
-    @Override
     public void onStart() {
         super.onStart();
+
+        RemoteCallback remoteCallback = getIntent().getParcelableExtra(Utils.EXTRA_REMOTE_CALLBACK);
         Intent intent = new Intent();
         intent.setComponent(new ComponentName(this, MainInteractionService.class));
+        intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK, remoteCallback);
         Log.i(TAG, "Starting service.");
         finish();
         startService(intent);
     }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        notify(Utils.TEST_ACTIVITY_DESTROY);
+    }
 }
diff --git a/tests/tests/assist/service/src/android/assist/service/MainInteractionService.java b/tests/tests/assist/service/src/android/assist/service/MainInteractionService.java
index 3aa8261..d5e3a6d 100644
--- a/tests/tests/assist/service/src/android/assist/service/MainInteractionService.java
+++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionService.java
@@ -19,6 +19,7 @@
 import static android.service.voice.VoiceInteractionSession.SHOW_WITH_ASSIST;
 import static android.service.voice.VoiceInteractionSession.SHOW_WITH_SCREENSHOT;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -31,17 +32,14 @@
 import android.service.voice.VoiceInteractionSession;
 import android.util.Log;
 
-import java.lang.Exception;
-import java.lang.Override;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 public class MainInteractionService extends VoiceInteractionService {
     static final String TAG = "MainInteractionService";
     private Intent mIntent;
     private boolean mReady = false;
-    private BroadcastReceiver mBroadcastReceiver, mResumeReceiver;
-    private CountDownLatch mResumeLatch;
+    private BroadcastReceiver mBroadcastReceiver;
+    private AutoResetLatch mResumeLatch = new AutoResetLatch();
+
+    private RemoteCallback mRemoteCallback;
 
     @Override
     public void onCreate() {
@@ -60,10 +58,22 @@
     public int onStartCommand(Intent intent, int flags, int startId) {
         Log.i(TAG, "onStartCommand received - intent: " + intent);
         mIntent = intent;
+        mRemoteCallback = mIntent.getParcelableExtra(Utils.EXTRA_REMOTE_CALLBACK);
         maybeStart();
         return START_NOT_STICKY;
     }
 
+    protected void notify(String action) {
+        if (mRemoteCallback == null) {
+            throw new IllegalStateException("Test ran expecting " + action + " but did not register"
+                    + "callback");
+        } else {
+            Bundle bundle = new Bundle();
+            bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, action);
+            mRemoteCallback.sendResult(bundle);
+        }
+    }
+
     private void maybeStart() {
         if (mIntent == null || !mReady) {
             Log.wtf(TAG, "Can't start session because either intent is null or onReady() "
@@ -71,28 +81,25 @@
         } else {
             if (isActiveService(this, new ComponentName(this, getClass()))) {
                 if (mIntent.getBooleanExtra(Utils.EXTRA_REGISTER_RECEIVER, false)) {
-                    mResumeLatch = new CountDownLatch(1);
                     if (mBroadcastReceiver == null) {
                         mBroadcastReceiver = new MainInteractionServiceBroadcastReceiver();
                         IntentFilter filter = new IntentFilter();
                         filter.addAction(Utils.BROADCAST_INTENT_START_ASSIST);
-                        registerReceiver(mBroadcastReceiver, filter);
+                        registerReceiver(mBroadcastReceiver, filter,
+                                Context.RECEIVER_VISIBLE_TO_INSTANT_APPS);
                         Log.i(TAG, "Registered receiver to start session later");
-
-                        IntentFilter resumeFilter = new IntentFilter(Utils.APP_3P_HASRESUMED);
-                        mResumeReceiver = new MainServiceAppResumeReceiver();
-                        registerReceiver(mResumeReceiver, resumeFilter);
-                        Log.i(TAG, "Registered receiver for resuming activity");
                     }
-                    sendBroadcast(new Intent(Utils.ASSIST_RECEIVER_REGISTERED));
-              } else {
-                  Log.i(TAG, "Yay! about to start session");
-                  Bundle bundle = new Bundle();
-                  bundle.putString(Utils.TESTCASE_TYPE,
-                          mIntent.getStringExtra(Utils.TESTCASE_TYPE));
-                  showSession(bundle, VoiceInteractionSession.SHOW_WITH_ASSIST |
-                      VoiceInteractionSession.SHOW_WITH_SCREENSHOT);
-              }
+                    notify(Utils.ASSIST_RECEIVER_REGISTERED);
+                } else {
+                    Log.i(TAG, "Yay! about to start session");
+                    Bundle bundle = new Bundle();
+                    bundle.putString(Utils.TESTCASE_TYPE,
+                            mIntent.getStringExtra(Utils.TESTCASE_TYPE));
+                    bundle.putParcelable(Utils.EXTRA_REMOTE_CALLBACK,
+                            mIntent.getParcelableExtra(Utils.EXTRA_REMOTE_CALLBACK));
+                    showSession(bundle, VoiceInteractionSession.SHOW_WITH_ASSIST |
+                            VoiceInteractionSession.SHOW_WITH_SCREENSHOT);
+                }
             } else {
                 Log.wtf(TAG, "**** Not starting MainInteractionService because" +
                         " it is not set as the current voice interaction service");
@@ -104,53 +111,20 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             Log.i(TAG, "Received broadcast to start session now: " + intent);
-            if (intent.getAction().equals(Utils.BROADCAST_INTENT_START_ASSIST)) {
+            String action = intent.getAction();
+            if (action.equals(Utils.BROADCAST_INTENT_START_ASSIST)) {
                 String testCaseName = intent.getStringExtra(Utils.TESTCASE_TYPE);
-                Log.i(TAG, "trying to start 3p activity: " + testCaseName);
                 Bundle extras = intent.getExtras();
                 if (extras == null) {
                     extras = new Bundle();
                 }
-                RemoteCallback contextReadycallback = intent
-                        .getParcelableExtra(Utils.EXTRA_CALLBACK_CONTEXT_READY);
-                extras.putParcelable(Utils.EXTRA_CALLBACK_CONTEXT_READY, contextReadycallback);
-                if (testCaseName.equals(Utils.SCREENSHOT)) {
-                    try {
-                        // extra info to pass along to 3p activity.
 
-                        Intent intent3p = new Intent();
-                        Log.i(TAG, "starting the 3p app again");
-                        intent3p.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                        intent3p.setAction("android.intent.action.TEST_APP_" + testCaseName);
-                        intent3p.setComponent(Utils.getTestAppComponent(testCaseName));
-                        intent3p.putExtras(extras);
-                        startActivity(intent3p);
-                        if (!MainInteractionService.this.mResumeLatch
-                                .await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-                            Log.i(TAG, "waited for 3p activity to resume");
-                        }
-                    } catch (Exception e) {
-                        Log.i(TAG, "failed so reload 3p app: " + e.toString());
-                    }
-                }
                 extras.putString(Utils.TESTCASE_TYPE, mIntent.getStringExtra(Utils.TESTCASE_TYPE));
+                extras.putParcelable(Utils.EXTRA_REMOTE_CALLBACK, mRemoteCallback);
                 MainInteractionService.this.showSession(
                         extras, SHOW_WITH_ASSIST | SHOW_WITH_SCREENSHOT);
-            }
-        }
-    }
-
-    private class MainServiceAppResumeReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(Utils.APP_3P_HASRESUMED)) {
-                Log.i(MainInteractionService.TAG,
-                    "3p activity has resumed in this new receiver");
-                if (MainInteractionService.this.mResumeLatch != null) {
-                    MainInteractionService.this.mResumeLatch.countDown();
-                } else {
-                    Log.i(TAG, "mResumeLatch was null");
-                }
+            } else {
+                Log.e(TAG, "MainInteractionServiceBroadcastReceiver: invalid action " + action);
             }
         }
     }
@@ -161,4 +135,4 @@
             unregisterReceiver(mBroadcastReceiver);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
index 068a4a8..f349971 100644
--- a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
+++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
@@ -18,35 +18,25 @@
 
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
-import android.assist.service.R;
+import android.assist.common.Utils;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.graphics.Bitmap;
-import android.graphics.Color;
-
 import android.graphics.Point;
 import android.os.Bundle;
 import android.os.RemoteCallback;
 import android.service.voice.VoiceInteractionSession;
-import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewTreeObserver;
 
-import java.io.ByteArrayOutputStream;
-import java.util.Date;
-
-import android.assist.common.Utils;
-import android.view.WindowManager;
-
 public class MainInteractionSession extends VoiceInteractionSession {
     static final String TAG = "MainInteractionSession";
 
-    Intent mStartIntent;
     Context mContext;
     Bundle mAssistData = new Bundle();
 
@@ -58,7 +48,7 @@
     private BroadcastReceiver mReceiver;
     private String mTestName;
     private View mContentView;
-    private RemoteCallback mContextReadyCallback;
+    private RemoteCallback mRemoteCallback;
 
     MainInteractionSession(Context context) {
         super(context);
@@ -75,11 +65,15 @@
                 if (action.equals(Utils.HIDE_SESSION)) {
                     hide();
                 }
+
+                Bundle bundle = new Bundle();
+                bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.HIDE_SESSION_COMPLETE);
+                mRemoteCallback.sendResult(bundle);
             }
         };
         IntentFilter filter = new IntentFilter();
         filter.addAction(Utils.HIDE_SESSION);
-        mContext.registerReceiver(mReceiver, filter);
+        mContext.registerReceiver(mReceiver, filter, Context.RECEIVER_VISIBLE_TO_INSTANT_APPS);
     }
 
     @Override
@@ -109,7 +103,7 @@
         mCurColor = args.getInt(Utils.SCREENSHOT_COLOR_KEY);
         mDisplayHeight = args.getInt(Utils.DISPLAY_HEIGHT_KEY);
         mDisplayWidth = args.getInt(Utils.DISPLAY_WIDTH_KEY);
-        mContextReadyCallback = args.getParcelable(Utils.EXTRA_CALLBACK_CONTEXT_READY);
+        mRemoteCallback = args.getParcelable(Utils.EXTRA_REMOTE_CALLBACK);
         super.onShow(args, showFlags);
         if (mContentView == null) return; // Happens when ui is not enabled.
         mContentView.getViewTreeObserver().addOnPreDrawListener(
@@ -120,11 +114,12 @@
                     Display d = mContentView.getDisplay();
                     Point displayPoint = new Point();
                     d.getRealSize(displayPoint);
-                    Intent intent = new Intent(Utils.BROADCAST_CONTENT_VIEW_HEIGHT);
-                    intent.putExtra(Utils.EXTRA_CONTENT_VIEW_HEIGHT, mContentView.getHeight());
-                    intent.putExtra(Utils.EXTRA_CONTENT_VIEW_WIDTH, mContentView.getWidth());
-                    intent.putExtra(Utils.EXTRA_DISPLAY_POINT, displayPoint);
-                    mContext.sendBroadcast(intent);
+                    Bundle bundle = new Bundle();
+                    bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.BROADCAST_CONTENT_VIEW_HEIGHT);
+                    bundle.putInt(Utils.EXTRA_CONTENT_VIEW_HEIGHT, mContentView.getHeight());
+                    bundle.putInt(Utils.EXTRA_CONTENT_VIEW_WIDTH, mContentView.getWidth());
+                    bundle.putParcelable(Utils.EXTRA_DISPLAY_POINT, displayPoint);
+                    mRemoteCallback.sendResult(bundle);
                     return true;
                 }
             });
@@ -215,17 +210,10 @@
         } else if (!hasReceivedScreenshot) {
             Log.i(TAG, "waiting for screenshot before broadcasting results");
         } else {
-            if (mContextReadyCallback != null) {
-                Log.i(TAG, "maybeBroadcastResults(): calling callback " + mContextReadyCallback);
-                mContextReadyCallback.sendResult(mAssistData);
-            } else {
-                // TODO(b/133431034): should only use callbacks
-                Log.w(TAG, "maybeBroadcastResults(): no callback; broadcasting instead");
-                Intent intent = new Intent(Utils.BROADCAST_ASSIST_DATA_INTENT);
-                intent.putExtras(mAssistData);
-                Log.i(TAG, "broadcasting: " + intent+ ", Bundle = " + mAssistData);
-                mContext.sendBroadcast(intent);
-            }
+            Bundle bundle = new Bundle();
+            bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.BROADCAST_ASSIST_DATA_INTENT);
+            bundle.putAll(mAssistData);
+            mRemoteCallback.sendResult(bundle);
 
             hasReceivedAssistData = false;
             hasReceivedScreenshot = false;
diff --git a/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java b/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java
index 70669e5..0506bc9 100755
--- a/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java
@@ -16,14 +16,10 @@
 
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.util.Log;
 
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 
@@ -35,50 +31,20 @@
     private static final String TAG = "AssistStructureTest";
     private static final String TEST_CASE_TYPE = Utils.ASSIST_STRUCTURE;
 
-    private final CountDownLatch mHasDrawedLatch = new CountDownLatch(1);
+    private AutoResetLatch mHasDrawedLatch;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        setUpAndRegisterReceiver();
+        mHasDrawedLatch = new AutoResetLatch(1);
+        mActionLatchReceiver = new ActionLatchReceiver(Utils.APP_3P_HASDRAWED, mHasDrawedLatch);
         startTestActivity(TEST_CASE_TYPE);
     }
-
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
-    }
-
-    private void setUpAndRegisterReceiver() {
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new AssistStructureTestBroadcastReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.APP_3P_HASRESUMED);
-        filter.addAction(Utils.APP_3P_HASDRAWED);
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        mContext.registerReceiver(mReceiver, filter);
-    }
-
-    private void waitForOnResume() throws Exception {
-        Log.i(TAG, "waiting for onResume() before continuing");
-        if (!mHasResumedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            fail("Activity failed to resume in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
-        }
-
-    }
-
     private void waitForOnDraw() throws Exception {
         Log.i(TAG, "waiting for onDraw() before continuing");
         if (!mHasDrawedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
             fail("Activity failed to draw in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
         }
-
     }
 
     public void testAssistStructure() throws Throwable {
@@ -86,40 +52,16 @@
             Log.d(TAG, "Not running assist tests - voice_recognizers feature is not supported");
             return;
         }
-        start3pApp(TEST_CASE_TYPE, mHasDrawedLatch);
+        start3pApp(TEST_CASE_TYPE);
         startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady(mReadyLatch);
-        waitForOnResume();
+        waitForAssistantToBeReady();
         waitForOnDraw();
-        final CountDownLatch latch = startSession();
+        final AutoResetLatch latch = startSession();
         waitForContext(latch);
         getInstrumentation().waitForIdleSync();
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                verifyAssistDataNullness(false, false, false, false);
-                verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE), false /*FLAG_SECURE set*/);
-            }
+        runTestOnUiThread(() -> {
+            verifyAssistDataNullness(false, false, false, false);
+            verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE), false /*FLAG_SECURE set*/);
         });
     }
-
-    private class AssistStructureTestBroadcastReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(Utils.APP_3P_HASRESUMED)) {
-                if (mHasResumedLatch != null) {
-                    mHasResumedLatch.countDown();
-                }
-            } else if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED)) {
-                if (mReadyLatch != null) {
-                    mReadyLatch.countDown();
-                }
-            }else if (action.equals(Utils.APP_3P_HASDRAWED)) {
-                if (mHasDrawedLatch != null) {
-                    mHasDrawedLatch.countDown();
-                }
-            }
-        }
-    }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
index 438d905..dfb95dd 100644
--- a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
@@ -22,21 +22,21 @@
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.app.assist.AssistStructure.ViewNode;
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.LocaleList;
 import android.os.RemoteCallback;
-import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
+import android.util.Pair;
 import android.view.Display;
 import android.view.View;
 import android.view.ViewGroup;
@@ -45,11 +45,13 @@
 import android.widget.TextView;
 
 import com.android.compatibility.common.util.SettingsUtils;
-import com.android.compatibility.common.util.SystemUtil;
 
-import java.util.concurrent.CountDownLatch;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nullable;
+
 public class AssistTestBase extends ActivityInstrumentationTestCase2<TestStartActivity> {
     private static final String TAG = "AssistTestBase";
 
@@ -68,13 +70,24 @@
     protected AssistContent mAssistContent;
     protected AssistStructure mAssistStructure;
     protected boolean mScreenshot;
-    protected Bitmap mAppScreenshot;
-    protected BroadcastReceiver mReceiver;
     protected Bundle mAssistBundle;
     protected Context mContext;
-    protected final CountDownLatch mReadyLatch = new CountDownLatch(1);
-    protected final CountDownLatch mHasResumedLatch = new CountDownLatch(1);
-    private CountDownLatch mAssistDataReceivedLatch;
+    private AutoResetLatch mReadyLatch = new AutoResetLatch(1);
+    private AutoResetLatch mHas3pResumedLatch = new AutoResetLatch(1);
+    private AutoResetLatch mHasTestDestroyedLatch = new AutoResetLatch(1);
+    private AutoResetLatch mSessionCompletedLatch = new AutoResetLatch(1);
+    protected AutoResetLatch mAssistDataReceivedLatch = new AutoResetLatch();
+
+    protected ActionLatchReceiver mActionLatchReceiver;
+
+    private final RemoteCallback mRemoteCallback = new RemoteCallback((result) -> {
+        String action = result.getString(Utils.EXTRA_REMOTE_CALLBACK_ACTION);
+        mActionLatchReceiver.onAction(result, action);
+    });
+
+    @Nullable
+    protected RemoteCallback m3pActivityCallback;
+    private RemoteCallback m3pCallbackReceiving;
 
     protected boolean mScreenshotMatches;
     private Point mDisplaySize;
@@ -103,25 +116,19 @@
         mAssistContent = null;
         mAssistBundle = null;
 
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new TestResultsReceiver();
-        mContext.registerReceiver(mReceiver,
-            new IntentFilter(Utils.BROADCAST_ASSIST_DATA_INTENT));
+        mActionLatchReceiver = new ActionLatchReceiver();
 
         prepareDevice();
+        registerForAsyncReceivingCallback();
     }
 
     @Override
     protected void tearDown() throws Exception {
         mTestActivity.finish();
         mContext.sendBroadcast(new Intent(Utils.HIDE_SESSION));
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
+        m3pCallbackReceiving.sendResult(Utils.bundleOfRemoteAction(Utils.ACTION_END_OF_TEST));
         super.tearDown();
+        mSessionCompletedLatch.await(3, TimeUnit.SECONDS);
     }
 
     private void prepareDevice() throws Exception {
@@ -134,28 +141,66 @@
         runShellCommand("wm dismiss-keyguard");
     }
 
-    protected void startTest(String testName) {
-        mTestActivity.startTest(testName);
+    private void registerForAsyncReceivingCallback() {
+        HandlerThread handlerThread = new HandlerThread("AssistTestCallbackReceivingThread");
+        handlerThread.start();
+        Handler handler = new Handler(handlerThread.getLooper());
+
+        m3pCallbackReceiving = new RemoteCallback((results) -> {
+            String action = results.getString(Utils.EXTRA_REMOTE_CALLBACK_ACTION);
+            if (action.equals(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING_ACTION)) {
+                m3pActivityCallback = results.getParcelable(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING);
+            }
+        }, handler);
     }
 
-    protected void start3pApp(String testName) {
-        start3pApp(testName, /* hasDrawedLatch= */ null);
+    protected void startTest(String testName) throws Exception {
+        Log.i(TAG, "Starting test activity for TestCaseType = " + testName);
+        Intent intent = new Intent();
+        intent.putExtra(Utils.TESTCASE_TYPE, testName);
+        intent.setAction("android.intent.action.START_TEST_" + testName);
+        intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK, mRemoteCallback);
+        intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
+
+        mTestActivity.startActivity(intent);
+        waitForTestActivityOnDestroy();
     }
 
-    protected void start3pApp(String testName, CountDownLatch hasDrawedLatch) {
-        mTestActivity.start3pApp(testName, mHasResumedLatch, hasDrawedLatch);
+    protected void start3pApp(String testCaseName) throws Exception {
+        start3pApp(testCaseName, null);
+    }
+
+    protected void start3pApp(String testCaseName, Bundle extras) throws Exception {
+        Intent intent = new Intent();
+        intent.putExtra(Utils.TESTCASE_TYPE, testCaseName);
+        Utils.setTestAppAction(intent, testCaseName);
+        intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK, mRemoteCallback);
+        intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
+        intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK_RECEIVING, m3pCallbackReceiving);
+        if (extras != null) {
+            intent.putExtras(extras);
+        }
+
+        mTestActivity.startActivity(intent);
+        waitForOnResume();
     }
 
     /**
      * Starts the shim service activity
      */
     protected void startTestActivity(String testName) {
+        RemoteCallback remoteCallback = new RemoteCallback((result) -> {
+            String action = result.getString(Utils.EXTRA_REMOTE_CALLBACK_ACTION);
+            if (mActionLatchReceiver != null) {
+                mActionLatchReceiver.onAction(result, action);
+            }
+        });
+
         Intent intent = new Intent();
         mTestName = testName;
         intent.setAction("android.intent.action.TEST_START_ACTIVITY_" + testName);
-        intent.setComponent(new ComponentName(getInstrumentation().getContext(),
-                TestStartActivity.class));
         intent.putExtra(Utils.TESTCASE_TYPE, testName);
+        intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK, remoteCallback);
         setActivityIntent(intent);
         mTestActivity = getActivity();
         mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
@@ -164,33 +209,42 @@
     /**
      * Called when waiting for Assistant's Broadcast Receiver to be setup
      */
-    public void waitForAssistantToBeReady(CountDownLatch latch) throws Exception {
+    protected void waitForAssistantToBeReady() throws Exception {
         Log.i(TAG, "waiting for assistant to be ready before continuing");
-        if (!latch.await(Utils.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+        if (!mReadyLatch.await(Utils.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
             fail("Assistant was not ready before timeout of: " + Utils.TIMEOUT_MS + "msec");
         }
     }
 
+    private void waitForOnResume() throws Exception {
+        Log.i(TAG, "waiting for onResume() before continuing");
+        if (!mHas3pResumedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+            fail("Activity failed to resume in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
+        }
+    }
+
+    private void waitForTestActivityOnDestroy() throws Exception {
+        Log.i(TAG, "waiting for mTestActivity onDestroy() before continuing");
+        if (!mHasTestDestroyedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+            fail("mTestActivity failed to destroy in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
+        }
+    }
+
     /**
      * Send broadcast to MainInteractionService to start a session
      */
-    protected CountDownLatch startSession() {
+    protected AutoResetLatch startSession() {
         return startSession(mTestName, new Bundle());
     }
 
-    protected CountDownLatch startSession(String testName, Bundle extras) {
+    protected AutoResetLatch startSession(String testName, Bundle extras) {
         Intent intent = new Intent(Utils.BROADCAST_INTENT_START_ASSIST);
         Log.i(TAG, "passed in class test name is: " + testName);
         intent.putExtra(Utils.TESTCASE_TYPE, testName);
         addDimensionsToIntent(intent);
         intent.putExtras(extras);
-        mAssistDataReceivedLatch = new CountDownLatch(1);
-        final RemoteCallback contextReadyCallback = new RemoteCallback((result) -> {
-            Log.v(TAG, "Service called contextReady callback for " + testName + " RESULT: " + result);
-            setAssistResults(result);
-            mAssistDataReceivedLatch.countDown();
-        });
-        intent.putExtra(Utils.EXTRA_CALLBACK_CONTEXT_READY, contextReadyCallback);
+        intent.putExtra(Utils.EXTRA_REMOTE_CALLBACK, mRemoteCallback);
+        intent.setPackage("android.assist.service");
 
         mContext.sendBroadcast(intent);
         return mAssistDataReceivedLatch;
@@ -209,24 +263,7 @@
         intent.putExtra(Utils.DISPLAY_HEIGHT_KEY, mDisplaySize.y);
     }
 
-    /**
-     * Called after startTestActivity. Includes check for receiving context.
-     */
-    protected boolean waitForBroadcast() throws Exception {
-        mAssistDataReceivedLatch = new CountDownLatch(1);
-        start3pApp(mTestName);
-        startTest(mTestName);
-        return waitForContext(mAssistDataReceivedLatch);
-    }
-
-    protected boolean waitForContext(CountDownLatch sessionLatch) throws Exception {
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new TestResultsReceiver();
-        mContext.registerReceiver(mReceiver,
-                new IntentFilter(Utils.BROADCAST_ASSIST_DATA_INTENT));
-
+    protected boolean waitForContext(AutoResetLatch sessionLatch) throws Exception {
         if (!sessionLatch.await(Utils.getAssistDataTimeout(mTestName), TimeUnit.MILLISECONDS)) {
             fail("Fail to receive broadcast in " + Utils.getAssistDataTimeout(mTestName) + "msec");
         }
@@ -417,12 +454,12 @@
         }
     }
 
-    /** 
+    /**
      * Return true if the expected strings are found in the WebView, else fail.
      */
     private boolean traverseWebViewForText(ViewNode parentNode) {
         boolean textFound = false;
-        if (parentNode.getText() != null 
+        if (parentNode.getText() != null
                 && parentNode.getText().toString().equals(Utils.WEBVIEW_HTML_GREETING)) {
             return true;
         }
@@ -541,33 +578,12 @@
         }
     }
 
-    // TODO(b/133431034): remove?
-    class TestResultsReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equalsIgnoreCase(Utils.BROADCAST_ASSIST_DATA_INTENT)) {
-                Log.i(TAG, "Received broadcast with assist data.");
-                Bundle assistData = intent.getExtras();
-                AssistTestBase.this.setAssistResults(assistData);
-
-                if (mAssistDataReceivedLatch != null) {
-                    Log.i(AssistTestBase.TAG, "counting down latch. received assist data.");
-                    mAssistDataReceivedLatch.countDown();
-                }
-            } else if (intent.getAction().equals(Utils.APP_3P_HASRESUMED)) {
-                if (mHasResumedLatch != null) {
-                    mHasResumedLatch.countDown();
-                }
-            }
-        }
-    }
-
     protected void setAssistResults(Bundle assistData) {
         mAssistBundle = assistData.getBundle(Utils.ASSIST_BUNDLE_KEY);
         mAssistStructure = assistData.getParcelable(Utils.ASSIST_STRUCTURE_KEY);
         mAssistContent = assistData.getParcelable(Utils.ASSIST_CONTENT_KEY);
 
-        mScreenshot =assistData.getBoolean(Utils.ASSIST_SCREENSHOT_KEY, false);
+        mScreenshot = assistData.getBoolean(Utils.ASSIST_SCREENSHOT_KEY, false);
 
         mScreenshotMatches = assistData.getBoolean(Utils.COMPARE_SCREENSHOT_KEY, false);
     }
@@ -603,4 +619,44 @@
             return "screenshot_" + (value.equals("1") ? "enabled" : "disabled");
         }
     }
+
+    public class ActionLatchReceiver {
+
+        private final Map<String, AutoResetLatch> entries = new HashMap<>();
+
+        protected ActionLatchReceiver(Pair<String, AutoResetLatch>... entries) {
+            for (Pair<String, AutoResetLatch> entry : entries) {
+                if (entry.second == null) {
+                    throw new IllegalArgumentException("Test cannot pass in a null latch");
+                }
+                this.entries.put(entry.first, entry.second);
+            }
+
+            this.entries.put(Utils.HIDE_SESSION_COMPLETE, mSessionCompletedLatch);
+            this.entries.put(Utils.APP_3P_HASRESUMED, mHas3pResumedLatch);
+            this.entries.put(Utils.TEST_ACTIVITY_DESTROY, mHasTestDestroyedLatch);
+            this.entries.put(Utils.ASSIST_RECEIVER_REGISTERED, mReadyLatch);
+            this.entries.put(Utils.BROADCAST_ASSIST_DATA_INTENT, mAssistDataReceivedLatch);
+        }
+
+        protected ActionLatchReceiver(String action, AutoResetLatch latch) {
+            this(Pair.create(action, latch));
+        }
+
+        protected void onAction(Bundle bundle, String action) {
+            switch (action) {
+                case Utils.BROADCAST_ASSIST_DATA_INTENT:
+                    AssistTestBase.this.setAssistResults(bundle);
+                    // fall-through
+                default:
+                    AutoResetLatch latch = entries.get(action);
+                    if (latch == null) {
+                        Log.e(TAG, this.getClass() + ": invalid action " + action);
+                    } else {
+                        latch.countDown();
+                    }
+                    break;
+            }
+        }
+    }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/AssistantContentViewTest.java b/tests/tests/assist/src/android/assist/cts/AssistantContentViewTest.java
index cb09270..a4a28d7 100644
--- a/tests/tests/assist/src/android/assist/cts/AssistantContentViewTest.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistantContentViewTest.java
@@ -16,49 +16,31 @@
 
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.graphics.Point;
+import android.os.Bundle;
 import android.util.Log;
 
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /** Test verifying the Content View of the Assistant */
 public class AssistantContentViewTest extends AssistTestBase {
     private static final String TAG = "ContentViewTest";
-    private final CountDownLatch mContentViewLatch = new CountDownLatch(1);
-    private Intent mIntent;
+    private AutoResetLatch mContentViewLatch = new AutoResetLatch(1);
+    private Bundle mBundle;
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        setUpAndRegisterReceiver();
+        mActionLatchReceiver = new AssistantReceiver();
         startTestActivity(Utils.VERIFY_CONTENT_VIEW);
     }
 
     @Override
     public void tearDown() throws Exception {
+        mBundle = null;
         super.tearDown();
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
-    }
-
-    private void setUpAndRegisterReceiver() {
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new AssistantContentViewReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.BROADCAST_CONTENT_VIEW_HEIGHT);
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        mContext.registerReceiver(mReceiver, filter);
-
     }
 
     private void waitForContentView() throws Exception {
@@ -74,30 +56,26 @@
           return;
         }
         startTest(Utils.VERIFY_CONTENT_VIEW);
-        waitForAssistantToBeReady(mReadyLatch);
+        waitForAssistantToBeReady();
         startSession();
         waitForContentView();
-        int height = mIntent.getIntExtra(Utils.EXTRA_CONTENT_VIEW_HEIGHT, 0);
-        int width = mIntent.getIntExtra(Utils.EXTRA_CONTENT_VIEW_WIDTH, 0);
-        Point displayPoint = (Point) mIntent.getParcelableExtra(Utils.EXTRA_DISPLAY_POINT);
+        int height = mBundle.getInt(Utils.EXTRA_CONTENT_VIEW_HEIGHT, 0);
+        int width = mBundle.getInt(Utils.EXTRA_CONTENT_VIEW_WIDTH, 0);
+        Point displayPoint = mBundle.getParcelable(Utils.EXTRA_DISPLAY_POINT);
         assertEquals(displayPoint.y, height);
         assertEquals(displayPoint.x, width);
     }
 
-    private class AssistantContentViewReceiver extends BroadcastReceiver {
+    private class AssistantReceiver extends ActionLatchReceiver {
+
+        AssistantReceiver() {
+            super(Utils.BROADCAST_CONTENT_VIEW_HEIGHT, mContentViewLatch);
+        }
+
         @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(Utils.BROADCAST_CONTENT_VIEW_HEIGHT)) {
-                mIntent = intent;
-                if (mContentViewLatch != null) {
-                    mContentViewLatch.countDown();
-                }
-            } else if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED)) {
-                if (mReadyLatch != null) {
-                    mReadyLatch.countDown();
-                }
-            }
+        protected void onAction(Bundle bundle, String action) {
+            mBundle = bundle;
+            super.onAction(bundle, action);
         }
     }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/DisableContextTest.java b/tests/tests/assist/src/android/assist/cts/DisableContextTest.java
index 90788a0..11e404f 100644
--- a/tests/tests/assist/src/android/assist/cts/DisableContextTest.java
+++ b/tests/tests/assist/src/android/assist/cts/DisableContextTest.java
@@ -17,16 +17,9 @@
 package android.assist.cts;
 
 import android.assist.common.Utils;
-import android.assist.cts.AssistTestBase.ScreenshotEnabled;
-import android.assist.cts.AssistTestBase.StructureEnabled;
-import android.content.Context;
 import android.util.Log;
 
-import com.android.compatibility.common.util.SettingsUtils;
-import com.android.compatibility.common.util.SystemUtil;
-
 /** Test we receive proper assist data when context is disabled or enabled */
-
 public class DisableContextTest extends AssistTestBase {
     static final String TAG = "DisableContextTest";
 
@@ -53,15 +46,14 @@
         // Both settings off
         Log.i(TAG, "DisableContext: Screenshot OFF, Context OFF");
         setFeaturesEnabled(StructureEnabled.FALSE, ScreenshotEnabled.FALSE);
-        waitForBroadcast();
+        startTest(TEST_CASE_TYPE);
+        waitForContext(mAssistDataReceivedLatch);
 
         logContextAndScreenshotSetting();
         verifyAssistDataNullness(true, true, true, true);
     }
 
-    // TODO(b/133379285) need to figure out a way to finish the activity so this class can run
-    // multiple tests
-    public void disabled_TestContextOff() throws Exception {
+    public void testContextOff() throws Exception {
         if (!mContext.getPackageManager().hasSystemFeature(FEATURE_VOICE_RECOGNIZERS)) {
             Log.d(TAG, "Not running assist tests - voice_recognizers feature is not supported");
             return;
@@ -69,15 +61,14 @@
         // Screenshot off, context on
         Log.i(TAG, "DisableContext: Screenshot OFF, Context ON");
         setFeaturesEnabled(StructureEnabled.TRUE, ScreenshotEnabled.FALSE);
-        waitForBroadcast();
+        startTest(TEST_CASE_TYPE);
+        waitForContext(mAssistDataReceivedLatch);
 
         logContextAndScreenshotSetting();
         verifyAssistDataNullness(false, false, false, true);
     }
 
-    // TODO(b/133379285) need to figure out a way to finish the activity so this class can run
-    // multiple tests
-    public void disabled_testScreenshotOff() throws Exception {
+    public void testScreenshotOff() throws Exception {
         if (!mContext.getPackageManager().hasSystemFeature(FEATURE_VOICE_RECOGNIZERS)) {
             Log.d(TAG, "Not running assist tests - voice_recognizers feature is not supported");
             return;
@@ -85,7 +76,8 @@
         // Context off, screenshot on
         Log.i(TAG, "DisableContext: Screenshot ON, Context OFF");
         setFeaturesEnabled(StructureEnabled.FALSE, ScreenshotEnabled.TRUE);
-        waitForBroadcast();
+        startTest(TEST_CASE_TYPE);
+        waitForContext(mAssistDataReceivedLatch);
 
         logContextAndScreenshotSetting();
         verifyAssistDataNullness(true, true, true, true);
diff --git a/tests/tests/assist/src/android/assist/cts/ExtraAssistDataTest.java b/tests/tests/assist/src/android/assist/cts/ExtraAssistDataTest.java
index b5e799e..2acf4e3 100644
--- a/tests/tests/assist/src/android/assist/cts/ExtraAssistDataTest.java
+++ b/tests/tests/assist/src/android/assist/cts/ExtraAssistDataTest.java
@@ -15,18 +15,12 @@
  */
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.os.Bundle;
-import android.os.Process;
 import android.util.Log;
 
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 public class ExtraAssistDataTest extends AssistTestBase {
     private static final String TAG = "ExtraAssistDataTest";
     private static final String TEST_CASE_TYPE = Utils.EXTRA_ASSIST;
@@ -34,40 +28,18 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        setUpAndRegisterReceiver();
         startTestActivity(TEST_CASE_TYPE);
     }
 
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
-    }
-
-    private void setUpAndRegisterReceiver() {
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new ExtraAssistDataReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.APP_3P_HASRESUMED);
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        mContext.registerReceiver(mReceiver, filter);
-    }
-
     public void testAssistContentAndAssistData() throws Exception {
         if (mActivityManager.isLowRamDevice()) {
             Log.d(TAG, "Not running assist tests on low-RAM device.");
             return;
         }
         startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady(mReadyLatch);
+        waitForAssistantToBeReady();
         start3pApp(TEST_CASE_TYPE);
-        waitForOnResume();
-        final CountDownLatch latch = startSession();
+        final AutoResetLatch latch = startSession();
         waitForContext(latch);
         verifyAssistDataNullness(false, false, false, false);
 
@@ -89,29 +61,5 @@
         int expectedUid = Utils.getExpectedUid(extraAssistBundle);
         int actualUid = mAssistBundle.getInt(Intent.EXTRA_ASSIST_UID);
         assertEquals("Wrong value for EXTRA_ASSIST_UID", expectedUid, actualUid);
-
-    }
-
-    private void waitForOnResume() throws Exception {
-        Log.i(TAG, "waiting for onResume() before continuing");
-        if (!mHasResumedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            fail("Activity failed to resume in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
-        }
-    }
-
-    private class ExtraAssistDataReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(Utils.APP_3P_HASRESUMED)) {
-                if (mHasResumedLatch != null) {
-                    mHasResumedLatch.countDown();
-                }
-            } else if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED)) {
-                if (mReadyLatch != null) {
-                    mReadyLatch.countDown();
-                }
-            }
-        }
     }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/FlagSecureTest.java b/tests/tests/assist/src/android/assist/cts/FlagSecureTest.java
index 2d5a989..97573d8 100644
--- a/tests/tests/assist/src/android/assist/cts/FlagSecureTest.java
+++ b/tests/tests/assist/src/android/assist/cts/FlagSecureTest.java
@@ -16,16 +16,10 @@
 
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.util.Log;
 
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 /**
  * Test we receive proper assist data (root assistStructure with no children) when the assistant is
  * invoked on an app with FLAG_SECURE set.
@@ -38,66 +32,21 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        setUpAndRegisterReceiver();
         startTestActivity(TEST_CASE_TYPE);
     }
 
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
-    }
-
-    private void setUpAndRegisterReceiver() {
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new FlagSecureTestBroadcastReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.FLAG_SECURE_HASRESUMED);
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        mContext.registerReceiver(mReceiver, filter);
-    }
-
-    private void waitForOnResume() throws Exception {
-        Log.i(TAG, "waiting for onResume() before continuing");
-        if (!mHasResumedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            fail("Activity failed to resume in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
-        }
-    }
-
     public void testSecureActivity() throws Exception {
         if (!mContext.getPackageManager().hasSystemFeature(FEATURE_VOICE_RECOGNIZERS)) {
             Log.d(TAG, "Not running assist tests - voice_recognizers feature is not supported");
             return;
         }
         startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady(mReadyLatch);
+        waitForAssistantToBeReady();
         start3pApp(TEST_CASE_TYPE);
-        waitForOnResume();
-        final CountDownLatch latch = startSession();
+        final AutoResetLatch latch = startSession();
         waitForContext(latch);
         verifyAssistDataNullness(false, false, false, false);
         // verify that we have only the root window and not its children.
         verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE), true);
     }
-
-    private class FlagSecureTestBroadcastReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(Utils.FLAG_SECURE_HASRESUMED)) {
-                if (mHasResumedLatch != null) {
-                    mHasResumedLatch.countDown();
-                }
-            } else if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED)) {
-                if (mReadyLatch != null) {
-                    mReadyLatch.countDown();
-                }
-            }
-        }
-    }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/FocusChangeTest.java b/tests/tests/assist/src/android/assist/cts/FocusChangeTest.java
index e42b0d0..bc63a43 100644
--- a/tests/tests/assist/src/android/assist/cts/FocusChangeTest.java
+++ b/tests/tests/assist/src/android/assist/cts/FocusChangeTest.java
@@ -16,53 +16,31 @@
 
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.util.Log;
+import android.util.Pair;
 
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /** Test that triggering the Assistant causes the underlying Activity to lose focus **/
-
 public class FocusChangeTest extends AssistTestBase {
     private static final String TAG = "FocusChangeTest";
     private static final String TEST_CASE_TYPE = Utils.FOCUS_CHANGE;
 
-    private final CountDownLatch mHasGainedFocusLatch = new CountDownLatch(1);
-    private final CountDownLatch mHasLostFocusLatch = new CountDownLatch(1);
+    private AutoResetLatch mHasGainedFocusLatch = new AutoResetLatch(1);
+    private AutoResetLatch mHasLostFocusLatch = new AutoResetLatch(1);
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        setUpAndRegisterReceiver();
+        mActionLatchReceiver = new ActionLatchReceiver(
+                Pair.create(Utils.GAINED_FOCUS, mHasGainedFocusLatch),
+                Pair.create(Utils.LOST_FOCUS, mHasLostFocusLatch)
+        );
         startTestActivity(TEST_CASE_TYPE);
     }
 
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
-    }
-
-    private void setUpAndRegisterReceiver() {
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new FocusChangeTestReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.GAINED_FOCUS);
-        filter.addAction(Utils.LOST_FOCUS);
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        mContext.registerReceiver(mReceiver, filter);
-    }
-
     private void waitToGainFocus() throws Exception {
         Log.i(TAG, "Waiting for the underlying activity to gain focus before continuing.");
         if (!mHasGainedFocusLatch.await(Utils.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
@@ -74,7 +52,7 @@
         Log.i(TAG, "Waiting for the underlying activity to lose focus.");
         if (!mHasLostFocusLatch.await(Utils.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
             fail("Activity maintained focus despite the Assistant Firing"
-                 + Utils.TIMEOUT_MS + "msec.");
+                    + Utils.TIMEOUT_MS + "msec.");
         }
     }
 
@@ -84,26 +62,10 @@
             return;
         }
         startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady(mReadyLatch);
+        waitForAssistantToBeReady();
         start3pApp(TEST_CASE_TYPE);
         waitToGainFocus();
         startSession();
         waitToLoseFocus();
     }
-
-    private class FocusChangeTestReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(Utils.GAINED_FOCUS) && mHasGainedFocusLatch != null) {
-                mHasGainedFocusLatch.countDown();
-            } else if (action.equals(Utils.LOST_FOCUS) && mHasLostFocusLatch != null) {
-                mHasLostFocusLatch.countDown();
-            } else if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED)) {
-                if (mReadyLatch != null) {
-                    mReadyLatch.countDown();
-                }
-            }
-        }
-    }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/LargeViewHierarchyTest.java b/tests/tests/assist/src/android/assist/cts/LargeViewHierarchyTest.java
index cf2a47c..05a473e 100644
--- a/tests/tests/assist/src/android/assist/cts/LargeViewHierarchyTest.java
+++ b/tests/tests/assist/src/android/assist/cts/LargeViewHierarchyTest.java
@@ -16,20 +16,13 @@
 
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.util.Log;
 
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 /**
  *  Test that the AssistStructure returned is properly formatted.
  */
-
 public class LargeViewHierarchyTest extends AssistTestBase {
     private static final String TAG = "LargeViewHierarchyTest";
     private static final String TEST_CASE_TYPE = Utils.LARGE_VIEW_HIERARCHY;
@@ -37,37 +30,9 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        setUpAndRegisterReceiver();
         startTestActivity(TEST_CASE_TYPE);
     }
 
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
-    }
-
-    private void setUpAndRegisterReceiver() {
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new LargeViewTestBroadcastReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.APP_3P_HASRESUMED);
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        mContext.registerReceiver(mReceiver, filter);
-    }
-
-    private void waitForOnResume() throws Exception {
-        Log.i(TAG, "waiting for onResume() before continuing");
-        if (!mHasResumedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            fail("Activity failed to resume in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
-        }
-    }
-
     public void testTextView() throws Exception {
         if (mActivityManager.isLowRamDevice()) {
             Log.d(TAG, "Not running assist tests on low-RAM device.");
@@ -75,25 +40,12 @@
         }
         start3pApp(TEST_CASE_TYPE);
         startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady(mReadyLatch);
-        waitForOnResume();
-        final CountDownLatch latch = startSession();
+        waitForAssistantToBeReady();
+        final AutoResetLatch latch = startSession();
         waitForContext(latch);
         verifyAssistDataNullness(false, false, false, false);
 
         verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE),
                 false /*FLAG_SECURE set*/);
     }
-
-    private class LargeViewTestBroadcastReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(Utils.APP_3P_HASRESUMED) && mHasResumedLatch != null) {
-                mHasResumedLatch.countDown();
-            } else if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED) && mReadyLatch != null) {
-                mReadyLatch.countDown();
-            }
-        }
-    }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/LifecycleTest.java b/tests/tests/assist/src/android/assist/cts/LifecycleTest.java
index 037d534..c35f8f0 100644
--- a/tests/tests/assist/src/android/assist/cts/LifecycleTest.java
+++ b/tests/tests/assist/src/android/assist/cts/LifecycleTest.java
@@ -16,21 +16,16 @@
 
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
+import android.os.Bundle;
 import android.util.Log;
 
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /** Test we receive proper assist data when context is disabled or enabled */
-
 public class LifecycleTest extends AssistTestBase {
     private static final String TAG = "LifecycleTest";
-    private static final String ACTION_HAS_RESUMED = Utils.LIFECYCLE_HASRESUMED;
     private static final String ACTION_HAS_FOCUS = Utils.LIFECYCLE_HASFOCUS;
     private static final String ACTION_LOST_FOCUS = Utils.LIFECYCLE_LOSTFOCUS;
     private static final String ACTION_ON_PAUSE = Utils.LIFECYCLE_ONPAUSE;
@@ -39,46 +34,20 @@
 
     private static final String TEST_CASE_TYPE = Utils.LIFECYCLE;
 
-    private BroadcastReceiver mLifecycleTestBroadcastReceiver;
-    private final CountDownLatch mHasFocusLatch = new CountDownLatch(1);
-    private final CountDownLatch mLostFocusLatch = new CountDownLatch(1);
-    private final CountDownLatch mActivityLifecycleLatch = new CountDownLatch(1);
-    private final CountDownLatch mDestroyLatch = new CountDownLatch(1);
+    private AutoResetLatch mHasFocusLatch = new AutoResetLatch(1);
+    private AutoResetLatch mLostFocusLatch = new AutoResetLatch(1);
+    private AutoResetLatch mActivityLifecycleLatch = new AutoResetLatch(1);
+    private AutoResetLatch mDestroyLatch = new AutoResetLatch(1);
     private boolean mLostFocusIsLifecycle;
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mLifecycleTestBroadcastReceiver = new LifecycleTestReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(ACTION_HAS_RESUMED);
-        filter.addAction(ACTION_HAS_FOCUS);
-        filter.addAction(ACTION_LOST_FOCUS);
-        filter.addAction(ACTION_ON_PAUSE);
-        filter.addAction(ACTION_ON_STOP);
-        filter.addAction(ACTION_ON_DESTROY);
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        mContext.registerReceiver(mLifecycleTestBroadcastReceiver, filter);
+        mActionLatchReceiver = new LifecycleTestReceiver();
         mLostFocusIsLifecycle = false;
         startTestActivity(TEST_CASE_TYPE);
     }
 
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        if (mLifecycleTestBroadcastReceiver != null) {
-            mContext.unregisterReceiver(mLifecycleTestBroadcastReceiver);
-            mLifecycleTestBroadcastReceiver = null;
-        }
-    }
-
-    private void waitForOnResume() throws Exception {
-        Log.i(TAG, "waiting for onResume() before continuing");
-        if (!mHasResumedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            fail("Activity failed to resume in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
-        }
-    }
-
     private void waitForHasFocus() throws Exception {
         Log.i(TAG, "waiting for window focus gain before continuing");
         if (!mHasFocusLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
@@ -112,11 +81,10 @@
             return;
         }
         startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady(mReadyLatch);
+        waitForAssistantToBeReady();
         start3pApp(TEST_CASE_TYPE);
-        waitForOnResume();
         waitForHasFocus();
-        final CountDownLatch latch = startSession();
+        final AutoResetLatch latch = startSession();
         waitForContext(latch);
         // Since there is no UI, focus should not be lost.  We are counting focus lost as
         // a lifecycle event in this case.
@@ -124,7 +92,11 @@
         // calling the above (RACY!!!).
         waitForLostFocus();
         waitAndSeeIfLifecycleMethodsAreTriggered();
-        mContext.sendBroadcast(new Intent(Utils.HIDE_LIFECYCLE_ACTIVITY));
+
+        Bundle bundle = new Bundle();
+        bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.HIDE_LIFECYCLE_ACTIVITY);
+        m3pActivityCallback.sendResult(bundle);
+
         waitForDestroy();
     }
 
@@ -135,26 +107,27 @@
         }
         mLostFocusIsLifecycle = true;
         startTest(Utils.LIFECYCLE_NOUI);
-        waitForAssistantToBeReady(mReadyLatch);
+        waitForAssistantToBeReady();
         start3pApp(Utils.LIFECYCLE_NOUI);
-        waitForOnResume();
         waitForHasFocus();
-        final CountDownLatch latch = startSession();
+        final AutoResetLatch latch = startSession();
         waitForContext(latch);
         // Do this after waitForContext(), since we don't start looking for context until
         // calling the above (RACY!!!).
         waitAndSeeIfLifecycleMethodsAreTriggered();
-        mContext.sendBroadcast(new Intent(Utils.HIDE_LIFECYCLE_ACTIVITY));
+
+        Bundle bundle = new Bundle();
+        bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.HIDE_LIFECYCLE_ACTIVITY);
+        m3pActivityCallback.sendResult(bundle);
+
         waitForDestroy();
     }
 
-    private class LifecycleTestReceiver extends BroadcastReceiver {
+    private class LifecycleTestReceiver extends ActionLatchReceiver {
+
         @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(ACTION_HAS_RESUMED) && mHasResumedLatch != null) {
-                mHasResumedLatch.countDown();
-            } else if (action.equals(ACTION_HAS_FOCUS) && mHasFocusLatch != null) {
+        protected void onAction(Bundle bundle, String action) {
+            if (action.equals(ACTION_HAS_FOCUS) && mHasFocusLatch != null) {
                 mHasFocusLatch.countDown();
             } else if (action.equals(ACTION_LOST_FOCUS) && mLostFocusLatch != null) {
                 if (mLostFocusIsLifecycle) {
@@ -169,10 +142,8 @@
             } else if (action.equals(ACTION_ON_DESTROY) && mActivityLifecycleLatch != null) {
                 mActivityLifecycleLatch.countDown();
                 mDestroyLatch.countDown();
-            } else if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED)) {
-                if (mReadyLatch != null) {
-                    mReadyLatch.countDown();
-                }
+            } else {
+                super.onAction(bundle, action);
             }
         }
     }
diff --git a/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java b/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java
index e24ef54..9458cf3 100644
--- a/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java
+++ b/tests/tests/assist/src/android/assist/cts/ScreenshotTest.java
@@ -16,58 +16,38 @@
 
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.graphics.Color;
 import android.os.Bundle;
 import android.util.Log;
 
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 public class ScreenshotTest extends AssistTestBase {
     static final String TAG = "ScreenshotTest";
 
     private static final String TEST_CASE_TYPE = Utils.SCREENSHOT;
 
-    private BroadcastReceiver mScreenshotActivityReceiver;
-
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        // set up receiver
-        mScreenshotActivityReceiver = new ScreenshotTestReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        filter.addAction(Utils.APP_3P_HASRESUMED);
-        mContext.registerReceiver(mScreenshotActivityReceiver, filter);
-
         // start test start activity
         startTestActivity(TEST_CASE_TYPE);
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        if (mScreenshotActivityReceiver != null) {
-            mContext.unregisterReceiver(mScreenshotActivityReceiver);
-        }
-        super.tearDown();
-    }
-
     public void testRedScreenshot() throws Exception {
         if (mActivityManager.isLowRamDevice()) {
             Log.d(TAG, "Not running assist tests on low-RAM device.");
             return;
         }
-        Log.i(TAG, "Starting screenshot test");
-        startTest(TEST_CASE_TYPE);
-        Log.i(TAG, "start waitForAssistantToBeReady()");
-        waitForAssistantToBeReady(mReadyLatch);
 
-        waitForActivityResumeAndAssist(Color.RED);
+        startTest(TEST_CASE_TYPE);
+        waitForAssistantToBeReady();
+
+        Bundle bundle = new Bundle();
+        bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, Color.RED);
+        start3pApp(TEST_CASE_TYPE, bundle);
+
+        delayAndStartSession(Color.RED);
         verifyAssistDataNullness(false, false, false, false);
         assertTrue(mScreenshotMatches);
     }
@@ -77,12 +57,15 @@
             Log.d(TAG, "Not running assist tests on low-RAM device.");
             return;
         }
-        Log.i(TAG, "Starting screenshot test");
-        startTest(TEST_CASE_TYPE);
-        Log.i(TAG, "start waitForAssistantToBeReady()");
-        waitForAssistantToBeReady(mReadyLatch);
 
-        waitForActivityResumeAndAssist(Color.GREEN);
+        startTest(TEST_CASE_TYPE);
+        waitForAssistantToBeReady();
+
+        Bundle bundle = new Bundle();
+        bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, Color.GREEN);
+        start3pApp(TEST_CASE_TYPE, bundle);
+
+        delayAndStartSession(Color.GREEN);
         verifyAssistDataNullness(false, false, false, false);
         assertTrue(mScreenshotMatches);
     }
@@ -92,42 +75,28 @@
             Log.d(TAG, "Not running assist tests on low-RAM device.");
             return;
         }
-        Log.i(TAG, "Starting screenshot test");
-        startTest(TEST_CASE_TYPE);
-        Log.i(TAG, "start waitForAssistantToBeReady()");
-        waitForAssistantToBeReady(mReadyLatch);
 
-        waitForActivityResumeAndAssist(Color.BLUE);
+        startTest(TEST_CASE_TYPE);
+        waitForAssistantToBeReady();
+
+        Bundle bundle = new Bundle();
+        bundle.putInt(Utils.SCREENSHOT_COLOR_KEY, Color.BLUE);
+        start3pApp(TEST_CASE_TYPE, bundle);
+
+        delayAndStartSession(Color.BLUE);
         verifyAssistDataNullness(false, false, false, false);
         assertTrue(mScreenshotMatches);
     }
 
-    private void waitForActivityResumeAndAssist(int color) throws Exception {
+    private void delayAndStartSession(int color) throws Exception {
+        // Screenshot testing requires the entire screen to settle, including layout requests
+        // and any animations. The time is arbitrary as there is no good event for knowing when
+        // the Activity has settled.
+        Thread.sleep(350);
+
         Bundle extras = new Bundle();
         extras.putInt(Utils.SCREENSHOT_COLOR_KEY, color);
-        final CountDownLatch latch = startSession(TEST_CASE_TYPE, extras);
-        Log.i(TAG, "waiting for onResume() before continuing.");
-        if (!mHasResumedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            fail("activity failed to resume in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
-        }
+        final AutoResetLatch latch = startSession(TEST_CASE_TYPE, extras);
         waitForContext(latch);
     }
-
-    private class ScreenshotTestReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            Log.i(ScreenshotTest.TAG, "Got some broadcast: " + action);
-            if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED)) {
-                Log.i(ScreenshotTest.TAG, "Received assist receiver is registered.");
-                if (mReadyLatch != null) {
-                    mReadyLatch.countDown();
-                }
-            } else if (action.equals(Utils.APP_3P_HASRESUMED)) {
-                if (mHasResumedLatch != null) {
-                    mHasResumedLatch.countDown();
-                }
-            }
-        }
-    }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/TestStartActivity.java b/tests/tests/assist/src/android/assist/cts/TestStartActivity.java
index 80c6e48..eebf30d 100644
--- a/tests/tests/assist/src/android/assist/cts/TestStartActivity.java
+++ b/tests/tests/assist/src/android/assist/cts/TestStartActivity.java
@@ -16,9 +16,8 @@
 
 package android.assist.cts;
 
-import android.app.Activity;
+import android.assist.common.BaseRemoteCallbackActivity;
 import android.assist.common.Utils;
-import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
@@ -30,9 +29,7 @@
 import android.widget.ScrollView;
 import android.widget.TextView;
 
-import java.util.concurrent.CountDownLatch;
-
-public class TestStartActivity extends Activity {
+public class TestStartActivity extends BaseRemoteCallbackActivity {
     static final String TAG = "TestStartActivity";
 
     private ScrollView mScrollView;
@@ -51,8 +48,8 @@
                 return;
             case Utils.TEXTVIEW:
                 setContentView(R.layout.text_view);
-                mTextView =  (TextView) findViewById(R.id.text_view);
-                mScrollView = (ScrollView) findViewById(R.id.scroll_view);
+                mTextView = findViewById(R.id.text_view);
+                mScrollView = findViewById(R.id.scroll_view);
                 setTitle(R.string.textViewActivityTitle);
                 return;
             case Utils.LARGE_VIEW_HIERARCHY:
@@ -64,11 +61,11 @@
                         PackageManager.FEATURE_WEBVIEW)) {
                     setContentView(R.layout.webview);
                     setTitle(R.string.webViewActivityTitle);
-                    WebView webview = (WebView) findViewById(R.id.webview);
+                    WebView webview = findViewById(R.id.webview);
                     webview.setWebViewClient(new WebViewClient() {
                         @Override
                         public void onPageFinished(WebView view, String url) {
-                            sendBroadcast(new Intent(Utils.TEST_ACTIVITY_LOADED));
+                            TestStartActivity.this.notify(Utils.TEST_ACTIVITY_WEBVIEW_LOADED);
                         }
                     });
                     webview.loadData(Utils.WEBVIEW_HTML, "text/html", "UTF-8");
@@ -83,35 +80,6 @@
         Log.i(TAG, " in onResume");
     }
 
-    public void startTest(String testCaseName) {
-        Log.i(TAG, "Starting test activity for TestCaseType = " + testCaseName);
-        Intent intent = new Intent();
-        intent.putExtra(Utils.TESTCASE_TYPE, testCaseName);
-        intent.setAction("android.intent.action.START_TEST_" + testCaseName);
-        intent.setComponent(new ComponentName("android.assist.service",
-                "android.assist." + Utils.getTestActivity(testCaseName)));
-        startActivity(intent);
-    }
-
-    public void start3pApp(String testCaseName, CountDownLatch resumedLatch,
-            CountDownLatch drawedLatch) {
-        final RemoteCallback resumedCallback = new RemoteCallback((result) -> {
-            Log.v(TAG, "Testapp called resumed callback for " + testCaseName);
-            resumedLatch.countDown();
-        });
-        final RemoteCallback drawedCallback = new RemoteCallback((result) -> {
-            Log.v(TAG, "Testapp called drawed callback for " + testCaseName);
-            drawedLatch.countDown();
-        });
-        Intent intent = new Intent();
-        intent.putExtra(Utils.TESTCASE_TYPE, testCaseName);
-        intent.setAction("android.intent.action.TEST_APP_" + testCaseName);
-        intent.setComponent(Utils.getTestAppComponent(testCaseName));
-        intent.putExtra(Utils.EXTRA_CALLBACK_ACTIVITY_RESUMED, resumedCallback);
-        intent.putExtra(Utils.EXTRA_CALLBACK_ACTIVITY_DRAWED, drawedCallback);
-        startActivity(intent);
-    }
-
     @Override
     protected void onPause() {
         Log.i(TAG, " in onPause");
@@ -143,22 +111,26 @@
 
     public void scrollText(int scrollX, int scrollY, boolean scrollTextView,
             boolean scrollScrollView) {
-        if (scrollTextView) {
-            if (scrollX < 0 || scrollY < 0) {
-                scrollX = mTextView.getWidth();
-                scrollY = mTextView.getLayout().getLineTop(mTextView.getLineCount()) - mTextView.getHeight();
-            }
-            Log.i(TAG, "Scrolling text view to " + scrollX + ", " + scrollY);
-            mTextView.scrollTo(scrollX, scrollY);
-        } else if (scrollScrollView) {
-            if (scrollX < 0 || scrollY < 0) {
-                Log.i(TAG, "Scrolling scroll view to bottom right");
-                mScrollView.fullScroll(View.FOCUS_DOWN);
-                mScrollView.fullScroll(View.FOCUS_RIGHT);
-            } else {
-                Log.i(TAG, "Scrolling scroll view to " + scrollX + ", " + scrollY);
-                mScrollView.scrollTo(scrollX, scrollY);
-            }
+        if (scrollX < 0 || scrollY < 0) {
+            scrollX = mTextView.getWidth();
+            scrollY = mTextView.getLayout().getLineTop(mTextView.getLineCount()) - mTextView.getHeight();
         }
+        int finalScrollX = scrollX;
+        int finalScrollY = scrollY;
+        runOnUiThread(() -> {
+            if (scrollTextView) {
+                Log.i(TAG, "Scrolling text view to " + finalScrollX + ", " + finalScrollY);
+                mTextView.scrollTo(finalScrollX, finalScrollY);
+            } else if (scrollScrollView) {
+                if (finalScrollX < 0 || finalScrollY < 0) {
+                    Log.i(TAG, "Scrolling scroll view to bottom right");
+                    mScrollView.fullScroll(View.FOCUS_DOWN);
+                    mScrollView.fullScroll(View.FOCUS_RIGHT);
+                } else {
+                    Log.i(TAG, "Scrolling scroll view to " + finalScrollX + ", " + finalScrollY);
+                    mScrollView.scrollTo(finalScrollX, finalScrollY);
+                }
+            }
+        });
     }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/TextViewTest.java b/tests/tests/assist/src/android/assist/cts/TextViewTest.java
index a3ef572..6b06442 100644
--- a/tests/tests/assist/src/android/assist/cts/TextViewTest.java
+++ b/tests/tests/assist/src/android/assist/cts/TextViewTest.java
@@ -16,20 +16,14 @@
 
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
+import android.os.Bundle;
 import android.util.Log;
 
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 /**
  *  Test that the AssistStructure returned is properly formatted.
  */
-
 public class TextViewTest extends AssistTestBase {
     private static final String TAG = "TextViewTest";
     private static final String TEST_CASE_TYPE = Utils.TEXTVIEW;
@@ -37,50 +31,22 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        setUpAndRegisterReceiver();
         startTestActivity(TEST_CASE_TYPE);
     }
 
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
-    }
-
-    private void setUpAndRegisterReceiver() {
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new TextViewTestBroadcastReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.APP_3P_HASRESUMED);
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        mContext.registerReceiver(mReceiver, filter);
-    }
-
-    private void waitForOnResume() throws Exception {
-        Log.i(TAG, "waiting for onResume() before continuing");
-        if (!mHasResumedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            fail("Activity failed to resume in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
-        }
-    }
-
     public void testTextView() throws Exception {
         if (mActivityManager.isLowRamDevice()) {
             Log.d(TAG, "Not running assist tests on low-RAM device.");
             return;
         }
+
         start3pApp(TEST_CASE_TYPE);
         scrollTestApp(0, 0, true, false);
 
         // Verify that the text view contains the right text
         startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady(mReadyLatch);
-        waitForOnResume();
-        final CountDownLatch latch1 = startSession();
+        waitForAssistantToBeReady();
+        final AutoResetLatch latch1 = startSession();
         waitForContext(latch1);
         verifyAssistDataNullness(false, false, false, false);
 
@@ -89,39 +55,38 @@
 
         // Verify that the scroll position of the text view is accurate after scrolling.
         scrollTestApp(10, 50, true /* scrollTextView */, false /* scrollScrollView */);
-        waitForOnResume();
-        final CountDownLatch latch2 = startSession();
+        final AutoResetLatch latch2 = startSession();
         waitForContext(latch2);
         verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE), false);
 
         scrollTestApp(-1, -1, true, false);
-        waitForOnResume();
-        final CountDownLatch latch3 = startSession();
+        final AutoResetLatch latch3 = startSession();
         waitForContext(latch3);
         verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE), false);
 
         scrollTestApp(0, 0, true, true);
-        waitForOnResume();
-        final CountDownLatch latch4 = startSession();
+        final AutoResetLatch latch4 = startSession();
         waitForContext(latch4);
         verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE), false);
 
         scrollTestApp(10, 50, false, true);
-        waitForOnResume();
-        final CountDownLatch latch5 = startSession();
+        final AutoResetLatch latch5 = startSession();
         waitForContext(latch5);
         verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE), false);
     }
 
-    private class TextViewTestBroadcastReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(Utils.APP_3P_HASRESUMED) && mHasResumedLatch != null) {
-                mHasResumedLatch.countDown();
-            } else if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED) &&  mReadyLatch != null) {
-                mReadyLatch.countDown();
-            }
+    @Override
+    protected void scrollTestApp(int scrollX, int scrollY, boolean scrollTextView,
+            boolean scrollScrollView) {
+        super.scrollTestApp(scrollX, scrollY, scrollTextView, scrollScrollView);
+        Bundle bundle = new Bundle();
+        if (scrollTextView) {
+            bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.SCROLL_TEXTVIEW_ACTION);
+        } else if (scrollScrollView) {
+            bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.SCROLL_SCROLLVIEW_ACTION);
         }
+        bundle.putInt(Utils.SCROLL_X_POSITION, scrollX);
+        bundle.putInt(Utils.SCROLL_Y_POSITION, scrollY);
+        m3pActivityCallback.sendResult(bundle);
     }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/WebViewTest.java b/tests/tests/assist/src/android/assist/cts/WebViewTest.java
index a38362d..c913c82 100644
--- a/tests/tests/assist/src/android/assist/cts/WebViewTest.java
+++ b/tests/tests/assist/src/android/assist/cts/WebViewTest.java
@@ -16,68 +16,33 @@
 
 package android.assist.cts;
 
+import android.assist.common.AutoResetLatch;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.os.LocaleList;
 import android.util.Log;
 
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /**
  *  Test that the AssistStructure returned is properly formatted.
  */
-
 public class WebViewTest extends AssistTestBase {
     private static final String TAG = "WebViewTest";
     private static final String TEST_CASE_TYPE = Utils.WEBVIEW;
 
-    private boolean mWebViewSupported;
-    private final CountDownLatch mTestWebViewLatch = new CountDownLatch(1);
+    private final AutoResetLatch mTestWebViewLatch = new AutoResetLatch();
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        setUpAndRegisterReceiver();
+        mActionLatchReceiver = new ActionLatchReceiver(Utils.TEST_ACTIVITY_WEBVIEW_LOADED, mTestWebViewLatch);
         startTestActivity(TEST_CASE_TYPE);
     }
 
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
-    }
-
-    private void setUpAndRegisterReceiver() {
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-        }
-        mReceiver = new WebViewTestBroadcastReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.APP_3P_HASRESUMED);
-        filter.addAction(Utils.ASSIST_RECEIVER_REGISTERED);
-        filter.addAction(Utils.TEST_ACTIVITY_LOADED);
-        mContext.registerReceiver(mReceiver, filter);
-    }
-
-    private void waitForOnResume() throws Exception {
-        Log.i(TAG, "waiting for onResume() before continuing");
-        if (!mHasResumedLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            fail("Activity failed to resume in " + Utils.ACTIVITY_ONRESUME_TIMEOUT_MS + "msec");
-        }
-    }
-
     private void waitForTestActivity() throws Exception {
         Log.i(TAG, "waiting for webview in test activity to load");
         if (!mTestWebViewLatch.await(Utils.ACTIVITY_ONRESUME_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            // wait for webView to load completely.
+            fail("failed to receive load web view in " + Utils.TIMEOUT_MS + "msec");
         }
     }
 
@@ -91,10 +56,13 @@
         }
         start3pApp(TEST_CASE_TYPE);
         startTest(TEST_CASE_TYPE);
-        waitForAssistantToBeReady(mReadyLatch);
-        waitForOnResume();
+        waitForAssistantToBeReady();
         waitForTestActivity();
-        final CountDownLatch latch = startSession();
+
+        // WebView doesn't render fast enough before test runs, so use some arbirary delay
+        Thread.sleep(350);
+
+        final AutoResetLatch latch = startSession();
         waitForContext(latch);
         verifyAssistDataNullness(false, false, false, false);
         verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE),
@@ -102,18 +70,4 @@
         verifyAssistStructureHasWebDomain(Utils.WEBVIEW_HTML_DOMAIN);
         verifyAssistStructureHasLocaleList(Utils.WEBVIEW_LOCALE_LIST);
     }
-
-    private class WebViewTestBroadcastReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(Utils.APP_3P_HASRESUMED) && mHasResumedLatch != null) {
-                mHasResumedLatch.countDown();
-            } else if (action.equals(Utils.ASSIST_RECEIVER_REGISTERED) && mReadyLatch != null) {
-                mReadyLatch.countDown();
-            } else if (action.equals(Utils.TEST_ACTIVITY_LOADED) && mTestWebViewLatch != null) {
-                mTestWebViewLatch.countDown();
-            }
-        }
-    }
 }
diff --git a/tests/tests/assist/testapp/AndroidManifest.xml b/tests/tests/assist/testapp/AndroidManifest.xml
index ee4c68f..513d27a 100644
--- a/tests/tests/assist/testapp/AndroidManifest.xml
+++ b/tests/tests/assist/testapp/AndroidManifest.xml
@@ -27,18 +27,11 @@
                 android:label="Assist Structure Test Activity">
           <intent-filter>
               <action android:name="android.intent.action.TEST_APP_ASSIST_STRUCTURE" />
-              <action android:name="android.intent.action.TEST_APP_LARGE_VIEWHIERARCHY" />
+              <action android:name="android.intent.action.TEST_APP_LARGE_VIEW_HIERARCHY" />
               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.VOICE" />
           </intent-filter>
         </activity>
-        <activity android:name=".DisableContextActivity"
-            android:label="Disable Context Test Activity">
-            <intent-filter>
-                <action android:name="android.intent.action.TEST_APP_DISABLE_CONTEXT" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
         <activity android:name=".SecureActivity"
                   android:label="Secure Test Activity">
             <intent-filter>
@@ -51,6 +44,7 @@
                   android:label="Life Cycle Check Activity">
             <intent-filter>
                 <action android:name="android.intent.action.TEST_APP_LIFECYCLE" />
+                <action android:name="android.intent.action.TEST_APP_LIFECYCLE_NOUI" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.VOICE" />
             </intent-filter>
diff --git a/tests/tests/assist/testapp/src/android/assist/testapp/BaseThirdPartyActivity.java b/tests/tests/assist/testapp/src/android/assist/testapp/BaseThirdPartyActivity.java
new file mode 100644
index 0000000..5296a77
--- /dev/null
+++ b/tests/tests/assist/testapp/src/android/assist/testapp/BaseThirdPartyActivity.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.assist.testapp;
+
+import android.assist.common.BaseRemoteCallbackActivity;
+import android.assist.common.Utils;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+public class BaseThirdPartyActivity extends BaseRemoteCallbackActivity {
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        final View layout = findViewById(android.R.id.content);
+        ViewTreeObserver vto = layout.getViewTreeObserver();
+        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+            @Override
+            public void onGlobalLayout() {
+                layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                BaseThirdPartyActivity.this.notify(Utils.APP_3P_HASRESUMED);
+            }
+        });
+    }
+}
diff --git a/tests/tests/assist/testapp/src/android/assist/testapp/ExtraAssistDataActivity.java b/tests/tests/assist/testapp/src/android/assist/testapp/ExtraAssistDataActivity.java
index 4b4c909..6173005 100644
--- a/tests/tests/assist/testapp/src/android/assist/testapp/ExtraAssistDataActivity.java
+++ b/tests/tests/assist/testapp/src/android/assist/testapp/ExtraAssistDataActivity.java
@@ -15,10 +15,8 @@
  */
 package android.assist.testapp;
 
-import android.app.Activity;
 import android.app.assist.AssistContent;
 import android.assist.common.Utils;
-import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 
@@ -27,7 +25,7 @@
  * provide extra information to the assistant. Verify that the data passed from the activity matches
  * the data received in {@link android.service.voice.VoiceInteractionSession}.
  */
-public class ExtraAssistDataActivity extends Activity {
+public class ExtraAssistDataActivity extends BaseThirdPartyActivity {
     private static final String TAG = "ExtraAssistDataActivity";
 
     @Override
@@ -47,10 +45,4 @@
             Log.i(TAG, "Failed to get Structured JSON to put into the AssistContent.");
         }
     }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        sendBroadcast(new Intent(Utils.APP_3P_HASRESUMED));
-    }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/assist/testapp/src/android/assist/testapp/FocusChangeActivity.java b/tests/tests/assist/testapp/src/android/assist/testapp/FocusChangeActivity.java
index 4ab24ed..d4893c4 100644
--- a/tests/tests/assist/testapp/src/android/assist/testapp/FocusChangeActivity.java
+++ b/tests/tests/assist/testapp/src/android/assist/testapp/FocusChangeActivity.java
@@ -16,12 +16,10 @@
 
 package android.assist.testapp;
 
-import android.app.Activity;
 import android.assist.common.Utils;
-import android.content.Intent;
 import android.util.Log;
 
-public class FocusChangeActivity extends Activity {
+public class FocusChangeActivity extends BaseThirdPartyActivity {
     private static final String TAG = "FocusChangeActivity";
     private boolean mGainedFocus = false;
 
@@ -30,10 +28,10 @@
         if (hasFocus && !mGainedFocus) {
             mGainedFocus = true;
             Log.i(TAG, "gained focus");
-            sendBroadcast(new Intent(Utils.GAINED_FOCUS));
+            notify(Utils.GAINED_FOCUS);
         } else if (!hasFocus && mGainedFocus) {
             Log.i(TAG, "lost focus");
-            sendBroadcast(new Intent(Utils.LOST_FOCUS));
+            notify(Utils.LOST_FOCUS);
         }
     }
 }
diff --git a/tests/tests/assist/testapp/src/android/assist/testapp/LifecycleActivity.java b/tests/tests/assist/testapp/src/android/assist/testapp/LifecycleActivity.java
index 0602d3f..9f76bbe 100644
--- a/tests/tests/assist/testapp/src/android/assist/testapp/LifecycleActivity.java
+++ b/tests/tests/assist/testapp/src/android/assist/testapp/LifecycleActivity.java
@@ -16,42 +16,25 @@
 
 package android.assist.testapp;
 
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
+import android.assist.common.Utils;
 import android.os.Bundle;
 import android.util.Log;
 
-public class LifecycleActivity extends Activity {
+public class LifecycleActivity extends BaseThirdPartyActivity {
     private static final String TAG = "LifecycleActivity";
 
-    private BroadcastReceiver mReceiver;
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         Log.i(TAG, "LifecycleActivity created");
-        mReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                String action = intent.getAction();
-                if (action.equals("android.intent.action.hide_lifecycle_activity")) {
-                    finish();
-                }
-            }
-        };
-        IntentFilter filter = new IntentFilter();
-        filter.addAction("android.intent.action.hide_lifecycle_activity");
-        registerReceiver(mReceiver, filter);
     }
 
     @Override
-    protected void onResume() {
-        super.onResume();
-        Log.i(TAG, "Activity has resumed");
-        sendBroadcast(new Intent("android.intent.action.lifecycle_hasResumed"));
+    protected void onReceivedEventFromCaller(Bundle results, String action) {
+        super.onReceivedEventFromCaller(results, action);
+        if (action.equals(Utils.HIDE_LIFECYCLE_ACTIVITY)) {
+            finish();
+        }
     }
 
     @Override
@@ -59,31 +42,30 @@
         super.onWindowFocusChanged(hasFocus);
         Log.i(TAG, "Activity focus changed: " + hasFocus);
         if (hasFocus) {
-            sendBroadcast(new Intent("android.intent.action.lifecycle_hasFocus"));
+            notify("android.intent.action.lifecycle_hasFocus");
         } else {
-            sendBroadcast(new Intent("android.intent.action.lifecycle_lostFocus"));
+            notify("android.intent.action.lifecycle_lostFocus");
         }
     }
 
     @Override
     protected void onPause() {
         Log.i(TAG, "activity was paused");
-        sendBroadcast(new Intent("android.intent.action.lifecycle_onpause"));
+        notify("android.intent.action.lifecycle_onpause");
         super.onPause();
     }
 
     @Override
     protected void onStop() {
         Log.i(TAG, "activity was stopped");
-        sendBroadcast(new Intent("android.intent.action.lifecycle_onstop"));
+        notify("android.intent.action.lifecycle_onstop");
         super.onStop();
     }
 
     @Override
     protected void onDestroy() {
         Log.i(TAG, "activity was destroyed");
-        sendBroadcast(new Intent("android.intent.action.lifecycle_ondestroy"));
-        unregisterReceiver(mReceiver);
+        notify("android.intent.action.lifecycle_ondestroy");
         super.onDestroy();
     }
 }
diff --git a/tests/tests/assist/testapp/src/android/assist/testapp/ScreenshotActivity.java b/tests/tests/assist/testapp/src/android/assist/testapp/ScreenshotActivity.java
index fb08e77..6cf7ef6 100644
--- a/tests/tests/assist/testapp/src/android/assist/testapp/ScreenshotActivity.java
+++ b/tests/tests/assist/testapp/src/android/assist/testapp/ScreenshotActivity.java
@@ -15,15 +15,13 @@
  */
 package android.assist.testapp;
 
-import android.app.Activity;
 import android.assist.common.Utils;
-import android.content.Intent;
 import android.graphics.Color;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.View;
 
-public class ScreenshotActivity extends Activity {
+public class ScreenshotActivity extends BaseThirdPartyActivity {
     static final String TAG = "ScreenshotActivity";
 
     @Override
@@ -31,21 +29,11 @@
         super.onCreate(savedInstanceState);
         Log.i(TAG, "ScreenshotActivity created");
         setContentView(R.layout.screenshot_activity);
-    }
 
-    @Override
-    public void onResume() {
-        Log.i(TAG, " in onResume");
-        super.onResume();
         int backgroundColor = getIntent().getIntExtra(Utils.SCREENSHOT_COLOR_KEY, Color.WHITE);
         View view = findViewById(R.id.screenshot_activity);
         view.setBackgroundColor(backgroundColor);
         view.requestLayout();
-
-        // Tell service activity is in foreground.
-        Intent intent = new Intent(Utils.APP_3P_HASRESUMED);
-        sendBroadcast(intent);
-        Log.i(TAG, "Resumed broadcast sent.");
     }
 
     @Override
diff --git a/tests/tests/assist/testapp/src/android/assist/testapp/SecureActivity.java b/tests/tests/assist/testapp/src/android/assist/testapp/SecureActivity.java
index 0f812b7..ae41aca 100644
--- a/tests/tests/assist/testapp/src/android/assist/testapp/SecureActivity.java
+++ b/tests/tests/assist/testapp/src/android/assist/testapp/SecureActivity.java
@@ -16,17 +16,11 @@
 
 package android.assist.testapp;
 
-import android.app.Activity;
-import android.assist.common.Utils;
-import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
-import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.WindowManager;
 
-public class SecureActivity extends Activity {
+public class SecureActivity extends BaseThirdPartyActivity {
     static final String TAG = "SecureActivity";
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -36,19 +30,4 @@
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
             WindowManager.LayoutParams.FLAG_SECURE);
     }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        Log.i(TAG, "Activity has resumed");
-        final View layout = findViewById(android.R.id.content);
-        ViewTreeObserver vto = layout.getViewTreeObserver();
-        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-            @Override
-            public void onGlobalLayout() {
-                layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                sendBroadcast(new Intent(Utils.FLAG_SECURE_HASRESUMED));
-            }
-        });
-    }
 }
diff --git a/tests/tests/assist/testapp/src/android/assist/testapp/TestApp.java b/tests/tests/assist/testapp/src/android/assist/testapp/TestApp.java
index 7865c4d..c094435 100755
--- a/tests/tests/assist/testapp/src/android/assist/testapp/TestApp.java
+++ b/tests/tests/assist/testapp/src/android/assist/testapp/TestApp.java
@@ -16,29 +16,19 @@
 
 package android.assist.testapp;
 
-import android.app.Activity;
 import android.assist.common.Utils;
-import android.content.Intent;
 import android.os.Bundle;
-import android.os.RemoteCallback;
 import android.util.Log;
-import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 
-public class TestApp extends Activity {
+public class TestApp extends BaseThirdPartyActivity {
     static final String TAG = "TestApp";
 
     private String mTestCaseName;
-    private RemoteCallback mResumedCallback;
-    private RemoteCallback mDrawedCallback;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         Log.i(TAG, "TestApp created: " + getIntent());
-        mResumedCallback = getIntent().getParcelableExtra(Utils.EXTRA_CALLBACK_ACTIVITY_RESUMED);
-        mDrawedCallback = getIntent().getParcelableExtra(Utils.EXTRA_CALLBACK_ACTIVITY_DRAWED);
         mTestCaseName = getIntent().getStringExtra(Utils.TESTCASE_TYPE);
         switch (mTestCaseName) {
             case Utils.LARGE_VIEW_HIERARCHY:
@@ -50,38 +40,9 @@
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-        Log.i(TAG, "TestApp has resumed");
-        final View layout = findViewById(android.R.id.content);
-        ViewTreeObserver vto = layout.getViewTreeObserver();
-        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-            @Override
-            public void onGlobalLayout() {
-                layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                if (mResumedCallback != null) {
-                    Log.i(TAG, "onGlobalLayout(): notifying callback");
-                    mResumedCallback.sendResult(/* result= */ null);
-                } else {
-                    // TODO(b/133431034): should only use callbacks
-                    Log.w(TAG, "No resume callback onGlobalLayout(); broadcasting instead");
-                    sendBroadcast(new Intent(Utils.APP_3P_HASRESUMED));
-                }
-            }
-        });
-    }
-
-    @Override
     public void onEnterAnimationComplete() {
         Log.i(TAG, "TestApp onEnterAnimationComplete ");
-        if (mDrawedCallback != null) {
-            Log.i(TAG, "onEnterAnimationComplete(): notifying callback");
-            mDrawedCallback.sendResult(/* result= */ null);
-        } else {
-            // TODO(b/133431034): should only use callbacks
-            Log.w(TAG, "No resume callback onEnterAnimationComplete(); broadcasting instead");
-            sendBroadcast(new Intent(Utils.APP_3P_HASDRAWED));
-        }
+        notify(Utils.APP_3P_HASDRAWED);
     }
 
-}
\ No newline at end of file
+}
diff --git a/tests/tests/assist/testapp/src/android/assist/testapp/TextViewActivity.java b/tests/tests/assist/testapp/src/android/assist/testapp/TextViewActivity.java
index c031292..d7a32bb 100644
--- a/tests/tests/assist/testapp/src/android/assist/testapp/TextViewActivity.java
+++ b/tests/tests/assist/testapp/src/android/assist/testapp/TextViewActivity.java
@@ -16,25 +16,17 @@
 
 package android.assist.testapp;
 
-import android.app.Activity;
 import android.assist.common.Utils;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.os.Bundle;
 import android.text.method.ScrollingMovementMethod;
 import android.util.Log;
 import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.widget.ScrollView;
 import android.widget.TextView;
 
-public class TextViewActivity extends Activity {
+public class TextViewActivity extends BaseThirdPartyActivity {
     static final String TAG = "TextViewActivity";
 
-    private BroadcastReceiver mReceiver;
     private TextView mTextView;
     private ScrollView mScrollView;
 
@@ -43,68 +35,38 @@
         super.onCreate(savedInstanceState);
         Log.i(TAG, "TextViewActivity created");
         setContentView(R.layout.text_view);
-        mScrollView = (ScrollView) findViewById(R.id.scroll_view);
-        mTextView = (TextView) findViewById(R.id.text_view);
+        mScrollView = findViewById(R.id.scroll_view);
+        mTextView = findViewById(R.id.text_view);
         mTextView.setMovementMethod(new ScrollingMovementMethod());
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-        Log.i(TAG, "TextViewActivity has resumed");
+    protected void onReceivedEventFromCaller(Bundle results, String action) {
+        super.onReceivedEventFromCaller(results, action);
 
-        mReceiver = new ScrollReceiver();
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Utils.SCROLL_TEXTVIEW_ACTION);
-        filter.addAction(Utils.SCROLL_SCROLLVIEW_ACTION);
-        registerReceiver(mReceiver, filter);
-
-        final View layout = findViewById(android.R.id.content);
-        ViewTreeObserver vto = layout.getViewTreeObserver();
-        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-            @Override
-            public void onGlobalLayout() {
-                layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                sendBroadcast(new Intent(Utils.APP_3P_HASRESUMED));
+        int scrollX, scrollY;
+        scrollX = results.getInt(Utils.SCROLL_X_POSITION, 0);
+        scrollY = results.getInt(Utils.SCROLL_Y_POSITION, 0);
+        if (action.equals(Utils.SCROLL_TEXTVIEW_ACTION)) {
+            Log.i(TAG, "Scrolling textview to (" + scrollX + "," + scrollY + ")");
+            if (scrollX < 0 || scrollY < 0) {
+                // Scroll to bottom as negative positions are not possible.
+                scrollX = mTextView.getWidth();
+                scrollY = mTextView.getLayout().getLineTop(mTextView.getLineCount())
+                        - mTextView.getHeight();
             }
-        });
-    }
-
-    @Override
-    public void onPause() {
-        if (mReceiver != null) {
-            unregisterReceiver(mReceiver);
-        }
-        super.onPause();
-    }
-
-    class ScrollReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            int scrollX, scrollY;
-            scrollX = intent.getIntExtra(Utils.SCROLL_X_POSITION, 0);
-            scrollY = intent.getIntExtra(Utils.SCROLL_Y_POSITION, 0);
-            if (intent.getAction().equals(Utils.SCROLL_TEXTVIEW_ACTION)) {
-                Log.i(TAG, "Scrolling textview to (" + scrollX + "," + scrollY + ")");
-                if (scrollX < 0 || scrollY < 0) {
-                    // Scroll to bottom as negative positions are not possible.
-                    scrollX = mTextView.getWidth();
-                    scrollY = mTextView.getLayout().getLineTop(mTextView.getLineCount())
-                            - mTextView.getHeight();
-                }
-                TextViewActivity.this.mTextView.scrollTo(scrollX, scrollY);
-            } else if (intent.getAction().equals(Utils.SCROLL_SCROLLVIEW_ACTION)) {
-                Log.i(TAG, "Scrolling scrollview to (" + scrollX + "," + scrollY + ")");
-                if (scrollX < 0 || scrollY < 0) {
-                    // Scroll to bottom
-                    TextViewActivity.this.mScrollView.fullScroll(View.FOCUS_DOWN);
-                    TextViewActivity.this.mScrollView.fullScroll(View.FOCUS_RIGHT);
-                } else {
-                    TextViewActivity.this.mScrollView.scrollTo(scrollX, scrollY);
-                }
+            TextViewActivity.this.mTextView.scrollTo(scrollX, scrollY);
+        } else if (action.equals(Utils.SCROLL_SCROLLVIEW_ACTION)) {
+            Log.i(TAG, "Scrolling scrollview to (" + scrollX + "," + scrollY + ")");
+            if (scrollX < 0 || scrollY < 0) {
+                // Scroll to bottom
+                TextViewActivity.this.mScrollView.fullScroll(View.FOCUS_DOWN);
+                TextViewActivity.this.mScrollView.fullScroll(View.FOCUS_RIGHT);
+            } else {
+                TextViewActivity.this.mScrollView.scrollTo(scrollX, scrollY);
             }
-            Log.i(TAG, "the max height of this textview is: " + mTextView.getHeight());
-            Log.i(TAG, "the max line count of this text view is: " + mTextView.getMaxLines());
         }
+        Log.i(TAG, "the max height of this textview is: " + mTextView.getHeight());
+        Log.i(TAG, "the max line count of this text view is: " + mTextView.getMaxLines());
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/assist/testapp/src/android/assist/testapp/WebViewActivity.java b/tests/tests/assist/testapp/src/android/assist/testapp/WebViewActivity.java
index c62bf97..f092a0e 100644
--- a/tests/tests/assist/testapp/src/android/assist/testapp/WebViewActivity.java
+++ b/tests/tests/assist/testapp/src/android/assist/testapp/WebViewActivity.java
@@ -16,32 +16,26 @@
 
 package android.assist.testapp;
 
-import android.app.Activity;
 import android.assist.common.MyWebView;
 import android.assist.common.Utils;
-import android.content.Context;
-import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 
-public class WebViewActivity extends Activity {
+public class WebViewActivity extends BaseThirdPartyActivity {
     static final String TAG = "WebViewActivity";
 
-    private String mTestCaseName;
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         Log.i(TAG, "TestApp created");
-        mTestCaseName = getIntent().getStringExtra(Utils.TESTCASE_TYPE);
         setContentView(R.layout.webview);
-        MyWebView webview = (MyWebView) findViewById(R.id.webview);
+        MyWebView webview = findViewById(R.id.webview);
         webview.setWebViewClient(new WebViewClient() {
             @Override
-            public void onPageFinished(WebView view, String url){
-                sendBroadcast(new Intent(Utils.APP_3P_HASRESUMED));
+            public void onPageFinished(WebView view, String url) {
+                WebViewActivity.this.notify(Utils.APP_3P_HASRESUMED);
             }
         });
         webview.myLoadData(Utils.WEBVIEW_HTML_URL, Utils.WEBVIEW_HTML, "text/html", "UTF-8");
diff --git a/tests/tests/car/src/android/car/cts/CarInfoManagerTest.java b/tests/tests/car/src/android/car/cts/CarInfoManagerTest.java
index fc4571c..e3ca341 100644
--- a/tests/tests/car/src/android/car/cts/CarInfoManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarInfoManagerTest.java
@@ -42,6 +42,10 @@
 public class CarInfoManagerTest extends CarApiTestBase {
 
     private CarInfoManager mCarInfoManager;
+    // SCAME EvConnectorType in VHAL
+    private static final int SCAME = 11;
+    // GBT_DC EvConnectorType in VHAL
+    private static final int GBT_DC = 10;
 
     @Before
     public void setUp() throws Exception {
@@ -112,7 +116,8 @@
             Arrays.asList(EvConnectorType.UNKNOWN, EvConnectorType.J1772, EvConnectorType.MENNEKES,
                 EvConnectorType.CHADEMO, EvConnectorType.COMBO_1, EvConnectorType.COMBO_2,
                 EvConnectorType.TESLA_ROADSTER, EvConnectorType.TESLA_HPWC,
-                EvConnectorType.TESLA_SUPERCHARGER, EvConnectorType.GBT, EvConnectorType.OTHER);
+                EvConnectorType.TESLA_SUPERCHARGER, EvConnectorType.GBT, EvConnectorType.OTHER,
+                SCAME, GBT_DC);
 
         for (int result : actualResults) {
             assertThat(expectedResults).contains(result);
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
index 3ad6fee..379edc5 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
@@ -593,7 +593,7 @@
         // {@link TelephonyManager#iccOpenLogicalChannel} sends a Manage Channel (open) APDU
         // followed by a Select APDU with the given AID and p2 values. See Open Mobile API
         // Specification v3.2 Section 6.2.7.h and TS 102 221 for details.
-        int p2 = 0;
+        int p2 = 0x0C; // '0C' for no data returned (TS 102 221 Section 11.1.1.2)
         response = mTelephonyManager.iccOpenLogicalChannel("", p2);
         verifyValidIccOpenLogicalChannelResponse(response);
         mTelephonyManager.iccCloseLogicalChannel(response.getChannel());
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
index 1278f1e..7e29288 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
@@ -84,8 +84,10 @@
         allowedDensities.add(DisplayMetrics.DENSITY_400);
         allowedDensities.add(DisplayMetrics.DENSITY_420);
         allowedDensities.add(DisplayMetrics.DENSITY_440);
+        allowedDensities.add(DisplayMetrics.DENSITY_450);
         allowedDensities.add(DisplayMetrics.DENSITY_XXHIGH);
         allowedDensities.add(DisplayMetrics.DENSITY_560);
+        allowedDensities.add(DisplayMetrics.DENSITY_600);
         allowedDensities.add(DisplayMetrics.DENSITY_XXXHIGH);
         assertTrue("DisplayMetrics.DENSITY_DEVICE_STABLE must be one of the DisplayMetrics.DENSITY_* values: "
                 + allowedDensities, allowedDensities.contains(DisplayMetrics.DENSITY_DEVICE_STABLE));
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ColorStateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ColorStateListDrawableTest.java
index 1455255..562504c 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ColorStateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ColorStateListDrawableTest.java
@@ -24,6 +24,7 @@
 
 import android.R;
 import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
@@ -68,8 +69,22 @@
 
     @Test
     public void testDraw() {
-        Canvas c = new Canvas();
-        mDrawable.draw(c);
+        Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+
+        try {
+            Canvas canvas = new Canvas(bitmap);
+            mDrawable.setBounds(0, 0, 1, 1);
+
+            mDrawable.setState(STATE_RED);
+            mDrawable.draw(canvas);
+            assertEquals(Color.RED, bitmap.getPixel(0, 0));
+
+            mDrawable.setState(STATE_BLUE);
+            mDrawable.draw(canvas);
+            assertEquals(Color.BLUE, bitmap.getPixel(0, 0));
+        } finally {
+            bitmap.recycle();
+        }
     }
 
     @Test
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
index ba841c7..4cbddcb 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
@@ -1513,6 +1513,16 @@
         assertEquals(height, dr.getIntrinsicHeight());
     }
 
+    @Test
+    public void testIsProjectedWithNullLayer() {
+        try {
+            LayerDrawable dr = new LayerDrawable(new Drawable[] {null});
+            dr.isProjected();
+        } catch (NullPointerException excep) {
+            fail("isProjected should support null child layer drawables");
+        }
+    }
+
     // Since Mockito can't mock or spy on protected methods, we have a custom extension
     // of Drawable to track calls to protected methods. This class also has empty implementations
     // of the base abstract methods. In addition, this class also updates its padding on every
diff --git a/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java b/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
index 7e999be..0e6843d 100644
--- a/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
@@ -41,20 +41,24 @@
   private static final int MIN_SATELLITES_REQUIREMENT = 4;
   private static final double SECONDS_PER_NANO = 1.0e-9;
 
-  // GPS/GLONASS: according to http://cdn.intechopen.com/pdfs-wm/27712.pdf, the pseudorange in time
-  // is 65-83 ms, which is 18 ms range.
-  // GLONASS: orbit is a bit closer than GPS, so we add 0.003ms to the range, hence deltaiSeconds
-  // should be in the range of [0.0, 0.021] seconds.
-  // QZSS and BEIDOU: they have higher orbit, which will result in a small svTime, the deltai can be
-  // calculated as follows:
-  // assume a = QZSS/BEIDOU orbit Semi-Major Axis(42,164km for QZSS);
-  // b = GLONASS orbit Semi-Major Axis (25,508km);
-  // c = Speed of light (299,792km/s);
-  // e = earth radius (6,378km);
-  // in the extremely case of QZSS is on the horizon and GLONASS is on the 90 degree top
-  // max difference should be (sqrt(a^2-e^2) - (b-e))/c,
-  // which is around 0.076s.
-  private static final double PSEUDORANGE_THRESHOLD_IN_SEC = 0.021;
+    // GPS/GLONASS: according to http://cdn.intechopen.com/pdfs-wm/27712.pdf, the pseudorange in
+    // time
+    // is 65-83 ms, which is 18 ms range.
+    // GLONASS: orbit is a bit closer than GPS, so we add 0.003ms to the range, hence deltaiSeconds
+    // should be in the range of [0.0, 0.021] seconds.
+    // QZSS and BEIDOU: they have higher orbit, which will result in a small svTime, the deltai
+    // can be
+    // calculated as follows:
+    // assume a = QZSS/BEIDOU orbit Semi-Major Axis(42,164km for QZSS);
+    // b = GLONASS orbit Semi-Major Axis (25,508km);
+    // c = Speed of light (299,792km/s);
+    // e = earth radius (6,378km);
+    // in the extremely case of QZSS is on the horizon and GLONASS is on the 90 degree top
+    // max difference should be (sqrt(a^2-e^2) - (b-e))/c,
+    // which is around 0.076s.
+    // 2 Galileo satellites (E14 & E18) have elliptical orbits, so Galileo can have up-to 48ms of
+    // spread.
+    private static final double PSEUDORANGE_THRESHOLD_IN_SEC = 0.048;
   // Geosync constellations have a longer range vs typical MEO orbits
   // that are the short end of the range.
   private static final double PSEUDORANGE_THRESHOLD_BEIDOU_QZSS_IN_SEC = 0.076;
@@ -174,23 +178,27 @@
     return measurementConstellationMap;
   }
 
-  private ArrayList<GnssMeasurement> filterMeasurements(Collection<GnssMeasurement> measurements) {
-    ArrayList<GnssMeasurement> filteredMeasurement = new ArrayList<>();
-    for (GnssMeasurement measurement: measurements){
-      int constellationType = measurement.getConstellationType();
-      if (constellationType == GnssStatus.CONSTELLATION_GLONASS) {
-        if ((measurement.getState()
-            & (measurement.STATE_GLO_TOD_DECODED | measurement.STATE_GLO_TOD_KNOWN)) != 0) {
-          filteredMeasurement.add(measurement);
+    private static ArrayList<GnssMeasurement> filterMeasurements(
+            Collection<GnssMeasurement> measurements) {
+        ArrayList<GnssMeasurement> filteredMeasurement = new ArrayList<>();
+        for (GnssMeasurement measurement : measurements) {
+            int constellationType = measurement.getConstellationType();
+            if ((measurement.getState() & GnssMeasurement.STATE_CODE_LOCK) == 0) {
+                continue;
+            }
+            if (constellationType == GnssStatus.CONSTELLATION_GLONASS) {
+                if ((measurement.getState()
+                        & (GnssMeasurement.STATE_GLO_TOD_DECODED
+                        | GnssMeasurement.STATE_GLO_TOD_KNOWN)) != 0) {
+                    filteredMeasurement.add(measurement);
+                }
+            } else if ((measurement.getState() & (GnssMeasurement.STATE_TOW_DECODED
+                    | GnssMeasurement.STATE_TOW_KNOWN)) != 0) {
+                filteredMeasurement.add(measurement);
+            }
         }
-      }
-      else if ((measurement.getState()
-            & (measurement.STATE_TOW_DECODED | measurement.STATE_TOW_KNOWN)) != 0) {
-          filteredMeasurement.add(measurement);
-        }
+        return filteredMeasurement;
     }
-    return filteredMeasurement;
-  }
 
   /**
    * Uses the common reception time approach to calculate pseudorange time
diff --git a/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java b/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
index 1ceb025..0803da3 100644
--- a/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
@@ -57,6 +57,7 @@
     private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
     private static final int FRAME_RATE = 15;               // 15fps
     private static final int IFRAME_INTERVAL = 10;          // 10 seconds between I-frames
+    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
@@ -418,9 +419,17 @@
             decoder = MediaCodec.createDecoderByType(MIME_TYPE);
             outputSurface = new OutputSurface();
             outputSurface.changeFragmentShader(FRAGMENT_SHADER);
+            // do not allow frame drops
+            inputFormat.setInteger(KEY_ALLOW_FRAME_DROP, 0);
+
             decoder.configure(inputFormat, outputSurface.getSurface(), null, 0);
             decoder.start();
 
+            // verify that we are not dropping frames
+            inputFormat = decoder.getInputFormat();
+            assertEquals("Could not prevent frame dropping",
+                         0, inputFormat.getInteger(KEY_ALLOW_FRAME_DROP));
+
             editVideoData(inputData, decoder, outputSurface, inputSurface, encoder, outputData);
         } finally {
             if (VERBOSE) Log.d(TAG, "shutting down encoder, decoder");
@@ -617,6 +626,7 @@
 
             MediaFormat format = inputData.getMediaFormat();
             decoder = MediaCodec.createDecoderByType(MIME_TYPE);
+            format.setInteger(KEY_ALLOW_FRAME_DROP, 0);
             decoder.configure(format, surface.getSurface(), null, 0);
             decoder.start();
 
@@ -829,7 +839,7 @@
          * Gets the MediaFormat that was used by the encoder.
          */
         public MediaFormat getMediaFormat() {
-            return mMediaFormat;
+            return new MediaFormat(mMediaFormat);
         }
 
         /**
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
index 29cec3f..90cd301 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
@@ -794,6 +794,13 @@
                                 covered);
                     }
                 }
+                // non-standard points should not be covered by any other performance point
+                for (VideoCapabilities.PerformancePoint pp2 : points) {
+                    // using object equality to determine otherness
+                    assertFalse(pp2 + " for " + info.getCanonicalName()
+                            + " for media type " + mediaType + " covers " + pp,
+                            pp2 != pp && pp2.covers(pp));
+                }
             }
         }
     }
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 789d1ba..ede1711 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -237,9 +237,15 @@
         if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
             return; // skip
         }
+        MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080);
+        String[] decoderNames = MediaUtils.getDecoderNames(false, format);
 
-        // Play stream for 60 seconds
-        localHlsTest("unmuxed_1500k/index.m3u8", 60 * 1000, -1, false /*isAudioOnly*/);
+        if (decoderNames.length == 0) {
+            MediaUtils.skipTest("No decoders for " + format);
+        } else {
+            // Play stream for 60 seconds
+            localHlsTest("unmuxed_1500k/index.m3u8", 60 * 1000, -1, false /*isAudioOnly*/);
+        }
     }
 
 
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
index 8c9bf6e..e9deec9 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -35,6 +35,7 @@
 
 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
 
+import android.annotation.NonNull;
 import android.app.Instrumentation;
 import android.app.PendingIntent;
 import android.app.UiAutomation;
@@ -59,6 +60,7 @@
 import android.net.cts.util.CtsNetUtils;
 import android.net.util.KeepaliveUtils;
 import android.net.wifi.WifiManager;
+import android.os.Build;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.SystemClock;
@@ -99,6 +101,7 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -113,6 +116,8 @@
     private static final int CONNECT_TIMEOUT_MS = 2000;
     private static final int KEEPALIVE_CALLBACK_TIMEOUT_MS = 2000;
     private static final int KEEPALIVE_SOCKET_TIMEOUT_MS = 5000;
+    private static final int INTERVAL_KEEPALIVE_RETRY_MS = 500;
+    private static final int MAX_KEEPALIVE_RETRY_COUNT = 3;
     private static final int MIN_KEEPALIVE_INTERVAL = 10;
     private static final int NETWORK_CHANGE_METEREDNESS_TIMEOUT = 5000;
     private static final int NUM_TRIES_MULTIPATH_PREF_CHECK = 20;
@@ -120,6 +125,10 @@
     // device could have only one interface: data, wifi.
     private static final int MIN_NUM_NETWORK_TYPES = 1;
 
+    // Minimum supported keepalive counts for wifi and cellular.
+    public static final int MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT = 1;
+    public static final int MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT = 3;
+
     private Context mContext;
     private Instrumentation mInstrumentation;
     private ConnectivityManager mCm;
@@ -839,8 +848,7 @@
         return s;
     }
 
-    private int getSupportedKeepalivesFromRes() throws Exception {
-        final Network network = ensureWifiConnected();
+    private int getSupportedKeepalivesForNet(@NonNull Network network) throws Exception {
         final NetworkCapabilities nc = mCm.getNetworkCapabilities(network);
 
         // Get number of supported concurrent keepalives for testing network.
@@ -914,34 +922,46 @@
      * keepalives is set to 0.
      */
     @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
-    public void testKeepaliveUnsupported() throws Exception {
-        if (getSupportedKeepalivesFromRes() != 0) return;
+    public void testKeepaliveWifiUnsupported() throws Exception {
+        if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+            Log.i(TAG, "testKeepaliveUnsupported cannot execute unless device"
+                    + " supports WiFi");
+            return;
+        }
+
+        final Network network = ensureWifiConnected();
+        if (getSupportedKeepalivesForNet(network) != 0) return;
 
         adoptShellPermissionIdentity();
 
-        assertEquals(0, createConcurrentSocketKeepalives(1, 0));
-        assertEquals(0, createConcurrentSocketKeepalives(0, 1));
+        assertEquals(0, createConcurrentSocketKeepalives(network, 1, 0));
+        assertEquals(0, createConcurrentSocketKeepalives(network, 0, 1));
 
         dropShellPermissionIdentity();
     }
 
     @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
     public void testCreateTcpKeepalive() throws Exception {
+        if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+            Log.i(TAG, "testCreateTcpKeepalive cannot execute unless device supports WiFi");
+            return;
+        }
+
         adoptShellPermissionIdentity();
 
-        if (getSupportedKeepalivesFromRes() == 0) return;
+        final Network network = ensureWifiConnected();
+        if (getSupportedKeepalivesForNet(network) == 0) return;
         // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support
         // NAT-T keepalive. If keepalive limits from resource overlay is not zero, TCP keepalive
         // needs to be supported except if the kernel doesn't support it.
         if (!isTcpKeepaliveSupportedByKernel()) {
             // Sanity check to ensure the callback result is expected.
-            assertEquals(0, createConcurrentSocketKeepalives(0, 1));
+            assertEquals(0, createConcurrentSocketKeepalives(network, 0, 1));
             Log.i(TAG, "testCreateTcpKeepalive is skipped for kernel "
                     + VintfRuntimeInfo.getKernelVersion());
             return;
         }
 
-        final Network network = ensureWifiConnected();
         final byte[] requestBytes = CtsNetUtils.HTTP_REQUEST.getBytes("UTF-8");
         // So far only ipv4 tcp keepalive offload is supported.
         // TODO: add test case for ipv6 tcp keepalive offload when it is supported.
@@ -1007,80 +1027,102 @@
         }
     }
 
-    /**
-     * Creates concurrent keepalives until the specified counts of each type of keepalives are
-     * reached or the expected error callbacks are received for each type of keepalives.
-     *
-     * @return the total number of keepalives created.
-     */
-    private int createConcurrentSocketKeepalives(int nattCount, int tcpCount) throws Exception {
-        final Network network = ensureWifiConnected();
-
+    private ArrayList<SocketKeepalive> createConcurrentKeepalivesOfType(
+            int requestCount, @NonNull TestSocketKeepaliveCallback callback,
+            Supplier<SocketKeepalive> kaFactory) {
         final ArrayList<SocketKeepalive> kalist = new ArrayList<>();
-        final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
-        final Executor executor = mContext.getMainExecutor();
 
-        // Create concurrent TCP keepalives.
-        for (int i = 0; i < tcpCount; i++) {
-            // Assert that TCP connections can be established on wifi. The file descriptor of tcp
-            // sockets will be duplicated and kept valid in service side if the keepalives are
-            // successfully started.
-            try (Socket tcpSocket = getConnectedSocket(network, TEST_HOST, HTTP_PORT,
-                        0 /* Unused */, AF_INET)) {
-                final SocketKeepalive ka = mCm.createSocketKeepalive(network, tcpSocket, executor,
-                        callback);
-                ka.start(MIN_KEEPALIVE_INTERVAL);
-                TestSocketKeepaliveCallback.CallbackValue cv = callback.pollCallback();
-                assertNotNull(cv);
-                if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_ERROR) {
-                    if (i == 0 && cv.error == SocketKeepalive.ERROR_UNSUPPORTED) {
-                        // Unsupported.
-                        break;
-                    } else if (i != 0 && cv.error == SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES) {
-                        // Limit reached.
-                        break;
-                    }
-                }
-                if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_STARTED) {
-                    kalist.add(ka);
-                } else {
-                    fail("Unexpected error when creating " + (i + 1) + " TCP keepalives: " + cv);
-                }
-            }
-        }
+        int remainingRetries = MAX_KEEPALIVE_RETRY_COUNT;
 
-        // Assert that a Nat-T socket can be created.
-        final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
-        final UdpEncapsulationSocket nattSocket = mIpSec.openUdpEncapsulationSocket();
-
-        final InetAddress srcAddr = getFirstV4Address(network);
-        final InetAddress dstAddr = getAddrByName(TEST_HOST, AF_INET);
-        assertNotNull(srcAddr);
-        assertNotNull(dstAddr);
-
-        // Test concurrent Nat-T keepalives.
-        for (int i = 0; i < nattCount; i++) {
-            final SocketKeepalive ka = mCm.createSocketKeepalive(network, nattSocket,
-                    srcAddr, dstAddr, executor, callback);
+        // Test concurrent keepalives with the given supplier.
+        while (kalist.size() < requestCount) {
+            final SocketKeepalive ka = kaFactory.get();
             ka.start(MIN_KEEPALIVE_INTERVAL);
             TestSocketKeepaliveCallback.CallbackValue cv = callback.pollCallback();
             assertNotNull(cv);
             if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_ERROR) {
-                if (i == 0 && cv.error == SocketKeepalive.ERROR_UNSUPPORTED) {
+                if (kalist.size() == 0 && cv.error == SocketKeepalive.ERROR_UNSUPPORTED) {
                     // Unsupported.
                     break;
-                } else if (i != 0 && cv.error == SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES) {
-                    // Limit reached.
+                } else if (cv.error == SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES) {
+                    // Limit reached or temporary unavailable due to stopped slot is not yet
+                    // released.
+                    if (remainingRetries > 0) {
+                        SystemClock.sleep(INTERVAL_KEEPALIVE_RETRY_MS);
+                        remainingRetries--;
+                        continue;
+                    }
                     break;
                 }
             }
             if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_STARTED) {
                 kalist.add(ka);
             } else {
-                fail("Unexpected error when creating " + (i + 1) + " Nat-T keepalives: " + cv);
+                fail("Unexpected error when creating " + (kalist.size() + 1) + " "
+                        + ka.getClass().getSimpleName() + ": " + cv);
             }
         }
 
+        return kalist;
+    }
+
+    private @NonNull ArrayList<SocketKeepalive> createConcurrentNattSocketKeepalives(
+            @NonNull Network network, int requestCount,
+            @NonNull TestSocketKeepaliveCallback callback)  throws Exception {
+
+        final Executor executor = mContext.getMainExecutor();
+
+        // Initialize a real NaT-T socket.
+        final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
+        final UdpEncapsulationSocket nattSocket = mIpSec.openUdpEncapsulationSocket();
+        final InetAddress srcAddr = getFirstV4Address(network);
+        final InetAddress dstAddr = getAddrByName(TEST_HOST, AF_INET);
+        assertNotNull(srcAddr);
+        assertNotNull(dstAddr);
+
+        // Test concurrent Nat-T keepalives.
+        final ArrayList<SocketKeepalive> result = createConcurrentKeepalivesOfType(requestCount,
+                callback, () -> mCm.createSocketKeepalive(network, nattSocket,
+                        srcAddr, dstAddr, executor, callback));
+
+        nattSocket.close();
+        return result;
+    }
+
+    private @NonNull ArrayList<SocketKeepalive> createConcurrentTcpSocketKeepalives(
+            @NonNull Network network, int requestCount,
+            @NonNull TestSocketKeepaliveCallback callback) {
+        final Executor executor = mContext.getMainExecutor();
+
+        // Create concurrent TCP keepalives.
+        return createConcurrentKeepalivesOfType(requestCount, callback, () -> {
+            // Assert that TCP connections can be established. The file descriptor of tcp
+            // sockets will be duplicated and kept valid in service side if the keepalives are
+            // successfully started.
+            try (Socket tcpSocket = getConnectedSocket(network, TEST_HOST, HTTP_PORT,
+                    0 /* Unused */, AF_INET)) {
+                return mCm.createSocketKeepalive(network, tcpSocket, executor, callback);
+            } catch (Exception e) {
+                fail("Unexpected error when creating TCP socket: " + e);
+            }
+            return null;
+        });
+    }
+
+    /**
+     * Creates concurrent keepalives until the specified counts of each type of keepalives are
+     * reached or the expected error callbacks are received for each type of keepalives.
+     *
+     * @return the total number of keepalives created.
+     */
+    private int createConcurrentSocketKeepalives(
+            @NonNull Network network, int nattCount, int tcpCount) throws Exception {
+        final ArrayList<SocketKeepalive> kalist = new ArrayList<>();
+        final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
+
+        kalist.addAll(createConcurrentNattSocketKeepalives(network, nattCount, callback));
+        kalist.addAll(createConcurrentTcpSocketKeepalives(network, tcpCount, callback));
+
         final int ret = kalist.size();
 
         // Clean up.
@@ -1089,7 +1131,6 @@
             callback.expectStopped();
         }
         kalist.clear();
-        nattSocket.close();
 
         return ret;
     }
@@ -1099,8 +1140,15 @@
      * get leaked after iterations.
      */
     @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
-    public void testSocketKeepaliveLimit() throws Exception {
-        final int supported = getSupportedKeepalivesFromRes();
+    public void testSocketKeepaliveLimitWifi() throws Exception {
+        if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+            Log.i(TAG, "testSocketKeepaliveLimitWifi cannot execute unless device"
+                    + " supports WiFi");
+            return;
+        }
+
+        final Network network = ensureWifiConnected();
+        final int supported = getSupportedKeepalivesForNet(network);
         if (supported == 0) {
             return;
         }
@@ -1108,25 +1156,25 @@
         adoptShellPermissionIdentity();
 
         // Verifies that the supported keepalive slots meet MIN_SUPPORTED_KEEPALIVE_COUNT.
-        assertGreaterOrEqual(supported, KeepaliveUtils.MIN_SUPPORTED_KEEPALIVE_COUNT);
+        assertGreaterOrEqual(supported, MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT);
 
         // Verifies that Nat-T keepalives can be established.
-        assertEquals(supported, createConcurrentSocketKeepalives(supported + 1, 0));
+        assertEquals(supported, createConcurrentSocketKeepalives(network, supported + 1, 0));
         // Verifies that keepalives don't get leaked in second round.
-        assertEquals(supported, createConcurrentSocketKeepalives(supported + 1, 0));
+        assertEquals(supported, createConcurrentSocketKeepalives(network, supported, 0));
 
         // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support
         // NAT-T keepalive. Test below cases only if TCP keepalive is supported by kernel.
         if (isTcpKeepaliveSupportedByKernel()) {
-            assertEquals(supported, createConcurrentSocketKeepalives(0, supported + 1));
+            assertEquals(supported, createConcurrentSocketKeepalives(network, 0, supported + 1));
 
             // Verifies that different types can be established at the same time.
-            assertEquals(supported, createConcurrentSocketKeepalives(
+            assertEquals(supported, createConcurrentSocketKeepalives(network,
                     supported / 2, supported - supported / 2));
 
             // Verifies that keepalives don't get leaked in second round.
-            assertEquals(supported, createConcurrentSocketKeepalives(0, supported + 1));
-            assertEquals(supported, createConcurrentSocketKeepalives(
+            assertEquals(supported, createConcurrentSocketKeepalives(network, 0, supported));
+            assertEquals(supported, createConcurrentSocketKeepalives(network,
                     supported / 2, supported - supported / 2));
         }
 
@@ -1134,11 +1182,53 @@
     }
 
     /**
+     * Verifies that the concurrent keepalive slots meet the minimum telephony requirement, and
+     * don't get leaked after iterations.
+     */
+    @AppModeFull(reason = "Cannot request network in instant app mode")
+    public void testSocketKeepaliveLimitTelephony() throws Exception {
+        if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) {
+            Log.i(TAG, "testSocketKeepaliveLimitTelephony cannot execute unless device"
+                    + " supports telephony");
+            return;
+        }
+
+        final int firstSdk = Build.VERSION.FIRST_SDK_INT;
+        if (firstSdk < Build.VERSION_CODES.Q) {
+            Log.i(TAG, "testSocketKeepaliveLimitTelephony: skip test for devices launching"
+                    + " before Q: " + firstSdk);
+            return;
+        }
+
+        final Network network = mCtsNetUtils.connectToCell();
+        final int supported = getSupportedKeepalivesForNet(network);
+
+        adoptShellPermissionIdentity();
+
+        // Verifies that the supported keepalive slots meet minimum requirement.
+        assertGreaterOrEqual(supported, MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT);
+
+        // Verifies that Nat-T keepalives can be established.
+        assertEquals(supported, createConcurrentSocketKeepalives(network, supported + 1, 0));
+        // Verifies that keepalives don't get leaked in second round.
+        assertEquals(supported, createConcurrentSocketKeepalives(network, supported, 0));
+
+        dropShellPermissionIdentity();
+    }
+
+    /**
      * Verifies that the keepalive slots are limited as customized for unprivileged requests.
      */
     @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
     public void testSocketKeepaliveUnprivileged() throws Exception {
-        final int supported = getSupportedKeepalivesFromRes();
+        if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
+            Log.i(TAG, "testSocketKeepaliveUnprivileged cannot execute unless device"
+                    + " supports WiFi");
+            return;
+        }
+
+        final Network network = ensureWifiConnected();
+        final int supported = getSupportedKeepalivesForNet(network);
         if (supported == 0) {
             return;
         }
@@ -1154,7 +1244,8 @@
         assertGreaterOrEqual(supported, allowedUnprivilegedPerUid);
         final int expectedUnprivileged =
                 Math.min(allowedUnprivilegedPerUid, supported - reservedPrivilegedSlots);
-        assertEquals(expectedUnprivileged, createConcurrentSocketKeepalives(supported + 1, 0));
+        assertEquals(expectedUnprivileged,
+                createConcurrentSocketKeepalives(network, supported + 1, 0));
     }
 
     private static void assertGreaterOrEqual(long greater, long lesser) {
diff --git a/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java b/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java
index 78d2e08..e06bfbd 100644
--- a/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java
@@ -275,7 +275,7 @@
                 null);
 
         // All restricted permission should be whitelisted.
-        assertAllRestrictedPermissionWhitelisted();
+        eventually(this::assertAllRestrictedPermissionWhitelisted);
 
         // Some restricted permission should be granted.
         assertAllRestrictedPermissionGranted();
@@ -597,14 +597,52 @@
 
     @Test
     @AppModeFull
-    public void onSideLoadAllRestrictedPermissionsWhitelisted() throws Exception {
-        installRestrictedPermissionUserApp();
+    public void onSideLoadRestrictedPermissionsWhitelistingDefault() throws Exception {
+        installRestrictedPermissionUserApp(new SessionParams(SessionParams.MODE_FULL_INSTALL));
 
-        // All restricted permissions whitelisted on side-load.
-        assertAllRestrictedPermissionWhitelisted();
+        // All restricted permissions whitelisted on side-load by default
+        eventually(this::assertAllRestrictedPermissionWhitelisted);
     }
 
-    private static void installRestrictedPermissionUserApp() throws Exception {
+    @Test
+    @AppModeFull
+    public void onSideLoadAllRestrictedPermissionsWhitelisted() throws Exception {
+        SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
+        params.setWhitelistedRestrictedPermissions(SessionParams.RESTRICTED_PERMISSIONS_ALL);
+
+        installRestrictedPermissionUserApp(params);
+
+        eventually(this::assertAllRestrictedPermissionWhitelisted);
+    }
+
+    @Test
+    @AppModeFull
+    public void onSideLoadWhitelistSomePermissions() throws Exception {
+        Set<String> whitelistedPermissions = new ArraySet<>();
+        whitelistedPermissions.add(Manifest.permission.SEND_SMS);
+        whitelistedPermissions.add(Manifest.permission.READ_CALL_LOG);
+
+        SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
+        params.setWhitelistedRestrictedPermissions(whitelistedPermissions);
+
+        installRestrictedPermissionUserApp(params);
+
+        eventually(() -> assertRestrictedPermissionWhitelisted(whitelistedPermissions));
+    }
+
+    @Test
+    @AppModeFull
+    public void onSideLoadWhitelistNoPermissions() throws Exception {
+        SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
+        params.setWhitelistedRestrictedPermissions(Collections.emptySet());
+
+        installRestrictedPermissionUserApp(params);
+
+        eventually(this::assertNoRestrictedPermissionWhitelisted);
+    }
+
+    private static void installRestrictedPermissionUserApp(@NonNull SessionParams params)
+            throws Exception {
         final CountDownLatch installLatch = new CountDownLatch(1);
 
         // Create an install result receiver.
@@ -627,8 +665,6 @@
             // Create a session.
             final PackageInstaller packageInstaller = getContext()
                     .getPackageManager().getPackageInstaller();
-            final SessionParams params = new SessionParams(
-                    SessionParams.MODE_FULL_INSTALL);
             final int sessionId = packageInstaller.createSession(params);
             final Session session = packageInstaller.openSession(sessionId);
 
@@ -862,8 +898,8 @@
                         | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE);
 
             assertThat(whitelistedPermissions).isNotNull();
-            assertThat(whitelistedPermissions).containsExactlyElementsIn(
-                    expectedWhitelistedPermissions);
+            assertThat(whitelistedPermissions).named("Whitelisted permissions")
+                    .containsExactlyElementsIn(expectedWhitelistedPermissions);
 
             // Also assert that apps ops are properly set
             for (String permission : getRestrictedPermissionsOfApp()) {
@@ -1019,6 +1055,17 @@
                         getContext().getUser());
             }
         });
+
+        // Mark all permissions as reviewed as for pre-22 apps the restriction state might not be
+        // applied until reviewed
+        runWithShellPermissionIdentity(() -> {
+            final PackageManager packageManager = getContext().getPackageManager();
+            for (String permission : getRestrictedPermissionsOfApp()) {
+                packageManager.updatePermissionFlags(permission, PKG,
+                        PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0,
+                        getContext().getUser());
+            }
+        });
     }
 
     @After
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index a39941c..50f7a2f 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -1192,21 +1192,6 @@
                 // and see if more errors show up.
                 SystemClock.sleep(1000);
             }
-            if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
-                JSONArray crashes = getCrashReport(getName(), 5000);
-                if (crashes == null) {
-                    Log.e(TAG, "Crash results not found for test " + getName());
-                    return what;
-                } else if (CrashUtils.detectCrash(validProcessNames, true, crashes)) {
-                    return what;
-                } else {
-                    Log.i(TAG, "Crash ignored due to no security crash found for test " +
-                        getName());
-                    // 0 is the code for no error.
-                    return 0;
-                }
-
-            }
             return what;
         }
 
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
index 90fc1dd..fd65c97 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
@@ -41,6 +41,6 @@
                             .start();
                 }, true)
                 .runWithVerifier(new GoldenImageVerifier(getActivity(),
-                        R.drawable.golden_blue_circle, new MSSIMComparer(0.99)));
+                        R.drawable.golden_blue_circle, new MSSIMComparer(0.85)));
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
index 529582a..0f65c88 100644
--- a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
@@ -443,14 +443,23 @@
             mAutoCompleteTextView.refreshAutoCompleteResults();
         });
 
-        assertThat(getAutoCompleteSuggestions()).containsExactly("testTwo");
+        PollingCheck.waitFor(() -> {
+            List<Object> autoCompleteSuggestions = getAutoCompleteSuggestions();
+            return (autoCompleteSuggestions.size() == 1)
+                    && autoCompleteSuggestions.contains("testTwo");
+        });
 
         WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mAutoCompleteTextView, () -> {
             mAdapter.add("testThree");
             mAutoCompleteTextView.refreshAutoCompleteResults();
         });
 
-        assertThat(getAutoCompleteSuggestions()).containsExactly("testTwo", "testThree");
+        PollingCheck.waitFor(() -> {
+            List<Object> autoCompleteSuggestions = getAutoCompleteSuggestions();
+            return (autoCompleteSuggestions.size() == 2)
+                    && autoCompleteSuggestions.contains("testTwo")
+                    && autoCompleteSuggestions.contains("testThree");
+        });
     }
 
     @Test
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
index 404605e..3c4192c 100644
--- a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
@@ -414,7 +414,9 @@
                         mActivity.getDrawable(R.drawable.yellow_fill)));
 
         // Use instrumentation to emulate a tap on the spinner to bring down its popup
-        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mSpinnerDropdownMode);
+        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mSpinnerDropdownMode, () -> {
+            mSpinnerDropdownMode.performClick();
+        });
         // Verify that we're showing the popup
         PollingCheck.waitFor(() -> mSpinnerDropdownMode.isPopupShowing());
         // And test its fill