Merge "Adds FLAG_NOTIFY_FOR_DESCENDANTS to triggerContentUri." into rvc-dev
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml
index e5300ab..2a322aa 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml
@@ -5,4 +5,5 @@
     <string name="Ask">Ask every time</string>
     <string name="Allow">Allow</string>
     <string name="AllowAll">Allow all the time</string>
+    <string name="AllowForeground">Allow only while using the app</string>
 </resources>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml
index e5300ab..2a322aa 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml
@@ -5,4 +5,5 @@
     <string name="Ask">Ask every time</string>
     <string name="Allow">Allow</string>
     <string name="AllowAll">Allow all the time</string>
+    <string name="AllowForeground">Allow only while using the app</string>
 </resources>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
index 8b5630c..da6e44b 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
@@ -16,18 +16,16 @@
 
 package com.android.cts.usepermission;
 
-import static com.android.compatibility.common.util.UiAutomatorUtils.waitFindObject;
 import static com.android.compatibility.common.util.UiAutomatorUtils.getUiDevice;
+import static com.android.compatibility.common.util.UiAutomatorUtils.waitFindObject;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.TestCase.assertTrue;
 
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
 
 import android.Manifest;
 import android.app.Activity;
@@ -36,20 +34,16 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
-import android.icu.text.CaseMap;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.Direction;
-import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.UiScrollable;
 import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
 import android.text.Spanned;
 import android.text.style.ClickableSpan;
 import android.util.ArrayMap;
@@ -67,7 +61,6 @@
 import com.android.compatibility.common.util.UiDumpUtils;
 
 import junit.framework.Assert;
-import junit.framework.TestCase;
 
 import org.junit.Before;
 import org.junit.runner.RunWith;
@@ -76,7 +69,6 @@
 import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.regex.Pattern;
 
@@ -449,19 +441,27 @@
                     waitForIdle();
                 }
 
-                final boolean wasGranted = isTv() ? false : !(waitFindObject(byText(R.string.Deny)).isChecked() || (!legacyApp && waitFindObject(byText(R.string.Ask)).isChecked()));
+                final boolean wasGranted = isTv()
+                        ? false
+                        : !(waitFindObject(byText(R.string.Deny)).isChecked()
+                                || (legacyApp
+                                    && hasAskButton(permission)
+                                    && waitFindObject(byText(R.string.Ask)).isChecked()));
                 boolean alreadyChecked = false;
                 if (isTv()) {
                     waitFindObject(By.text(permissionLabel)).click();
                 } else if (state == STATE_ALLOWED) {
-                    UiObject2 object = waitFindObject(byText(R.string.Allow));
+                    UiObject2 object = waitFindObject(byText(
+                            showsForegroundOnlyButton(permission)
+                                    ? R.string.AllowForeground
+                                    : R.string.Allow));
                     alreadyChecked = object.isChecked();
                     if (!alreadyChecked) {
                         object.click();
                     }
                 } else if (state == STATE_DENIED){
                     UiObject2 object;
-                    if (legacyApp) {
+                    if (legacyApp || !hasAskButton(permission)) {
                         object = waitFindObject(byText(R.string.Deny));
                     } else {
                         object = waitFindObject(byText(R.string.Ask));
@@ -529,6 +529,19 @@
         return mPlatformResources.getString(resourceId);
     }
 
+    private boolean hasAskButton(String permission) {
+        return Manifest.permission.CAMERA.equals(permission)
+                || Manifest.permission.RECORD_AUDIO.equals(permission)
+                || Manifest.permission.ACCESS_FINE_LOCATION.equals(permission)
+                || Manifest.permission.ACCESS_COARSE_LOCATION.equals(permission)
+                || Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission);
+    }
+
+    private boolean showsForegroundOnlyButton(String permission) {
+        return Manifest.permission.CAMERA.equals(permission)
+                || Manifest.permission.RECORD_AUDIO.equals(permission);
+    }
+
     private void startActivity(final Intent intent) throws Exception {
         getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                 () -> {
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
index a958816..3be949d 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
@@ -285,9 +285,9 @@
     public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part1() throws Exception {
         // Make sure we don't have the permission
         assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+                .checkSelfPermission(Manifest.permission.CAMERA));
 
-        String[] permissions = new String[] {Manifest.permission.READ_CALENDAR};
+        String[] permissions = new String[] {Manifest.permission.CAMERA};
 
         // Request the permission and deny it
         BasePermissionActivity.Result firstResult = requestPermissions(permissions, () -> {
@@ -300,7 +300,7 @@
 
         // Request the permission and choose don't ask again
         BasePermissionActivity.Result secondResult = requestPermissions(new String[]{
-                Manifest.permission.READ_CALENDAR}, () -> {
+                Manifest.permission.CAMERA}, () -> {
             denyWithPrejudice();
             getUiDevice().waitForIdle();
         });
@@ -309,8 +309,8 @@
         assertPermissionRequestResult(secondResult, permissions, new boolean[] {false});
 
         // Clear the denial with prejudice
-        grantPermission(Manifest.permission.READ_CALENDAR);
-        revokePermission(Manifest.permission.READ_CALENDAR);
+        grantPermission(Manifest.permission.CAMERA);
+        revokePermission(Manifest.permission.CAMERA);
 
         // We just committed a suicide by revoking the permission. See part2 below...
     }
@@ -319,17 +319,17 @@
     public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part2() throws Exception {
         // Make sure we don't have the permission
         assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+                .checkSelfPermission(Manifest.permission.CAMERA));
 
         // Request the permission and allow it
         BasePermissionActivity.Result thirdResult = requestPermissions(new String[]{
-                Manifest.permission.READ_CALENDAR}, () -> {
-            clickAllowButton();
+                Manifest.permission.CAMERA}, () -> {
+            clickAllowForegroundButton();
             getUiDevice().waitForIdle();
         });
 
         // Make sure the permission is granted
-        assertPermissionRequestResult(thirdResult, new String[] {Manifest.permission.READ_CALENDAR},
+        assertPermissionRequestResult(thirdResult, new String[] {Manifest.permission.CAMERA},
                 new boolean[] {true});
     }
 
diff --git a/hostsidetests/incident/Android.bp b/hostsidetests/incident/Android.bp
index 1589078..3a3801b 100644
--- a/hostsidetests/incident/Android.bp
+++ b/hostsidetests/incident/Android.bp
@@ -26,5 +26,6 @@
         "tradefed",
         "compatibility-host-util",
         "platformprotos",
+        "truth-prebuilt",
     ],
 }
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/Android.bp b/hostsidetests/incident/apps/graphicsstatsapp/Android.bp
index 52b5c74..c64f8a8 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/Android.bp
+++ b/hostsidetests/incident/apps/graphicsstatsapp/Android.bp
@@ -24,6 +24,7 @@
         "ctstestrunner-axt",
         "compatibility-device-util-axt",
         "androidx.legacy_legacy-support-v4",
+        "truth-prebuilt",
     ],
     sdk_version: "test_current",
     // tag this module as a cts test artifact
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml b/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml
index be9d645..88e1eaf 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml
+++ b/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml
@@ -22,6 +22,8 @@
         <uses-library android:name="android.test.runner" />
         <activity android:name=".DrawFramesActivity"
                   android:label="GraphicsStats Test Activity"
+                  android:screenOrientation="locked"
+                  android:resizeableActivity="false"
                   android:theme="@style/DefaultTheme"/>
     </application>
 
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java
index 1bbc601..fd1206f 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java
+++ b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java
@@ -144,10 +144,6 @@
         }
     }
 
-    public void drawFrames(final int frameCount) throws InterruptedException, TimeoutException {
-        drawFrames(new int[frameCount]);
-    }
-
     public void waitForReady() throws InterruptedException, TimeoutException {
         if (!mReady.await(4, TimeUnit.SECONDS)) {
             throw new TimeoutException();
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java
index 56413f8..1a93309 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java
+++ b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java
@@ -15,13 +15,14 @@
  */
 package com.android.server.cts.device.graphicsstats;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 
 import androidx.test.filters.LargeTest;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.google.common.collect.Range;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -38,25 +39,37 @@
     public ActivityTestRule<DrawFramesActivity> mActivityRule =
             new ActivityTestRule<>(DrawFramesActivity.class);
 
-    @Test
-    public void testDrawTenFrames() throws Throwable {
+    void runTest(final int frameCount) throws Throwable {
+        runTest(new int[frameCount]);
+    }
+
+    void runTest(final int[] framesToDraw) throws Throwable {
         DrawFramesActivity activity = mActivityRule.getActivity();
         activity.waitForReady();
         int initialFrames = activity.getRenderedFramesCount();
-        assertTrue(initialFrames < 5);
-        assertEquals(0, activity.getDroppedReportsCount());
-        activity.drawFrames(10);
-        assertEquals(initialFrames + 10, activity.getRenderedFramesCount());
-        assertEquals(0, activity.getDroppedReportsCount());
+        assertThat(initialFrames).isLessThan(5);
+        assertThat(activity.getDroppedReportsCount()).isEqualTo(0);
+        activity.drawFrames(framesToDraw);
+        final int expectedFrameCount = initialFrames + framesToDraw.length;
+        assertThat(activity.getRenderedFramesCount()).isIn(
+                Range.closedOpen(expectedFrameCount, expectedFrameCount + 5));
+        assertThat(activity.getDroppedReportsCount()).isEqualTo(0);
+    }
+
+    @Test
+    public void testNothing() throws Throwable {
+        DrawFramesActivity activity = mActivityRule.getActivity();
+        activity.waitForReady();
+        activity.drawFrames(new int[10]);
+    }
+
+    @Test
+    public void testDrawTenFrames() throws Throwable {
+        runTest(10);
     }
 
     @Test
     public void testDrawJankyFrames() throws Throwable {
-        DrawFramesActivity activity = mActivityRule.getActivity();
-        activity.waitForReady();
-        int initialFrames = activity.getRenderedFramesCount();
-        assertTrue(initialFrames < 5);
-        assertEquals(0, activity.getDroppedReportsCount());
         int[] frames = new int[50];
         for (int i = 0; i < 10; i++) {
             int indx = i * 5;
@@ -65,26 +78,17 @@
             frames[indx + 2] = DrawFramesActivity.FRAME_JANK_LAYOUT;
             frames[indx + 3] = DrawFramesActivity.FRAME_JANK_MISS_VSYNC;
         }
-        activity.drawFrames(frames);
-        assertEquals(initialFrames + 50, activity.getRenderedFramesCount());
-        assertEquals(0, activity.getDroppedReportsCount());
+        runTest(frames);
     }
 
     @Test
     public void testDrawDaveyFrames() throws Throwable {
-        DrawFramesActivity activity = mActivityRule.getActivity();
-        activity.waitForReady();
-        int initialFrames = activity.getRenderedFramesCount();
-        assertTrue(initialFrames < 5);
-        assertEquals(0, activity.getDroppedReportsCount());
         int[] frames = new int[40];
         for (int i = 0; i < 10; i++) {
             int indx = i * 4;
             frames[indx] = DrawFramesActivity.FRAME_JANK_DAVEY;
             frames[indx + 2] = DrawFramesActivity.FRAME_JANK_DAVEY_JR;
         }
-        activity.drawFrames(frames);
-        assertEquals(initialFrames + 40, activity.getRenderedFramesCount());
-        assertEquals(0, activity.getDroppedReportsCount());
+        runTest(frames);
     }
 }
diff --git a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
index ea1f803..843531d 100644
--- a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
@@ -15,12 +15,14 @@
  */
 package com.android.server.cts;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.service.GraphicsStatsHistogramBucketProto;
 import android.service.GraphicsStatsJankSummaryProto;
 import android.service.GraphicsStatsProto;
 import android.service.GraphicsStatsServiceDumpProto;
 
-import com.android.tradefed.log.LogUtil.CLog;
+import com.google.common.collect.Range;
 
 import java.util.ArrayList;
 import java.util.Date;
@@ -46,7 +48,7 @@
         turnScreenOn();
         // Ensure that we have a starting point for our stats
         runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".SimpleDrawFrameTests",
-                "testDrawTenFrames");
+                "testNothing");
         // Kill to ensure that stats persist/merge across process death
         killTestApp();
     }
@@ -91,24 +93,24 @@
         int jankyDelta = summaryAfter.getJankyFrames() - summaryBefore.getJankyFrames();
         // Test draws 50 frames + 1 initial frame. We expect 40 of them to be janky,
         // 10 of each of ANIMATION, LAYOUT, RECORD_DRAW, and MISSED_VSYNC
-        assertTrue(frameDelta < 55);
-        assertTrue(jankyDelta >= 40);
-        assertTrue(jankyDelta < 45);
+
+        assertThat(frameDelta).isAtLeast(50);
+        assertThat(jankyDelta).isAtLeast(40);
+        assertThat(jankyDelta).isLessThan(45);
 
         // Although our current stats don't distinguish between ANIMATION, LAYOUT, and RECORD_DRAW
         // so this will just be slowUi +30
         int slowUiDelta = summaryAfter.getSlowUiThreadCount() - summaryBefore.getSlowUiThreadCount();
-        assertTrue(slowUiDelta >= 30);
+        assertThat(slowUiDelta).isAtLeast(28);
         int missedVsyncDelta = summaryAfter.getMissedVsyncCount()
                 - summaryBefore.getMissedVsyncCount();
-        assertTrue(missedVsyncDelta >= 10);
-        assertTrue(missedVsyncDelta <= 11);
+        assertThat(missedVsyncDelta).isIn(Range.closed(10, 11));
 
         int veryJankyDelta = countFramesAbove(statsAfter, 60) - countFramesAbove(statsBefore, 60);
         // The 1st frame could be >40ms, but nothing after that should be
-        assertTrue(veryJankyDelta <= 2);
+        assertThat(veryJankyDelta).isAtMost(2);
         int noGPUJank = countGPUFramesAbove(statsAfter, 60) - countGPUFramesAbove(statsBefore, 60);
-        assertTrue(noGPUJank == 0);
+        assertThat(noGPUJank).isEqualTo(0);
     }
 
     public void testDaveyDrawFrame() throws Exception {
@@ -123,13 +125,12 @@
         int jankyDelta = summaryAfter.getJankyFrames() - summaryBefore.getJankyFrames();
         // Test draws 40 frames + 1 initial frame. We expect 10 of them to be daveys,
         // 10 of them to be daveyjrs, and 20 to jank from missed vsync (from the davey/daveyjr prior to it)
-        assertTrue(frameDelta < 45);
-        assertTrue(jankyDelta >= 20);
-        assertTrue(jankyDelta < 25);
+        assertThat(frameDelta).isAtLeast(40);
+        assertThat(jankyDelta).isAtLeast(20);
+        assertThat(jankyDelta).isLessThan(25);
 
         int gt150msDelta = countFramesAbove(statsAfter, 150) - countFramesAbove(statsBefore, 150);
-        assertTrue(gt150msDelta >= 20); // 10 davey jrs + 10 daveys + maybe first 2 frames
-        assertTrue(gt150msDelta <= 22);
+        assertThat(gt150msDelta).isIn(Range.closed(20, 22));
         int gt700msDelta = countFramesAbove(statsAfter, 700) - countFramesAbove(statsBefore, 700);
         assertEquals(10, gt700msDelta); // 10 daveys
     }
@@ -139,10 +140,10 @@
     }
 
     private GraphicsStatsProto[] doRunDrawTest(String testName, boolean canRetry) throws Exception {
-        GraphicsStatsProto statsBefore = fetchStats();
-        assertNotNull(statsBefore);
         killTestApp();
         turnScreenOn();
+        GraphicsStatsProto statsBefore = fetchStats();
+        assertNotNull(statsBefore);
         runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".SimpleDrawFrameTests",  testName);
         killTestApp();
         GraphicsStatsProto statsAfter = fetchStats();
diff --git a/hostsidetests/securitybulletin/securityPatch/Bug-115739809/poc.cpp b/hostsidetests/securitybulletin/securityPatch/Bug-115739809/poc.cpp
index ef0a5cb..1a7e5b6 100755
--- a/hostsidetests/securitybulletin/securityPatch/Bug-115739809/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/Bug-115739809/poc.cpp
@@ -49,6 +49,8 @@
         case InputMessage::Type::KEY: {
             // uint32_t seq
             outMsg->body.key.seq = msg.body.key.seq;
+            // int32_t eventId
+            outMsg->body.key.eventId = msg.body.key.eventId;
             // nsecs_t eventTime
             outMsg->body.key.eventTime = msg.body.key.eventTime;
             // int32_t deviceId
@@ -78,6 +80,8 @@
         case InputMessage::Type::MOTION: {
             // uint32_t seq
             outMsg->body.motion.seq = msg.body.motion.seq;
+            // int32_t eventId
+            outMsg->body.motion.eventId = msg.body.key.eventId;
             // nsecs_t eventTime
             outMsg->body.motion.eventTime = msg.body.motion.eventTime;
             // int32_t deviceId
@@ -146,6 +150,7 @@
         }
         case InputMessage::Type::FOCUS: {
             outMsg->body.focus.seq = msg.body.focus.seq;
+            outMsg->body.focus.eventId = msg.body.focus.eventId;
             outMsg->body.focus.hasFocus = msg.body.focus.hasFocus;
             outMsg->body.focus.inTouchMode = msg.body.focus.inTouchMode;
             break;
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
index 9c55177..7458be5 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
@@ -22,7 +22,10 @@
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningServiceInfo;
 import android.app.AlarmManager;
+import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
@@ -61,6 +64,8 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.compatibility.common.util.ShellIdentityUtils;
+
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -71,6 +76,8 @@
 public class AtomTests {
     private static final String TAG = AtomTests.class.getSimpleName();
 
+    private static final String MY_PACKAGE_NAME = "com.android.server.cts.device.statsd";
+
     @Test
     public void testAudioState() {
         // TODO: This should surely be getTargetContext(), here and everywhere, but test first.
@@ -230,6 +237,58 @@
     }
 
     @Test
+    public void testForegroundServiceAccessAppOp() throws Exception {
+        Context context = InstrumentationRegistry.getContext();
+        Intent fgsIntent = new Intent(context, StatsdCtsForegroundService.class);
+        AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+
+        // No foreground service session
+        noteAppOp(appOpsManager, AppOpsManager.OPSTR_COARSE_LOCATION, true);
+
+        // Foreground service session 1
+        context.startService(fgsIntent);
+        while (!checkIfServiceRunning(context, StatsdCtsForegroundService.class.getName())) {
+            sleep(50);
+        }
+        noteAppOp(appOpsManager, AppOpsManager.OPSTR_CAMERA, true);
+        noteAppOp(appOpsManager, AppOpsManager.OPSTR_FINE_LOCATION, true);
+        noteAppOp(appOpsManager, AppOpsManager.OPSTR_CAMERA, true);
+        noteAppOp(appOpsManager, AppOpsManager.OPSTR_RECORD_AUDIO, false);
+        noteAppOp(appOpsManager, AppOpsManager.OPSTR_RECORD_AUDIO, true);
+        context.stopService(fgsIntent);
+
+        // No foreground service session
+        noteAppOp(appOpsManager, AppOpsManager.OPSTR_COARSE_LOCATION, true);
+
+        // TODO(b/149098800): Start fgs a second time and log OPSTR_CAMERA again
+    }
+
+    /** @param doNote true if should use noteOp; false if should use startOp. */
+    private void noteAppOp(AppOpsManager appOpsManager, String opStr, boolean doNote) {
+        if (doNote) {
+            ShellIdentityUtils.invokeMethodWithShellPermissions(appOpsManager,
+                    (aom) -> aom.noteOp(opStr, android.os.Process.myUid(), MY_PACKAGE_NAME, null,
+                            "statsdTest"));
+        } else {
+            ShellIdentityUtils.invokeMethodWithShellPermissions(appOpsManager,
+                    (aom) -> aom.startOp(opStr, android.os.Process.myUid(),
+                            MY_PACKAGE_NAME, null, "statsdTest"));
+        }
+        sleep(500);
+    }
+
+    /** Check if service is running. */
+    public boolean checkIfServiceRunning(Context context, String serviceName) {
+        ActivityManager manager = context.getSystemService(ActivityManager.class);
+        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
+            if (serviceName.equals(service.service.getClassName()) && service.foreground) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Test
     public void testGpsScan() {
         Context context = InstrumentationRegistry.getContext();
         final LocationManager locManager = context.getSystemService(LocationManager.class);
@@ -396,7 +455,7 @@
 
     @Test
     public void testScheduledJob() throws Exception {
-        final ComponentName name = new ComponentName("com.android.server.cts.device.statsd",
+        final ComponentName name = new ComponentName(MY_PACKAGE_NAME,
                 StatsdJobService.class.getName());
 
         Context context = InstrumentationRegistry.getContext();
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index 1d4b2d6..ac45c06 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -22,7 +22,6 @@
 import android.os.WakeLockLevelEnum;
 import android.server.ErrorSource;
 
-import com.android.internal.os.StatsdConfigProto.FieldMatcher;
 import com.android.internal.os.StatsdConfigProto.StatsdConfig;
 import com.android.os.AtomsProto;
 import com.android.os.AtomsProto.ANROccurred;
@@ -40,12 +39,13 @@
 import com.android.os.AtomsProto.DangerousPermissionStateSampled;
 import com.android.os.AtomsProto.DeviceCalculatedPowerBlameUid;
 import com.android.os.AtomsProto.FlashlightStateChanged;
+import com.android.os.AtomsProto.ForegroundServiceAppOpSessionEnded;
 import com.android.os.AtomsProto.ForegroundServiceStateChanged;
 import com.android.os.AtomsProto.GpsScanStateChanged;
 import com.android.os.AtomsProto.HiddenApiUsed;
 import com.android.os.AtomsProto.IonHeapSize;
-import com.android.os.AtomsProto.LooperStats;
 import com.android.os.AtomsProto.LmkKillOccurred;
+import com.android.os.AtomsProto.LooperStats;
 import com.android.os.AtomsProto.MediaCodecStateChanged;
 import com.android.os.AtomsProto.OverlayStateChanged;
 import com.android.os.AtomsProto.PackageNotificationPreferences;
@@ -73,7 +73,6 @@
 import java.lang.ProcessBuilder;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -544,6 +543,51 @@
                 atom -> atom.getForegroundServiceStateChanged().getState().getNumber());
     }
 
+
+    public void testForegroundServiceAccessAppOp() throws Exception {
+        if (statsdDisabled()) {
+            return;
+        }
+        final int atomTag = Atom.FOREGROUND_SERVICE_APP_OP_SESSION_ENDED_FIELD_NUMBER;
+        final String name = "testForegroundServiceAccessAppOp";
+
+        createAndUploadConfig(atomTag, false);
+        Thread.sleep(WAIT_TIME_SHORT);
+
+        runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", name);
+
+        // Sorted list of events in order in which they occurred.
+        List<EventMetricData> data = getEventMetricDataList();
+
+        assertWithMessage("Wrong atom size").that(data.size()).isEqualTo(3);
+        for (int i = 0; i < data.size(); i++) {
+            ForegroundServiceAppOpSessionEnded atom
+                    = data.get(i).getAtom().getForegroundServiceAppOpSessionEnded();
+            final int opName = atom.getAppOpName().getNumber();
+            final int acceptances = atom.getCountOpsAccepted();
+            final int rejections = atom.getCountOpsRejected();
+            final int count = acceptances + rejections;
+            int expectedCount = 0;
+            switch (opName) {
+                case ForegroundServiceAppOpSessionEnded.AppOpName.OP_CAMERA_VALUE:
+                    expectedCount = 2;
+                    break;
+                case ForegroundServiceAppOpSessionEnded.AppOpName.OP_FINE_LOCATION_VALUE:
+                    expectedCount = 1;
+                    break;
+                case ForegroundServiceAppOpSessionEnded.AppOpName.OP_RECORD_AUDIO_VALUE:
+                    expectedCount = 2;
+                    break;
+                case ForegroundServiceAppOpSessionEnded.AppOpName.OP_COARSE_LOCATION_VALUE:
+                    // fall-through
+                default:
+                    fail("Unexpected opName " + opName);
+            }
+            assertWithMessage("Wrong count for " + opName).that(count).isEqualTo(expectedCount);
+
+        }
+    }
+
     public void testGpsScan() throws Exception {
         if (statsdDisabled()) {
             return;
diff --git a/tests/accessibility/res/drawable/size_48x48.jpg b/tests/accessibility/res/drawable/jpg_48_48.jpg
similarity index 100%
rename from tests/accessibility/res/drawable/size_48x48.jpg
rename to tests/accessibility/res/drawable/jpg_48_48.jpg
Binary files differ
diff --git a/tests/accessibility/res/drawable/png_72_72.png b/tests/accessibility/res/drawable/png_72_72.png
new file mode 100644
index 0000000..941458d
--- /dev/null
+++ b/tests/accessibility/res/drawable/png_72_72.png
Binary files differ
diff --git a/tests/accessibility/res/drawable/vector_drawable_6kdp_6kdp.xml b/tests/accessibility/res/drawable/vector_drawable_6kdp_6kdp.xml
new file mode 100644
index 0000000..0d11dc0
--- /dev/null
+++ b/tests/accessibility/res/drawable/vector_drawable_6kdp_6kdp.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="6000dp"
+        android:height="6000dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71 -0.2,-0.2 -0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z"/>
+</vector>
diff --git a/tests/accessibility/res/raw/test_file b/tests/accessibility/res/raw/test_file
new file mode 100644
index 0000000..acea7ed
--- /dev/null
+++ b/tests/accessibility/res/raw/test_file
@@ -0,0 +1,12 @@
+10101010110101010101101010101011010101010110101010101101010101011010101010110
+1010101011010101010110101010101101010101011010101011010101101101010101011011011010101101101
+1011010101010011010101010110101011011010101010110101011011010101010110110110101010101101
+10110101010101101010101011010101010110101010101101010101010101101010101011010101
+101101010101011010101010110101010101101010101011010101101011010101010110101010101101010101011010101
+101101010101101010101011010101101101010101011010101001010110101011011010101010110110101010101
+10110101010101101010101011010101010110101010101101010101010101101
+101101010101010110101010101101010110110101010101101010101011010101011101010101011010101101101010
+10110101010101011010101101101010101011010101101010101011010101101010101011010101
+101101010101011010101011010101010110101011011010101010110101010101101010101
+
+
diff --git a/tests/accessibility/res/values/strings.xml b/tests/accessibility/res/values/strings.xml
index de1539a..40c3359 100644
--- a/tests/accessibility/res/values/strings.xml
+++ b/tests/accessibility/res/values/strings.xml
@@ -32,8 +32,26 @@
     <!-- Description of the speaking accessibility service -->
     <string name="some_description">Some description</string>
 
+    <!-- Html description of the vibrating accessibility service -->
+    <string name="html_description_vibrating_accessibility_service"><![CDATA[
+    <A href=\"fake_link\">Test link</a> <IMG src = \"R.drawable.file_name\">
+    ]]></string>
+
     <!-- Html description of the speaking accessibility service -->
-    <string name="some_html_description">Some html description</string>
+    <string name="html_description_speaking_accessibility_service"><![CDATA[
+    <a href=\"fake_link\"> <img src=\"R.drawable.file_name\">
+    ]]></string>
+
+    <!-- Html description of the speaking and vibrating accessibility service -->
+    <string name="html_description_speaking_and_vibrating_accessibility_service"><![CDATA[
+    <a href=fake_link> <img src=R.drawable.file_name>
+    ]]></string>
+
+    <!-- Html description of the accessibility button service -->
+    <string name="html_description_accessibility_button_service"><![CDATA[
+    <img src=\"r.drawable.file_name\"> <img alt=\"foo\" src=\"R.drawable.file_name\">
+    <img src=\"file://path\"> <img src=\"http://path\">
+    ]]></string>
 
     <!-- Summary of the speaking accessibility service -->
     <string name="some_summary">Some summary</string>
diff --git a/tests/accessibility/res/xml/accessibility_button_service.xml b/tests/accessibility/res/xml/accessibility_button_service.xml
index d475266..e483fd4 100644
--- a/tests/accessibility/res/xml/accessibility_button_service.xml
+++ b/tests/accessibility/res/xml/accessibility_button_service.xml
@@ -18,4 +18,6 @@
                        android:accessibilityEventTypes="typeAllMask"
                        android:accessibilityFeedbackType="feedbackGeneric"
                        android:accessibilityFlags="flagRequestAccessibilityButton"
+                       android:animatedImageDrawable="@raw/test_file"
+                       android:htmlDescription="@string/html_description_accessibility_button_service"
                        android:notificationTimeout="0" />
\ No newline at end of file
diff --git a/tests/accessibility/res/xml/speaking_accessibilityservice.xml b/tests/accessibility/res/xml/speaking_accessibilityservice.xml
index ede686d..9128309 100644
--- a/tests/accessibility/res/xml/speaking_accessibilityservice.xml
+++ b/tests/accessibility/res/xml/speaking_accessibilityservice.xml
@@ -21,9 +21,9 @@
     android:canRequestTouchExplorationMode="true"
     android:canRequestFilterKeyEvents="true"
     android:settingsActivity="foo.bar.Activity"
-    android:animatedImageDrawable="@drawable/size_48x48"
+    android:animatedImageDrawable="@drawable/jpg_48_48"
     android:description="@string/some_description"
-    android:htmlDescription="@string/some_html_description"
+    android:htmlDescription="@string/html_description_speaking_accessibility_service"
     android:summary="@string/some_summary"
     android:nonInteractiveUiTimeout="1000"
     android:interactiveUiTimeout="6000"/>
\ No newline at end of file
diff --git a/tests/accessibility/res/xml/speaking_and_vibrating_accessibilityservice.xml b/tests/accessibility/res/xml/speaking_and_vibrating_accessibilityservice.xml
index 3ac8661..09d36c6 100644
--- a/tests/accessibility/res/xml/speaking_and_vibrating_accessibilityservice.xml
+++ b/tests/accessibility/res/xml/speaking_and_vibrating_accessibilityservice.xml
@@ -22,7 +22,7 @@
     android:canRequestFilterKeyEvents="true"
     android:canRequestEnhancedWebAccessibility="true"
     android:settingsActivity="foo.bar.Activity"
-    android:animatedImageDrawable="@drawable/size_48x48"
+    android:animatedImageDrawable="@drawable/vector_drawable_6kdp_6kdp"
     android:description="@string/some_description"
-    android:htmlDescription="@string/some_html_description"
+    android:htmlDescription="@string/html_description_speaking_and_vibrating_accessibility_service"
     android:summary="@string/some_summary" />
diff --git a/tests/accessibility/res/xml/vibrating_accessibilityservice.xml b/tests/accessibility/res/xml/vibrating_accessibilityservice.xml
index 93d9f0d..ddf4018 100644
--- a/tests/accessibility/res/xml/vibrating_accessibilityservice.xml
+++ b/tests/accessibility/res/xml/vibrating_accessibilityservice.xml
@@ -20,4 +20,6 @@
     android:canRetrieveWindowContent="true"
     android:canRequestTouchExplorationMode="true"
     android:nonInteractiveUiTimeout="2000"
+    android:animatedImageDrawable="@drawable/png_72_72"
+    android:htmlDescription="@string/html_description_vibrating_accessibility_service"
     android:interactiveUiTimeout="5000"/>
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
index d2f7c2d..8a75b54 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
@@ -19,6 +19,7 @@
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
@@ -26,13 +27,16 @@
 import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
 import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule;
 import android.accessibilityservice.AccessibilityServiceInfo;
-import android.app.Service;
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
@@ -49,22 +53,44 @@
  */
 @RunWith(AndroidJUnit4.class)
 public class AccessibilityServiceInfoTest {
+    private AccessibilityManager mAccessibilityManager;
+    private PackageManager mPackageManager;
+    private Context mContext;
 
-    private InstrumentedAccessibilityServiceTestRule<SpeakingAccessibilityService>
+    private final InstrumentedAccessibilityServiceTestRule<SpeakingAccessibilityService>
             mSpeakingAccessibilityServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
-                    SpeakingAccessibilityService.class);
+            SpeakingAccessibilityService.class);
 
-    private InstrumentedAccessibilityServiceTestRule<VibratingAccessibilityService>
+    private final InstrumentedAccessibilityServiceTestRule<VibratingAccessibilityService>
             mVibratingAccessibilityServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
-                    VibratingAccessibilityService.class);
+            VibratingAccessibilityService.class);
+
+    private final InstrumentedAccessibilityServiceTestRule<SpeakingAndVibratingAccessibilityService>
+            mSpeakingAndVibratingAccessibilityServiceRule =
+            new InstrumentedAccessibilityServiceTestRule<>(
+                    SpeakingAndVibratingAccessibilityService.class, /* enableService= */ false);
+
+    private final InstrumentedAccessibilityServiceTestRule<AccessibilityButtonService>
+            mA11yButtonServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
+            AccessibilityButtonService.class, /* enableService= */ false);
 
     @Rule
     public final RuleChain mRuleChain = RuleChain
             .outerRule(mVibratingAccessibilityServiceRule)
             .around(mSpeakingAccessibilityServiceRule)
+            .around(mSpeakingAndVibratingAccessibilityServiceRule)
+            .around(mA11yButtonServiceRule)
             // Inner rule capture failure and dump data before finishing a11y service
             .around(new AccessibilityDumpOnFailureRule());
 
+    @Before
+    public void setUp() throws Exception {
+        mContext = getInstrumentation().getContext();
+        mAccessibilityManager = getInstrumentation().getContext().getSystemService(
+                AccessibilityManager.class);
+        mPackageManager = getInstrumentation().getContext().getPackageManager();
+    }
+
     /**
      * Tests whether a service can that requested it can retrieve
      * window content.
@@ -73,13 +99,12 @@
     @SuppressWarnings("deprecation")
     @Test
     public void testAccessibilityServiceInfoForEnabledService() {
-        AccessibilityManager accessibilityManager = (AccessibilityManager)
-                getInstrumentation().getContext().getSystemService(Service.ACCESSIBILITY_SERVICE);
-        List<AccessibilityServiceInfo> enabledServices =
-            accessibilityManager.getEnabledAccessibilityServiceList(
-                    AccessibilityServiceInfo.FEEDBACK_SPOKEN);
-        assertSame("There should be one speaking service.", 1, enabledServices.size());
-        AccessibilityServiceInfo speakingService = enabledServices.get(0);
+        final List<AccessibilityServiceInfo> enabledServices =
+                mAccessibilityManager.getEnabledAccessibilityServiceList(
+                        AccessibilityServiceInfo.FEEDBACK_SPOKEN);
+        assertSame(/* message= */ "There should be one speaking service.",
+                /* expected= */ 1, enabledServices.size());
+        final AccessibilityServiceInfo speakingService = enabledServices.get(0);
         assertSame(AccessibilityEvent.TYPES_ALL_MASK, speakingService.eventTypes);
         assertSame(AccessibilityServiceInfo.FEEDBACK_SPOKEN, speakingService.feedbackType);
         assertEquals(AccessibilityServiceInfo.DEFAULT
@@ -89,8 +114,8 @@
                 | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS
                 | AccessibilityServiceInfo.FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK,
                 speakingService.flags);
-        assertSame(0l, speakingService.notificationTimeout);
-        assertEquals("Some description", speakingService.getDescription());
+        assertSame(/* expected= */ 0l, speakingService.notificationTimeout);
+        assertEquals(/* expected= */ "Some description", speakingService.getDescription());
         assertNull(speakingService.packageNames /*all packages*/);
         assertNotNull(speakingService.getId());
         assertSame(speakingService.getCapabilities(),
@@ -98,15 +123,86 @@
                 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
                 | AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
         assertEquals("foo.bar.Activity", speakingService.getSettingsActivityName());
-        assertNotNull(speakingService.loadAnimatedImage(getInstrumentation().getContext()));
-        assertEquals("Some description", speakingService.loadDescription(
-                getInstrumentation().getContext().getPackageManager()));
-        assertEquals("Some html description", speakingService.loadHtmlDescription(
-                getInstrumentation().getContext().getPackageManager()));
-        assertEquals("Some summary", speakingService.loadSummary(
-                getInstrumentation().getContext().getPackageManager()));
+        assertNotNull(speakingService.loadAnimatedImage(mContext));
+        assertEquals(/* expected= */ "Some description",
+                speakingService.loadDescription(mPackageManager));
+        assertEquals(/* expected= */
+                "<invalidtag href=\"fake_link\"> <img src=\"R.drawable.file_name\">",
+                speakingService.loadHtmlDescription(mPackageManager));
+        assertEquals(/* expected= */ "Some summary",
+                speakingService.loadSummary(mPackageManager));
         assertNotNull(speakingService.getResolveInfo());
-        assertEquals(6000, speakingService.getInteractiveUiTimeoutMillis());
-        assertEquals(1000, speakingService.getNonInteractiveUiTimeoutMillis());
+        assertEquals(/* expected= */ 6000,
+                speakingService.getInteractiveUiTimeoutMillis());
+        assertEquals(/* expected= */ 1000,
+                speakingService.getNonInteractiveUiTimeoutMillis());
+    }
+
+    /**
+     * Tests the html description of accessibility services whether to meet the custom
+     * specification.
+     */
+    @Test
+    public void testAccessibilityServicesHtmlDescription() {
+        mSpeakingAndVibratingAccessibilityServiceRule.enableService();
+        mA11yButtonServiceRule.enableService();
+        final List<AccessibilityServiceInfo> enabledServices =
+                mAccessibilityManager.getEnabledAccessibilityServiceList(
+                        AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+        final AccessibilityServiceInfo vibratingService =
+                mVibratingAccessibilityServiceRule.getService().getServiceInfo();
+        final AccessibilityServiceInfo speakingService =
+                mSpeakingAccessibilityServiceRule.getService().getServiceInfo();
+        final AccessibilityServiceInfo speakingAndVibratingService =
+                mSpeakingAndVibratingAccessibilityServiceRule.getService().getServiceInfo();
+        final AccessibilityServiceInfo a11yService =
+                mA11yButtonServiceRule.getService().getServiceInfo();
+
+        assertSame(/* message= */ "There should be four services.", /* expected= */ 4,
+                enabledServices.size());
+        assertEquals(/* expected= */
+                "<invalidtag href=\"fake_link\">Test link</invalidtag> "
+                        + "<IMG src = \"R.drawable.file_name\">",
+                vibratingService.loadHtmlDescription(mPackageManager));
+        assertEquals(/* expected= */
+                "<invalidtag href=\"fake_link\"> <img src=\"R.drawable.file_name\">",
+                speakingService.loadHtmlDescription(mPackageManager));
+        assertEquals(/* expected= */
+                "<invalidtag href=fake_link> <invalidtag src=R.drawable.file_name>",
+                speakingAndVibratingService.loadHtmlDescription(mPackageManager));
+        assertEquals(/* expected= */
+                "<invalidtag src=\"r.drawable.file_name\"> "
+                        + "<invalidtag alt=\"foo\" src=\"R.drawable.file_name\"> "
+                        + "<invalidtag src=\"file://path\"> "
+                        + "<invalidtag src=\"http://path\">",
+                a11yService.loadHtmlDescription(mPackageManager));
+    }
+
+    /**
+     * Tests the animated image resource of accessibility services whether to meet the custom
+     * specification.
+     */
+    @Test
+    public void testAccessibilityServicesAnimatedImageResource() {
+        mSpeakingAndVibratingAccessibilityServiceRule.enableService();
+        mA11yButtonServiceRule.enableService();
+        final List<AccessibilityServiceInfo> enabledServices =
+                mAccessibilityManager.getEnabledAccessibilityServiceList(
+                        AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+        final AccessibilityServiceInfo vibratingService =
+                mVibratingAccessibilityServiceRule.getService().getServiceInfo();
+        final AccessibilityServiceInfo speakingService =
+                mSpeakingAccessibilityServiceRule.getService().getServiceInfo();
+        final AccessibilityServiceInfo speakingAndVibratingService =
+                mSpeakingAndVibratingAccessibilityServiceRule.getService().getServiceInfo();
+        final AccessibilityServiceInfo a11yService =
+                mA11yButtonServiceRule.getService().getServiceInfo();
+
+        assertSame(/* message= */ "There should be four services.", /* expected= */ 4,
+                enabledServices.size());
+        assertNotNull(vibratingService.loadAnimatedImage(mContext));
+        assertNotNull(speakingService.loadAnimatedImage(mContext));
+        assertNull(speakingAndVibratingService.loadAnimatedImage(mContext));
+        assertNull(a11yService.loadAnimatedImage(mContext));
     }
 }
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
index 4111baf..8f79102 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
@@ -18,6 +18,7 @@
 
 import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -69,6 +70,8 @@
     private final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
             new AccessibilityDumpOnFailureRule();
 
+    private AccessibilityEmbeddedHierarchyActivity mActivity;
+
     @Rule
     public final RuleChain mRuleChain = RuleChain
             .outerRule(mActivityRule)
@@ -90,8 +93,9 @@
 
     @Before
     public void setUp() throws Throwable {
-        launchActivityAndWaitForItToBeOnscreen(sInstrumentation, sUiAutomation, mActivityRule)
-                .waitForEmbeddedHierarchy();
+        mActivity = launchActivityAndWaitForItToBeOnscreen(sInstrumentation, sUiAutomation,
+                mActivityRule);
+        mActivity.waitForEmbeddedHierarchy();
     }
 
     @Test
@@ -114,6 +118,7 @@
         final AccessibilityNodeInfo target =
                 findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
         final AccessibilityNodeInfo parent = target.getParent();
+
         final Rect hostViewBoundsInScreen = new Rect();
         final Rect embeddedViewBoundsInScreen = new Rect();
         parent.getBoundsInScreen(hostViewBoundsInScreen);
@@ -125,6 +130,36 @@
                 hostViewBoundsInScreen.contains(embeddedViewBoundsInScreen));
     }
 
+    @Test
+    public void testEmbeddedViewHasCorrectBoundAfterHostViewMove() {
+        final AccessibilityNodeInfo target =
+                findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
+
+        final Rect hostViewBoundsInScreen = new Rect();
+        final Rect newEmbeddedViewBoundsInScreen = new Rect();
+        final Rect oldEmbeddedViewBoundsInScreen = new Rect();
+        target.getBoundsInScreen(oldEmbeddedViewBoundsInScreen);
+
+        // Move Host SurfaceView from (0, 0) to (100, 100).
+        mActivity.requestNewLayoutForTest();
+
+        final AccessibilityNodeInfo newTarget =
+                findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
+        final AccessibilityNodeInfo parent = newTarget.getParent();
+
+        newTarget.getBoundsInScreen(newEmbeddedViewBoundsInScreen);
+        parent.getBoundsInScreen(hostViewBoundsInScreen);
+
+        assertTrue("hostViewBoundsInScreen" + hostViewBoundsInScreen.toShortString()
+                        + " doesn't contain newEmbeddedViewBoundsInScreen"
+                        + newEmbeddedViewBoundsInScreen.toShortString(),
+                hostViewBoundsInScreen.contains(newEmbeddedViewBoundsInScreen));
+        assertFalse("newEmbeddedViewBoundsInScreen" + newEmbeddedViewBoundsInScreen.toShortString()
+                        + " shouldn't be the same with oldEmbeddedViewBoundsInScreen"
+                        + oldEmbeddedViewBoundsInScreen.toShortString(),
+                newEmbeddedViewBoundsInScreen.equals(oldEmbeddedViewBoundsInScreen));
+    }
+
     private AccessibilityNodeInfo findEmbeddedAccessibilityNodeInfo(AccessibilityNodeInfo root) {
         final int childCount = root.getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -150,8 +185,11 @@
             AccessibilityTestActivity implements SurfaceHolder.Callback {
         private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
 
-        private static final int DEFAULT_WIDTH = 200;
-        private static final int DEFAULT_HEIGHT = 200;
+        private static final int DEFAULT_WIDTH = 150;
+        private static final int DEFAULT_HEIGHT = 150;
+
+        private static final int POSITION_X = 50;
+        private static final int POSITION_Y = 50;
 
         private SurfaceView mSurfaceView;
         private SurfaceControlViewHost mViewHost;
@@ -195,5 +233,13 @@
                 throw new AssertionError(e);
             }
         }
+
+        public void requestNewLayoutForTest() {
+            sInstrumentation.runOnMainSync(() -> {
+                mSurfaceView.setX(POSITION_X);
+                mSurfaceView.setY(POSITION_Y);
+                mSurfaceView.requestLayout();
+            });
+        }
     }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAuthenticationTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAuthenticationTest.java
new file mode 100644
index 0000000..678bad0
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAuthenticationTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts.inline;
+
+import static android.app.Activity.RESULT_OK;
+import static android.autofillservice.cts.Helper.ID_PASSWORD;
+import static android.autofillservice.cts.Helper.ID_USERNAME;
+import static android.autofillservice.cts.Helper.UNUSED_AUTOFILL_VALUE;
+import static android.autofillservice.cts.Helper.getContext;
+import static android.autofillservice.cts.Timeouts.MOCK_IME_TIMEOUT_MS;
+import static android.autofillservice.cts.inline.InstrumentedAutoFillServiceInlineEnabled.SERVICE_NAME;
+
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectBindInput;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.autofillservice.cts.AbstractLoginActivityTestCase;
+import android.autofillservice.cts.AuthenticationActivity;
+import android.autofillservice.cts.CannedFillResponse;
+import android.autofillservice.cts.Helper;
+import android.content.IntentSender;
+import android.os.Process;
+
+import com.android.cts.mockime.ImeEventStream;
+import com.android.cts.mockime.MockImeSession;
+
+import org.junit.Test;
+
+public class InlineAuthenticationTest extends AbstractLoginActivityTestCase {
+
+    private static final String TAG = "InlineAuthenticationTest";
+
+    @Override
+    protected void enableService() {
+        Helper.enableAutofillService(getContext(), SERVICE_NAME);
+    }
+
+    @Test
+    public void testDatasetAuthTwoFields() throws Exception {
+        datasetAuthTwoFields(/* cancelFirstAttempt */ false);
+    }
+
+    private void datasetAuthTwoFields(boolean cancelFirstAttempt) throws Exception {
+        // Set service.
+        enableService();
+
+        final MockImeSession mockImeSession = sMockImeSessionRule.getMockImeSession();
+        assumeTrue("MockIME not available", mockImeSession != null);
+
+        // Prepare the authenticated response
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedFillResponse.CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .build());
+        final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+                .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                        .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
+                        .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
+                        .setPresentation(createPresentation("auth"))
+                        .setInlinePresentation(createInlinePresentation("auth"))
+                        .setAuthentication(authentication)
+                        .build());
+        sReplier.addResponse(builder.build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        final ImeEventStream stream = mockImeSession.openEventStream();
+        mockImeSession.callRequestShowSelf(0);
+
+        // Wait until the MockIme gets bound to the TestActivity.
+        expectBindInput(stream, Process.myPid(), MOCK_IME_TIMEOUT_MS);
+
+        // Trigger auto-fill.
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        mUiBot.waitForIdle();
+        sReplier.getNextFillRequest();
+        mUiBot.assertSuggestionStrip(1);
+
+        // Make sure UI is show on 2nd field as well
+        mUiBot.selectByRelativeId(ID_PASSWORD);
+        mUiBot.waitForIdle();
+        mUiBot.assertSuggestionStrip(1);
+
+        // Now tap on 1st field to show it again...
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        mUiBot.waitForIdle();
+        mUiBot.assertSuggestionStrip(1);
+
+        // TODO(b/149891961): add logic for cancelFirstAttempt
+
+        // ...and select it this time
+        AuthenticationActivity.setResultCode(RESULT_OK);
+        mUiBot.selectSuggestion(0);
+        mUiBot.waitForIdle();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
new file mode 100644
index 0000000..941ebe2
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts.inline;
+
+import static android.autofillservice.cts.CannedFillResponse.DO_NOT_REPLY_RESPONSE;
+import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
+import static android.autofillservice.cts.Helper.ID_PASSWORD;
+import static android.autofillservice.cts.Helper.ID_USERNAME;
+import static android.autofillservice.cts.Helper.NULL_DATASET_ID;
+import static android.autofillservice.cts.Helper.assertFillEventForDatasetAuthenticationSelected;
+import static android.autofillservice.cts.Helper.assertFillEventForDatasetSelected;
+import static android.autofillservice.cts.Helper.assertFillEventForDatasetShown;
+import static android.autofillservice.cts.Helper.assertFillEventForSaveShown;
+import static android.autofillservice.cts.Helper.assertNoDeprecatedClientState;
+import static android.autofillservice.cts.Helper.getContext;
+import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilConnected;
+import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilDisconnected;
+import static android.autofillservice.cts.inline.InstrumentedAutoFillServiceInlineEnabled.SERVICE_NAME;
+import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
+
+import android.autofillservice.cts.AbstractLoginActivityTestCase;
+import android.autofillservice.cts.AuthenticationActivity;
+import android.autofillservice.cts.CannedFillResponse;
+import android.autofillservice.cts.CannedFillResponse.CannedDataset;
+import android.autofillservice.cts.Helper;
+import android.autofillservice.cts.InstrumentedAutoFillService;
+import android.autofillservice.cts.LoginActivity;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.platform.test.annotations.AppModeFull;
+import android.service.autofill.FillEventHistory;
+import android.service.autofill.FillEventHistory.Event;
+import android.support.test.uiautomator.UiObject2;
+import android.view.View;
+
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * Test that uses {@link LoginActivity} to test {@link FillEventHistory}.
+ */
+@AppModeFull(reason = "Service-specific test")
+public class InlineFillEventHistoryTest extends AbstractLoginActivityTestCase {
+
+    @Override
+    protected void enableService() {
+        Helper.enableAutofillService(getContext(), SERVICE_NAME);
+    }
+
+    @Test
+    public void testNoDatasetAndSave() throws Exception {
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_USERNAME)
+                .build());
+
+        // Trigger auto-fill and IME.
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        mUiBot.waitForIdle();
+
+        sReplier.getNextFillRequest();
+
+        // Suggestion strip was never shown.
+        mUiBot.assertNoSuggestionStripEver();
+
+        // Change username
+        mActivity.syncRunOnUiThread(() ->  mActivity.onUsername((v) -> v.setText("ID")));
+        mUiBot.waitForIdle();
+
+        // Trigger save UI.
+        mActivity.tapSave();
+        mUiBot.waitForIdle();
+
+        // Confirm the save UI shown
+        final UiObject2 saveUi = mUiBot.assertSaveShowing(SAVE_DATA_TYPE_GENERIC);
+
+        // Save it...
+        mUiBot.saveForAutofill(saveUi, true);
+        mUiBot.waitForIdle();
+        sReplier.getNextSaveRequest();
+
+        // Verify save event
+        final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(1);
+        assertNoDeprecatedClientState(selection);
+        final List<Event> events = selection.getEvents();
+        assertFillEventForSaveShown(events.get(0), NULL_DATASET_ID);
+    }
+
+    @Test
+    public void testOneDatasetAndSave() throws Exception {
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_USERNAME)
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "id")
+                        .setField(ID_PASSWORD, "pass")
+                        .setPresentation(createPresentation("Dataset"))
+                        .setInlinePresentation(createInlinePresentation("Dataset"))
+                        .build())
+                .build());
+
+        // Trigger auto-fill and IME.
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        mUiBot.waitForIdle();
+        sReplier.getNextFillRequest();
+
+        // Suggestion strip was shown.
+        mUiBot.assertSuggestionStrip(1);
+        mUiBot.waitForIdle();
+
+        mUiBot.selectSuggestion(0);
+
+        // Change username and password
+        mActivity.syncRunOnUiThread(() ->  mActivity.onUsername((v) -> v.setText("ID")));
+        mActivity.syncRunOnUiThread(() ->  mActivity.onPassword((v) -> v.setText("PASS")));
+        mUiBot.waitForIdle();
+
+        // Trigger save UI.
+        mActivity.tapSave();
+        mUiBot.waitForIdle();
+
+        // Confirm the save UI shown
+        final UiObject2 saveUi = mUiBot.assertUpdateShowing(SAVE_DATA_TYPE_GENERIC);
+
+        // Save it...
+        mUiBot.saveForAutofill(saveUi, true);
+        mUiBot.waitForIdle();
+        sReplier.getNextSaveRequest();
+
+        // Verify events history
+        final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(4);
+        assertNoDeprecatedClientState(selection);
+        final List<Event> events = selection.getEvents();
+        assertFillEventForDatasetShown(events.get(0));
+        assertFillEventForDatasetSelected(events.get(1), NULL_DATASET_ID);
+        assertFillEventForDatasetShown(events.get(0));
+        assertFillEventForSaveShown(events.get(3), NULL_DATASET_ID);
+    }
+
+    @Test
+    public void testDatasetAuthenticationSelected() throws Exception {
+        enableService();
+
+        // Set up FillResponse with dataset authentication
+        Bundle clientState = new Bundle();
+        clientState.putCharSequence("clientStateKey", "clientStateValue");
+
+        // Prepare the authenticated response
+        final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+                new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("Dataset"))
+                        .setInlinePresentation(createInlinePresentation("Dataset"))
+                        .build());
+
+        sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
+                new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "username")
+                        .setId("name")
+                        .setPresentation(createPresentation("authentication"))
+                        .setInlinePresentation(createInlinePresentation("authentication"))
+                        .setAuthentication(authentication)
+                        .build())
+                .setExtras(clientState).build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill and IME.
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        mUiBot.waitForIdle();
+
+        // ...
+        sReplier.getNextFillRequest();
+        mUiBot.assertSuggestionStrip(1);
+
+        // Authenticate
+        mUiBot.selectSuggestion(0);
+        mUiBot.waitForIdle();
+        mActivity.assertAutoFilled();
+
+        // Verify fill selection
+        final List<Event> events = InstrumentedAutoFillService.getFillEvents(2);
+        assertFillEventForDatasetShown(events.get(0), "clientStateKey", "clientStateValue");
+        assertFillEventForDatasetAuthenticationSelected(events.get(1), "name",
+                "clientStateKey", "clientStateValue");
+    }
+
+    @Test
+    public void testNoEvents_whenServiceReturnsNullResponse() throws Exception {
+        enableService();
+
+        // First reset
+        sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
+                new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "username")
+                        .setPresentation(createPresentation("dataset1"))
+                        .setInlinePresentation(createInlinePresentation("dataset1"))
+                        .build())
+                .build());
+        mActivity.expectAutoFill("username");
+
+        // Trigger auto-fill and IME.
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        waitUntilConnected();
+        sReplier.getNextFillRequest();
+        mUiBot.selectSuggestion(0);
+        mUiBot.waitForIdle();
+        mActivity.assertAutoFilled();
+
+        {
+            // Verify fill selection
+            final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(2);
+            assertNoDeprecatedClientState(selection);
+            final List<Event> events = selection.getEvents();
+            assertFillEventForDatasetShown(events.get(0));
+            assertFillEventForDatasetSelected(events.get(1), NULL_DATASET_ID);
+        }
+
+        // Second request
+        sReplier.addResponse(NO_RESPONSE);
+        mActivity.onPassword(View::requestFocus);
+        sReplier.getNextFillRequest();
+        mUiBot.assertNoSuggestionStripEver();
+        waitUntilDisconnected();
+
+        InstrumentedAutoFillService.assertNoFillEventHistory();
+    }
+
+    @Test
+    public void testNoEvents_whenServiceReturnsFailure() throws Exception {
+        enableService();
+
+        // First reset
+        sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
+                new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "username")
+                        .setPresentation(createPresentation("dataset1"))
+                        .setInlinePresentation(createInlinePresentation("dataset1"))
+                        .build())
+                .build());
+        mActivity.expectAutoFill("username");
+
+        // Trigger auto-fill and IME.
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        waitUntilConnected();
+        sReplier.getNextFillRequest();
+        mUiBot.selectSuggestion(0);
+        mUiBot.waitForIdle();
+        mActivity.assertAutoFilled();
+
+        {
+            // Verify fill selection
+            final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(2);
+            assertNoDeprecatedClientState(selection);
+            final List<Event> events = selection.getEvents();
+            assertFillEventForDatasetShown(events.get(0));
+            assertFillEventForDatasetSelected(events.get(1), NULL_DATASET_ID);
+        }
+
+        // Second request
+        sReplier.addResponse(new CannedFillResponse.Builder().returnFailure("D'OH!").build());
+        mActivity.onPassword(View::requestFocus);
+        sReplier.getNextFillRequest();
+        mUiBot.assertNoSuggestionStripEver();
+        waitUntilDisconnected();
+
+        InstrumentedAutoFillService.assertNoFillEventHistory();
+    }
+
+    @Test
+    public void testNoEvents_whenServiceTimesout() throws Exception {
+        enableService();
+
+        // First reset
+        sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
+                new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "username")
+                        .setPresentation(createPresentation("dataset1"))
+                        .setInlinePresentation(createInlinePresentation("dataset1"))
+                        .build())
+                .build());
+        mActivity.expectAutoFill("username");
+
+        // Trigger auto-fill and IME.
+        mUiBot.selectByRelativeId(ID_USERNAME);
+        waitUntilConnected();
+        sReplier.getNextFillRequest();
+        mUiBot.selectSuggestion(0);
+        mUiBot.waitForIdle();
+        mActivity.assertAutoFilled();
+
+        {
+            // Verify fill selection
+            final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(2);
+            assertNoDeprecatedClientState(selection);
+            final List<Event> events = selection.getEvents();
+            assertFillEventForDatasetShown(events.get(0));
+            assertFillEventForDatasetSelected(events.get(1), NULL_DATASET_ID);
+        }
+
+        // Second request
+        sReplier.addResponse(DO_NOT_REPLY_RESPONSE);
+        mActivity.onPassword(View::requestFocus);
+        sReplier.getNextFillRequest();
+        waitUntilDisconnected();
+
+        InstrumentedAutoFillService.assertNoFillEventHistory();
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
new file mode 100644
index 0000000..17bcc2f
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts.inline;
+
+import static android.autofillservice.cts.Helper.assertTextAndValue;
+import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.Helper.getContext;
+import static android.autofillservice.cts.SimpleSaveActivity.ID_COMMIT;
+import static android.autofillservice.cts.SimpleSaveActivity.ID_INPUT;
+import static android.autofillservice.cts.SimpleSaveActivity.ID_PASSWORD;
+import static android.autofillservice.cts.inline.InstrumentedAutoFillServiceInlineEnabled.SERVICE_NAME;
+import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
+
+import android.autofillservice.cts.AutoFillServiceTestCase;
+import android.autofillservice.cts.AutofillActivityTestRule;
+import android.autofillservice.cts.CannedFillResponse;
+import android.autofillservice.cts.Helper;
+import android.autofillservice.cts.InstrumentedAutoFillService;
+import android.autofillservice.cts.SimpleSaveActivity;
+import android.support.test.uiautomator.UiObject2;
+
+import androidx.annotation.NonNull;
+
+import org.junit.Test;
+
+public class InlineSimpleSaveActivityTest
+        extends AutoFillServiceTestCase.AutoActivityLaunch<SimpleSaveActivity> {
+
+    private static final String TAG = "InlineSimpleSaveActivityTest";
+    protected SimpleSaveActivity mActivity;
+
+    @Override
+    protected void enableService() {
+        Helper.enableAutofillService(getContext(), SERVICE_NAME);
+    }
+
+    @NonNull
+    @Override
+    protected AutofillActivityTestRule<SimpleSaveActivity> getActivityRule() {
+        return new AutofillActivityTestRule<SimpleSaveActivity>(SimpleSaveActivity.class) {
+            @Override
+            protected void afterActivityLaunched() {
+                mActivity = getActivity();
+            }
+        };
+    }
+
+    @Test
+    public void testAutofillSave() throws Exception {
+        // Set service.
+        enableService();
+
+         // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_INPUT)
+                .build());
+
+        // Trigger auto-fill and IME.
+        mUiBot.selectByRelativeId(ID_INPUT);
+        mUiBot.waitForIdle();
+
+        sReplier.getNextFillRequest();
+
+        // Suggestion strip was never shown.
+        mUiBot.assertNoSuggestionStripEver();
+
+        // Change input
+        mActivity.syncRunOnUiThread(() -> mActivity.getInput().setText("ID"));
+        mUiBot.waitForIdle();
+
+        // Trigger save UI.
+        mUiBot.selectByRelativeId(ID_COMMIT);
+        mUiBot.waitForIdle();
+
+        // Confirm the save UI shown
+        final UiObject2 saveUi = mUiBot.assertSaveShowing(SAVE_DATA_TYPE_GENERIC);
+
+        // Save it...
+        mUiBot.saveForAutofill(saveUi, true);
+
+        // ... and assert results
+        final InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();
+        assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_INPUT), "ID");
+    }
+
+    @Test
+    public void testAutofill_oneDatasetAndSave() throws Exception {
+        // Set service.
+        enableService();
+
+        final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+                .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_INPUT, ID_PASSWORD)
+                .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                        .setField(ID_INPUT, "id")
+                        .setField(ID_PASSWORD, "pass")
+                        .setPresentation(createPresentation("YO"))
+                        .setInlinePresentation(createInlinePresentation("YO"))
+                        .build());
+        sReplier.addResponse(builder.build());
+        mActivity.expectAutoFill("id", "pass");
+
+        // Trigger auto-fill and IME.
+        mUiBot.selectByRelativeId(ID_INPUT);
+        mUiBot.waitForIdle();
+
+        sReplier.getNextFillRequest();
+
+        // Confirm one suggestion
+        mUiBot.assertSuggestionStrip(1);
+
+        // Select suggestion
+        mUiBot.selectSuggestion(0);
+        mUiBot.waitForIdle();
+
+        // Check the results.
+        mActivity.expectAutoFill("id", "pass");
+
+        // Change input
+        mActivity.syncRunOnUiThread(() -> mActivity.getInput().setText("ID"));
+        mUiBot.waitForIdle();
+
+        // Trigger save UI.
+        mUiBot.selectByRelativeId(ID_COMMIT);
+        mUiBot.waitForIdle();
+
+        // Confirm the save UI shown
+        final UiObject2 saveUi = mUiBot.assertUpdateShowing(SAVE_DATA_TYPE_GENERIC);
+
+        // Save it...
+        mUiBot.saveForAutofill(saveUi, true);
+
+        // ... and assert results
+        final InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();
+        assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_INPUT), "ID");
+        assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_PASSWORD), "pass");
+    }
+}
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index f6113bf..507859b 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -477,6 +477,16 @@
             </meta-data>
         </service>
 
+        <service
+            android:name=".TestDream"
+            android:exported="true"
+            android:permission="android.permission.BIND_DREAM_SERVICE">
+            <intent-filter>
+                <action android:name="android.service.dreams.DreamService" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </service>
+
         <!-- Disable home activities by default or it may disturb other tests by
              showing ResolverActivity when start home activity -->
         <activity-alias android:name=".HomeActivity"
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
index 300398d..6751a1a 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
@@ -204,6 +204,9 @@
     public static final ComponentName POPUP_MPP_ACTIVITY =
             component("PopupMinimalPostProcessingActivity");
 
+    public static final ComponentName TEST_DREAM_SERVICE =
+            component("TestDream");
+
     /**
      * Action and extra key constants for {@link #INPUT_METHOD_TEST_ACTIVITY}.
      */
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/TestDream.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TestDream.java
new file mode 100644
index 0000000..3a6cca0
--- /dev/null
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/TestDream.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.server.wm.app;
+
+import android.service.dreams.DreamService;
+
+public class TestDream extends DreamService {
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DreamManagerServiceTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DreamManagerServiceTests.java
new file mode 100644
index 0000000..78ef876
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DreamManagerServiceTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.server.wm;
+
+import static android.server.wm.app.Components.TEST_DREAM_SERVICE;
+
+import android.app.DreamManager;
+import android.content.ComponentName;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.FlakyTest;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.Test;
+
+@Presubmit
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+public class DreamManagerServiceTests extends ActivityManagerTestBase {
+
+    private static final ComponentName DREAM_ACTIVITY_COMPONENT_NAME =
+            new ComponentName(TEST_DREAM_SERVICE.getPackageName(),
+                              "android.service.dreams.DreamActivity");
+
+    private void startDream(ComponentName name) {
+        DreamManager dreamer = mContext.getSystemService(DreamManager.class);
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            dreamer.startDream(name);
+        });
+    }
+
+    private void stopDream() {
+        DreamManager dreamer = mContext.getSystemService(DreamManager.class);
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            dreamer.stopDream();
+        });
+    }
+
+    private void setActiveDream(ComponentName dream) {
+        DreamManager dreamer = mContext.getSystemService(DreamManager.class);
+        SystemUtil.runWithShellPermissionIdentity(() -> {
+            dreamer.setActiveDream(dream);
+        });
+    }
+
+    @Test
+    public void testStartAndStopDream() throws Exception {
+        setActiveDream(TEST_DREAM_SERVICE);
+
+        startDream(TEST_DREAM_SERVICE);
+        mWmState.waitForValidState(DREAM_ACTIVITY_COMPONENT_NAME);
+        mWmState.assertVisibility(DREAM_ACTIVITY_COMPONENT_NAME, true);
+        mWmState.assertHomeActivityVisible(false);
+
+        stopDream();
+        mWmState.waitAndAssertActivityRemoved(DREAM_ACTIVITY_COMPONENT_NAME);
+
+        mWmState.assertHomeActivityVisible(true);
+    }
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
index c454c84..5121a39 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
@@ -292,7 +292,6 @@
      * Tests launching a single instance home activity on virtual display with system decoration
      * support.
      */
-    @FlakyTest(bugId = 149070587)
     @Test
     public void testLaunchSingleHomeActivityOnDisplayWithDecorations() {
         createManagedHomeActivitySession(SINGLE_HOME_ACTIVITY);
@@ -316,7 +315,6 @@
      * Tests launching a single instance home activity with SECONDARY_HOME on virtual display with
      * system decoration support.
      */
-    @FlakyTest(bugId = 149070587)
     @Test
     public void testLaunchSingleSecondaryHomeActivityOnDisplayWithDecorations() {
         createManagedHomeActivitySession(SINGLE_SECONDARY_HOME_ACTIVITY);
@@ -340,7 +338,6 @@
      * Tests launching a multi-instance home activity on virtual display with system decoration
      * support.
      */
-    @FlakyTest(bugId = 149070587)
     @Test
     public void testLaunchHomeActivityOnDisplayWithDecorations() {
         createManagedHomeActivitySession(HOME_ACTIVITY);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index 998f553..0b44b01 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -24,11 +24,11 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
-import static android.server.wm.WindowManagerState.STATE_RESUMED;
-import static android.server.wm.WindowManagerState.STATE_STOPPED;
 import static android.server.wm.ComponentNameUtils.getActivityName;
 import static android.server.wm.ComponentNameUtils.getWindowName;
 import static android.server.wm.UiDeviceUtils.pressWindowButton;
+import static android.server.wm.WindowManagerState.STATE_RESUMED;
+import static android.server.wm.WindowManagerState.STATE_STOPPED;
 import static android.server.wm.app.Components.ALWAYS_FOCUSABLE_PIP_ACTIVITY;
 import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
 import static android.server.wm.app.Components.LAUNCH_ENTER_PIP_ACTIVITY;
@@ -88,10 +88,10 @@
 import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.server.wm.WindowManagerState.ActivityTask;
 import android.server.wm.CommandSession.ActivityCallback;
 import android.server.wm.CommandSession.SizeInfo;
 import android.server.wm.TestJournalProvider.TestJournalContainer;
+import android.server.wm.WindowManagerState.ActivityTask;
 import android.server.wm.settings.SettingsSession;
 import android.util.Log;
 import android.util.Size;
@@ -109,7 +109,6 @@
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.function.Function;
 
 /**
  * Build/Install/Run:
@@ -210,46 +209,6 @@
         mWmState.assertVisibility(PIP_ACTIVITY, true);
     }
 
-    private void waitForValidPinnedStackBounds(Function<WindowManagerState, Rect> boundsFunc) {
-        mWmState.waitForWithAmState(wmState -> {
-            final Rect bounds = boundsFunc.apply(wmState);
-            final Rect displayStableBounds = wmState.getStableBounds();
-            return bounds.width() > 0 && bounds.height() > 0
-                    && displayStableBounds.contains(bounds);
-        }, "valid pinned stack bounds");
-    }
-
-    @Test
-    public void testPinnedStackOutOfBoundsInsetsNonNegative() throws Exception {
-        final WindowManagerState wmState = mWmState;
-
-        // Launch an activity into the pinned stack
-        launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true",
-                EXTRA_TAP_TO_FINISH, "true");
-        // Wait for animation complete since we are comparing bounds
-        waitForEnterPipAnimationComplete(PIP_ACTIVITY);
-
-        // Get the display dimensions
-        WindowManagerState.WindowState windowState = getWindowState(PIP_ACTIVITY);
-        WindowManagerState.DisplayContent display =
-                wmState.getDisplay(windowState.getDisplayId());
-        Rect displayRect = display.getDisplayRect();
-
-        // Move the pinned stack offscreen
-        final int stackId = getPinnedStack().mRootTaskId;
-        final int top = 0;
-        final int left = displayRect.width() - 200;
-        resizePinnedStack(stackId, left, top, left + 500, top + 500);
-
-        // Ensure that the surface insets are not negative
-        windowState = getWindowState(PIP_ACTIVITY);
-        Rect contentInsets = windowState.getContentInsets();
-        if (contentInsets != null) {
-            assertTrue(contentInsets.left >= 0 && contentInsets.top >= 0
-                    && contentInsets.width() >= 0 && contentInsets.height() >= 0);
-        }
-    }
-
     @Test
     public void testPinnedStackInBoundsAfterRotation() {
         // Launch an activity into the pinned stack
@@ -299,6 +258,9 @@
     }
 
     private void testEnterPipAspectRatio(int num, int denom) throws Exception {
+        // Launch a test activity so that we're not over home
+        launchActivity(TEST_ACTIVITY);
+
         launchActivity(PIP_ACTIVITY,
                 EXTRA_ENTER_PIP, "true",
                 EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
@@ -324,6 +286,9 @@
     }
 
     private void testResizePipAspectRatio(int num, int denom) throws Exception {
+        // Launch a test activity so that we're not over home
+        launchActivity(TEST_ACTIVITY);
+
         launchActivity(PIP_ACTIVITY,
                 EXTRA_ENTER_PIP, "true",
                 EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
@@ -349,6 +314,9 @@
     }
 
     private void testEnterPipExtremeAspectRatio(int num, int denom) throws Exception {
+        // Launch a test activity so that we're not over home
+        launchActivity(TEST_ACTIVITY);
+
         // Assert that we could not create a pinned stack with an extreme aspect ratio
         launchActivity(PIP_ACTIVITY,
                 EXTRA_ENTER_PIP, "true",
@@ -370,6 +338,9 @@
     }
 
     private void testSetPipExtremeAspectRatio(int num, int denom) throws Exception {
+        // Launch a test activity so that we're not over home
+        launchActivity(TEST_ACTIVITY);
+
         // Try to resize the a normal pinned stack to an extreme aspect ratio and ensure that
         // fails (the aspect ratio remains the same)
         launchActivity(PIP_ACTIVITY,
@@ -882,6 +853,7 @@
         }
     }
 
+    @Ignore("b/149946388")
     @Test
     public void testEnterPipInterruptedCallbacks() {
         final TransitionAnimationScaleSession transitionAnimationScaleSession =
@@ -1018,18 +990,13 @@
         waitForEnterPip(PIP_ACTIVITY);
         assertPinnedStackExists();
         ActivityTask stack = mWmState.getStandardStackByWindowingMode(WINDOWING_MODE_PINNED);
-        int stackId = stack.mRootTaskId;
         int taskId = stack.getTopTask().mTaskId;
 
         // Launch task overlay activity into PiP activity task
         launchPinnedActivityAsTaskOverlay(TRANSLUCENT_TEST_ACTIVITY, taskId);
 
-        // Finish the task overlay activity while animating and ensure that the PiP activity never
-        // got resumed.
+        // Finish the task overlay activity and ensure that the PiP activity never got resumed.
         separateTestJournal();
-        SystemUtil.runWithShellPermissionIdentity(
-                () -> mAtm.resizePinnedStack(stackId, new Rect(20, 20, 500, 500),
-                        true /* animate */));
         mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
         mWmState.waitFor((amState) ->
                         !amState.containsActivity(TRANSLUCENT_TEST_ACTIVITY),
@@ -1287,13 +1254,24 @@
 
     /**
      * Waits until the picture-in-picture animation has finished.
+     * TODO(b/149947030): use the transition completed signal from TaskOrganizer
      */
     private void waitForEnterPipAnimationComplete(ComponentName activityName) {
         waitForEnterPip(activityName);
-        mWmState.waitFor((amState) -> {
-                ActivityTask stack = amState.getStandardRootTaskByWindowingMode(WINDOWING_MODE_PINNED);
-                return stack != null && !stack.mAnimatingBounds;
-            }, "pinned stack bounds animation to finish");
+        final Rect pinnedStackBounds = new Rect();
+        mWmState.waitForWithAmState(wmState -> {
+            final Rect displayStableBounds = wmState.getStableBounds();
+            Rect newBounds = wmState.getStandardStackByWindowingMode(WINDOWING_MODE_PINNED)
+                    .getBounds();
+            if (pinnedStackBounds.equals(newBounds)
+                    && (displayStableBounds.width() / 2) > newBounds.width()
+                    && (displayStableBounds.height() / 2) > newBounds.height()) {
+                return true;
+            } else if (newBounds != null) {
+                pinnedStackBounds.set(newBounds);
+            }
+            return false;
+        }, "stack bounds stabilized, consider in pinned mode");
     }
 
     /**
@@ -1307,12 +1285,28 @@
 
     /**
      * Waits until the picture-in-picture animation to fullscreen has finished.
+     * TODO(b/149947030): use the transition completed signal from TaskOrganizer
      */
     private void waitForExitPipToFullscreen(ComponentName activityName) {
         mWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
                 .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
                 .setActivityType(ACTIVITY_TYPE_STANDARD)
                 .build());
+        final Rect stackBounds = new Rect();
+        mWmState.waitForWithAmState(wmState -> {
+            final Rect displayStableBounds = wmState.getStableBounds();
+            final ActivityTask task = wmState.getTaskByActivity(activityName);
+            if (task == null) return false;
+            Rect newBounds = task.getBounds();
+            if (stackBounds.equals(newBounds)
+                    && (displayStableBounds.width() / 2) < newBounds.width()
+                    && (displayStableBounds.height() / 2) < newBounds.height()) {
+                return true;
+            } else if (newBounds != null) {
+                stackBounds.set(newBounds);
+            }
+            return false;
+        }, "stack bounds stabilized, consider in fullscreen mode");
     }
 
     /**
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index b7352fe..cd054c2 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -101,6 +101,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
 
 import static java.lang.Integer.toHexString;
 
@@ -529,9 +530,18 @@
     }
 
     protected ComponentName getDefaultSecondaryHomeComponent() {
+        assumeTrue(supportsMultiDisplay());
         int resId = Resources.getSystem().getIdentifier(
-                "config_secondaryHomeComponent", "string", "android");
-        return ComponentName.unflattenFromString(mContext.getResources().getString(resId));
+                "config_secondaryHomePackage", "string", "android");
+        final Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_SECONDARY_HOME);
+        intent.setPackage(mContext.getResources().getString(resId));
+        final ResolveInfo resolveInfo =
+                mContext.getPackageManager().resolveActivity(intent, MATCH_DEFAULT_ONLY);
+        assertNotNull("Should have default secondary home activity", resolveInfo);
+
+        return new ComponentName(resolveInfo.activityInfo.packageName,
+                resolveInfo.activityInfo.name);
     }
 
     /**
@@ -902,12 +912,6 @@
                         new Rect(0, 0, taskWidth, taskHeight)));
     }
 
-    protected void resizePinnedStack(
-            int stackId, int stackLeft, int stackTop, int stackWidth, int stackHeight) {
-        SystemUtil.runWithShellPermissionIdentity(() -> mAtm.resizePinnedStack(stackId,
-                new Rect(stackLeft, stackTop, stackWidth, stackHeight), false /* animate */));
-    }
-
     protected void pressAppSwitchButtonAndWaitForRecents() {
         pressAppSwitchButton();
         mWmState.waitForRecentsActivityVisible();
diff --git a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java
index ab44335..afae17e 100644
--- a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java
+++ b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java
@@ -22,12 +22,15 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.app.UiModeManager;
+import android.content.res.Configuration;
 import android.os.PowerManager;
 
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.compatibility.common.util.BatteryUtils;
+import com.android.compatibility.common.util.SettingsUtils;
 import com.android.compatibility.common.util.SystemUtil;
 
 import org.junit.Test;
@@ -91,4 +94,57 @@
             assertFalse(manager.isPowerSaveMode());
         });
     }
+
+    /** Tests that Battery Saver exemptions activate when car mode is active. */
+    @Test
+    public void testCarModeExceptions() throws Exception {
+        UiModeManager uiModeManager = getContext().getSystemService(UiModeManager.class);
+        uiModeManager.disableCarMode(0);
+
+        final PowerManager powerManager = BatteryUtils.getPowerManager();
+
+        try {
+            runDumpsysBatteryUnplug();
+
+            SettingsUtils.set(SettingsUtils.NAMESPACE_GLOBAL, "battery_saver_constants",
+                    "gps_mode=" + PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF
+                    + ",enable_night_mode=true");
+
+            enableBatterySaver(true);
+
+            // Allow time for UI change.
+            Thread.sleep(1000);
+            assertTrue(powerManager.isPowerSaveMode());
+            assertEquals(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF,
+                    powerManager.getLocationPowerSaveMode());
+            assertEquals(Configuration.UI_MODE_NIGHT_YES,
+                    getContext().getResources().getConfiguration().uiMode
+                        & Configuration.UI_MODE_NIGHT_MASK);
+
+            uiModeManager.enableCarMode(0);
+            // Allow time for UI change.
+            Thread.sleep(1000);
+
+            final int locationPowerSaveMode = powerManager.getLocationPowerSaveMode();
+            assertTrue("Location power save mode didn't change from " + locationPowerSaveMode,
+                    locationPowerSaveMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY
+                            || locationPowerSaveMode == PowerManager.LOCATION_MODE_NO_CHANGE);
+            assertEquals(Configuration.UI_MODE_NIGHT_NO,
+                getContext().getResources().getConfiguration().uiMode
+                    & Configuration.UI_MODE_NIGHT_MASK);
+
+            uiModeManager.disableCarMode(0);
+            // Allow time for UI change.
+            Thread.sleep(1000);
+
+            assertEquals(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF,
+                powerManager.getLocationPowerSaveMode());
+            assertEquals(Configuration.UI_MODE_NIGHT_YES,
+                getContext().getResources().getConfiguration().uiMode
+                    & Configuration.UI_MODE_NIGHT_MASK);
+        } finally {
+            uiModeManager.disableCarMode(0);
+            SettingsUtils.delete(SettingsUtils.NAMESPACE_GLOBAL, "battery_saver_constants");
+        }
+    }
 }
diff --git a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
index 583ff7c..1a27bf0 100644
--- a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
@@ -26,7 +26,9 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
@@ -215,4 +217,62 @@
                 PARTIALLY_DIRECT_BOOT_AWARE_PACKAGE_NAME, 0);
         assertTrue(applicationInfo.isEncryptionAware());
     }
+
+    @Test
+    public void testWriteToParcelDontSquash() throws Exception {
+        // Make sure ApplicationInfo.writeToParcel() doesn't do the "squashing",
+        // because Parcel.allowSquashing() isn't called.
+
+        mApplicationInfo = getContext().getPackageManager().getApplicationInfo(mPackageName, 0);
+
+        final Parcel p = Parcel.obtain();
+        mApplicationInfo.writeToParcel(p, 0);
+        mApplicationInfo.writeToParcel(p, 0);
+
+        // Don't call Parcel.allowSquashing()
+
+        p.setDataPosition(0);
+        final ApplicationInfo copy1 = ApplicationInfo.CREATOR.createFromParcel(p);
+        final ApplicationInfo copy2 = ApplicationInfo.CREATOR.createFromParcel(p);
+
+        p.recycle();
+
+        assertNotSame(mApplicationInfo, copy1);
+
+        // writeToParcel() doesn't do the squashing, so copy1 and copy2 will be different.
+        assertNotSame(copy1, copy2);
+
+        // Check several fields to make sure they're properly copied.
+        assertEquals(mApplicationInfo.packageName, copy2.packageName);
+        assertEquals(copy1.packageName, copy2.packageName);
+
+        assertEquals(mApplicationInfo.flags, copy2.flags);
+        assertEquals(copy1.flags, copy2.flags);
+    }
+
+    @Test
+    public void testWriteToParcelSquash() throws Exception {
+        // Make sure ApplicationInfo.writeToParcel() does the "squashing", after
+        // Parcel.allowSquashing() is called.
+
+        mApplicationInfo = getContext().getPackageManager().getApplicationInfo(mPackageName, 0);
+
+        final Parcel p = Parcel.obtain();
+
+        final boolean prevSquashing = p.allowSquashing(); // Allow squashing.
+
+        mApplicationInfo.writeToParcel(p, 0);
+        mApplicationInfo.writeToParcel(p, 0);
+
+        p.setDataPosition(0);
+        final ApplicationInfo copy1 = ApplicationInfo.CREATOR.createFromParcel(p);
+        final ApplicationInfo copy2 = ApplicationInfo.CREATOR.createFromParcel(p);
+
+        p.recycle();
+
+        assertNotSame(mApplicationInfo, copy1);
+        assertSame(copy1, copy2); //
+
+        p.restoreAllowSquashing(prevSquashing);
+    }
 }
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java b/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
index b2aae0d..8cfab20 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
@@ -18,6 +18,7 @@
 
 
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageItemInfo;
@@ -63,6 +64,19 @@
         p.recycle();
     }
 
+    public void testApplicationInfoSame() {
+        ApplicationInfo ai = mPackageInfo.applicationInfo;
+
+        // Make sure all the components in it has the same ApplicationInfo.
+        for (ComponentInfo[] ar : new ComponentInfo[][]{
+                mPackageInfo.activities, mPackageInfo.services, mPackageInfo.providers,
+                mPackageInfo.receivers}) {
+            for (ComponentInfo ci : ar) {
+                assertSame("component=" + ci.getComponentName(), ai, ci.applicationInfo);
+            }
+        }
+    }
+
     private void checkPkgInfoSame(PackageInfo expected, PackageInfo actual) {
         assertEquals(expected.packageName, actual.packageName);
         assertEquals(expected.getLongVersionCode(), actual.getLongVersionCode());
diff --git a/tests/tests/content/src/android/content/pm/cts/ProviderInfoListTest.java b/tests/tests/content/src/android/content/pm/cts/ProviderInfoListTest.java
new file mode 100644
index 0000000..2578058
--- /dev/null
+++ b/tests/tests/content/src/android/content/pm/cts/ProviderInfoListTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.cts;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ProviderInfoList;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ProviderInfoListTest extends AndroidTestCase {
+    private static final String PACKAGE_NAME = "android.content.cts";
+
+    public void testApplicationInfoSquashed() throws Exception {
+        final PackageManager pm = getContext().getPackageManager();
+        final PackageInfo pi = pm.getPackageInfo(PACKAGE_NAME,
+                PackageManager.GET_PROVIDERS | PackageManager.GET_UNINSTALLED_PACKAGES);
+
+        // Make sure the package contains more than 1 providers.
+        assertNotNull(pi);
+        assertNotNull(pi.providers);
+        assertTrue(pi.providers.length > 1);
+
+        final List<ProviderInfo> providers = new ArrayList<>();
+        Collections.addAll(providers, pi.providers);
+
+        // Create a target list.
+        final ProviderInfoList source = ProviderInfoList.fromList(providers);
+
+        // Parcel it and uparcel
+        final Parcel p = Parcel.obtain();
+        source.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        final ProviderInfoList dest = ProviderInfoList.CREATOR.createFromParcel(p);
+        p.recycle();
+
+        final List<ProviderInfo> destList = dest.getList();
+        assertEquals(source.getList().size(), destList.size());
+        for (int i = 0; i < destList.size(); i++) {
+            assertEquals(destList.get(0).applicationInfo, destList.get(i).applicationInfo);
+        }
+    }
+}
diff --git a/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
index 44a9cc2..d5361d7 100644
--- a/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -163,7 +163,7 @@
 
         // Analyze results
         assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures + ", ITERATIONS="
-                        + NUM_OF_RTT_ITERATIONS,
+                        + NUM_OF_RTT_ITERATIONS + ", AP RSSI=" + testAp.level,
                 numFailures <= NUM_OF_RTT_ITERATIONS * MAX_FAILURE_RATE_PERCENT / 100);
         if (numFailures != NUM_OF_RTT_ITERATIONS) {
             double distanceAvg = distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
diff --git a/tests/tests/provider/OWNERS b/tests/tests/provider/OWNERS
index fea932d..ed13f6fa 100644
--- a/tests/tests/provider/OWNERS
+++ b/tests/tests/provider/OWNERS
@@ -5,3 +5,5 @@
 tgunn@google.com
 nicksauer@google.com
 nona@google.com
+nandana@google.com
+zezeozue@google.com
diff --git a/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml b/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml
index f1829f6..31ffdd8 100644
--- a/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml
+++ b/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml
@@ -50,6 +50,14 @@
                 <data android:scheme="tel" />
             </intent-filter>
         </activity>
+        <service
+            android:name=".DialerInCallService"
+            android:permission="android.permission.BIND_INCALL_SERVICE">
+            <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
+            <intent-filter>
+                <action android:name="android.telecom.InCallService" />
+            </intent-filter>
+        </service>
 
         <!-- Sms -->
         <activity android:name=".SmsSendToActivity">
@@ -64,7 +72,6 @@
             android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
             <intent-filter>
                 <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
-                <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="smsto" />
             </intent-filter>
         </service>
diff --git a/tests/tests/role/CtsRoleTestApp28/AndroidManifest.xml b/tests/tests/role/CtsRoleTestApp28/AndroidManifest.xml
index 8fd7012..574f768 100644
--- a/tests/tests/role/CtsRoleTestApp28/AndroidManifest.xml
+++ b/tests/tests/role/CtsRoleTestApp28/AndroidManifest.xml
@@ -45,6 +45,14 @@
                 <data android:scheme="tel" />
             </intent-filter>
         </activity>
+        <service
+            android:name=".DialerInCallService"
+            android:permission="android.permission.BIND_INCALL_SERVICE">
+            <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
+            <intent-filter>
+                <action android:name="android.telecom.InCallService" />
+            </intent-filter>
+        </service>
 
         <!-- Sms -->
         <activity android:name=".SmsSendToActivity">
@@ -59,7 +67,6 @@
             android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
             <intent-filter>
                 <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
-                <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="smsto" />
             </intent-filter>
         </service>