Merge "DO Disclosure: update instructions for enterprise installed apps, admin granted permission and entrise set default apps test cases." into oc-dev
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index 54fdb08..a8b9863 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -391,8 +391,6 @@
         s,e,_,_,_ = cam.do_3a(get_results=True, do_af=False)
         req = its.objects.manual_capture_request(s, e)
         fps = 30
-        if "60fps" in sys.argv:
-            fps = 60
         req["android.control.aeTargetFpsRange"] = [fps, fps]
         print "Capturing %dx%d with sens. %d, exp. time %.1fms" % (
                 W, H, s, e*NSEC_TO_MSEC)
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index a613050..1787b42 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -48,6 +48,7 @@
                   android:required="false" />
     <uses-feature android:name="android.software.vr.mode" android:required="false" />
     <uses-feature android:name="android.hardware.vr.high_performance" android:required="false"/>
+    <uses-feature android:name="android.software.companion_device_setup" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
diff --git a/hostsidetests/devicepolicy/app/Assistant/Android.mk b/hostsidetests/devicepolicy/app/Assistant/Android.mk
new file mode 100644
index 0000000..196f323
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsDevicePolicyAssistApp
+
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 compatibility-device-util android-support-test
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/Assistant/AndroidManifest.xml b/hostsidetests/devicepolicy/app/Assistant/AndroidManifest.xml
new file mode 100644
index 0000000..5fc20de
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/AndroidManifest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.devicepolicy.assistapp" >
+
+    <application>
+
+        <service android:name=".MyInteractionService"
+                android:label="CTS test voice interaction service"
+                android:permission="android.permission.BIND_VOICE_INTERACTION"
+                android:exported="true">
+            <meta-data android:name="android.voice_interaction"
+                    android:resource="@xml/interaction_service" />
+            <intent-filter>
+                <action android:name="android.service.voice.VoiceInteractionService" />
+            </intent-filter>
+        </service>
+
+        <service android:name=".MyInteractionSessionService"
+                android:permission="android.permission.BIND_VOICE_INTERACTION">
+        </service>
+
+        <activity android:name=".SettingsActivity"
+                android:exported="true">
+        </activity>
+    </application>
+
+    <instrumentation
+            android:name="android.support.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.cts.devicepolicy.assistapp"
+            android:label="Assistant related device policy CTS" />
+
+</manifest>
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/Assistant/res/xml/interaction_service.xml b/hostsidetests/devicepolicy/app/Assistant/res/xml/interaction_service.xml
new file mode 100644
index 0000000..a3fe680
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/res/xml/interaction_service.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<voice-interaction-service xmlns:android="http://schemas.android.com/apk/res/android"
+        android:sessionService="com.android.cts.devicepolicy.assistapp.MyInteractionSessionService"
+        android:recognitionService="com.android.cts.devicepolicy.assistapp.MyInteractionService"
+        android:settingsActivity="com.android.cts.devicepolicy.assistapp.SettingsActivity"
+        android:supportsAssist="true" />
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionService.java b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionService.java
new file mode 100644
index 0000000..e232540
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionService.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.devicepolicy.assistapp;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.service.voice.VoiceInteractionService;
+import android.util.Log;
+
+import static android.service.voice.VoiceInteractionSession.SHOW_WITH_ASSIST;
+import static android.service.voice.VoiceInteractionSession.SHOW_WITH_SCREENSHOT;
+
+public class MyInteractionService extends VoiceInteractionService {
+    private static final String TAG = "DevicePolicyAssistTest";
+    private static final String ACTION_CHECK_IS_READY = "voice_interaction_service.is_ready";
+    private static final String ACTION_SHOW_SESSION = "voice_interaction_service.show_session";
+    private AssistReceiver mReceiver;
+    private boolean mReady;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mReceiver = new AssistReceiver();
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(ACTION_CHECK_IS_READY);
+        intentFilter.addAction(ACTION_SHOW_SESSION);
+        registerReceiver(mReceiver, intentFilter);
+    }
+
+    @Override
+    public void onReady() {
+        super.onReady();
+        Log.d(TAG, "onReady() called");
+        mReady = true;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        Log.d(TAG, "onDestroy() called");
+        unregisterReceiver(mReceiver);
+        mReceiver = null;
+    }
+
+    private class AssistReceiver extends BroadcastReceiver {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.d(TAG, "AssistReceiver: " + intent + " mReady: " + mReady);
+            if (ACTION_CHECK_IS_READY.equals(intent.getAction())) {
+                setResultCode(mReady ? Activity.RESULT_OK : Activity.RESULT_CANCELED);
+            } else if (ACTION_SHOW_SESSION.equals(intent.getAction())) {
+                showSession(
+                        new Bundle(),
+                        SHOW_WITH_ASSIST | SHOW_WITH_SCREENSHOT);
+            }
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionSessionService.java b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionSessionService.java
new file mode 100644
index 0000000..5eae4f7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionSessionService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.devicepolicy.assistapp;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.service.voice.VoiceInteractionSession;
+import android.service.voice.VoiceInteractionSessionService;
+import android.util.Log;
+
+public class MyInteractionSessionService extends VoiceInteractionSessionService {
+    private static final String TAG = "DevicePolicyAssistTest";
+    private static final String ACTION_HANDLE_SCREENSHOT =
+            "voice_interaction_session_service.handle_screenshot";
+    private static final String KEY_HAS_SCREENSHOT = "has_screenshot";
+
+    @Override
+    public VoiceInteractionSession onNewSession(Bundle args) {
+        return new MainInteractionSession(this);
+    }
+
+    public static class MainInteractionSession extends VoiceInteractionSession {
+
+        public MainInteractionSession(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onHandleScreenshot(Bitmap screenshot) {
+            Log.d(TAG, "onHandleScreenshot() called with: screenshot = [" + screenshot + "]");
+            Intent intent = new Intent(ACTION_HANDLE_SCREENSHOT);
+            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+            intent.putExtra(KEY_HAS_SCREENSHOT, screenshot != null);
+            getContext().sendBroadcast(intent);
+            finish();
+        }
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/SettingsActivity.java
similarity index 61%
copy from hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java
copy to hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/SettingsActivity.java
index e7a9e73..1f6d34f 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java
+++ b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/SettingsActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -13,19 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.cts.devicepolicy.assistapp;
 
-package com.android.cts.comp;
+import android.app.Activity;
 
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-/**
- * Dummy service that is exported.
- */
-public class ExportedCrossUserService extends Service {
-    @Override
-    public IBinder onBind(Intent intent) {
-        return null;
-    }
+public class SettingsActivity extends Activity {
 }
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/AndroidManifest.xml
index 89ac4ae..820f1be 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/AndroidManifest.xml
@@ -37,11 +37,12 @@
         </receiver>
         <activity android:name="com.android.compatibility.common.util.devicepolicy.provisioning.StartProvisioningActivity"/>
 
-        <service android:name=".CrossUserService"
-                android:exported="false">
+        <service android:name=".ProtectedCrossUserService"
+                android:exported="true"
+                android:permission="android.permission.BIND_DEVICE_ADMIN">
         </service>
 
-        <service android:name=".ExportedCrossUserService"
+        <service android:name=".UnprotectedCrossUserService"
                 android:exported="true">
         </service>
     </application>
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceFailsTest.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceFailsTest.java
index 476b99c..319d7ec 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceFailsTest.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceFailsTest.java
@@ -66,7 +66,7 @@
     private void checkCannotBind(String targetPackageName, UserHandle otherProfile) {
         try {
             final Intent serviceIntent = new Intent();
-            serviceIntent.setClassName(targetPackageName, CrossUserService.class.getName());
+            serviceIntent.setClassName(targetPackageName, ProtectedCrossUserService.class.getName());
             bind(serviceIntent, EMPTY_SERVICE_CONNECTION, otherProfile);
             fail("SecurityException should be thrown");
         } catch (SecurityException ex) {
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceGoodSetupTest.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceGoodSetupTest.java
index ad65367..e7386cd 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceGoodSetupTest.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceGoodSetupTest.java
@@ -33,7 +33,6 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
 import android.util.Log;
@@ -107,16 +106,17 @@
     }
 
     /**
-     * Make sure we cannot bind exported service.
+     * Make sure we cannot bind unprotected service.
      */
-    public void testCannotBind_exportedCrossUserService() throws Exception {
-        final Intent serviceIntent = new Intent(mContext, ExportedCrossUserService.class);
+    public void testCannotBind_unprotectedCrossUserService() throws Exception {
+        final Intent serviceIntent = new Intent(mContext, UnprotectedCrossUserService.class);
         for (UserHandle targetUser : mTargetUsers) {
             try {
                 bind(serviceIntent, EMPTY_SERVICE_CONNECTION, targetUser);
                 fail("SecurityException should be thrown for target user " + targetUser);
             } catch (SecurityException ex) {
-                MoreAsserts.assertContainsRegex("must be unexported", ex.getMessage());
+                MoreAsserts.assertContainsRegex(
+                        "must be protected by BIND_DEVICE_ADMIN", ex.getMessage());
             }
         }
     }
@@ -126,7 +126,7 @@
      */
     public void testCheckCannotBind_nonManagingPackage() throws Exception {
         final Intent serviceIntent = new Intent();
-        serviceIntent.setClassName(NON_MANAGING_PACKAGE, CrossUserService.class.getName());
+        serviceIntent.setClassName(NON_MANAGING_PACKAGE, ProtectedCrossUserService.class.getName());
         for (UserHandle targetUser : mTargetUsers) {
             try {
                 bind(serviceIntent, EMPTY_SERVICE_CONNECTION, targetUser);
@@ -142,7 +142,7 @@
      */
     public void testCannotBind_sameUser() throws Exception {
         try {
-            final Intent serviceIntent = new Intent(mContext, CrossUserService.class);
+            final Intent serviceIntent = new Intent(mContext, ProtectedCrossUserService.class);
             bind(serviceIntent, EMPTY_SERVICE_CONNECTION, Process.myUserHandle());
             fail("IllegalArgumentException should be thrown");
         } catch (IllegalArgumentException ex) {
@@ -199,7 +199,7 @@
                 Log.d(TAG, "onServiceDisconnected is called");
             }
         };
-        final Intent serviceIntent = new Intent(mContext, CrossUserService.class);
+        final Intent serviceIntent = new Intent(mContext, ProtectedCrossUserService.class);
         assertTrue(bind(serviceIntent, serviceConnection, targetUserHandle));
         IInterface service = queue.poll(5, TimeUnit.SECONDS);
         assertNotNull("binding to the target service timed out", service);
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/CrossUserService.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ProtectedCrossUserService.java
similarity index 95%
rename from hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/CrossUserService.java
rename to hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ProtectedCrossUserService.java
index 3b95b94..76e926a 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/CrossUserService.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ProtectedCrossUserService.java
@@ -25,7 +25,7 @@
 /**
  * Handle the cross user call from the device admin in other side.
  */
-public class CrossUserService extends Service {
+public class ProtectedCrossUserService extends Service {
 
     private final ICrossUserService.Stub mBinder = new ICrossUserService.Stub() {
         public String echo(String msg) {
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/UnprotectedCrossUserService.java
similarity index 93%
rename from hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java
rename to hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/UnprotectedCrossUserService.java
index e7a9e73..8540737 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/UnprotectedCrossUserService.java
@@ -23,7 +23,7 @@
 /**
  * Dummy service that is exported.
  */
-public class ExportedCrossUserService extends Service {
+public class UnprotectedCrossUserService extends Service {
     @Override
     public IBinder onBind(Intent intent) {
         return null;
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/AffiliationTest.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/AffiliationTest.java
index 7a1fa40..442e544 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/AffiliationTest.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/AffiliationTest.java
@@ -21,9 +21,11 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.test.AndroidTestCase;
+
 import com.android.cts.comp.AdminReceiver;
-import java.util.Arrays;
-import java.util.List;
+
+import java.util.Collections;
+import java.util.Set;
 
 public class AffiliationTest extends AndroidTestCase {
 
@@ -39,7 +41,7 @@
         ComponentName admin = AdminReceiver.getComponentName(getContext());
         DevicePolicyManager dpm = (DevicePolicyManager)
                 mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
-        List<String> ids = Arrays.asList(id);
+        Set<String> ids = Collections.singleton(id);
         dpm.setAffiliationIds(admin, ids);
         assertEquals(ids, dpm.getAffiliationIds(admin));
     }
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java
new file mode 100644
index 0000000..db54ac3
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java
@@ -0,0 +1,98 @@
+package com.android.cts.deviceandprofileowner;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import com.android.compatibility.common.util.BlockingBroadcastReceiver;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Testing
+ * {@link android.app.admin.DevicePolicyManager#setScreenCaptureDisabled(ComponentName, boolean)}
+ * is enforced in {@link android.service.voice.VoiceInteractionSession#onHandleScreenshot(Bitmap)}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class AssistScreenCaptureDisabledTest {
+    private static final String TAG = "DevicePolicyAssistTest";
+    
+    private static final String ACTION_CHECK_IS_READY = "voice_interaction_service.is_ready";
+    private static final String ACTION_SHOW_SESSION = "voice_interaction_service.show_session";
+    private static final String ACTION_HANDLE_SCREENSHOT =
+            "voice_interaction_session_service.handle_screenshot";
+    private static final String KEY_HAS_SCREENSHOT = "has_screenshot";
+    private static final String ASSIST_PACKAGE = "com.android.cts.devicepolicy.assistapp";
+
+    private static final int MAX_ATTEMPTS_COUNT = 5;
+    private static final int WAIT_IN_SECOND = 5;
+    private Context mContext;
+
+    @Before
+    public void setup() {
+        mContext = InstrumentationRegistry.getContext();
+    }
+
+    @Test
+    public void testScreenCaptureImpossible_assist() throws Exception {
+        assertScreenCapturePossible(false);
+    }
+
+    @Test
+    public void testScreenCapturePossible_assist() throws Exception {
+        assertScreenCapturePossible(true);
+    }
+
+    private void assertScreenCapturePossible(boolean possible) throws InterruptedException {
+        // Wait until voice interaction service is ready by sending broadcast to ask for status.
+        Intent checkIsReadyIntent = new Intent(ACTION_CHECK_IS_READY);
+        checkIsReadyIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        checkIsReadyIntent.setPackage(ASSIST_PACKAGE);
+        boolean isAssistReady = false;
+        for (int i = 0; i < MAX_ATTEMPTS_COUNT && !isAssistReady; i++) {
+            Log.d(TAG, "assertScreenCapturePossible: wait for assist service ready, attempt " + i);
+            final LinkedBlockingQueue<Boolean> q = new LinkedBlockingQueue<>();
+            mContext.sendOrderedBroadcast(checkIsReadyIntent, null, new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    q.offer(getResultCode() == Activity.RESULT_OK);
+                }
+            }, null, Activity.RESULT_CANCELED, null, null);
+            Boolean result = q.poll(WAIT_IN_SECOND, TimeUnit.SECONDS);
+            isAssistReady = result != null && result;
+        }
+        Assert.assertTrue(isAssistReady);
+
+        // Send broadcast to voice interaction service and ask for screnshot.
+        BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(
+                mContext, ACTION_HANDLE_SCREENSHOT);
+        try {
+            receiver.register();
+            Intent showSessionIntent = new Intent(ACTION_SHOW_SESSION);
+            showSessionIntent.setPackage(ASSIST_PACKAGE);
+            mContext.sendBroadcast(showSessionIntent);
+            Intent screenShotIntent = receiver.awaitForBroadcast();
+            Assert.assertNotNull(screenShotIntent);
+            Assert.assertTrue(screenShotIntent.hasExtra(KEY_HAS_SCREENSHOT));
+            assertEquals(possible, screenShotIntent.getBooleanExtra(KEY_HAS_SCREENSHOT, false));
+        } finally {
+            receiver.unregisterQuietly();
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
index b7f9066..c5b3e96 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
@@ -16,7 +16,7 @@
 package com.android.cts.deviceandprofileowner;
 
 import android.app.admin.DevicePolicyManager;
-import android.util.Log;
+import android.support.v4.content.LocalBroadcastManager;
 
 /**
  * Tests for {@link DevicePolicyManager#setScreenCaptureDisabled} and
@@ -26,6 +26,12 @@
 
     private static final String TAG = "ScreenCaptureDisabledTest";
 
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
     public void testSetScreenCaptureDisabled_false() throws Exception {
         mDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, false);
         assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AffiliationTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AffiliationTest.java
index 4ccb3c6..a9b43c6 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AffiliationTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AffiliationTest.java
@@ -16,26 +16,24 @@
 
 package com.android.cts.deviceowner;
 
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
-
-import static org.junit.Assert.assertArrayEquals;
-
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.util.Collections;
-import java.util.List;
+import java.util.Set;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertArrayEquals;
 
 @RunWith(AndroidJUnit4.class)
 public class AffiliationTest {
@@ -52,13 +50,33 @@
     }
 
     @Test
+    public void testSetAffiliationId_null() {
+        try {
+            mDevicePolicyManager.setAffiliationIds(mAdminComponent, null);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException ex) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void testSetAffiliationId_containsEmptyString() {
+        try {
+            mDevicePolicyManager.setAffiliationIds(mAdminComponent, Collections.singleton(null));
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException ex) {
+            // Expected
+        }
+    }
+
+    @Test
     public void testSetAffiliationId1() {
-        setAffiliationIds(Collections.singletonList("id.number.1"));
+        setAffiliationIds(Collections.singleton("id.number.1"));
     }
 
     @Test
     public void testSetAffiliationId2() {
-        setAffiliationIds(Collections.singletonList("id.number.2"));
+        setAffiliationIds(Collections.singleton("id.number.2"));
     }
 
     @Test
@@ -75,11 +93,11 @@
         assertTrue(mDevicePolicyManager.isLockTaskPermitted("package1"));
         assertFalse(mDevicePolicyManager.isLockTaskPermitted("package3"));
 
-        final List<String> previousAffiliationIds =
+        final Set<String> previousAffiliationIds =
                 mDevicePolicyManager.getAffiliationIds(mAdminComponent);
         try {
             // Clearing affiliation ids for this user. Lock task methods unavailable.
-            setAffiliationIds(Collections.<String>emptyList());
+            setAffiliationIds(Collections.emptySet());
             checkLockTaskMethodsThrow();
             assertFalse(mDevicePolicyManager.isLockTaskPermitted("package1"));
 
@@ -92,7 +110,7 @@
         }
     }
 
-    private void setAffiliationIds(List<String> ids) {
+    private void setAffiliationIds(Set<String> ids) {
         mDevicePolicyManager.setAffiliationIds(mAdminComponent, ids);
         assertEquals(ids, mDevicePolicyManager.getAffiliationIds(mAdminComponent));
     }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index d3cde44..d20d5e4 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -138,7 +138,7 @@
         removeOwners();
         removeTestUsers();
         // Unlock keyguard before test
-        executeShellCommand("wm dismiss-keyguard");
+        wakeupAndDismissKeyguard();
     }
 
     @Override
@@ -764,4 +764,9 @@
             }
         }
     }
+
+    protected void wakeupAndDismissKeyguard() throws Exception {
+        executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        executeShellCommand("wm dismiss-keyguard");
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index da902d3..865d785 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -96,9 +96,15 @@
     private static final String AUTOFILL_APP_PKG = "com.android.cts.devicepolicy.autofillapp";
     private static final String AUTOFILL_APP_APK = "CtsDevicePolicyAutofillApp.apk";
 
+    protected static final String ASSIST_APP_PKG = "com.android.cts.devicepolicy.assistapp";
+    protected static final String ASSIST_APP_APK = "CtsDevicePolicyAssistApp.apk";
+
     private static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES
             = "enabled_notification_policy_access_packages";
 
+    protected static final String ASSIST_INTERACTION_SERVICE =
+            ASSIST_APP_PKG + "/.MyInteractionService";
+
     // ID of the user all tests are run as. For device owner this will be the primary user, for
     // profile owner it is the user id of the created profile.
     protected int mUserId;
@@ -364,6 +370,21 @@
         }
     }
 
+    public void testScreenCaptureDisabled_assist() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        try {
+            // Install and enable assistant, notice that profile can't have assistant.
+            installAppAsUser(ASSIST_APP_APK, mPrimaryUserId);
+            setVoiceInteractionService(ASSIST_INTERACTION_SERVICE);
+            setScreenCaptureDisabled_assist(mUserId, true /* disabled */);
+        } finally {
+            setScreenCaptureDisabled_assist(mUserId, false /* disabled */);
+            clearVoiceInteractionService();
+        }
+    }
+
     public void testSupportMessage() throws Exception {
         if (!mHasFeature) {
             return;
@@ -773,35 +794,44 @@
      */
     protected void startSimpleActivityAsUser(int userId) throws Exception {
         installAppAsUser(TEST_APP_APK, userId);
+        wakeupAndDismissKeyguard();
         String command = "am start -W --user " + userId + " " + TEST_APP_PKG + "/"
                 + TEST_APP_PKG + ".SimpleActivity";
         getDevice().executeShellCommand(command);
     }
 
-    // TODO: Remove this after investigation in b/28995242 is done
-    // So we can check which one is the top window / activity.
-    private void runDumpsysWindow() throws Exception {
-        String command = "dumpsys window displays";
-        CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
-        command = "dumpsys activity a";
-        CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
-    }
-
     protected void setScreenCaptureDisabled(int userId, boolean disabled) throws Exception {
         String testMethodName = disabled
                 ? "testSetScreenCaptureDisabled_true"
                 : "testSetScreenCaptureDisabled_false";
         executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
         startSimpleActivityAsUser(userId);
-        // [b/28995242], dump windows to make sure the top window is
-        // ScreenCaptureDisabledActivity.
-        runDumpsysWindow();
         testMethodName = disabled
                 ? "testScreenCaptureImpossible"
                 : "testScreenCapturePossible";
         executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
     }
 
+    protected void setScreenCaptureDisabled_assist(int userId, boolean disabled) throws Exception {
+        // Set the policy.
+        String testMethodName = disabled
+                ? "testSetScreenCaptureDisabled_true"
+                : "testSetScreenCaptureDisabled_false";
+        executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
+        // Make sure the foreground activity is from the target user.
+        startSimpleActivityAsUser(userId);
+        // Check whether the VoiceInteractionService can retrieve the screenshot.
+        testMethodName = disabled
+                ? "testScreenCaptureImpossible_assist"
+                : "testScreenCapturePossible_assist";
+        installAppAsUser(DEVICE_ADMIN_APK, mPrimaryUserId);
+        runDeviceTestsAsUser(
+                DEVICE_ADMIN_PKG,
+                ".AssistScreenCaptureDisabledTest",
+                testMethodName,
+                mPrimaryUserId);
+    }
+
     /**
      * Allows packageName to manage notification policy configuration, which
      * includes toggling zen mode.
@@ -843,4 +873,16 @@
         }
         return new ArrayList<String>(Arrays.asList(settingValue.split(":|\n")));
     }
+
+    protected void setVoiceInteractionService(String componentName)
+            throws DeviceNotAvailableException {
+        getDevice().setSetting(
+                mPrimaryUserId, "secure", "voice_interaction_service", componentName);
+        getDevice().setSetting(mPrimaryUserId, "secure", "assist_structure_enabled", "1");
+        getDevice().setSetting(mPrimaryUserId, "secure", "assist_screenshot_enabled", "1");
+    }
+
+    protected void clearVoiceInteractionService() throws DeviceNotAvailableException {
+        getDevice().executeShellCommand("settings delete secure voice_interaction_service");
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 8fce788..ac846a3 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -346,6 +346,14 @@
         executeDeviceTestMethod(".NetworkLoggingTest", "testNetworkLoggingAndRetrieval");
     }
 
+    public void testSetAffiliationId_IllegalArgumentException() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        executeDeviceTestMethod(".AffiliationTest", "testSetAffiliationId_null");
+        executeDeviceTestMethod(".AffiliationTest", "testSetAffiliationId_containsEmptyString");
+    }
+
     public void testLockTask_deviceOwnerUser() throws Exception {
         if (!mHasFeature) {
             return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
index a2d8057..0022804 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
@@ -78,6 +78,36 @@
         executeDeviceTestMethod(".ScreenCaptureDisabledTest", "testScreenCapturePossible");
     }
 
+    public void testScreenCaptureDisabled_assist_allowedPrimaryUser() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        // disable screen capture in profile
+        executeDeviceTestMethod(".ScreenCaptureDisabledTest", "testSetScreenCaptureDisabled_true");
+        try {
+            // Install and enable assistant in personal side.
+            installAppAsUser(ASSIST_APP_APK, mParentUserId);
+            setVoiceInteractionService(ASSIST_INTERACTION_SERVICE);
+
+            // Start an activity in parent user.
+            installAppAsUser(DEVICE_ADMIN_APK, mParentUserId);
+            startSimpleActivityAsUser(mParentUserId);
+
+            // Verify assistant app can't take a screenshot.
+            runDeviceTestsAsUser(
+                    DEVICE_ADMIN_PKG,
+                    ".AssistScreenCaptureDisabledTest",
+                    "testScreenCapturePossible_assist",
+                    mPrimaryUserId);
+        } finally {
+            // enable screen capture in profile
+            executeDeviceTestMethod(
+                    ".ScreenCaptureDisabledTest",
+                    "testSetScreenCaptureDisabled_false");
+            clearVoiceInteractionService();
+        }
+    }
+
     @Override
     public void testDisallowSetWallpaper_allowed() throws Exception {
         // Managed profile doesn't have wallpaper.
diff --git a/hostsidetests/inputmethodservice/hostside/AndroidTest.xml b/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
index c943aee..470e666 100644
--- a/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
+++ b/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
@@ -16,6 +16,10 @@
 -->
 
 <configuration description="Config for CTS Input Method Service host test cases">
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+        <option name="run-command" value="wm dismiss-keyguard" />
+    </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsInputMethodServiceEventProvider.apk" />
diff --git a/hostsidetests/media/Android.mk b/hostsidetests/media/Android.mk
new file mode 100644
index 0000000..36e9066
--- /dev/null
+++ b/hostsidetests/media/Android.mk
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, common) \
+    $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := tests
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_MODULE := CtsMediaHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
+
diff --git a/hostsidetests/media/AndroidTest.xml b/hostsidetests/media/AndroidTest.xml
new file mode 100644
index 0000000..0a6410c
--- /dev/null
+++ b/hostsidetests/media/AndroidTest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS media host test cases">
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsMediaHostTestCases.jar" />
+        <option name="runtime-hint" value="30m" />
+    </test>
+</configuration>
+
diff --git a/hostsidetests/media/app/MediaSessionTest/Android.mk b/hostsidetests/media/app/MediaSessionTest/Android.mk
new file mode 100644
index 0000000..eb9059d
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTest/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsMediaSessionHostTestApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src) \
+    $(call all-java-files-under, ../../common)
+
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-util
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml b/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml
new file mode 100644
index 0000000..60e82dd
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.media.session.cts">
+
+    <uses-sdk android:minSdkVersion="26"/>
+
+    <application />
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.media.session.cts"
+        android:label="MediaSession multi-user case CTS Tests" />
+
+</manifest>
diff --git a/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java b/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java
new file mode 100644
index 0000000..2186038
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 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.media.session.cts;
+
+import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_PKG;
+
+import android.content.Context;
+import android.content.ComponentName;
+import android.test.AndroidTestCase;
+import android.media.session.MediaSessionManager;
+import android.media.session.MediaController;
+
+import java.util.List;
+
+/**
+ * Tests {@link MediaSessionManager} with the multi-user environment.
+ * <p>Don't run tests here directly. They aren't stand-alone tests and each test will be run
+ * indirectly by the host-side test CtsMediaHostTestCases after the proper device setup.
+ */
+public class MediaSessionManagerTest extends AndroidTestCase {
+    private MediaSessionManager mMediaSessionManager;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mMediaSessionManager = (MediaSessionManager) getContext().getSystemService(
+                Context.MEDIA_SESSION_SERVICE);
+    }
+
+    /**
+     * Tests if the MediaSessionTestHelper doesn't have an active media session.
+     */
+    public void testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper() throws Exception {
+        List<MediaController> controllers = mMediaSessionManager.getActiveSessions(
+                createFakeNotificationListener());
+        for (MediaController controller : controllers) {
+            if (controller.getPackageName().equals(MEDIA_SESSION_TEST_HELPER_PKG)) {
+                fail("Media session for the media session app shouldn't be available");
+                return;
+            }
+        }
+    }
+
+    /**
+     * Tests if the MediaSessionTestHelper has an active media session.
+     */
+    public void testGetActiveSessions_hasMediaSessionFromMediaSessionTestHelper() throws Exception {
+        List<MediaController> controllers = mMediaSessionManager.getActiveSessions(
+                createFakeNotificationListener());
+        for (MediaController controller : controllers) {
+            if (controller.getPackageName().equals(MEDIA_SESSION_TEST_HELPER_PKG)) {
+                // Test success
+                return;
+            }
+        }
+        fail("Media session for the media session app is expected");
+    }
+
+    /**
+     * Tests if there's no media session.
+     */
+    public void testGetActiveSessions_noMediaSession() throws Exception {
+        List<MediaController> controllers = mMediaSessionManager.getActiveSessions(
+                createFakeNotificationListener());
+        assertTrue(controllers.isEmpty());
+    }
+
+    /**
+     * Returns the ComponentName of the notification listener for this test.
+     * <p>Notification listener will be enabled by the host-side test.
+     */
+    private ComponentName createFakeNotificationListener() {
+        return new ComponentName(getContext(), MediaSessionManagerTest.class);
+    }
+}
+
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/Android.mk b/hostsidetests/media/app/MediaSessionTestHelper/Android.mk
new file mode 100644
index 0000000..3944cb6
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTestHelper/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src) \
+    $(call all-java-files-under, ../../common)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsMediaSessionTestHelper
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/AndroidManifest.xml b/hostsidetests/media/app/MediaSessionTestHelper/AndroidManifest.xml
new file mode 100644
index 0000000..1e29eca
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTestHelper/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.media.app.media_session_test_helper"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <application android:label="@string/label">
+        <service android:name=".MediaSessionTestHelperService">
+            <intent-filter>
+                <action android:name="android.media.app.media_session_test_helper.ACTION_CONTROL" />
+            </intent-filter>
+        </service>
+    </application>
+</manifest>
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/res/values/strings.xml b/hostsidetests/media/app/MediaSessionTestHelper/res/values/strings.xml
new file mode 100644
index 0000000..fb75fdb
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTestHelper/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="label">MediaSessionTestHelper for media host-side CTS tests</string>
+</resources>
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/src/android/media/app/media_session_test_helper/MediaSessionTestHelperService.java b/hostsidetests/media/app/MediaSessionTestHelper/src/android/media/app/media_session_test_helper/MediaSessionTestHelperService.java
new file mode 100644
index 0000000..a161ba5
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTestHelper/src/android/media/app/media_session_test_helper/MediaSessionTestHelperService.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 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.media.app.media_session_test_helper;
+
+import android.app.Notification;
+import android.app.Service;
+import android.content.Intent;
+import android.media.session.MediaSession;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import android.media.cts.MediaSessionTestHelperConstants;
+
+/**
+ * Service of the media session's host-side CTS helper.
+ * <p>This is the foreground service to prevent this process from being killed by the OOM killer
+ * while the host-side tests are running.
+ */
+public class MediaSessionTestHelperService extends Service {
+    private static final String TAG = "MediaSessionTestHelperService";
+
+    private static final int NOTIFICATION_ID = 100;
+
+    private MediaSession mMediaSession;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        // Build notification UI to make this a foreground service.
+        Notification notification = new Notification.Builder(this)
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setContentTitle(getString(R.string.label)).build();
+        startForeground(NOTIFICATION_ID, notification);
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        super.onStartCommand(intent, flags, startId);
+        if (!TextUtils.equals(intent.getAction(), MediaSessionTestHelperConstants.ACTION_CONTROL)) {
+            Log.e(TAG, "Invalid action " + intent.getAction() + ". Test may fail");
+            return START_STICKY;
+        }
+        int flag = intent.getIntExtra(MediaSessionTestHelperConstants.EXTRA_CONTROL_COMMAND, 0);
+        if ((flag & MediaSessionTestHelperConstants.FLAG_CREATE_MEDIA_SESSION) != 0) {
+            if (mMediaSession == null) {
+                mMediaSession = new MediaSession(this, TAG);
+            }
+        }
+        if (mMediaSession != null) {
+            if ((flag & MediaSessionTestHelperConstants.FLAG_SET_MEDIA_SESSION_ACTIVE) != 0) {
+                mMediaSession.setActive(true);
+            }
+            if ((flag & MediaSessionTestHelperConstants.FLAG_SET_MEDIA_SESSION_INACTIVE) != 0) {
+                mMediaSession.setActive(false);
+            }
+        }
+        if ((flag & MediaSessionTestHelperConstants.FLAG_RELEASE_MEDIA_SESSION) != 0) {
+            releaseMediaSession();
+        }
+        return START_STICKY;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        // It's not a bind service.
+        return null;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        releaseMediaSession();
+    }
+
+    private void releaseMediaSession() {
+        if (mMediaSession != null) {
+            mMediaSession.release();
+            mMediaSession = null;
+        }
+    }
+}
diff --git a/hostsidetests/media/common/android/media/cts/MediaSessionTestHelperConstants.java b/hostsidetests/media/common/android/media/cts/MediaSessionTestHelperConstants.java
new file mode 100644
index 0000000..8c8dc54
--- /dev/null
+++ b/hostsidetests/media/common/android/media/cts/MediaSessionTestHelperConstants.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 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.media.cts;
+
+/**
+ * Defines constants for controlling the media session test helper app, which can start media
+ * playback and create the media session for test.
+ * <p>Any change in these constants should also be applied to the media session test helper app.
+ * <p>Don't add Android specific imports because this will be used by the both host-side and
+ * device-side.
+ */
+public class MediaSessionTestHelperConstants {
+    /**
+     * Package name of the media session test helper.
+     */
+    public static final String MEDIA_SESSION_TEST_HELPER_PKG =
+            "android.media.app.media_session_test_helper";
+    /**
+     * Package binary file name of the media session test helper`.
+     */
+    public static final String MEDIA_SESSION_TEST_HELPER_APK = "CtsMediaSessionTestHelper.apk";
+
+    /**
+     * Intent action name to control media sesion test helper.
+     */
+    public static final String ACTION_CONTROL =
+            "android.media.app.media_session_test_helper.ACTION_CONTROL";
+    /**
+     * Intent extra key name to control media session test helper.
+     */
+    public static final String EXTRA_CONTROL_COMMAND =
+            "android.media.app.media_session_test_helper.EXTRA_CONTROL_COMMAND";
+
+    /**
+     * Intent extra value for the key {@link #EXTRA_CONTROL_COMMAND} to create the media session
+     * if it doesn't exist.
+     * @see buildControlCommand
+     */
+    public static final int FLAG_CREATE_MEDIA_SESSION = 0x01;
+    /**
+     * Intent extra value for the key {@link #EXTRA_CONTROL_COMMAND} to set the media session active
+     * if it exists.
+     * @see buildControlCommand
+     */
+    public static final int FLAG_SET_MEDIA_SESSION_ACTIVE = 0x02;
+    /**
+     * Intent extra value for the key {@link #EXTRA_CONTROL_COMMAND} to set the media session
+     * inactive if it exists.
+     * @see buildControlCommand
+     */
+    public static final int FLAG_SET_MEDIA_SESSION_INACTIVE = 0x04;
+    /**
+     * Intent extra value for the key {@link #EXTRA_CONTROL_COMMAND} to release the media session
+     * if it was created.
+     * @see buildControlCommand
+     */
+    public static final int FLAG_RELEASE_MEDIA_SESSION = 0x08;
+
+    private MediaSessionTestHelperConstants() {
+        // Prevent from the instantiation.
+    }
+
+    /**
+     * Builds the control command for the media session test helper app.
+     *
+     * @param userId user id to send the command
+     * @param flag bit masked flag among {@link #FLAG_CREATE_MEDIA_SESSION},
+     *            {@link #FLAG_SET_MEDIA_SESSION_ACTIVE}, {@link #FLAG_SET_MEDIA_SESSION_INACTIVE},
+     *            and {@link #FLAG_RELEASE_MEDIA_SESSION}. If multiple flags are specificed,
+     *            operations will be exceuted in order.
+     **/
+    public static String buildControlCommand(int userId, int flag) {
+        return "am start-foreground-service --user " + userId + " -a " + ACTION_CONTROL + " --ei "
+                + EXTRA_CONTROL_COMMAND + " " + flag + " " + MEDIA_SESSION_TEST_HELPER_PKG;
+    }
+}
diff --git a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
new file mode 100644
index 0000000..ef8ba5b
--- /dev/null
+++ b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2017 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.media.cts;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Base class for host-side tests for multi-user aware media APIs.
+ */
+public class BaseMultiUserTest extends DeviceTestCase implements IBuildReceiver {
+    private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+
+    /**
+     * The defined timeout (in milliseconds) is used as a maximum waiting time when expecting the
+     * command output from the device. At any time, if the shell command does not output anything
+     * for a period longer than the defined timeout the Tradefed run terminates.
+     */
+    private static final long DEFAULT_SHELL_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+
+    /**
+     * Instrumentation test runner argument key used for individual test timeout
+     **/
+    protected static final String TEST_TIMEOUT_INST_ARGS_KEY = "timeout_msec";
+
+    /**
+     * Sets timeout (in milliseconds) that will be applied to each test. In the
+     * event of a test timeout it will log the results and proceed with executing the next test.
+     */
+    private static final long DEFAULT_TEST_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+    private static final String SETTINGS_PACKAGE_VERIFIER_NAMESPACE = "global";
+    private static final String SETTINGS_PACKAGE_VERIFIER_NAME = "package_verifier_enable";
+
+    /**
+     * User ID for all users.
+     * The value is from the UserHandle class.
+     */
+    protected static final int USER_ALL = -1;
+
+    /**
+     * User ID for the system user.
+     * The value is from the UserHandle class.
+     */
+    protected static final int USER_SYSTEM = 0;
+
+    private IBuildInfo mCtsBuild;
+    private String mPackageVerifier;
+
+    private Set<String> mExistingPackages;
+    private List<Integer> mExistingUsers;
+
+    @Override
+    protected void setUp() throws Exception {
+        // Ensure that build has been set before test is run.
+        assertNotNull(mCtsBuild);
+        mExistingPackages = getDevice().getInstalledPackageNames();
+
+        // Disable the package verifier to avoid the dialog when installing an app
+        mPackageVerifier = getSettings(SETTINGS_PACKAGE_VERIFIER_NAMESPACE,
+                SETTINGS_PACKAGE_VERIFIER_NAME, USER_ALL);
+        putSettings(SETTINGS_PACKAGE_VERIFIER_NAMESPACE,
+                SETTINGS_PACKAGE_VERIFIER_NAME, "0", USER_ALL);
+
+        mExistingUsers = new ArrayList();
+        int primaryUserId = getDevice().getPrimaryUserId();
+        mExistingUsers.add(primaryUserId);
+        mExistingUsers.add(USER_SYSTEM);
+
+        executeShellCommand("am switch-user " + primaryUserId);
+        executeShellCommand("wm dismiss-keyguard");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Reset the package verifier setting to its original value.
+        putSettings(SETTINGS_PACKAGE_VERIFIER_NAMESPACE, SETTINGS_PACKAGE_VERIFIER_NAME,
+                mPackageVerifier, USER_ALL);
+
+        // Remove users created during the test.
+        for (int userId : getDevice().listUsers()) {
+            if (!mExistingUsers.contains(userId)) {
+                removeUser(userId);
+            }
+        }
+        // Remove packages installed during the test.
+        for (String packageName : getDevice().getUninstallablePackageNames()) {
+            if (mExistingPackages.contains(packageName)) {
+                continue;
+            }
+            CLog.d("Removing leftover package: " + packageName);
+            getDevice().uninstallPackage(packageName);
+        }
+        super.tearDown();
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = buildInfo;
+    }
+
+    /**
+     * Installs the app as if the user of the ID {@param userId} has installed the app.
+     *
+     * @param appFileName file name of the app.
+     * @param userId user ID to install the app against.
+     */
+    protected void installAppAsUser(String appFileName, int userId)
+            throws FileNotFoundException, DeviceNotAvailableException {
+        CLog.d("Installing app " + appFileName + " for user " + userId);
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+        String result = getDevice().installPackageForUser(
+                buildHelper.getTestFile(appFileName), true, true, userId, "-t");
+        assertNull("Failed to install " + appFileName + " for user " + userId + ": " + result,
+                result);
+    }
+
+    /**
+     * Excutes shell command and returns the result.
+     *
+     * @param command command to run.
+     * @return result from the command. If the result was {@code null}, empty string ("") will be
+     *    returned instead. Otherwise, trimmed result will be returned.
+     */
+    protected @Nonnull String executeShellCommand(final String command) throws Exception {
+        CLog.d("Starting command " + command);
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.d("Output for command " + command + ": " + commandOutput);
+        return commandOutput != null ? commandOutput.trim() : "";
+    }
+
+    private int createAndStartUser(String extraParam) throws Exception {
+        String command = "pm create-user" + extraParam + " TestUser_" + System.currentTimeMillis();
+        String commandOutput = executeShellCommand(command);
+
+        String[] tokens = commandOutput.split("\\s+");
+        assertTrue(tokens.length > 0);
+        assertEquals("Success:", tokens[0]);
+        int userId = Integer.parseInt(tokens[tokens.length-1]);
+
+        // Start user for MediaSessionService to notice the created user.
+        getDevice().startUser(userId);
+        return userId;
+    }
+
+    /**
+     * Creates and starts a new user.
+     */
+    protected int createAndStartUser() throws Exception {
+        return createAndStartUser("");
+    }
+
+    /**
+     * Creates and starts a restricted profile for the {@param parentUserId}.
+     *
+     * @param parentUserId parent user id.
+     */
+    protected int createAndStartRestrictedProfile(int parentUserId) throws Exception {
+        return createAndStartUser(" --profileOf " + parentUserId + " --restricted");
+    }
+
+    /**
+     * Creates and starts a managed profile for the {@param parentUserId}.
+     *
+     * @param parentUserId parent user id.
+     */
+    protected int createAndStartManagedProfile(int parentUserId) throws Exception {
+        return createAndStartUser(" --profileOf " + parentUserId + " --managed");
+    }
+
+    /**
+     * Removes the user that is created during the test.
+     * <p>It will be no-op if the user cannot be removed or doesn't exist.
+     *
+     * @param userId user ID to remove.
+     */
+    protected void removeUser(int userId) throws Exception  {
+        if (getDevice().listUsers().contains(userId) && userId != USER_SYSTEM
+                && !mExistingUsers.contains(userId)) {
+            // Don't log output, as tests sometimes set no debug user restriction, which
+            // causes this to fail, we should still continue and remove the user.
+            String stopUserCommand = "am stop-user -w -f " + userId;
+            CLog.d("Stopping and removing user " + userId);
+            getDevice().executeShellCommand(stopUserCommand);
+            assertTrue("Couldn't remove user", getDevice().removeUser(userId));
+        }
+    }
+
+    /**
+     * Runs tests on the device as if it's {@param userId}.
+     *
+     * @param pkgName test package file name that contains the {@link AndroidTestCase}
+     * @param testClassName Class name to test within the test package. Can be {@code null} if you
+     *    want to run all test classes in the package.
+     * @param testMethodName Method name to test within the test class. Can be {@code null} if you
+     *    want to run all test methods in the class. Will be ignored if {@param testClassName} is
+     *    {@code null}.
+     * @param userId user ID to run the tests as.
+     */
+    protected void runDeviceTestsAsUser(
+            String pkgName, @Nullable String testClassName,
+            @Nullable String testMethodName, int userId) throws DeviceNotAvailableException {
+        if (testClassName != null && testClassName.startsWith(".")) {
+            testClassName = pkgName + testClassName;
+        }
+
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
+                pkgName, RUNNER, getDevice().getIDevice());
+        testRunner.setMaxTimeToOutputResponse(DEFAULT_SHELL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        testRunner.addInstrumentationArg(
+                TEST_TIMEOUT_INST_ARGS_KEY, Long.toString(DEFAULT_TEST_TIMEOUT_MILLIS));
+        if (testClassName != null && testMethodName != null) {
+            testRunner.setMethodName(testClassName, testMethodName);
+        } else if (testClassName != null) {
+            testRunner.setClassName(testClassName);
+        }
+
+        CollectingTestListener listener = new CollectingTestListener();
+        assertTrue(getDevice().runInstrumentationTestsAsUser(testRunner, userId, listener));
+
+        final TestRunResult result = listener.getCurrentRunResults();
+        if (result.isRunFailure()) {
+            throw new AssertionError("Failed to successfully run device tests for "
+                    + result.getName() + ": " + result.getRunFailureMessage());
+        }
+        if (result.getNumTests() == 0) {
+            throw new AssertionError("No tests were run on the device");
+        }
+
+        if (result.hasFailedTests()) {
+            // Build a meaningful error message
+            StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
+            for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+                    result.getTestResults().entrySet()) {
+                if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+                    errorBuilder.append(resultEntry.getKey().toString());
+                    errorBuilder.append(":\n");
+                    errorBuilder.append(resultEntry.getValue().getStackTrace());
+                }
+            }
+            throw new AssertionError(errorBuilder.toString());
+        }
+    }
+
+    /**
+     * Checks whether it is possible to create the desired number of users.
+     */
+    protected boolean canCreateAdditionalUsers(int numberOfUsers)
+            throws DeviceNotAvailableException {
+        return getDevice().listUsers().size() + numberOfUsers <=
+                getDevice().getMaxNumberOfUsersSupported();
+    }
+
+    /**
+     * Gets the system setting as a string from the system settings provider for the user.
+     *
+     * @param namespace namespace of the setting.
+     * @param name name of the setting.
+     * @param userId user ID to query the setting. Can be {@link #USER_ALL}.
+     * @return value of the system setting provider with the given namespace and name.
+     *    {@code null}, empty string, or "null" will be returned to the empty string ("") instead.
+     */
+    protected @Nonnull String getSettings(@Nonnull String namespace, @Nonnull String name,
+            int userId) throws Exception {
+        String userFlag = (userId == USER_ALL) ? "" : " --user " + userId;
+        String commandOutput = executeShellCommand(
+                "settings" + userFlag + " get " + namespace + " " + name);
+        if (commandOutput == null || commandOutput.isEmpty() || commandOutput.equals("null")) {
+            commandOutput = "";
+        }
+        return commandOutput;
+    }
+
+    /**
+     * Puts the string to the system settings provider for the user.
+     * <p>This deletes the setting for an empty {@param value} as 'settings put' doesn't allow
+     * putting empty value.
+     *
+     * @param namespace namespace of the setting.
+     * @param name name of the setting.
+     * @param value value of the system setting provider with the given namespace and name.
+     * @param userId user ID to set the setting. Can be {@link #USER_ALL}.
+     */
+    protected void putSettings(@Nonnull String namespace, @Nonnull String name,
+            @Nullable String value, int userId) throws Exception {
+        if (value == null || value.isEmpty()) {
+            // Delete the setting if the value is null or empty as 'settings put' doesn't accept
+            // them.
+            // Ignore userId here because 'settings delete' doesn't support it.
+            executeShellCommand("settings delete " + namespace + " " + name);
+        } else {
+            String userFlag = (userId == USER_ALL) ? "" : " --user " + userId;
+            executeShellCommand("settings" + userFlag + " put " + namespace + " " + name
+                    + " " + value);
+        }
+    }
+}
diff --git a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
new file mode 100644
index 0000000..d665f5f
--- /dev/null
+++ b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2017 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.media.session.cts;
+
+import static android.media.cts.MediaSessionTestHelperConstants.FLAG_CREATE_MEDIA_SESSION;
+import static android.media.cts.MediaSessionTestHelperConstants.FLAG_SET_MEDIA_SESSION_ACTIVE;
+import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_APK;
+import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_PKG;
+
+import android.media.cts.BaseMultiUserTest;
+import android.media.cts.MediaSessionTestHelperConstants;
+
+import android.platform.test.annotations.RequiresDevice;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringJoiner;
+import java.util.StringTokenizer;
+
+/**
+ * Host-side test for the media session manager that installs and runs device-side tests after the
+ * proper device setup.
+ * <p>Corresponding device-side tests are written in the {@link #DEVICE_SIDE_TEST_CLASS}
+ * which is in the {@link #DEVICE_SIDE_TEST_APK}.
+ */
+public class MediaSessionManagerHostTest extends BaseMultiUserTest {
+    /**
+     * Package name of the device-side tests.
+     */
+    private static final String DEVICE_SIDE_TEST_PKG = "android.media.session.cts";
+    /**
+     * Package file name (.apk) for the device-side tests.
+     */
+    private static final String DEVICE_SIDE_TEST_APK = "CtsMediaSessionHostTestApp.apk";
+    /**
+     * Fully qualified class name for the device-side tests.
+     */
+    private static final String DEVICE_SIDE_TEST_CLASS =
+            "android.media.session.cts.MediaSessionManagerTest";
+
+    private static final String SETTINGS_NOTIFICATION_LISTENER_NAMESPACE = "secure";
+    private static final String SETTINGS_NOTIFICATION_LISTENER_NAME =
+            "enabled_notification_listeners";
+
+    // Keep the original notification listener list to clean up.
+    private Map<Integer, String> mNotificationListeners;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mNotificationListeners = new HashMap<>();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        // Cleanup
+        for (int userId : mNotificationListeners.keySet()) {
+            String notificationListener = mNotificationListeners.get(userId);
+            putSettings(SETTINGS_NOTIFICATION_LISTENER_NAMESPACE,
+                    SETTINGS_NOTIFICATION_LISTENER_NAME, notificationListener, userId);
+        }
+        super.tearDown();
+    }
+
+    /**
+     * Tests {@link MediaSessionManager#getActiveSessions} with the multi-users environment.
+     */
+    @RequiresDevice
+    public void testGetActiveSessions() throws Exception {
+        // Ensure that the previously running media session test helper app doesn't exist.
+        getDevice().uninstallPackage(MEDIA_SESSION_TEST_HELPER_PKG);
+
+        int primaryUserId = getDevice().getPrimaryUserId();
+
+        allowGetActiveSessionForTest(primaryUserId);
+        installAppAsUser(DEVICE_SIDE_TEST_APK, primaryUserId);
+        runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
+
+        installAppAsUser(MEDIA_SESSION_TEST_HELPER_APK, primaryUserId);
+        sendControlCommand(primaryUserId, FLAG_CREATE_MEDIA_SESSION);
+        runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
+
+        sendControlCommand(primaryUserId, FLAG_SET_MEDIA_SESSION_ACTIVE);
+        runTest("testGetActiveSessions_hasMediaSessionFromMediaSessionTestHelper");
+
+        if (!canCreateAdditionalUsers(1)) {
+            CLog.w("Cannot create a new user. Skipping multi-user test cases.");
+            return;
+        }
+
+        // Test if another user can get the session.
+        int newUser = createAndStartUser();
+        installAppAsUser(DEVICE_SIDE_TEST_APK, newUser);
+        allowGetActiveSessionForTest(newUser);
+        runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
+        removeUser(newUser);
+
+        // Test if another managed profile can get the session.
+        // Remove the created user first not to exceed system's user number limit.
+        newUser = createAndStartManagedProfile(primaryUserId);
+        installAppAsUser(DEVICE_SIDE_TEST_APK, newUser);
+        allowGetActiveSessionForTest(newUser);
+        runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
+        removeUser(newUser);
+
+        // Test if another restricted profile can get the session.
+        // Remove the created user first not to exceed system's user number limit.
+        newUser = createAndStartRestrictedProfile(primaryUserId);
+        installAppAsUser(DEVICE_SIDE_TEST_APK, newUser);
+        allowGetActiveSessionForTest(newUser);
+        runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
+    }
+
+    private void runTest(String testMethodName) throws DeviceNotAvailableException {
+        runTestAsUser(testMethodName, getDevice().getPrimaryUserId());
+    }
+
+    private void runTestAsUser(String testMethodName, int userId)
+            throws DeviceNotAvailableException {
+        runDeviceTestsAsUser(DEVICE_SIDE_TEST_PKG, DEVICE_SIDE_TEST_CLASS,
+                testMethodName, userId);
+    }
+
+    /**
+     * Allows the {@link #DEVICE_SIDE_TEST_CLASS} to call
+     * {@link MediaSessionManager#getActiveSessions} for testing.
+     * <p>{@link MediaSessionManager#getActiveSessions} bypasses the permission check if the
+     * caller is the enabled notification listener. This method uses the behavior by making
+     * {@link #DEVICE_SIDE_TEST_CLASS} as the notification listener. So any change in this
+     * should be also applied to the class.
+     * <p>Note that the device-side test {@link android.media.cts.MediaSessionManagerTest} already
+     * covers the test for failing {@link MediaSessionManager#getActiveSessions} without the
+     * permission nor the notification listener.
+     */
+    private void allowGetActiveSessionForTest(int userId) throws Exception {
+        final String NOTIFICATION_LISTENER_DELIM = ":";
+        if (mNotificationListeners.get(userId) != null) {
+            // Already enabled.
+            return;
+        }
+        String list = getSettings(SETTINGS_NOTIFICATION_LISTENER_NAMESPACE,
+                SETTINGS_NOTIFICATION_LISTENER_NAME, userId);
+
+        String notificationListener = DEVICE_SIDE_TEST_PKG + "/" + DEVICE_SIDE_TEST_CLASS;
+        // Ensure that the list doesn't contain notificationListener already.
+        // This can happen if the test is killed while running.
+        StringTokenizer tokenizer = new StringTokenizer(list, NOTIFICATION_LISTENER_DELIM);
+        StringJoiner joiner = new StringJoiner(NOTIFICATION_LISTENER_DELIM);
+        while (tokenizer.hasMoreTokens()) {
+            String token = tokenizer.nextToken();
+            if (!token.isEmpty() && !token.equals(notificationListener)) {
+                joiner.add(token);
+            }
+        }
+        list = joiner.toString();
+        // Preserve the original list.
+        mNotificationListeners.put(userId, list);
+        // Allow get active sessions by setting notification listener.
+        joiner.add(notificationListener);
+        putSettings(SETTINGS_NOTIFICATION_LISTENER_NAMESPACE,
+                SETTINGS_NOTIFICATION_LISTENER_NAME, joiner.toString(), userId);
+    }
+
+    private void sendControlCommand(int userId, int flag) throws Exception {
+        executeShellCommand(MediaSessionTestHelperConstants.buildControlCommand(userId, flag));
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
index f60abfa..79d3c3f 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
@@ -21,8 +21,8 @@
 
 import android.app.Activity;
 import android.app.ActivityOptions;
+import android.app.PictureInPictureParams;
 import android.content.BroadcastReceiver;
-import android.app.PictureInPictureArgs;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -32,6 +32,7 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Log;
+import android.util.Rational;
 import android.view.WindowManager;
 
 public class PipActivity extends AbstractLifecycleLogActivity {
@@ -58,12 +59,23 @@
     // Calls enterPictureInPicture() on creation
     private static final String EXTRA_ENTER_PIP = "enter_pip";
     // Used with EXTRA_AUTO_ENTER_PIP, value specifies the aspect ratio to enter PIP with
-    private static final String EXTRA_ENTER_PIP_ASPECT_RATIO = "enter_pip_aspect_ratio";
+    private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR =
+            "enter_pip_aspect_ratio_numerator";
+    // Used with EXTRA_AUTO_ENTER_PIP, value specifies the aspect ratio to enter PIP with
+    private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR =
+            "enter_pip_aspect_ratio_denominator";
     // Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value
-    private static final String EXTRA_SET_ASPECT_RATIO = "set_aspect_ratio";
+    private static final String EXTRA_SET_ASPECT_RATIO_NUMERATOR = "set_aspect_ratio_numerator";
+    // Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value
+    private static final String EXTRA_SET_ASPECT_RATIO_DENOMINATOR = "set_aspect_ratio_denominator";
     // Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value with a
     // fixed delay
-    private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY = "set_aspect_ratio_with_delay";
+    private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR =
+            "set_aspect_ratio_with_delay_numerator";
+    // Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value with a
+    // fixed delay
+    private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR =
+            "set_aspect_ratio_with_delay_denominator";
     // Adds a click listener to finish this activity when it is clicked
     private static final String EXTRA_TAP_TO_FINISH = "tap_to_finish";
     // Calls requestAutoEnterPictureInPicture() with the value provided
@@ -102,14 +114,17 @@
                         startIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
                         startActivity(startIntent);
 
-                        if (intent.hasExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY)) {
+                        if (intent.hasExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR)
+                                && intent.hasExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR)) {
                             // Ugly, but required to wait for the startActivity to actually start
                             // the activity...
                             mHandler.postDelayed(() -> {
-                                PictureInPictureArgs args = new PictureInPictureArgs();
-                                args.setAspectRatio(Float.valueOf(intent.getStringExtra(
-                                        EXTRA_SET_ASPECT_RATIO_WITH_DELAY)));
-                                setPictureInPictureArgs(args);
+                                final PictureInPictureParams.Builder builder =
+                                        new PictureInPictureParams.Builder();
+                                builder.setAspectRatio(getAspectRatio(intent,
+                                        EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR,
+                                        EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR));
+                                setPictureInPictureParams(builder.build());
                             }, 100);
                         }
                         break;
@@ -142,26 +157,33 @@
 
         // Enter picture in picture with the given aspect ratio if provided
         if (getIntent().hasExtra(EXTRA_ENTER_PIP)) {
-            if (getIntent().hasExtra(EXTRA_ENTER_PIP_ASPECT_RATIO)) {
+            if (getIntent().hasExtra(EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR)
+                    && getIntent().hasExtra(EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR)) {
                 try {
-                    final float aspectRatio = Float.valueOf(getIntent().getStringExtra(
-                            EXTRA_ENTER_PIP_ASPECT_RATIO));
-                    enterPictureInPictureMode(new PictureInPictureArgs(aspectRatio, null));
+                    final PictureInPictureParams.Builder builder =
+                            new PictureInPictureParams.Builder();
+                    builder.setAspectRatio(getAspectRatio(getIntent(),
+                            EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR,
+                            EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR));
+                    enterPictureInPictureMode(builder.build());
                 } catch (Exception e) {
                     // This call can fail intentionally if the aspect ratio is too extreme
                 }
             } else {
-                enterPictureInPictureMode();
+                enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
             }
         }
 
         // We need to wait for either enterPictureInPicture() or requestAutoEnterPictureInPicture()
         // to be called before setting the aspect ratio
-        if (getIntent().hasExtra(EXTRA_SET_ASPECT_RATIO)) {
-            final float aspectRatio = Float.valueOf(getIntent().getStringExtra(
-                    EXTRA_SET_ASPECT_RATIO));
+        if (getIntent().hasExtra(EXTRA_SET_ASPECT_RATIO_NUMERATOR)
+                && getIntent().hasExtra(EXTRA_SET_ASPECT_RATIO_DENOMINATOR)) {
+            final PictureInPictureParams.Builder builder =
+                    new PictureInPictureParams.Builder();
+            builder.setAspectRatio(getAspectRatio(getIntent(),
+                    EXTRA_SET_ASPECT_RATIO_NUMERATOR, EXTRA_SET_ASPECT_RATIO_DENOMINATOR));
             try {
-                setPictureInPictureArgs(new PictureInPictureArgs(aspectRatio, null));
+                setPictureInPictureParams(builder.build());
             } catch (Exception e) {
                 // This call can fail intentionally if the aspect ratio is too extreme
             }
@@ -214,7 +236,7 @@
 
         // Enter PIP on move to background
         if (getIntent().hasExtra(EXTRA_ENTER_PIP_ON_PAUSE)) {
-            enterPictureInPictureMode();
+            enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
         }
     }
 
@@ -223,7 +245,7 @@
         super.onStop();
 
         if (getIntent().hasExtra(EXTRA_ASSERT_NO_ON_STOP_BEFORE_PIP) && !mEnteredPictureInPicture) {
-            Log.w("PipActivity", "Unexpected onStop() called before entering picture-in-picture");
+            Log.w(TAG, "Unexpected onStop() called before entering picture-in-picture");
             finish();
         }
     }
@@ -239,6 +261,13 @@
     public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
         super.onPictureInPictureModeChanged(isInPictureInPictureMode);
 
+        // Fail early if the activity state does not match the dispatched state
+        if (isInPictureInPictureMode() != isInPictureInPictureMode) {
+            Log.w(TAG, "Received onPictureInPictureModeChanged mode=" + isInPictureInPictureMode
+                    + " activityState=" + isInPictureInPictureMode());
+            finish();
+        }
+
         // Mark that we've entered picture-in-picture so that we can stop checking for
         // EXTRA_ASSERT_NO_ON_STOP_BEFORE_PIP
         if (isInPictureInPictureMode) {
@@ -250,7 +279,7 @@
             // checking that the stacks ever changed). Therefor, we need to delay here slightly to
             // allow the tests to verify that the stacks have changed before re-entering.
             mHandler.postDelayed(() -> {
-                enterPictureInPictureMode();
+                enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
             }, 1000);
         }
     }
@@ -284,4 +313,13 @@
     protected String getTag() {
         return TAG;
     }
+
+    /**
+     * @return a {@link Rational} aspect ratio from the given intent and extras.
+     */
+    private Rational getAspectRatio(Intent intent, String extraNum, String extraDenom) {
+        return new Rational(
+                Integer.valueOf(intent.getStringExtra(extraNum)),
+                Integer.valueOf(intent.getStringExtra(extraDenom)));
+    }
 }
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 038eb8d..65f507e 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -49,9 +49,16 @@
 
     private static final String EXTRA_FIXED_ORIENTATION = "fixed_orientation";
     private static final String EXTRA_ENTER_PIP = "enter_pip";
-    private static final String EXTRA_ENTER_PIP_ASPECT_RATIO = "enter_pip_aspect_ratio";
-    private static final String EXTRA_SET_ASPECT_RATIO = "set_aspect_ratio";
-    private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY = "set_aspect_ratio_with_delay";
+    private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR =
+            "enter_pip_aspect_ratio_numerator";
+    private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR =
+            "enter_pip_aspect_ratio_denominator";
+    private static final String EXTRA_SET_ASPECT_RATIO_NUMERATOR = "set_aspect_ratio_numerator";
+    private static final String EXTRA_SET_ASPECT_RATIO_DENOMINATOR = "set_aspect_ratio_denominator";
+    private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR =
+            "set_aspect_ratio_with_delay_numerator";
+    private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR =
+            "set_aspect_ratio_with_delay_denominator";
     private static final String EXTRA_ENTER_PIP_ON_PAUSE = "enter_pip_on_pause";
     private static final String EXTRA_TAP_TO_FINISH = "tap_to_finish";
     private static final String EXTRA_START_ACTIVITY = "start_activity";
@@ -91,11 +98,13 @@
     private static final float FLOAT_COMPARE_EPSILON = 0.005f;
 
     // Corresponds to com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio
-    private static final float MIN_ASPECT_RATIO = 1f / 2.39f;
-    private static final float BELOW_MIN_ASPECT_RATIO = MIN_ASPECT_RATIO - FLOAT_COMPARE_EPSILON;
+    private static final int MIN_ASPECT_RATIO_NUMERATOR = 100;
+    private static final int MIN_ASPECT_RATIO_DENOMINATOR = 239;
+    private static final int BELOW_MIN_ASPECT_RATIO_DENOMINATOR = MIN_ASPECT_RATIO_DENOMINATOR + 1;
     // Corresponds to com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio
-    private static final float MAX_ASPECT_RATIO = 2.39f;
-    private static final float ABOVE_MAX_ASPECT_RATIO = MAX_ASPECT_RATIO + FLOAT_COMPARE_EPSILON;
+    private static final int MAX_ASPECT_RATIO_NUMERATOR = 239;
+    private static final int MAX_ASPECT_RATIO_DENOMINATOR = 100;
+    private static final int ABOVE_MAX_ASPECT_RATIO_NUMERATOR = MAX_ASPECT_RATIO_NUMERATOR + 1;
 
     public void testEnterPictureInPictureMode() throws Exception {
         pinnedStackTester(getAmStartCmd(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true"), PIP_ACTIVITY,
@@ -270,42 +279,44 @@
     }
 
     public void testEnterPipAspectRatioMin() throws Exception {
-        testEnterPipAspectRatio(MAX_ASPECT_RATIO);
+        testEnterPipAspectRatio(MIN_ASPECT_RATIO_NUMERATOR, MIN_ASPECT_RATIO_DENOMINATOR);
     }
 
     public void testEnterPipAspectRatioMax() throws Exception {
-        testEnterPipAspectRatio(MIN_ASPECT_RATIO);
+        testEnterPipAspectRatio(MAX_ASPECT_RATIO_NUMERATOR, MAX_ASPECT_RATIO_DENOMINATOR);
     }
 
-    private void testEnterPipAspectRatio(float aspectRatio) throws Exception {
+    private void testEnterPipAspectRatio(int num, int denom) throws Exception {
         if (!supportsPip()) return;
 
         launchActivity(PIP_ACTIVITY,
                 EXTRA_ENTER_PIP, "true",
-                EXTRA_ENTER_PIP_ASPECT_RATIO, Float.toString(aspectRatio));
+                EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+                EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
         assertPinnedStackExists();
 
         // Assert that we have entered PIP and that the aspect ratio is correct
         Rectangle pinnedStackBounds =
                 mAmWmState.getAmState().getStackById(PINNED_STACK_ID).getBounds();
         assertTrue(floatEquals((float) pinnedStackBounds.width / pinnedStackBounds.height,
-                aspectRatio));
+                (float) num / denom));
     }
 
     public void testResizePipAspectRatioMin() throws Exception {
-        testResizePipAspectRatio(MIN_ASPECT_RATIO);
+        testResizePipAspectRatio(MIN_ASPECT_RATIO_NUMERATOR, MIN_ASPECT_RATIO_DENOMINATOR);
     }
 
     public void testResizePipAspectRatioMax() throws Exception {
-        testResizePipAspectRatio(MAX_ASPECT_RATIO);
+        testResizePipAspectRatio(MAX_ASPECT_RATIO_NUMERATOR, MAX_ASPECT_RATIO_DENOMINATOR);
     }
 
-    private void testResizePipAspectRatio(float aspectRatio) throws Exception {
+    private void testResizePipAspectRatio(int num, int denom) throws Exception {
         if (!supportsPip()) return;
 
         launchActivity(PIP_ACTIVITY,
                 EXTRA_ENTER_PIP, "true",
-                EXTRA_SET_ASPECT_RATIO, Float.toString(aspectRatio));
+                EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+                EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
         assertPinnedStackExists();
 
         // Hacky, but we need to wait for the enterPictureInPicture animation to complete and
@@ -314,7 +325,8 @@
         mAmWmState.waitForWithAmState(mDevice, (state) -> {
             Rectangle pinnedStackBounds = state.getStackById(PINNED_STACK_ID).getBounds();
             boolean isValidAspectRatio = floatEquals(
-                    (float) pinnedStackBounds.width / pinnedStackBounds.height, aspectRatio);
+                    (float) pinnedStackBounds.width / pinnedStackBounds.height,
+                    (float) num / denom);
             result[0] = isValidAspectRatio;
             return isValidAspectRatio;
         }, "Waiting for pinned stack to be resized");
@@ -322,45 +334,54 @@
     }
 
     public void testEnterPipExtremeAspectRatioMin() throws Exception {
-        testEnterPipExtremeAspectRatio(BELOW_MIN_ASPECT_RATIO);
+        testEnterPipExtremeAspectRatio(MIN_ASPECT_RATIO_NUMERATOR,
+                BELOW_MIN_ASPECT_RATIO_DENOMINATOR);
     }
 
     public void testEnterPipExtremeAspectRatioMax() throws Exception {
-        testEnterPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO);
+        testEnterPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO_NUMERATOR,
+                MAX_ASPECT_RATIO_DENOMINATOR);
     }
 
-    private void testEnterPipExtremeAspectRatio(float aspectRatio) throws Exception {
+    private void testEnterPipExtremeAspectRatio(int num, int denom) throws Exception {
         if (!supportsPip()) return;
 
         // Assert that we could not create a pinned stack with an extreme aspect ratio
         launchActivity(PIP_ACTIVITY,
                 EXTRA_ENTER_PIP, "true",
-                EXTRA_ENTER_PIP_ASPECT_RATIO, Float.toString(aspectRatio));
+                EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+                EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
         assertPinnedStackDoesNotExist();
     }
 
     public void testSetPipExtremeAspectRatioMin() throws Exception {
-        testSetPipExtremeAspectRatio(BELOW_MIN_ASPECT_RATIO);
+        testSetPipExtremeAspectRatio(MIN_ASPECT_RATIO_NUMERATOR,
+                BELOW_MIN_ASPECT_RATIO_DENOMINATOR);
     }
 
     public void testSetPipExtremeAspectRatioMax() throws Exception {
-        testSetPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO);
+        testSetPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO_NUMERATOR,
+                MAX_ASPECT_RATIO_DENOMINATOR);
     }
 
-    private void testSetPipExtremeAspectRatio(float aspectRatio) throws Exception {
+    private void testSetPipExtremeAspectRatio(int num, int denom) throws Exception {
         if (!supportsPip()) return;
 
         // 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,
                 EXTRA_ENTER_PIP, "true",
-                EXTRA_ENTER_PIP_ASPECT_RATIO, Float.toString(MAX_ASPECT_RATIO),
-                EXTRA_SET_ASPECT_RATIO, Float.toString(aspectRatio));
+                EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR,
+                        Integer.toString(MAX_ASPECT_RATIO_NUMERATOR),
+                EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR,
+                        Integer.toString(MAX_ASPECT_RATIO_DENOMINATOR),
+                EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+                EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
         assertPinnedStackExists();
         Rectangle pinnedStackBounds =
                 mAmWmState.getAmState().getStackById(PINNED_STACK_ID).getBounds();
         assertTrue(floatEquals((float) pinnedStackBounds.width / pinnedStackBounds.height,
-                MAX_ASPECT_RATIO));
+                (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR));
     }
 
     public void testDisallowPipLaunchFromStoppedActivity() throws Exception {
@@ -434,7 +455,8 @@
         // Launch the PIP activity on pause, and set the aspect ratio
         launchActivity(PIP_ACTIVITY,
                 EXTRA_ENTER_PIP_ON_PAUSE, "true",
-                EXTRA_SET_ASPECT_RATIO, Float.toString(MAX_ASPECT_RATIO));
+                EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(MAX_ASPECT_RATIO_NUMERATOR),
+                EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(MAX_ASPECT_RATIO_DENOMINATOR));
 
         // Go home while the pip activity is open to trigger auto-PIP
         launchHomeActivity();
@@ -446,7 +468,8 @@
         mAmWmState.waitForWithAmState(mDevice, (state) -> {
             Rectangle pinnedStackBounds = state.getStackById(PINNED_STACK_ID).getBounds();
             boolean isValidAspectRatio = floatEquals(
-                    (float) pinnedStackBounds.width / pinnedStackBounds.height, MAX_ASPECT_RATIO);
+                    (float) pinnedStackBounds.width / pinnedStackBounds.height,
+                    (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR);
             result[0] = isValidAspectRatio;
             return isValidAspectRatio;
         }, "Waiting for pinned stack to be resized");
@@ -806,8 +829,9 @@
 
         // Trigger it to go back to fullscreen and try to set the aspect ratio, and ensure that the
         // call to set the aspect ratio did not prevent the PiP from returning to fullscreen
-        executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_EXPAND_PIP + " -e "
-                + EXTRA_SET_ASPECT_RATIO_WITH_DELAY + " 1.23456789");
+        executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_EXPAND_PIP
+                + " -e " + EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR + " 123456789"
+                + " -e " + EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR + " 100000000");
         mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
         assertPinnedStackDoesNotExist();
     }
@@ -851,6 +875,9 @@
         assertPinnedStackExists();
         int taskId = mAmWmState.getAmState().getStackById(PINNED_STACK_ID).getTopTask().mTaskId;
 
+        // Ensure that we don't any any other overlays as a result of launching into PIP
+        launchHomeActivity();
+
         // Launch task overlay activity into PiP activity task
         launchActivityAsTaskOverlay(TRANSLUCENT_TEST_ACTIVITY, taskId, PINNED_STACK_ID);
 
@@ -858,10 +885,7 @@
         executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_FINISH);
         mAmWmState.waitForWithAmState(mDevice, (amState) -> {
             ActivityStack stack = amState.getStackById(PINNED_STACK_ID);
-            if (stack != null) {
-                return false;
-            }
-            return true;
+            return stack == null;
         }, "Waiting for pinned stack to be removed...");
         assertPinnedStackDoesNotExist();
     }
@@ -908,15 +932,13 @@
         if (expectTopTaskHasActivity) {
             ActivityTask topTask = mAmWmState.getAmState().getStackById(
                     FULLSCREEN_WORKSPACE_STACK_ID).getTopTask();
-            Activity topActivity = topTask.mActivities.get(0);
-            assertTrue(topActivity.name.equals(ActivityManagerTestBase.getActivityComponentName(
+            assertTrue(topTask.containsActivity(ActivityManagerTestBase.getActivityComponentName(
                     activityName)));
         }
         if (expectBottomTaskHasActivity) {
             ActivityTask bottomTask = mAmWmState.getAmState().getStackById(
                     FULLSCREEN_WORKSPACE_STACK_ID).getBottomTask();
-            Activity bottomActivity = bottomTask.mActivities.get(0);
-            assertTrue(bottomActivity.name.equals(ActivityManagerTestBase.getActivityComponentName(
+            assertTrue(bottomTask.containsActivity(ActivityManagerTestBase.getActivityComponentName(
                     activityName)));
         }
     }
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
index 6565215..56fed31 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
@@ -607,6 +607,18 @@
         public String getResizeMode() {
             return mResizeMode;
         }
+
+        /**
+         * @return whether this task contains the given activity.
+         */
+        public boolean containsActivity(String activityName) {
+            for (Activity activity : mActivities) {
+                if (activity.name.equals(activityName)) {
+                    return true;
+                }
+            }
+            return false;
+        }
     }
 
     static class Activity {
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 521d5a3..3200409 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -359,7 +359,7 @@
                         .setSmallIcon(R.drawable.black)
                         .setContentTitle("notify#" + id)
                         .setContentText("This is #" + id + "notification  ")
-                        .setTimeout(timeout)
+                        .setTimeoutAfter(timeout)
                         .build();
         mNotificationManager.notify(id, notification);
 
diff --git a/tests/app/src/android/app/cts/NotificationTest.java b/tests/app/src/android/app/cts/NotificationTest.java
index 75f75b2..b3d833f 100644
--- a/tests/app/src/android/app/cts/NotificationTest.java
+++ b/tests/app/src/android/app/cts/NotificationTest.java
@@ -76,11 +76,11 @@
 
     public void testBuilderConstructor() {
         mNotification = new Notification.Builder(mContext, CHANNEL.getId()).build();
-        assertEquals(CHANNEL.getId(), mNotification.getChannel());
+        assertEquals(CHANNEL.getId(), mNotification.getChannelId());
         assertEquals(Notification.BADGE_ICON_NONE, mNotification.getBadgeIconType());
         assertNull(mNotification.getShortcutId());
         assertEquals(Notification.GROUP_ALERT_ALL, mNotification.getGroupAlertBehavior());
-        assertEquals((long) 0, mNotification.getTimeout());
+        assertEquals((long) 0, mNotification.getTimeoutAfter());
     }
 
     public void testDescribeContents() {
@@ -94,7 +94,7 @@
         mNotification = new Notification.Builder(mContext, CHANNEL.getId())
                 .setBadgeIconType(Notification.BADGE_ICON_SMALL)
                 .setShortcutId(SHORTCUT_ID)
-                .setTimeout(TIMEOUT)
+                .setTimeoutAfter(TIMEOUT)
                 .setSettingsText(SETTING_TEXT)
                 .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN)
                 .build();
@@ -149,8 +149,8 @@
         assertEquals(mNotification.iconLevel, result.iconLevel);
         assertEquals(mNotification.getShortcutId(), result.getShortcutId());
         assertEquals(mNotification.getBadgeIconType(), result.getBadgeIconType());
-        assertEquals(mNotification.getTimeout(), result.getTimeout());
-        assertEquals(mNotification.getChannel(), result.getChannel());
+        assertEquals(mNotification.getTimeoutAfter(), result.getTimeoutAfter());
+        assertEquals(mNotification.getChannelId(), result.getChannelId());
         assertEquals(mNotification.getSettingsText(), result.getSettingsText());
         assertEquals(mNotification.getGroupAlertBehavior(), result.getGroupAlertBehavior());
 
@@ -210,7 +210,7 @@
                 .setContentIntent(contentIntent)
                 .setBadgeIconType(Notification.BADGE_ICON_SMALL)
                 .setShortcutId(SHORTCUT_ID)
-                .setTimeout(TIMEOUT)
+                .setTimeoutAfter(TIMEOUT)
                 .setSettingsText(SETTING_TEXT)
                 .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
                 .build();
@@ -218,10 +218,10 @@
         assertEquals(CONTENT_TITLE, mNotification.extras.getString(Notification.EXTRA_TITLE));
         assertEquals(1, mNotification.icon);
         assertEquals(contentIntent, mNotification.contentIntent);
-        assertEquals(CHANNEL.getId(), mNotification.getChannel());
+        assertEquals(CHANNEL.getId(), mNotification.getChannelId());
         assertEquals(Notification.BADGE_ICON_SMALL, mNotification.getBadgeIconType());
         assertEquals(SHORTCUT_ID, mNotification.getShortcutId());
-        assertEquals(TIMEOUT, mNotification.getTimeout());
+        assertEquals(TIMEOUT, mNotification.getTimeoutAfter());
         assertEquals(SETTING_TEXT, mNotification.getSettingsText());
         assertEquals(Notification.GROUP_ALERT_SUMMARY, mNotification.getGroupAlertBehavior());
     }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
index 786ff40..430c612 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
@@ -62,9 +62,9 @@
 
         final Parcelable result;
         if (sResponse != null) {
-            result = sResponse.asFillResponse(structure);
+            result = sResponse.asFillResponse((id) -> Helper.findNodeByResourceId(structure, id));
         } else if (sDataset != null) {
-            result = sDataset.asDataset(structure);
+            result = sDataset.asDataset((id) -> Helper.findNodeByResourceId(structure, id));
         } else {
             throw new IllegalStateException("no dataset or response");
         }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index b456dd7..9f5368f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -22,11 +22,11 @@
 import static android.autofillservice.cts.Helper.getAutofillIds;
 import android.app.assist.AssistStructure;
 import android.app.assist.AssistStructure.ViewNode;
-import android.autofillservice.cts.CannedFillResponse.Builder;
 import android.content.IntentSender;
 import android.os.Bundle;
 import android.service.autofill.Dataset;
 import android.service.autofill.FillCallback;
+import android.service.autofill.FillContext;
 import android.service.autofill.FillResponse;
 import android.service.autofill.SaveInfo;
 import android.view.autofill.AutofillId;
@@ -38,6 +38,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 /**
  * Helper class used to produce a {@link FillResponse} based on expected fields that should be
@@ -66,7 +67,7 @@
     private final IntentSender mAuthentication;
     private final String[] mAuthenticationIds;
     private final String[] mIgnoredIds;
-    private final CharSequence mNegativeActionLabel;
+    private final int mNegativeActionStyle;
     private final IntentSender mNegativeActionListener;
     private final int mFlags;
 
@@ -81,7 +82,7 @@
         mAuthentication = builder.mAuthentication;
         mAuthenticationIds = builder.mAuthenticationIds;
         mIgnoredIds = builder.mIgnoredIds;
-        mNegativeActionLabel = builder.mNegativeActionLabel;
+        mNegativeActionStyle = builder.mNegativeActionStyle;
         mNegativeActionListener = builder.mNegativeActionListener;
         mFlags = builder.mFlags;
     }
@@ -96,45 +97,37 @@
      * Creates a new response, replacing the dataset field ids by the real ids from the assist
      * structure.
      */
-    FillResponse asFillResponse(AssistStructure structure) {
+    FillResponse asFillResponse(Function<String, ViewNode> nodeResolver) {
         final FillResponse.Builder builder = new FillResponse.Builder();
         if (mDatasets != null) {
             for (CannedDataset cannedDataset : mDatasets) {
-                final Dataset dataset = cannedDataset.asDataset(structure);
+                final Dataset dataset = cannedDataset.asDataset(nodeResolver);
                 assertWithMessage("Cannot create datase").that(dataset).isNotNull();
                 builder.addDataset(dataset);
             }
         }
         if (mRequiredSavableIds != null) {
-            final SaveInfo.Builder saveInfo;
-
-            if (mRequiredSavableIds == null) {
-                saveInfo = new SaveInfo.Builder(mSaveType, null);
-            } else {
-                saveInfo = new SaveInfo.Builder(mSaveType,
-                        getAutofillIds(structure, mRequiredSavableIds));
-            }
+            final SaveInfo.Builder saveInfo = new SaveInfo.Builder(mSaveType,
+                    getAutofillIds(nodeResolver, mRequiredSavableIds));
 
             saveInfo.setFlags(mFlags);
 
             if (mOptionalSavableIds != null) {
-                saveInfo.setOptionalIds(getAutofillIds(structure, mOptionalSavableIds));
+                saveInfo.setOptionalIds(getAutofillIds(nodeResolver, mOptionalSavableIds));
             }
             if (mSaveDescription != null) {
                 saveInfo.setDescription(mSaveDescription);
             }
-            if (mNegativeActionLabel != null) {
-                saveInfo.setNegativeAction(mNegativeActionLabel, mNegativeActionListener);
-            }
+            saveInfo.setNegativeAction(mNegativeActionStyle, mNegativeActionListener);
             builder.setSaveInfo(saveInfo.build());
         }
         if (mIgnoredIds != null) {
-            builder.setIgnoredIds(getAutofillIds(structure, mIgnoredIds));
+            builder.setIgnoredIds(getAutofillIds(nodeResolver, mIgnoredIds));
         }
         return builder
                 .setClientState(mExtras)
-                .setAuthentication(getAutofillIds(structure, mAuthenticationIds), mAuthentication,
-                        mPresentation)
+                .setAuthentication(getAutofillIds(nodeResolver, mAuthenticationIds),
+                        mAuthentication, mPresentation)
                 .build();
     }
 
@@ -163,7 +156,7 @@
         private IntentSender mAuthentication;
         private String[] mAuthenticationIds;
         private String[] mIgnoredIds;
-        private CharSequence mNegativeActionLabel;
+        private int mNegativeActionStyle;
         private IntentSender mNegativeActionListener;
         private int mFlags;
 
@@ -246,9 +239,9 @@
         /**
          * Sets the negative action spec.
          */
-        public Builder setNegativeAction(CharSequence label,
+        public Builder setNegativeAction(int style,
                 IntentSender listener) {
-            mNegativeActionLabel = label;
+            mNegativeActionStyle = style;
             mNegativeActionListener = listener;
             return this;
         }
@@ -291,7 +284,7 @@
         /**
          * Creates a new dataset, replacing the field ids by the real ids from the assist structure.
          */
-        Dataset asDataset(AssistStructure structure) {
+        Dataset asDataset(Function<String, ViewNode> nodeResolver) {
             final Dataset.Builder builder = (mPresentation == null)
                     ? new Dataset.Builder()
                     : new Dataset.Builder(mPresentation);
@@ -299,9 +292,8 @@
             if (mFieldValues != null) {
                 for (Map.Entry<String, AutofillValue> entry : mFieldValues.entrySet()) {
                     final String resourceId = entry.getKey();
-                    final ViewNode node = findNodeByResourceId(structure, resourceId);
+                    final ViewNode node = nodeResolver.apply(resourceId);
                     if (node == null) {
-                        dumpStructure("asDataset()", structure);
                         throw new AssertionError("No node with resource id " + resourceId);
                     }
                     final AutofillId id = node.getAutofillId();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index e19fa0c..f1491b4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -27,6 +27,7 @@
 import android.os.Bundle;
 import android.os.UserManager;
 import android.service.autofill.Dataset;
+import android.service.autofill.FillContext;
 import android.service.autofill.FillResponse;
 import android.support.annotation.NonNull;
 import android.support.test.InstrumentationRegistry;
@@ -40,8 +41,10 @@
 
 import com.android.compatibility.common.util.SystemUtil;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 /**
  * Helper for common funcionalities.
@@ -163,6 +166,15 @@
     }
 
     /**
+     * Dump the contexts on logcat.
+     */
+    static void dumpStructure(String message, List<FillContext> contexts) {
+        for (FillContext context : contexts) {
+            dumpStructure(message, context.getStructure());
+        }
+    }
+
+    /**
      * Dumps the state of the autofill service on logcat.
      */
     static void dumpAutofillService() {
@@ -227,6 +239,19 @@
     /**
      * Gets a node given its Android resource id, or {@code null} if not found.
      */
+    static ViewNode findNodeByResourceId(ArrayList<FillContext> contexts, String resourceId) {
+        for (FillContext context : contexts) {
+            ViewNode node = findNodeByResourceId(context.getStructure(), resourceId);
+            if (node != null) {
+                return node;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets a node given its Android resource id, or {@code null} if not found.
+     */
     static ViewNode findNodeByResourceId(ViewNode node, String resourceId) {
         if (resourceId.equals(node.getIdEntry())) {
             return node;
@@ -530,15 +555,15 @@
      * Creates an array of {@link AutofillId} mapped from the {@code structure} nodes with the given
      * {@code resourceIds}.
      */
-    static AutofillId[] getAutofillIds(AssistStructure structure, String[] resourceIds) {
+    static AutofillId[] getAutofillIds(Function<String, ViewNode> nodeResolver,
+            String[] resourceIds) {
         if (resourceIds == null) return null;
 
         final AutofillId[] requiredIds = new AutofillId[resourceIds.length];
         for (int i = 0; i < resourceIds.length; i++) {
             final String resourceId = resourceIds[i];
-            final ViewNode node = findNodeByResourceId(structure, resourceId);
+            final ViewNode node = nodeResolver.apply(resourceId);
             if (node == null) {
-                dumpStructure("getAutofillIds()", structure);
                 throw new AssertionError("No node with savable resourceId " + resourceId);
             }
             requiredIds[i] = node.getAutofillId();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index 44ca039..61b47af 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -38,6 +38,7 @@
 import android.service.autofill.SaveCallback;
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -85,21 +86,17 @@
     @Override
     public void onFillRequest(android.service.autofill.FillRequest request,
             CancellationSignal cancellationSignal, FillCallback callback) {
-        final AssistStructure structure = request.getStructure();
-        if (DUMP_FILL_REQUESTS) dumpStructure("onFillRequest()", structure);
+        if (DUMP_FILL_REQUESTS) dumpStructure("onFillRequest()", request.getFillContexts());
 
-        sReplier.onFillRequest(structure, request.getClientState(), cancellationSignal, callback,
-                request.getFlags());
+        sReplier.onFillRequest(request.getFillContexts(), request.getClientState(),
+                cancellationSignal, callback, request.getFlags());
     }
 
     @Override
     public void onSaveRequest(android.service.autofill.SaveRequest request,
             SaveCallback callback) {
-        final List<FillContext> contexts = request.getFillContexts();
-        final AssistStructure structure = contexts.get(contexts.size() - 1).getStructure();
-
-        if (DUMP_SAVE_REQUESTS) dumpStructure("onSaveRequest()", structure);
-        sReplier.onSaveRequest(structure, request.getClientState(), callback);
+        if (DUMP_SAVE_REQUESTS) dumpStructure("onSaveRequest()", request.getFillContexts());
+        sReplier.onSaveRequest(request.getFillContexts(), request.getClientState(), callback);
     }
 
     /**
@@ -152,18 +149,20 @@
      */
     static final class FillRequest {
         final AssistStructure structure;
+        final ArrayList<FillContext> contexts;
         final Bundle data;
         final CancellationSignal cancellationSignal;
         final FillCallback callback;
         final int flags;
 
-        private FillRequest(AssistStructure structure, Bundle data,
+        private FillRequest(ArrayList<FillContext> contexts, Bundle data,
                 CancellationSignal cancellationSignal, FillCallback callback, int flags) {
-            this.structure = structure;
+            this.contexts = contexts;
             this.data = data;
             this.cancellationSignal = cancellationSignal;
             this.callback = callback;
             this.flags = flags;
+            structure = contexts.get(contexts.size() - 1).getStructure();
         }
     }
 
@@ -173,12 +172,18 @@
      * that can be asserted at the end of a test case.
      */
     static final class SaveRequest {
+        final List<FillContext> contexts;
         final AssistStructure structure;
         final Bundle data;
         final SaveCallback callback;
 
-        private SaveRequest(AssistStructure structure, Bundle data, SaveCallback callback) {
-            this.structure = structure;
+        private SaveRequest(List<FillContext> contexts, Bundle data, SaveCallback callback) {
+            if (contexts != null && contexts.size() > 0) {
+                structure = contexts.get(contexts.size() - 1).getStructure();
+            } else {
+                structure = null;
+            }
+            this.contexts = contexts;
             this.data = data;
             this.callback = callback;
         }
@@ -277,7 +282,7 @@
             mSaveRequests.clear();
         }
 
-        private void onFillRequest(AssistStructure structure, Bundle data,
+        private void onFillRequest(ArrayList<FillContext> contexts, Bundle data,
                 CancellationSignal cancellationSignal, FillCallback callback, int flags) {
             try {
                 CannedFillResponse response = null;
@@ -288,7 +293,7 @@
                     Thread.currentThread().interrupt();
                 }
                 if (response == null) {
-                    dumpStructure("onFillRequest() without response", structure);
+                    dumpStructure("onFillRequest() without response", contexts);
                     throw new IllegalStateException("No CannedResponse");
                 }
                 if (response == NO_RESPONSE) {
@@ -296,19 +301,20 @@
                     return;
                 }
 
-                final FillResponse fillResponse = response.asFillResponse(structure);
+                final FillResponse fillResponse = response.asFillResponse(
+                        (id) -> Helper.findNodeByResourceId(contexts, id));
 
                 Log.v(TAG, "onFillRequest(): fillResponse = " + fillResponse);
                 callback.onSuccess(fillResponse);
             } finally {
-                mFillRequests.offer(new FillRequest(structure, data, cancellationSignal, callback,
+                mFillRequests.offer(new FillRequest(contexts, data, cancellationSignal, callback,
                         flags));
             }
         }
 
-        private void onSaveRequest(AssistStructure structure, Bundle data, SaveCallback callback) {
+        private void onSaveRequest(List<FillContext> contexts, Bundle data, SaveCallback callback) {
             Log.d(TAG, "onSaveRequest()");
-            mSaveRequests.offer(new SaveRequest(structure, data, callback));
+            mSaveRequests.offer(new SaveRequest(contexts, data, callback));
             callback.onSuccess();
         }
     }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 30cfde7..51f8e12 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -61,7 +61,9 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.os.Bundle;
+import android.platform.test.annotations.Presubmit;
 import android.service.autofill.FillEventHistory;
+import android.service.autofill.SaveInfo;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.uiautomator.UiObject2;
 import android.view.View;
@@ -334,6 +336,7 @@
     }
 
     @Test
+    @Presubmit
     public void testAutoFillOneDatasetAndSave() throws Exception {
         // Set service.
         enableService();
@@ -1146,7 +1149,7 @@
     }
 
     @Test
-    public void testCustomNegativeSaveButton() throws Exception {
+    public void testRejectStyleNegativeSaveButton() throws Exception {
         enableService();
 
         // Set service behavior.
@@ -1159,7 +1162,7 @@
 
         sReplier.addResponse(new CannedFillResponse.Builder()
                 .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
-                .setNegativeAction("Foo", listener)
+                .setNegativeAction(SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT, listener)
                 .build());
 
         // Trigger auto-fill.
@@ -1185,7 +1188,8 @@
         }, intentFilter);
 
         // Trigger the negative button.
-        sUiBot.saveForAutofill(false, SAVE_DATA_TYPE_PASSWORD);
+        sUiBot.saveForAutofill(SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT,
+                false, SAVE_DATA_TYPE_PASSWORD);
 
         // Wait for the custom action.
         assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue();
@@ -1194,6 +1198,55 @@
     }
 
     @Test
+    public void testCancelStyleNegativeSaveButton() throws Exception {
+        enableService();
+
+        // Set service behavior.
+
+        final String intentAction = "android.autofillservice.cts.CUSTOM_ACTION";
+
+        // Configure the save UI.
+        final IntentSender listener = PendingIntent.getBroadcast(
+                getContext(), 0, new Intent(intentAction), 0).getIntentSender();
+
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
+                .setNegativeAction(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, listener)
+                .build());
+
+        // Trigger auto-fill.
+        mActivity.onUsername(View::requestFocus);
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+
+        // Trigger save.
+        mActivity.onUsername((v) -> v.setText("foo"));
+        mActivity.onPassword((v) -> v.setText("foo"));
+        mActivity.tapLogin();
+
+        // Start watching for the negative intent
+        final CountDownLatch latch = new CountDownLatch(1);
+        final IntentFilter intentFilter = new IntentFilter(intentAction);
+        getContext().registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                getContext().unregisterReceiver(this);
+                latch.countDown();
+            }
+        }, intentFilter);
+
+        // Trigger the negative button.
+        sUiBot.saveForAutofill(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL,
+                false, SAVE_DATA_TYPE_PASSWORD);
+
+        // Wait for the custom action.
+        assertThat(latch.await(500, TimeUnit.SECONDS)).isTrue();
+
+        assertNoDanglingSessions();
+    }
+
+    @Test
     public void testGetTextInputType() throws Exception {
         // Set service.
         enableService();
@@ -1253,13 +1306,17 @@
         assertThat(usernameContainer.getChildCount()).isEqualTo(2);
     }
 
+    private static final boolean BUG_36171235_FIXED = false;
+
+    @Test
     public void testAutofillManuallyOneDataset() throws Exception {
         // Set service.
         enableService();
 
+        if (BUG_36171235_FIXED)
         // And activity.
         mActivity.onUsername((v) -> {
-            // v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+            v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
             // TODO: setting an empty text, otherwise longPress() does not
             // display the AUTOFILL context menu. Need to fix it, but it's a test case issue...
             v.setText("");
@@ -1274,7 +1331,11 @@
         mActivity.expectAutoFill("dude", "sweet");
 
         // Long-press field to trigger AUTOFILL menu.
-        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+        if (BUG_36171235_FIXED) {
+            sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+        } else {
+            mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
+        }
 
         final FillRequest fillRequest = sReplier.getNextFillRequest();
         assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
@@ -1286,10 +1347,12 @@
         mActivity.assertAutoFilled();
     }
 
+    @Test
     public void testAutofillManuallyTwoDatasetsPickFirst() throws Exception {
         autofillManuallyTwoDatasets(true);
     }
 
+    @Test
     public void testAutofillManuallyTwoDatasetsPickSecond() throws Exception {
         autofillManuallyTwoDatasets(false);
     }
@@ -1298,9 +1361,10 @@
         // Set service.
         enableService();
 
+        if (BUG_36171235_FIXED)
         // And activity.
         mActivity.onUsername((v) -> {
-            // v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+            v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
             // TODO: setting an empty text, otherwise longPress() does not display the AUTOFILL
             // context menu. Need to fix it, but it's a test case issue...
             v.setText("");
@@ -1327,7 +1391,11 @@
         }
 
         // Long-press field to trigger AUTOFILL menu.
-        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+        if (BUG_36171235_FIXED) {
+            sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+        } else {
+            mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
+        }
 
         final FillRequest fillRequest = sReplier.getNextFillRequest();
         assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
index 32844d4..026cf08 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
@@ -54,9 +54,11 @@
             if (structure != null) {
                 Parcelable result;
                 if (sResponse != null) {
-                    result = sResponse.asFillResponse(structure);
+                    result = sResponse.asFillResponse(
+                            (id) -> Helper.findNodeByResourceId(structure, id));
                 } else if (sDataset != null) {
-                    result = sDataset.asDataset(structure);
+                    result = sDataset.asDataset(
+                            (id) -> Helper.findNodeByResourceId(structure, id));
                 } else {
                     throw new IllegalStateException("no dataset or response");
                 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
index 76c8c70..d474dc8 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
@@ -24,8 +24,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.app.assist.AssistStructure;
+import android.app.assist.AssistStructure.ViewNode;
+import android.os.Bundle;
 import android.support.test.rule.ActivityTestRule;
 import android.util.Log;
+import android.view.autofill.AutofillValue;
 import android.widget.EditText;
 
 import org.junit.Before;
@@ -52,11 +56,17 @@
     public void loginOnTwoFragments() throws Exception {
         enableService();
         try {
-            // Set expectations.
+            Bundle clientState = new Bundle();
+            clientState.putString("key", "value1");
             sReplier.addResponse(new CannedFillResponse.Builder()
-                    .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText1").build());
+                    .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                            .setField("editText1", "editText1-autofilled")
+                            .setPresentation(createPresentation("dataset1"))
+                            .build())
+                    .setExtras(clientState)
+                    .build());
 
-            final InstrumentedAutoFillService.FillRequest[] request =
+            final InstrumentedAutoFillService.FillRequest[] fillRequest =
                     new InstrumentedAutoFillService.FillRequest[1];
 
             // Trigger autofill
@@ -67,37 +77,123 @@
                 });
 
                 try {
-                    request[0] = sReplier.getNextFillRequest();
+                    fillRequest[0] = sReplier.getNextFillRequest();
                 } catch (InterruptedException e) {
                     throw new RuntimeException(e);
                 }
             }, (int) (FILL_TIMEOUT_MS * 2));
 
-            assertThat(findNodeByResourceId(request[0].structure, "editText1")).isNotNull();
-            assertThat(findNodeByResourceId(request[0].structure, "editText2")).isNotNull();
-            assertThat(findNodeByResourceId(request[0].structure, "editText3")).isNull();
-            assertThat(findNodeByResourceId(request[0].structure, "editText4")).isNull();
-            assertThat(findNodeByResourceId(request[0].structure, "editText5")).isNull();
+            assertThat(fillRequest[0].data).isNull();
 
-            Log.i(LOG_TAG, "Switching Fragments");
+            AssistStructure structure = fillRequest[0].contexts.get(0).getStructure();
+            assertThat(fillRequest[0].contexts.size()).isEqualTo(1);
+            assertThat(findNodeByResourceId(structure, "editText1")).isNotNull();
+            assertThat(findNodeByResourceId(structure, "editText2")).isNotNull();
+            assertThat(findNodeByResourceId(structure, "editText3")).isNull();
+            assertThat(findNodeByResourceId(structure, "editText4")).isNull();
+            assertThat(findNodeByResourceId(structure, "editText5")).isNull();
+
+            // Wait until autofill has been applied
+            sUiBot.selectDataset("dataset1");
+            sUiBot.assertShownByText("editText1-autofilled");
+
+            // Manually fill view
+            mActivity.syncRunOnUiThread(() -> mEditText2.setText("editText2-manually-filled"));
 
             // Replacing the fragment focused a previously unknown view which triggers a new
             // partition
+            clientState.putString("key", "value2");
             sReplier.addResponse(new CannedFillResponse.Builder()
-                    .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText3").build());
+                    .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                            .setField("editText3", "editText3-autofilled")
+                            .setField("editText4", "editText4-autofilled")
+                            .setPresentation(createPresentation("dataset2"))
+                            .build())
+                    .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText2", "editText5")
+                    .setExtras(clientState)
+                    .build());
 
+            Log.i(LOG_TAG, "Switching Fragments");
             mActivity.syncRunOnUiThread(
                     () -> mActivity.getFragmentManager().beginTransaction().replace(
                             R.id.rootContainer, new FragmentWithMoreEditTexts(),
                             FRAGMENT_TAG).commitNow());
+            EditText mEditText5 = mActivity.findViewById(R.id.editText5);
 
-            request[0] = sReplier.getNextFillRequest();
+            fillRequest[0] = sReplier.getNextFillRequest();
 
-            assertThat(findNodeByResourceId(request[0].structure, "editText1")).isNull();
-            assertThat(findNodeByResourceId(request[0].structure, "editText2")).isNull();
-            assertThat(findNodeByResourceId(request[0].structure, "editText3")).isNotNull();
-            assertThat(findNodeByResourceId(request[0].structure, "editText4")).isNotNull();
-            assertThat(findNodeByResourceId(request[0].structure, "editText5")).isNotNull();
+            // The fillRequest should have a fillContext for each partition. The first partition
+            // should be filled in
+            assertThat(fillRequest[0].contexts.size()).isEqualTo(2);
+
+            assertThat(fillRequest[0].data.getString("key")).isEqualTo("value1");
+
+            AssistStructure structure1 = fillRequest[0].contexts.get(0).getStructure();
+            ViewNode editText1Node = findNodeByResourceId(structure1, "editText1");
+            // The actual value in the structure is not updated in FillRequest-contexts, but the
+            // autofill value is. For text views in SaveRequest both are updated, but this is the
+            // only exception.
+            assertThat(editText1Node.getAutofillValue()).isEqualTo(
+                    AutofillValue.forText("editText1-autofilled"));
+
+            ViewNode editText2Node = findNodeByResourceId(structure1, "editText2");
+            // Manually filled fields are not send to onFill. They appear in onSave if they are set
+            // as saveable fields.
+            assertThat(editText2Node.getText().toString()).isEqualTo("");
+
+            assertThat(findNodeByResourceId(structure1, "editText3")).isNull();
+            assertThat(findNodeByResourceId(structure1, "editText4")).isNull();
+            assertThat(findNodeByResourceId(structure1, "editText5")).isNull();
+
+            AssistStructure structure2 = fillRequest[0].contexts.get(1).getStructure();
+
+            assertThat(findNodeByResourceId(structure2, "editText1")).isNull();
+            assertThat(findNodeByResourceId(structure2, "editText2")).isNull();
+            assertThat(findNodeByResourceId(structure2, "editText3")).isNotNull();
+            assertThat(findNodeByResourceId(structure2, "editText4")).isNotNull();
+            assertThat(findNodeByResourceId(structure2, "editText5")).isNotNull();
+
+            // Wait until autofill has been applied
+            sUiBot.selectDataset("dataset2");
+            sUiBot.assertShownByText("editText3-autofilled");
+            sUiBot.assertShownByText("editText4-autofilled");
+
+            // Manually fill view
+            mActivity.syncRunOnUiThread(() -> mEditText5.setText("editText5-manually-filled"));
+
+            // Finish activity and save data
+            mActivity.finish();
+            sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_GENERIC);
+
+            // The saveRequest should have a fillContext for each partition with all the data
+            InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();
+            assertThat(saveRequest.contexts.size()).isEqualTo(2);
+
+            assertThat(saveRequest.data.getString("key")).isEqualTo("value2");
+
+            structure1 = saveRequest.contexts.get(0).getStructure();
+            editText1Node = findNodeByResourceId(structure1, "editText1");
+            assertThat(editText1Node.getText().toString()).isEqualTo("editText1-autofilled");
+
+            editText2Node = findNodeByResourceId(structure1, "editText2");
+            assertThat(editText2Node.getText().toString()).isEqualTo("editText2-manually-filled");
+
+            assertThat(findNodeByResourceId(structure1, "editText3")).isNull();
+            assertThat(findNodeByResourceId(structure1, "editText4")).isNull();
+            assertThat(findNodeByResourceId(structure1, "editText5")).isNull();
+
+            structure2 = saveRequest.contexts.get(1).getStructure();
+            assertThat(findNodeByResourceId(structure2, "editText1")).isNull();
+            assertThat(findNodeByResourceId(structure2, "editText2")).isNull();
+
+            ViewNode editText3Node = findNodeByResourceId(structure2, "editText3");
+            assertThat(editText3Node.getText().toString()).isEqualTo("editText3-autofilled");
+
+            ViewNode editText4Node = findNodeByResourceId(structure2, "editText4");
+            assertThat(editText4Node.getText().toString()).isEqualTo("editText4-autofilled");
+
+            ViewNode editText5Node = findNodeByResourceId(structure2, "editText5");
+            assertThat(editText5Node.getText().toString()).isEqualTo("editText5-manually-filled");
         } finally {
             disableService();
         }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index 3b8c12a..fa7780a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -31,6 +31,7 @@
 import android.app.UiAutomation;
 import android.content.res.Resources;
 import android.os.SystemClock;
+import android.service.autofill.SaveInfo;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
@@ -249,6 +250,10 @@
     }
 
     UiObject2 assertSaveShowing(String description, int... types) {
+        return assertSaveShowing(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, description, types);
+    }
+
+    UiObject2 assertSaveShowing(int negativeButtonStyle, String description, int... types) {
         final UiObject2 snackbar = waitForObject(By.res("android", RESOURCE_ID_SAVE_SNACKBAR),
                 SAVE_TIMEOUT_MS);
 
@@ -288,6 +293,12 @@
             assertWithMessage("save subtitle(%s)", description).that(saveSubTitle).isNotNull();
         }
 
+        final String negativeButtonText = (negativeButtonStyle
+                == SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT) ? "NOT NOW" : "NO THANKS";
+        UiObject2 negativeButton = snackbar.findObject(By.text(negativeButtonText));
+        assertWithMessage("negative button (%s)", negativeButtonText)
+                .that(negativeButton).isNotNull();
+
         final String expectedAccessibilityTitle =
                 getString(RESOURCE_STRING_SAVE_SNACKBAR_ACCESSIBILITY_TITLE);
         assertAccessibilityTitle(snackbar, expectedAccessibilityTitle);
@@ -302,7 +313,19 @@
      * @param types expected types of save info.
      */
     void saveForAutofill(boolean yesDoIt, int... types) {
-        final UiObject2 saveSnackBar = assertSaveShowing(null, types);
+        final UiObject2 saveSnackBar = assertSaveShowing(
+                SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL,null, types);
+        saveForAutofill(saveSnackBar, yesDoIt);
+    }
+
+    /**
+     * Taps an option in the save snackbar.
+     *
+     * @param yesDoIt {@code true} for 'YES', {@code false} for 'NO THANKS'.
+     * @param types expected types of save info.
+     */
+    void saveForAutofill(int negativeButtonStyle, boolean yesDoIt, int... types) {
+        final UiObject2 saveSnackBar = assertSaveShowing(negativeButtonStyle,null, types);
         saveForAutofill(saveSnackBar, yesDoIt);
     }
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
index 670832c..2102773 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
@@ -41,7 +41,6 @@
 import android.view.autofill.AutofillValue;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -161,7 +160,8 @@
     @Override
     public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
         if (mOverrideDispatchProvideAutofillStructure) {
-            Log.d(TAG, "Overriding dispatchProvideAutofillStructure");
+            Log.d(TAG, "Overriding dispatchProvideAutofillStructure()");
+            structure.setAutofillId(getAutofillId());
             onProvideAutofillVirtualStructure(structure, flags);
         } else {
             super.dispatchProvideAutofillStructure(structure, flags);
@@ -184,7 +184,7 @@
             final ViewStructure child = mSync
                     ? structure.newChild(index)
                     : structure.asyncNewChild(index);
-            child.setAutofillId(structure, item.id);
+            child.setAutofillId(structure.getAutofillId(), item.id);
             child.setDataIsSensitive(item.sensitive);
             index++;
             final String className = item.editable ? TEXT_CLASS : LABEL_CLASS;
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index e4ca5af..ba902bf 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -296,5 +296,12 @@
     "android.telecom.cts.WiredHeadsetTest"
   ],
   bug: 26149528
+},
+{
+  desciption: "Seems to be failing on X86, flaky on arm. Root cause to be investigated",
+  names: [
+    "android.webkit.cts.WebViewClientTest#testOnRenderProcessGone"
+  ],
+  bug: 37704262
 }
 ]
diff --git a/tests/jdwp/AndroidTest.xml b/tests/jdwp/AndroidTest.xml
index 3cd1be2..9bab5b1 100644
--- a/tests/jdwp/AndroidTest.xml
+++ b/tests/jdwp/AndroidTest.xml
@@ -30,10 +30,11 @@
         <option name="classpath" value="/data/local/tmp/ctsjdwp/CtsJdwpTestCases.jar" />
         <option name="dalvik-arg" value="-Xcompiler-option" />
         <option name="dalvik-arg" value="--debuggable" />
+        <option name="dalvik-arg" value="-Xusejit:true" />
         <option name="dalvik-arg" value="-Djpda.settings.verbose=false" />
         <option name="dalvik-arg" value="-Djpda.settings.timeout=10000" />
         <option name="dalvik-arg" value="-Djpda.settings.waitingTime=10000" />
-        <option name="dalvik-arg" value="-Djpda.settings.debuggeeJavaPath='dalvikvm|#ABI#| -XXlib:libart.so -Xcompiler-option --debuggable'" />
+        <option name="dalvik-arg" value="-Djpda.settings.debuggeeJavaPath='dalvikvm|#ABI#| -XXlib:libart.so -Xcompiler-option --debuggable -Xusejit:true'" />
         <option name="known-failures" value="/expectations/jdwp-known-failures.txt" />
         <option name="runtime-hint" value="16m" />
 
diff --git a/tests/tests/app/AndroidManifest.xml b/tests/tests/app/AndroidManifest.xml
index be903e3..707b22b 100644
--- a/tests/tests/app/AndroidManifest.xml
+++ b/tests/tests/app/AndroidManifest.xml
@@ -23,6 +23,11 @@
 
         <activity android:name=".ApplyOverrideConfigurationActivity"
                   android:configChanges="orientation|screenSize" />
+
+        <activity android:name=".PictureInPictureActivity"
+                  android:resizeableActivity="false"
+                  android:supportsPictureInPicture="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" />
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java b/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java
index d08b29f..da02a81 100644
--- a/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java
@@ -15,12 +15,16 @@
  */
 package android.app.cts;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
-import android.app.ActivityManager;
+import android.app.Activity;
+import android.app.Instrumentation;
 import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -32,9 +36,20 @@
 @RunWith(AndroidJUnit4.class)
 public class PictureInPictureActionsTest {
 
+    private Activity mActivity;
+
+    @Rule
+    public ActivityTestRule<PictureInPictureActivity> mActivityRule =
+            new ActivityTestRule<>(PictureInPictureActivity.class);
+
+    @Before
+    public void setup() {
+        mActivity = mActivityRule.getActivity();
+    }
+
     @Test
     public void testNumPictureInPictureActions() throws Exception {
-        // Currently enforce that there are a max of three actions
-        assertEquals(ActivityManager.getMaxNumPictureInPictureActions(), 3);
+        // Currently enforce that there are at least 3 actions
+        assertTrue(mActivity.getMaxNumPictureInPictureActions() >= 3);
     }
 }
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureActivity.java b/tests/tests/app/src/android/app/cts/PictureInPictureActivity.java
new file mode 100644
index 0000000..75245b7
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.app.cts;
+
+import android.app.Activity;
+
+public class PictureInPictureActivity extends Activity {
+    // Empty
+}
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
new file mode 100644
index 0000000..639c4d1
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.app.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.PictureInPictureParams;
+import android.app.PictureInPictureParams.Builder;
+import android.graphics.Rect;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Rational;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+/**
+ * Tests the {@link PictureInPictureParams} builder.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PictureInPictureParamsBuilderTest {
+
+    @Test
+    public void testBuildParams() throws Exception {
+        // Set the params
+        Builder builder = new Builder()
+                .setAspectRatio(new Rational(1, 2))
+                .setActions(new ArrayList<>())
+                .setSourceRectHint(new Rect(0, 0, 100, 100));
+
+        PictureInPictureParams params = builder.build();
+        assertTrue(Float.compare(0.5f, params.getAspectRatio()) == 0);
+        assertTrue(params.getActions().isEmpty());
+        assertEquals(new Rect(0, 0, 100, 100), params.getSourceRectHint());
+
+        // Reset the params
+        builder.setAspectRatio(null)
+                .setActions(null)
+                .setSourceRectHint(null);
+        params = builder.build();
+
+        assertTrue(Float.compare(0f, params.getAspectRatio()) == 0);
+        assertNull(params.getActions());
+        assertNull(params.getSourceRectHint());
+    }
+}
diff --git a/tests/tests/content/res/values/attrs.xml b/tests/tests/content/res/values/attrs.xml
index 12b731b..236ee6c 100644
--- a/tests/tests/content/res/values/attrs.xml
+++ b/tests/tests/content/res/values/attrs.xml
@@ -49,6 +49,7 @@
     <attr name="type15" format="reference"/>
     <attr name="type16" format="string"/>
     <attr name="type17" format="reference|color"/>
+    <attr name="type18" format="reference|string"/>
     <attr name="typeEmpty" format="reference"/>
     <attr name="typeUndefined" format="reference"/>
     <declare-styleable name="style1">
@@ -69,6 +70,7 @@
         <attr name="type15"/>
         <attr name="type16"/>
         <attr name="type17"/>
+        <attr name="type18"/>
         <attr name="typeEmpty"/>
         <attr name="typeUndefined"/>
     </declare-styleable>
diff --git a/tests/tests/content/res/values/styles.xml b/tests/tests/content/res/values/styles.xml
index d1c30d7..b4db3ac 100644
--- a/tests/tests/content/res/values/styles.xml
+++ b/tests/tests/content/res/values/styles.xml
@@ -34,6 +34,7 @@
         <item name="type15">@array/difficultyLevel</item>
         <item name="type16">Typed Value!</item>
         <item name="type17">@color/testcolor_orientation</item>
+        <item name="type18">@font/samplefont</item>
         <item name="typeEmpty">@empty</item>
         <item name="typeUndefined">@null</item>
     </style>
@@ -181,4 +182,8 @@
     <style name="Theme_OrientationDependent">
         <item name="themeDimension">999px</item>
     </style>
+
+    <style name="Theme_InlineString">
+        <item name="testString">"This is a string"</item>
+    </style>
 </resources>
diff --git a/tests/tests/content/src/android/content/cts/ContentResolverTest.java b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
index e5e8fe4..d1c03d2 100644
--- a/tests/tests/content/src/android/content/cts/ContentResolverTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
@@ -427,7 +427,7 @@
         Bundle queryArgs = new Bundle();
         queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 10);
         queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 3);
-        queryArgs.putInt(TestPagingContentProvider.RECORDSET_SIZE, 100);
+        queryArgs.putInt(TestPagingContentProvider.RECORD_COUNT, 100);
 
         mCursor = mContentResolver.query(
                 TestPagingContentProvider.PAGED_DATA_URI, null, queryArgs, null);
@@ -436,8 +436,8 @@
         extras = extras != null ? extras : Bundle.EMPTY;
 
         assertEquals(3, mCursor.getCount());
-        assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
-        assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_SIZE));
+        assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_COUNT));
+        assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_COUNT));
 
         String[] honoredArgs = extras.getStringArray(ContentResolver.EXTRA_HONORED_ARGS);
         assertNotNull(honoredArgs);
diff --git a/tests/tests/content/src/android/content/cts/TestPagingContentProvider.java b/tests/tests/content/src/android/content/cts/TestPagingContentProvider.java
index 42e0019..6e38809 100644
--- a/tests/tests/content/src/android/content/cts/TestPagingContentProvider.java
+++ b/tests/tests/content/src/android/content/cts/TestPagingContentProvider.java
@@ -42,7 +42,7 @@
     static final Uri UNPAGED_DATA_URI = Uri.parse("content://" + AUTHORITY + "/un-paged/");
 
     /** Required queryArgument specifying corpus size. */
-    static final String RECORDSET_SIZE = "test-recordset-size";
+    static final String RECORD_COUNT = "test-record-count";
     static final String COLUMN_POS = "ColumnPos";
     static final String COLUMN_A = "ColumnA";
     static final String COLUMN_B = "ColumnB";
@@ -69,26 +69,28 @@
 
         queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY;
 
-        int recordsetSize = queryArgs.getInt(RECORDSET_SIZE, Integer.MIN_VALUE);
-        if (recordsetSize == Integer.MIN_VALUE) {
+        int recordCount = queryArgs.getInt(RECORD_COUNT, Integer.MIN_VALUE);
+        if (recordCount == Integer.MIN_VALUE) {
             throw new RuntimeException("Recordset size must be specified.");
         }
 
-        if (recordsetSize < 0) {
+        if (recordCount < 0) {
             throw new RuntimeException("Recordset size must be >= 0");
         }
 
         Cursor cursor = null;
         if (PAGED_DATA_URI.equals(uri)) {
-            cursor = buildPagedResults(queryArgs, recordsetSize);
+            cursor = buildPagedResults(queryArgs, recordCount);
         } else if (UNPAGED_DATA_URI.equals(uri)) {
-            cursor = buildUnpagedResults(recordsetSize);
+            cursor = buildUnpagedResults(recordCount);
         }
 
         if (cursor == null) {
             throw new IllegalArgumentException("Unsupported URI: " + uri);
         }
 
+        cursor.setNotificationUri(getContext().getContentResolver(), uri);
+
         Log.v(TAG, "Final cursor contains " + cursor.getCount() + " rows.");
         return cursor;
     }
@@ -118,7 +120,7 @@
             ContentResolver.QUERY_ARG_OFFSET,
             ContentResolver.QUERY_ARG_LIMIT
         });
-        extras.putInt(ContentResolver.EXTRA_TOTAL_SIZE, recordsetSize);
+        extras.putInt(ContentResolver.EXTRA_TOTAL_COUNT, recordsetSize);
         return c;
     }
 
diff --git a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
index b7a621f..24c61ae 100644
--- a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
+++ b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
@@ -83,6 +83,16 @@
     }
 
     @SmallTest
+    public void testObtainStyledAttributesWithInlineStringInTheme() {
+        mResTheme.applyStyle(R.style.Theme_InlineString, false);
+        final TypedArray ta = mResTheme.obtainStyledAttributes(new int[] { R.attr.testString });
+        assertNotNull(ta);
+        assertEquals(1, ta.length());
+        assertEquals(TypedValue.TYPE_STRING, ta.getType(0));
+        assertEquals("This is a string", ta.getString(0));
+    }
+
+    @SmallTest
     public void testResolveAttribute() {
         final TypedValue value = new TypedValue();
         getContext().getResources().getValue(R.raw.testmp3, value, true);
diff --git a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
index b31b446..5739554 100644
--- a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
@@ -25,6 +25,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.graphics.Typeface;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.TypedValue;
@@ -48,9 +49,9 @@
     private static final String EXPECTED_TEXT = "TypedArray Test!";
     private static final String[] EXPECTED_TEXT_ARRAY = {"Easy", "Medium", "Hard"};
     private static final TypedValue DEF_VALUE = new TypedValue();
-    private static final int EXPECTED_INDEX_COUNT = 17;
+    private static final int EXPECTED_INDEX_COUNT = 18;
     private static final String EXPTECTED_POS_DESCRIP = "<internal>";
-    private static final int EXPECTED_LENGTH = 19;
+    private static final int EXPECTED_LENGTH = 20;
     private static final String EXPECTED_NON_RESOURCE_STRING = "testNonResourcesString";
     private static final String XML_BEGIN = "resources";
     private static final int EXPECTED_INT_ATT = 86400;
@@ -62,7 +63,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mTypedArray = getContext().getTheme().obtainStyledAttributes(R.style.Whatever, R.styleable.style1);
+        mTypedArray = getContext().getTheme()
+                .obtainStyledAttributes(R.style.Whatever, R.styleable.style1);
     }
 
     @Override
@@ -167,6 +169,9 @@
             actual_indices[idx] = attr_index;
         }
 
+        final Typeface font = t.getFont(R.styleable.style1_type18);
+        assertEquals(mContext.getResources().getFont(R.font.samplefont), font);
+
         // NOTE: order does not matter here.
         // R.styleable.style1_typeEmpty and R.styleable.style1_typeUndefined are not
         // expected because TYPE_NULL values do not get included in the index list.
@@ -187,7 +192,8 @@
                 R.styleable.style1_type14,
                 R.styleable.style1_type15,
                 R.styleable.style1_type16,
-                R.styleable.style1_type17);
+                R.styleable.style1_type17,
+                R.styleable.style1_type18);
     }
 
     public void testPeekValue() {
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
index a296659..e255f8e 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
@@ -122,6 +122,18 @@
         assertSame(sRGB, cs);
     }
 
+    @Test
+    public void createDefaultColorSpace() {
+        ColorSpace sRGB = ColorSpace.get(ColorSpace.Named.SRGB);
+        Bitmap.Config[] configs = new Bitmap.Config[] {
+                Bitmap.Config.ALPHA_8, Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888
+        };
+        for (Bitmap.Config config : configs) {
+            Bitmap bitmap = Bitmap.createBitmap(32, 32, config, true);
+            assertSame(sRGB, bitmap.getColorSpace());
+        }
+    }
+
     @Test(expected = IllegalArgumentException.class)
     public void createWithoutColorSpace() {
         Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888, true, null);
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
index 4156ed5..0d43322 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
@@ -129,7 +129,7 @@
     @Test
     public void testCopyConfigs() {
         Config[] supportedConfigs = new Config[] {
-                Config.ALPHA_8, Config.RGB_565, Config.ARGB_8888
+                Config.ALPHA_8, Config.RGB_565, Config.ARGB_8888, Config.RGBA_F16,
         };
         for (Config src : supportedConfigs) {
             for (Config dst : supportedConfigs) {
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
index 61d46b2..358e401 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
@@ -15,7 +15,9 @@
  */
 package android.graphics.cts;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
 
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
@@ -97,5 +99,26 @@
         canvas.drawPoint(0, 0, paint);
         ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(0, 0));
     }
+
+    @Test
+    public void testGetColorMatrix() {
+        ColorMatrixColorFilter filter = new ColorMatrixColorFilter(new ColorMatrix());
+        ColorMatrix getMatrix = new ColorMatrix();
+
+        filter.getColorMatrix(getMatrix);
+        assertEquals(new ColorMatrix(), getMatrix);
+
+        ColorMatrix scaleTranslate = new ColorMatrix(new float[] {
+                1, 0, 0, 0, 8,
+                0, 2, 0, 0, 7,
+                0, 0, 3, 0, 6,
+                0, 0, 0, 4, 5
+        });
+
+        filter = new ColorMatrixColorFilter(scaleTranslate);
+        filter.getColorMatrix(getMatrix);
+        assertEquals(scaleTranslate, getMatrix);
+        assertArrayEquals(scaleTranslate.getArray(), getMatrix.getArray(), 0);
+    }
 }
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
index 3f82150..fdbf92e 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
@@ -435,12 +435,14 @@
 
         assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getSource());
         assertSame(ColorSpace.get(ColorSpace.Named.DCI_P3), connector.getDestination());
+        assertSame(ColorSpace.RenderIntent.PERCEPTUAL, connector.getRenderIntent());
 
         connector = ColorSpace.connect(
                 ColorSpace.get(ColorSpace.Named.SRGB),
                 ColorSpace.get(ColorSpace.Named.SRGB));
 
         assertSame(connector.getDestination(), connector.getSource());
+        assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent());
 
         connector = ColorSpace.connect(ColorSpace.get(ColorSpace.Named.DCI_P3));
         assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getDestination());
@@ -543,6 +545,7 @@
                 ColorSpace.get(ColorSpace.Named.SRGB));
 
         assertSame(connector.getSource(), connector.getDestination());
+        assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent());
 
         float[] source = new float[] { 0.11112f, 0.22227f, 0.444448f };
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
index da2b934..c7befa8 100644
--- a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
@@ -35,6 +35,10 @@
 public class LightingColorFilterTest {
     private static final int TOLERANCE = 2;
 
+    private void verifyColor(int expected, int actual) {
+        ColorUtils.verifyColor(expected, actual, TOLERANCE);
+    }
+
     @Test
     public void testLightingColorFilter() {
         Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
@@ -86,7 +90,22 @@
         verifyColor(Color.argb(0x80, 30, 30, 30), bitmap.getPixel(0, 0));
     }
 
-    private void verifyColor(int expected, int actual) {
-        ColorUtils.verifyColor(expected, actual, TOLERANCE);
+    @Test
+    public void testGetColorAdd() {
+        LightingColorFilter filter = new LightingColorFilter(Color.WHITE, Color.BLACK);
+        ColorUtils.verifyColor(Color.BLACK, filter.getColorAdd());
+
+        filter = new LightingColorFilter(0x87654321, 0x12345678);
+        ColorUtils.verifyColor(0x12345678, filter.getColorAdd());
+    }
+
+
+    @Test
+    public void testGetColorMultiply() {
+        LightingColorFilter filter = new LightingColorFilter(Color.WHITE, Color.BLACK);
+        ColorUtils.verifyColor(Color.WHITE, filter.getColorMultiply());
+
+        filter = new LightingColorFilter(0x87654321, 0x12345678);
+        ColorUtils.verifyColor(0x87654321, filter.getColorMultiply());
     }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/PathTest.java b/tests/tests/graphics/src/android/graphics/cts/PathTest.java
index db3884c..ade4a97 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PathTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PathTest.java
@@ -16,6 +16,11 @@
 
 package android.graphics.cts;
 
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -25,11 +30,10 @@
 import android.graphics.RectF;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static org.junit.Assert.*;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class PathTest {
@@ -440,6 +444,41 @@
         assertEquals(expectedRect, offsettedRect);
     }
 
+    @Test
+    public void testApproximate_rect_cw() {
+        Path path = new Path();
+        path.addRect(0, 0, 100, 100, Path.Direction.CW);
+        assertArrayEquals(new float[] {
+                0, 0, 0,
+                0.25f, 100, 0,
+                0.50f, 100, 100,
+                0.75f, 0, 100,
+                1, 0, 0,
+        }, path.approximate(1f), 0);
+    }
+
+    @Test
+    public void testApproximate_rect_ccw() {
+        Path path = new Path();
+        path.addRect(0, 0, 100, 100, Path.Direction.CCW);
+        assertArrayEquals(new float[] {
+                0, 0, 0,
+                0.25f, 0, 100,
+                0.50f, 100, 100,
+                0.75f, 100, 0,
+                1, 0, 0,
+        }, path.approximate(1f), 0);
+    }
+
+    @Test
+    public void testApproximate_empty() {
+        Path path = new Path();
+        assertArrayEquals(new float[] {
+                0, 0, 0,
+                1, 0, 0,
+        }, path.approximate(0.5f), 0);
+    }
+
     private static void verifyPathsAreEquivalent(Path actual, Path expected) {
         Bitmap actualBitmap = drawAndGetBitmap(actual);
         Bitmap expectedBitmap = drawAndGetBitmap(expected);
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index ba657bf..4c6eb27 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -78,6 +78,11 @@
                 && (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
                         || packageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION));
     }
+    @Override
+    protected void tearDown() throws Exception {
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), false);
+    }
 
     public void testMicrophoneMute() throws Exception {
         mAudioManager.setMicrophoneMute(true);
@@ -94,7 +99,7 @@
             mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
         } finally {
             Utils.toggleNotificationPolicyAccess(
-                mContext.getPackageName(), getInstrumentation(), false);
+                    mContext.getPackageName(), getInstrumentation(), false);
         }
         Settings.System.putInt(mContext.getContentResolver(), SOUND_EFFECTS_ENABLED, 1);
 
@@ -193,165 +198,150 @@
         if (mUseFixedVolume || !mHasVibrator) {
             return;
         }
-        try {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), true);
-            // VIBRATE_SETTING_ON
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
-            assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
-                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        // VIBRATE_SETTING_ON
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
+        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                    mAudioManager.getRingerMode());
-            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                mAudioManager.getRingerMode());
+        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-            // VIBRATE_SETTING_OFF
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
-            assertEquals(VIBRATE_SETTING_OFF,
-                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        // VIBRATE_SETTING_OFF
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
+        assertEquals(VIBRATE_SETTING_OFF,
+                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                    mAudioManager.getRingerMode());
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                mAudioManager.getRingerMode());
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-            // VIBRATE_SETTING_ONLY_SILENT
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
-            assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
-                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        // VIBRATE_SETTING_ONLY_SILENT
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
+        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                    mAudioManager.getRingerMode());
-            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                mAudioManager.getRingerMode());
+        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
 
-            // VIBRATE_TYPE_NOTIFICATION
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
-            assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
-                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
-            assertEquals(VIBRATE_SETTING_OFF, mAudioManager
-                    .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
-            assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
-                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
-        } finally {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
-        }
+        // VIBRATE_TYPE_NOTIFICATION
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
+        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
+        assertEquals(VIBRATE_SETTING_OFF, mAudioManager
+                .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
+        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+                mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
     }
 
     public void testVibrateRinger() throws Exception {
         if (mUseFixedVolume || !mHasVibrator) {
             return;
         }
-        try {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), true);
-            // VIBRATE_TYPE_RINGER
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
-            assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
-                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        // VIBRATE_TYPE_RINGER
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
+        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                    mAudioManager.getRingerMode());
-            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                mAudioManager.getRingerMode());
+        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-            // VIBRATE_SETTING_OFF
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
-            assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        // VIBRATE_SETTING_OFF
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
+        assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                    mAudioManager.getRingerMode());
-            // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will
-            // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to
-            // disable the vibration for incoming calls only.
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                mAudioManager.getRingerMode());
+        // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will
+        // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to
+        // disable the vibration for incoming calls only.
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-            // VIBRATE_SETTING_ONLY_SILENT
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
-            assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
-                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        // VIBRATE_SETTING_ONLY_SILENT
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
+        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-            assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+        assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                    mAudioManager.getRingerMode());
-            assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+        assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                mAudioManager.getRingerMode());
+        assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
 
-            // VIBRATE_TYPE_NOTIFICATION
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
-            assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
-                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
-            assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-            mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
-            assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
-                    mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
-        } finally {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
-        }
+        // VIBRATE_TYPE_NOTIFICATION
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
+        assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
+        assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+        mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
+        assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+                mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
     }
 
     public void testAccessRingMode() throws Exception {
-        try {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), true);
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+
+        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+        // AudioService#setRingerMode() has:
+        // if (isTelevision) return;
+        if (mUseFixedVolume || mIsTelevision) {
             assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+        } else {
+            assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+        }
 
-            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-            // AudioService#setRingerMode() has:
-            // if (isTelevision) return;
-            if (mUseFixedVolume || mIsTelevision) {
-                assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-            } else {
-                assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
-            }
-
-            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-            if (mUseFixedVolume || mIsTelevision) {
-                assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-            } else {
-                assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
-                        mAudioManager.getRingerMode());
-            }
-        } finally {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
+        mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+        if (mUseFixedVolume || mIsTelevision) {
+            assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+        } else {
+            assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+                    mAudioManager.getRingerMode());
         }
     }
 
@@ -359,32 +349,47 @@
         if (mUseFixedVolume || mIsTelevision) {
             return;
         }
+        // Apps without policy access cannot change silent -> normal or silent -> vibrate.
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+        assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), false);
+
         try {
-            // Apps without policy access cannot change silent -> normal or silent -> vibrate.
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), true);
-            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-            assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
-
-            try {
-                mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-                fail("Apps without notification policy access cannot change ringer mode");
-            } catch (SecurityException e) {
-            }
-
-            try {
-                mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-                fail("Apps without notification policy access cannot change ringer mode");
-            } catch (SecurityException e) {
-            }
-
-            // Apps without policy access cannot change normal -> silent.
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), true);
             mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-            assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+            fail("Apps without notification policy access cannot change ringer mode");
+        } catch (SecurityException e) {
+        }
+
+        try {
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            fail("Apps without notification policy access cannot change ringer mode");
+        } catch (SecurityException e) {
+        }
+
+        // Apps without policy access cannot change normal -> silent.
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), false);
+
+        try {
+            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+            fail("Apps without notification policy access cannot change ringer mode");
+        } catch (SecurityException e) {
+        }
+        assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+
+        if (mHasVibrator) {
+            // Apps without policy access cannot change vibrate -> silent.
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
             Utils.toggleNotificationPolicyAccess(
                     mContext.getPackageName(), getInstrumentation(), false);
 
@@ -393,33 +398,13 @@
                 fail("Apps without notification policy access cannot change ringer mode");
             } catch (SecurityException e) {
             }
+
+            // Apps without policy access can change vibrate -> normal and vice versa.
+            assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
             assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-
-            if (mHasVibrator) {
-                // Apps without policy access cannot change vibrate -> silent.
-                Utils.toggleNotificationPolicyAccess(
-                        mContext.getPackageName(), getInstrumentation(), true);
-                mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-                assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
-                Utils.toggleNotificationPolicyAccess(
-                        mContext.getPackageName(), getInstrumentation(), false);
-
-                try {
-                    mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-                    fail("Apps without notification policy access cannot change ringer mode");
-                } catch (SecurityException e) {
-                }
-
-                // Apps without policy access can change vibrate -> normal and vice versa.
-                assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
-                mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-                assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-                mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
-                assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
-            }
-        } finally {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
+            mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+            assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
         }
     }
 
@@ -464,150 +449,145 @@
     }
 
     public void testVolume() throws Exception {
-        try {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), true);
-            int volume, volumeDelta;
-            int[] streams = {AudioManager.STREAM_ALARM,
-                    AudioManager.STREAM_MUSIC,
-                    AudioManager.STREAM_VOICE_CALL,
-                    AudioManager.STREAM_RING};
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        int volume, volumeDelta;
+        int[] streams = {AudioManager.STREAM_ALARM,
+                AudioManager.STREAM_MUSIC,
+                AudioManager.STREAM_VOICE_CALL,
+                AudioManager.STREAM_RING};
 
-            mAudioManager.adjustVolume(ADJUST_RAISE, 0);
-            // adjusting volume is aynchronous, wait before other volume checks
-            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
-            mAudioManager.adjustSuggestedStreamVolume(
-                    ADJUST_LOWER, USE_DEFAULT_STREAM_TYPE, 0);
-            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
-            int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);
+        mAudioManager.adjustVolume(ADJUST_RAISE, 0);
+        // adjusting volume is aynchronous, wait before other volume checks
+        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+        mAudioManager.adjustSuggestedStreamVolume(
+                ADJUST_LOWER, USE_DEFAULT_STREAM_TYPE, 0);
+        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+        int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);
 
-            for (int stream : streams) {
-                // set ringer mode to back normal to not interfere with volume tests
-                mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        for (int stream : streams) {
+            // set ringer mode to back normal to not interfere with volume tests
+            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
 
-                int maxVolume = mAudioManager.getStreamMaxVolume(stream);
-                int minVolume = mAudioManager.getStreamMinVolume(stream);
+            int maxVolume = mAudioManager.getStreamMaxVolume(stream);
+            int minVolume = mAudioManager.getStreamMinVolume(stream);
 
-                // validate min
-                assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0);
-                assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume,
-                        maxVolume),
-                        minVolume < maxVolume);
+            // validate min
+            assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0);
+            assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume,
+                    maxVolume),
+                    minVolume < maxVolume);
 
-                mAudioManager.setStreamVolume(stream, 1, 0);
-                if (mUseFixedVolume) {
-                    assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
-                    continue;
-                }
-                assertEquals(String.format("stream=%d", stream),
-                             1, mAudioManager.getStreamVolume(stream));
-
-                if (stream == AudioManager.STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) {
-                    // due to new regulations, music sent over a wired headset may be volume limited
-                    // until the user explicitly increases the limit, so we can't rely on being able
-                    // to set the volume to getStreamMaxVolume(). Instead, determine the current limit
-                    // by increasing the volume until it won't go any higher, then use that volume as
-                    // the maximum for the purposes of this test
-                    int curvol = 0;
-                    int prevvol = 0;
-                    do {
-                        prevvol = curvol;
-                        mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
-                        curvol = mAudioManager.getStreamVolume(stream);
-                    } while (curvol != prevvol);
-                    maxVolume = maxMusicVolume = curvol;
-                }
-                mAudioManager.setStreamVolume(stream, maxVolume, 0);
-                mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
-                assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
-
-                volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
-                mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, stream, 0);
-                Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
-                assertEquals(maxVolume - volumeDelta, mAudioManager.getStreamVolume(stream));
-
-                // volume lower
-                mAudioManager.setStreamVolume(stream, maxVolume, 0);
-                volume = mAudioManager.getStreamVolume(stream);
-                while (volume > minVolume) {
-                    volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
-                    mAudioManager.adjustStreamVolume(stream, ADJUST_LOWER, 0);
-                    assertEquals(Math.max(0, volume - volumeDelta),
-                            mAudioManager.getStreamVolume(stream));
-                    volume = mAudioManager.getStreamVolume(stream);
-                }
-
-                mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
-
-                // volume raise
-                mAudioManager.setStreamVolume(stream, 1, 0);
-                volume = mAudioManager.getStreamVolume(stream);
-                while (volume < maxVolume) {
-                    volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
-                    mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
-                    assertEquals(Math.min(volume + volumeDelta, maxVolume),
-                            mAudioManager.getStreamVolume(stream));
-                    volume = mAudioManager.getStreamVolume(stream);
-                }
-
-                // volume same
-                mAudioManager.setStreamVolume(stream, maxVolume, 0);
-                for (int k = 0; k < maxVolume; k++) {
-                    mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
-                    assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
-                }
-
-                mAudioManager.setStreamVolume(stream, maxVolume, 0);
-            }
-
+            mAudioManager.setStreamVolume(stream, 1, 0);
             if (mUseFixedVolume) {
-                return;
+                assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
+                continue;
+            }
+            assertEquals(String.format("stream=%d", stream),
+                    1, mAudioManager.getStreamVolume(stream));
+
+            if (stream == AudioManager.STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) {
+                // due to new regulations, music sent over a wired headset may be volume limited
+                // until the user explicitly increases the limit, so we can't rely on being able
+                // to set the volume to getStreamMaxVolume(). Instead, determine the current limit
+                // by increasing the volume until it won't go any higher, then use that volume as
+                // the maximum for the purposes of this test
+                int curvol = 0;
+                int prevvol = 0;
+                do {
+                    prevvol = curvol;
+                    mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
+                    curvol = mAudioManager.getStreamVolume(stream);
+                } while (curvol != prevvol);
+                maxVolume = maxMusicVolume = curvol;
+            }
+            mAudioManager.setStreamVolume(stream, maxVolume, 0);
+            mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
+            assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
+
+            volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
+            mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, stream, 0);
+            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+            assertEquals(maxVolume - volumeDelta, mAudioManager.getStreamVolume(stream));
+
+            // volume lower
+            mAudioManager.setStreamVolume(stream, maxVolume, 0);
+            volume = mAudioManager.getStreamVolume(stream);
+            while (volume > minVolume) {
+                volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
+                mAudioManager.adjustStreamVolume(stream, ADJUST_LOWER, 0);
+                assertEquals(Math.max(0, volume - volumeDelta),
+                        mAudioManager.getStreamVolume(stream));
+                volume = mAudioManager.getStreamVolume(stream);
             }
 
-            // adjust volume
-            mAudioManager.adjustVolume(ADJUST_RAISE, 0);
-            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+            mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
 
-            MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
-            assertNotNull(mp);
-            mp.setAudioStreamType(STREAM_MUSIC);
-            mp.setLooping(true);
-            mp.start();
-            Thread.sleep(TIME_TO_PLAY);
-            assertTrue(mAudioManager.isMusicActive());
-
-            // adjust volume as ADJUST_SAME
-            for (int k = 0; k < maxMusicVolume; k++) {
-                mAudioManager.adjustVolume(ADJUST_SAME, 0);
-                Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
-                assertEquals(maxMusicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
+            // volume raise
+            mAudioManager.setStreamVolume(stream, 1, 0);
+            volume = mAudioManager.getStreamVolume(stream);
+            while (volume < maxVolume) {
+                volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
+                mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
+                assertEquals(Math.min(volume + volumeDelta, maxVolume),
+                        mAudioManager.getStreamVolume(stream));
+                volume = mAudioManager.getStreamVolume(stream);
             }
 
-            // adjust volume as ADJUST_RAISE
-            mAudioManager.setStreamVolume(STREAM_MUSIC, 0, 0);
-            volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
-            mAudioManager.adjustVolume(ADJUST_RAISE, 0);
-            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
-            assertEquals(Math.min(volumeDelta, maxMusicVolume),
-                    mAudioManager.getStreamVolume(STREAM_MUSIC));
+            // volume same
+            mAudioManager.setStreamVolume(stream, maxVolume, 0);
+            for (int k = 0; k < maxVolume; k++) {
+                mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
+                assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
+            }
 
-            // adjust volume as ADJUST_LOWER
-            mAudioManager.setStreamVolume(STREAM_MUSIC, maxMusicVolume, 0);
-            maxMusicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
-            volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
-            mAudioManager.adjustVolume(ADJUST_LOWER, 0);
-            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
-            assertEquals(Math.max(0, maxMusicVolume - volumeDelta),
-                    mAudioManager.getStreamVolume(STREAM_MUSIC));
-
-            mp.stop();
-            mp.release();
-            Thread.sleep(TIME_TO_PLAY);
-            assertFalse(mAudioManager.isMusicActive());
-        } finally {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
+            mAudioManager.setStreamVolume(stream, maxVolume, 0);
         }
+
+        if (mUseFixedVolume) {
+            return;
+        }
+
+        // adjust volume
+        mAudioManager.adjustVolume(ADJUST_RAISE, 0);
+        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+
+        MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
+        assertNotNull(mp);
+        mp.setAudioStreamType(STREAM_MUSIC);
+        mp.setLooping(true);
+        mp.start();
+        Thread.sleep(TIME_TO_PLAY);
+        assertTrue(mAudioManager.isMusicActive());
+
+        // adjust volume as ADJUST_SAME
+        for (int k = 0; k < maxMusicVolume; k++) {
+            mAudioManager.adjustVolume(ADJUST_SAME, 0);
+            Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+            assertEquals(maxMusicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
+        }
+
+        // adjust volume as ADJUST_RAISE
+        mAudioManager.setStreamVolume(STREAM_MUSIC, 0, 0);
+        volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
+        mAudioManager.adjustVolume(ADJUST_RAISE, 0);
+        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+        assertEquals(Math.min(volumeDelta, maxMusicVolume),
+                mAudioManager.getStreamVolume(STREAM_MUSIC));
+
+        // adjust volume as ADJUST_LOWER
+        mAudioManager.setStreamVolume(STREAM_MUSIC, maxMusicVolume, 0);
+        maxMusicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
+        volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
+        mAudioManager.adjustVolume(ADJUST_LOWER, 0);
+        Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+        assertEquals(Math.max(0, maxMusicVolume - volumeDelta),
+                mAudioManager.getStreamVolume(STREAM_MUSIC));
+
+        mp.stop();
+        mp.release();
+        Thread.sleep(TIME_TO_PLAY);
+        assertFalse(mAudioManager.isMusicActive());
     }
 
     public void testAccessibilityVolume() throws Exception {
@@ -681,77 +661,72 @@
             return;
         }
         int[] streams = { AudioManager.STREAM_RING };
-        try {
-            // Mute streams
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), true);
-            mAudioManager.setRingerMode(RINGER_MODE_SILENT);
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
-            // Verify streams cannot be unmuted without policy access.
-            for (int stream : streams) {
-                try {
-                    mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0);
-                    assertEquals("Apps without Notification policy access can't change ringer mode",
-                            RINGER_MODE_SILENT, mAudioManager.getRingerMode());
-                } catch (SecurityException e) {
-                }
-
-                try {
-                    mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
-                            0);
-                    assertEquals("Apps without Notification policy access can't change ringer mode",
-                            RINGER_MODE_SILENT, mAudioManager.getRingerMode());
-                } catch (SecurityException e) {
-                }
-
-                try {
-                    mAudioManager.setStreamMute(stream, false);
-                    assertEquals("Apps without Notification policy access can't change ringer mode",
-                            RINGER_MODE_SILENT, mAudioManager.getRingerMode());
-                } catch (SecurityException e) {
-                }
+        // Mute streams
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), false);
+        // Verify streams cannot be unmuted without policy access.
+        for (int stream : streams) {
+            try {
+                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0);
+                assertEquals("Apps without Notification policy access can't change ringer mode",
+                        RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+            } catch (SecurityException e) {
             }
 
-            // This ensures we're out of vibrate or silent modes.
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), true);
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-            for (int stream : streams) {
-                // ensure each stream is on and turned up.
-                mAudioManager.setStreamVolume(stream,
-                        mAudioManager.getStreamMaxVolume(stream),
+            try {
+                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
                         0);
-
-                Utils.toggleNotificationPolicyAccess(
-                        mContext.getPackageName(), getInstrumentation(), false);
-                try {
-                    mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
-                    assertEquals("Apps without Notification policy access can't change ringer mode",
-                            RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-                } catch (SecurityException e) {
-                }
-                try {
-                    mAudioManager.adjustStreamVolume(
-                            stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
-                    assertEquals("Apps without Notification policy access can't change ringer mode",
-                            RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-                } catch (SecurityException e) {
-                }
-
-                try {
-                    mAudioManager.setStreamMute(stream, true);
-                    assertEquals("Apps without Notification policy access can't change ringer mode",
-                            RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-                } catch (SecurityException e) {
-                }
-                Utils.toggleNotificationPolicyAccess(
-                        mContext.getPackageName(), getInstrumentation(), true);
-                testStreamMuting(stream);
+                assertEquals("Apps without Notification policy access can't change ringer mode",
+                        RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+            } catch (SecurityException e) {
             }
-        } finally {
+
+            try {
+                mAudioManager.setStreamMute(stream, false);
+                assertEquals("Apps without Notification policy access can't change ringer mode",
+                        RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+            } catch (SecurityException e) {
+            }
+        }
+
+        // This ensures we're out of vibrate or silent modes.
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        for (int stream : streams) {
+            // ensure each stream is on and turned up.
+            mAudioManager.setStreamVolume(stream,
+                    mAudioManager.getStreamMaxVolume(stream),
+                    0);
+
             Utils.toggleNotificationPolicyAccess(
                     mContext.getPackageName(), getInstrumentation(), false);
+            try {
+                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
+                assertEquals("Apps without Notification policy access can't change ringer mode",
+                        RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+            } catch (SecurityException e) {
+            }
+            try {
+                mAudioManager.adjustStreamVolume(
+                        stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
+                assertEquals("Apps without Notification policy access can't change ringer mode",
+                        RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+            } catch (SecurityException e) {
+            }
+
+            try {
+                mAudioManager.setStreamMute(stream, true);
+                assertEquals("Apps without Notification policy access can't change ringer mode",
+                        RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+            } catch (SecurityException e) {
+            }
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            testStreamMuting(stream);
         }
     }
 
@@ -765,44 +740,39 @@
                 AudioManager.STREAM_ALARM
         };
 
-        try {
-            int muteAffectedStreams = System.getInt(mContext.getContentResolver(),
-                    System.MUTE_STREAMS_AFFECTED,
-                    // Same defaults as in AudioService. Should be kept in
-                    // sync.
-                    ((1 << AudioManager.STREAM_MUSIC) |
-                            (1 << AudioManager.STREAM_RING) |
-                            (1 << AudioManager.STREAM_NOTIFICATION) |
-                            (1 << AudioManager.STREAM_SYSTEM)));
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), true);
-            // This ensures we're out of vibrate or silent modes.
-            mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
-            for (int stream : streams) {
-                // ensure each stream is on and turned up.
-                mAudioManager.setStreamVolume(stream,
-                        mAudioManager.getStreamMaxVolume(stream),
+        int muteAffectedStreams = System.getInt(mContext.getContentResolver(),
+                System.MUTE_STREAMS_AFFECTED,
+                // Same defaults as in AudioService. Should be kept in
+                // sync.
+                ((1 << AudioManager.STREAM_MUSIC) |
+                        (1 << AudioManager.STREAM_RING) |
+                        (1 << AudioManager.STREAM_NOTIFICATION) |
+                        (1 << AudioManager.STREAM_SYSTEM)));
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), true);
+        // This ensures we're out of vibrate or silent modes.
+        mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+        Utils.toggleNotificationPolicyAccess(
+                mContext.getPackageName(), getInstrumentation(), false);
+        for (int stream : streams) {
+            // ensure each stream is on and turned up.
+            mAudioManager.setStreamVolume(stream,
+                    mAudioManager.getStreamMaxVolume(stream),
+                    0);
+            if (((1 << stream) & muteAffectedStreams) == 0) {
+                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
+                assertFalse("Stream " + stream + " should not be affected by mute.",
+                        mAudioManager.isStreamMute(stream));
+                mAudioManager.setStreamMute(stream, true);
+                assertFalse("Stream " + stream + " should not be affected by mute.",
+                        mAudioManager.isStreamMute(stream));
+                mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
                         0);
-                if (((1 << stream) & muteAffectedStreams) == 0) {
-                    mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
-                    assertFalse("Stream " + stream + " should not be affected by mute.",
-                            mAudioManager.isStreamMute(stream));
-                    mAudioManager.setStreamMute(stream, true);
-                    assertFalse("Stream " + stream + " should not be affected by mute.",
-                            mAudioManager.isStreamMute(stream));
-                    mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
-                            0);
-                    assertFalse("Stream " + stream + " should not be affected by mute.",
-                            mAudioManager.isStreamMute(stream));
-                    continue;
-                }
-                testStreamMuting(stream);
+                assertFalse("Stream " + stream + " should not be affected by mute.",
+                        mAudioManager.isStreamMute(stream));
+                continue;
             }
-        } finally {
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
+            testStreamMuting(stream);
         }
     }
 
@@ -863,8 +833,6 @@
 
         } finally {
             setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
         }
     }
 
@@ -888,8 +856,6 @@
 
         } finally {
             setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
         }
     }
 
@@ -912,8 +878,6 @@
             assertEquals(7, mAudioManager.getStreamVolume(AudioManager.STREAM_RING));
         } finally {
             setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
         }
     }
 
@@ -935,8 +899,6 @@
             assertEquals(7, mAudioManager.getStreamVolume(AudioManager.STREAM_RING));
         } finally {
             setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
-            Utils.toggleNotificationPolicyAccess(
-                    mContext.getPackageName(), getInstrumentation(), false);
         }
     }
 
diff --git a/tests/tests/media/src/android/media/cts/Utils.java b/tests/tests/media/src/android/media/cts/Utils.java
index fb461fe..33cc1b7 100644
--- a/tests/tests/media/src/android/media/cts/Utils.java
+++ b/tests/tests/media/src/android/media/cts/Utils.java
@@ -27,7 +27,7 @@
 import android.os.HandlerThread;
 import android.os.ParcelFileDescriptor;
 import android.provider.Settings;
-
+import com.google.android.collect.Lists;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -87,44 +87,77 @@
 
     protected static void toggleNotificationPolicyAccess(String packageName,
             Instrumentation instrumentation, boolean on) throws IOException {
-        Context context = instrumentation.getContext();
+
+        // Read the setting listing the package allowed to manage notification policy configuration
+        String alreadyEnabledServices = querryNotificationPolicyAccessPakages(instrumentation);
+
+        // The property is a list of : separated package
+        List<String> enabledServices = Lists.newArrayList(alreadyEnabledServices.split(":"));
+
+        // Actually add or remove the package from the list
+        if (on) {
+            // Only add the package if it is not already in the list
+            if (!enabledServices.contains(packageName)) {
+                enabledServices.add(packageName);
+                setNotificationPolicyAccessPackages(enabledServices, instrumentation);
+            }
+        } else {
+            // Remove all instance of the package in the list
+            if (enabledServices.removeIf(packageName::equals)) {
+                // Only update the settings if there was a change
+                setNotificationPolicyAccessPackages(enabledServices, instrumentation);
+            }
+        }
+    }
+
+    /** Read the setting listing the package allowed to manage notification policy configuration */
+    private static String querryNotificationPolicyAccessPakages(Instrumentation instrumentation) {
+        ContentResolver cr = instrumentation.getContext().getContentResolver();
+        String enabledService = Settings.Secure.getString(
+                cr,Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
+
+        // A non existing property is equivalent to no package listed
+        if (enabledService == null) {
+            enabledService = "";
+        }
+        return enabledService;
+    }
+
+    private static void setNotificationPolicyAccessPackages(final List<String> enabledServicesList,
+            final Instrumentation instrumentation) throws IOException {
+        // Format the list back to a string
+        String enabledServices = String.join(":", enabledServicesList);
+
+        // If the list is empty, remove the property by setting it to null
+        String enabledServicesStrOrNull = enabledServices.isEmpty() ? "null" : enabledServices;
+
+        // Write back the property to the settings database
+        String command = "settings --user cur put secure "
+                + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + "  "
+                + enabledServicesStrOrNull;
 
         // Get permission to enable accessibility
         UiAutomation uiAutomation = instrumentation.getUiAutomation();
 
-        ContentResolver cr = context.getContentResolver();
-        String alreadyEnabledServices = Settings.Secure.getString(
-                cr, Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
-        ParcelFileDescriptor fd = null;
-        if (on) {
-            if ((alreadyEnabledServices == null) || !alreadyEnabledServices.contains(packageName)) {
-                // Change the settings to enable the media cts package
-                final String newEnabledServices = (alreadyEnabledServices == null) ? packageName
-                        : alreadyEnabledServices + ":" + packageName;
-                fd = uiAutomation.executeShellCommand(
-                        "settings --user cur put secure "
-                                + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + " "
-                                + newEnabledServices);
+        // Execute command
+        try (ParcelFileDescriptor fd = uiAutomation.executeShellCommand(command)) {
+            Assert.assertNotNull("Failed to execute shell command: " + command, fd);
+            // Wait for the command to finish by reading until EOF
+            try (InputStream in = new FileInputStream(fd.getFileDescriptor())) {
+                byte[] buffer = new byte[4096];
+                while (in.read(buffer) > 0) {}
+            } catch (IOException e) {
+                throw new IOException("Could not read stdout of command: " + command, e);
             }
-        } else if (alreadyEnabledServices != null) {
-            int index =  alreadyEnabledServices.indexOf(":" + packageName);
-            if (index >= 0) {
-                fd = uiAutomation.executeShellCommand(
-                        "settings --user cur put secure "
-                                + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + " "
-                                + alreadyEnabledServices.substring(0, index));
-            } else if (alreadyEnabledServices.equals(packageName)) {
-                // "packageName" is the only enabled service
-                fd = uiAutomation.executeShellCommand("settings --user cur put secure "
-                        + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + "  null");
-            }
+        } finally {
+            uiAutomation.destroy();
         }
-        if (fd != null) {
-            InputStream in = new FileInputStream(fd.getFileDescriptor());
-            byte[] buffer = new byte[4096];
-            while (in.read(buffer) > 0) ;
-        }
-        uiAutomation.destroy();
+
+        // Read the settings again to make sure it is updated
+        String nowEnabledServices = querryNotificationPolicyAccessPakages(instrumentation);
+        Assert.assertEquals("Wrote setting should be the same as the read one",
+                enabledServices, nowEnabledServices);
+
     }
 
     /**
diff --git a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
deleted file mode 100644
index bcecee1..0000000
--- a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2017 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.net.cts;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.IpSecAlgorithm;
-import android.net.IpSecManager;
-import android.net.IpSecTransform;
-import android.os.ParcelFileDescriptor;
-import android.system.Os;
-import android.system.OsConstants;
-import android.test.AndroidTestCase;
-import java.io.ByteArrayOutputStream;
-import java.net.DatagramSocket;
-import java.io.FileDescriptor;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-
-public class IpSecManagerTest extends AndroidTestCase {
-
-    private static final String TAG = IpSecManagerTest.class.getSimpleName();
-
-    private IpSecManager mISM;
-
-    private ConnectivityManager mCM;
-
-    private static final InetAddress GOOGLE_DNS_4;
-    private static final InetAddress GOOGLE_DNS_6;
-
-    static {
-        try {
-            // Google Public DNS Addresses;
-            GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
-            GOOGLE_DNS_6 = InetAddress.getByName("2001:4860:4860::8888");
-        } catch (UnknownHostException e) {
-            throw new RuntimeException("Could not resolve DNS Addresses", e);
-        }
-    }
-
-    private static final InetAddress[] GOOGLE_DNS_LIST =
-            new InetAddress[] {GOOGLE_DNS_4, GOOGLE_DNS_6};
-
-    private static final int DROID_SPI = 0xD1201D;
-
-    private static final byte[] CRYPT_KEY =
-            new byte[] {
-                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
-                0x0E, 0x0F
-            };
-    private static final byte[] AUTH_KEY =
-            new byte[] {
-                0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x7F
-            };
-
-    protected void setUp() throws Exception {
-        super.setUp();
-        mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
-        mISM = (IpSecManager) getContext().getSystemService(Context.IPSEC_SERVICE);
-    }
-
-    /*
-     * Allocate a random SPI
-     * Allocate a specific SPI using previous randomly created SPI value
-     * Realloc the same SPI that was specifically created (expect SpiUnavailable)
-     * Close SPIs
-     */
-    public void testAllocSpi() throws Exception {
-        for (InetAddress addr : GOOGLE_DNS_LIST) {
-            IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
-            randomSpi = mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, addr);
-            assertTrue(
-                    "Failed to receive a valid SPI",
-                    randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
-
-            droidSpi =
-                    mISM.reserveSecurityParameterIndex(
-                            IpSecTransform.DIRECTION_IN, addr, DROID_SPI);
-            assertTrue(
-                    "Failed to allocate specified SPI, " + DROID_SPI,
-                    droidSpi.getSpi() == DROID_SPI);
-
-            try {
-                mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_IN, addr, DROID_SPI);
-                fail("Duplicate SPI was allowed to be created");
-            } catch (IpSecManager.SpiUnavailableException expected) {
-                // This is a success case because we expect a dupe SPI to throw
-            }
-
-            randomSpi.close();
-            droidSpi.close();
-        }
-    }
-
-    /*
-     * Alloc outbound SPI
-     * Alloc inbound SPI
-     * Create transport mode transform
-     * open socket
-     * apply transform to socket
-     * send data on socket
-     * release transform
-     * send data (expect exception)
-     */
-    public void testCreateTransform() throws Exception {
-        InetAddress local = InetAddress.getLoopbackAddress();
-        IpSecManager.SecurityParameterIndex outSpi =
-                mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
-
-        IpSecManager.SecurityParameterIndex inSpi =
-                mISM.reserveSecurityParameterIndex(
-                        IpSecTransform.DIRECTION_IN, local, outSpi.getSpi());
-
-        IpSecTransform transform =
-                new IpSecTransform.Builder(mContext)
-                        .setSpi(IpSecTransform.DIRECTION_OUT, outSpi)
-                        .setEncryption(
-                                IpSecTransform.DIRECTION_OUT,
-                                new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
-                        .setAuthentication(
-                                IpSecTransform.DIRECTION_OUT,
-                                new IpSecAlgorithm(
-                                        IpSecAlgorithm.AUTH_HMAC_SHA256,
-                                        AUTH_KEY,
-                                        AUTH_KEY.length * 8))
-                        .setSpi(IpSecTransform.DIRECTION_IN, inSpi)
-                        .setEncryption(
-                                IpSecTransform.DIRECTION_IN,
-                                new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
-                        .setAuthentication(
-                                IpSecTransform.DIRECTION_IN,
-                                new IpSecAlgorithm(
-                                        IpSecAlgorithm.AUTH_HMAC_SHA256,
-                                        AUTH_KEY,
-                                        CRYPT_KEY.length * 8))
-                        .buildTransportModeTransform(local);
-
-        // Hack to ensure the socket doesn't block indefinitely on failure
-        DatagramSocket localSocket = new DatagramSocket(8888);
-        localSocket.setSoTimeout(500);
-        ParcelFileDescriptor pin = ParcelFileDescriptor.fromDatagramSocket(localSocket);
-        FileDescriptor udpSocket = pin.getFileDescriptor();
-
-        mISM.applyTransportModeTransform(udpSocket, transform);
-        byte[] data = new String("Best test data ever!").getBytes("UTF-8");
-
-        byte[] in = new byte[data.length];
-        Os.sendto(udpSocket, data, 0, data.length, 0, local, 8888);
-        Os.read(udpSocket, in, 0, in.length);
-        assertTrue("Encapsulated data did not match.", Arrays.equals(data, in));
-        mISM.removeTransportModeTransform(udpSocket, transform);
-        Os.close(udpSocket);
-        transform.close();
-    }
-}
diff --git a/tests/tests/os/src/android/os/cts/BuildTest.java b/tests/tests/os/src/android/os/cts/BuildTest.java
index d489a6a..c9650bd 100644
--- a/tests/tests/os/src/android/os/cts/BuildTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildTest.java
@@ -33,6 +33,7 @@
 
 import junit.framework.TestCase;
 
+import static android.os.Build.VERSION.CODENAME;
 import static android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
 
 public class BuildTest extends TestCase {
@@ -223,21 +224,7 @@
         assertTrue(TYPE_PATTERN.matcher(Build.TYPE).matches());
 
         assertNotEmpty(Build.USER);
-    }
 
-    public void testBuildConstants_forPrereleaseOrRelease() {
-        checkBuildConstants(CUR_DEVELOPMENT);
-    }
-
-    @RestrictedBuildTest // Expected to fail on prelease/dev builds, http://b/35922665
-    public void testBuildConstants_forRelease() {
-        checkBuildConstants(CUR_DEVELOPMENT - 1);
-    }
-
-    /**
-     * @param maxAllowedValue the maximum permitted value for constants other than CUR_DEVELOPMENT
-     */
-    private static void checkBuildConstants(int maxAllowedValue) {
         // CUR_DEVELOPMENT must be larger than any released version.
         Field[] fields = Build.VERSION_CODES.class.getDeclaredFields();
         for (Field field : fields) {
@@ -253,9 +240,12 @@
                     // It should be okay to change the value of this constant in future, but it
                     // should at least be a conscious decision.
                     assertEquals(10000, fieldValue);
+                } else if (fieldName.equals(CODENAME) && !CODENAME.equals("REL")) {
+                    // This is the current development version.
+                    assertEquals(CUR_DEVELOPMENT, fieldValue);
                 } else {
-                    assertTrue("Expected " + fieldName + " value to be <= " + maxAllowedValue
-                            + ", got " + fieldValue, fieldValue <= maxAllowedValue);
+                    assertTrue("Expected " + fieldName + " value to be < " + CUR_DEVELOPMENT
+                            + ", got " + fieldValue, fieldValue < CUR_DEVELOPMENT);
                 }
             }
         }
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceDataStoreTest.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceDataStoreTest.java
index 2e30e0c..8e521b9 100644
--- a/tests/tests/preference2/src/android/preference2/cts/PreferenceDataStoreTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceDataStoreTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.AdditionalMatchers.or;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
@@ -35,9 +36,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.preference.CheckBoxPreference;
 import android.preference.Preference;
 import android.preference.PreferenceDataStore;
 import android.preference.PreferenceManager;
@@ -149,6 +152,40 @@
         assertEquals(TEST_DEFAULT_STR, mPreference.defaultValue);
     }
 
+    /**
+     * Test that the initial value is taken from the data store (before the preference gets assigned
+     * to the preference hierarchy).
+     */
+    @Test
+    public void testInitialValueIsTakenFromDSOnPref() {
+        when(mDataStore.getBoolean(anyString(), anyBoolean())).thenReturn(true);
+
+        CheckBoxPreference pref = new CheckBoxPreference(mActivityRule.getActivity());
+        pref.setKey("CheckboxTestPref");
+        pref.setPreferenceDataStore(mDataStore);
+
+        mScreen.addPreference(pref);
+
+        assertTrue(pref.isChecked());
+    }
+
+    /**
+     * Test that the initial value is taken from the data store (before the preference gets assigned
+     * to the preference hierarchy).
+     */
+    @Test
+    public void testInitialValueIsTakenFromDSOnMgr() {
+        when(mDataStore.getBoolean(anyString(), anyBoolean())).thenReturn(true);
+        mManager.setPreferenceDataStore(mDataStore);
+
+        CheckBoxPreference pref = new CheckBoxPreference(mActivityRule.getActivity());
+        pref.setKey("CheckboxTestPref");
+
+        mScreen.addPreference(pref);
+
+        assertTrue(pref.isChecked());
+    }
+
     @Test
     public void testPutStringSetWithDataStoreOnPref() {
         mPreference.setPreferenceDataStore(mDataStore);
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceParentGroupTest.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceParentGroupTest.java
index 5de6e81..a645dc8 100644
--- a/tests/tests/preference2/src/android/preference2/cts/PreferenceParentGroupTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceParentGroupTest.java
@@ -26,6 +26,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.test.UiThreadTest;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -56,6 +57,7 @@
      * from code.
      */
     @Test
+    @UiThreadTest
     public void parentViaCodeTest() {
         PreferenceScreen screen = mActivity.getPreferenceScreen();
         assertNull(screen.getParent());
@@ -84,6 +86,7 @@
      * To see the tested hierarchy check pref_nested.xml.
      */
     @Test
+    @UiThreadTest
     public void parentViaInflationTest() {
         PreferenceScreen screen = mActivity.getPreferenceScreen();
 
@@ -112,6 +115,7 @@
      * Adds preference into two different groups without removing it first.
      */
     @Test
+    @UiThreadTest
     public void parentDoubleAddTest() throws InterruptedException {
         PreferenceScreen screen = mActivity.getPreferenceScreen();
 
diff --git a/tests/tests/graphics/src/android/graphics/fonts/cts/FontRequestTest.java b/tests/tests/provider/src/android/provider/cts/FontRequestTest.java
similarity index 62%
rename from tests/tests/graphics/src/android/graphics/fonts/cts/FontRequestTest.java
rename to tests/tests/provider/src/android/provider/cts/FontRequestTest.java
index 1b00975..d9b8a7f 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/cts/FontRequestTest.java
+++ b/tests/tests/provider/src/android/provider/cts/FontRequestTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.graphics.fonts.cts;
+package android.provider.cts;
 
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
@@ -22,7 +22,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
-import android.graphics.fonts.FontRequest;
+import android.provider.FontRequest;
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -35,7 +35,7 @@
 import java.util.List;
 
 /**
- * Tests for {@link android.graphics.fonts.FontRequest}.
+ * Tests for {@link android.provider.FontRequest}.
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -47,46 +47,6 @@
             Base64.decode("e04fd020ea3a6910a2d808002b30", Base64.DEFAULT);
     private static final List<List<byte[]>> CERTS = Arrays.asList(Arrays.asList(BYTE_ARRAY));
 
-    @Test
-    public void testWriteToParcel() {
-        // GIVEN a FontRequest created with the long constructor
-        FontRequest request = new FontRequest(PROVIDER, PACKAGE, QUERY, CERTS);
-
-        // WHEN we write it to a Parcel
-        Parcel dest = Parcel.obtain();
-        request.writeToParcel(dest, 0);
-        dest.setDataPosition(0);
-
-        // THEN we create from that parcel and get the same values.
-        FontRequest result = FontRequest.CREATOR.createFromParcel(dest);
-        assertEquals(PROVIDER, result.getProviderAuthority());
-        assertEquals(PACKAGE, result.getProviderPackage());
-        assertEquals(QUERY, result.getQuery());
-        assertEquals(CERTS.size(), result.getCertificates().size());
-        List<byte[]> cert = CERTS.get(0);
-        List<byte[]> resultCert = result.getCertificates().get(0);
-        assertEquals(cert.size(), resultCert.size());
-        assertTrue(Arrays.equals(cert.get(0), resultCert.get(0)));
-    }
-
-    @Test
-    public void testWriteToParcel_shortConstructor() {
-        // GIVEN a FontRequest created with the short constructor
-        FontRequest request = new FontRequest(PROVIDER, PACKAGE, QUERY);
-
-        // WHEN we write it to a Parcel
-        Parcel dest = Parcel.obtain();
-        request.writeToParcel(dest, 0);
-        dest.setDataPosition(0);
-
-        // THEN we create from that parcel and get the same values.
-        FontRequest result = FontRequest.CREATOR.createFromParcel(dest);
-        assertEquals(PROVIDER, result.getProviderAuthority());
-        assertEquals(PACKAGE, result.getProviderPackage());
-        assertEquals(QUERY, result.getQuery());
-        assertNotNull(result.getCertificates());
-        assertEquals(0, result.getCertificates().size());
-    }
 
     @Test(expected = NullPointerException.class)
     public void testShortConstructor_nullAuthority() {
diff --git a/tests/tests/provider/src/android/provider/cts/FontsContractTest.java b/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
index 472aed8..745a490 100644
--- a/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
@@ -29,8 +29,8 @@
 import android.content.pm.PackageInfo;
 import android.content.Context;
 import android.graphics.Typeface;
-import android.graphics.fonts.FontRequest;
 import android.graphics.fonts.FontVariationAxis;
+import android.provider.FontRequest;
 import android.provider.FontsContract;
 import android.provider.FontsContract.FontFamilyResult;
 import android.provider.FontsContract.FontInfo;
diff --git a/tests/tests/security/res/raw/bug_34097672.mp4 b/tests/tests/security/res/raw/bug_34097672.mp4
new file mode 100644
index 0000000..79acdf4
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_34097672.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_34360591.mp4 b/tests/tests/security/res/raw/bug_34360591.mp4
new file mode 100644
index 0000000..28c47d3
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_34360591.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index f120426..031b9f7 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -73,6 +73,10 @@
      before any existing test methods
      ***********************************************************/
 
+    public void testStagefright_bug_34360591() throws Exception {
+        doStagefrightTest(R.raw.bug_34360591);
+    }
+
     public void testStagefright_bug_35763994() throws Exception {
         doStagefrightTest(R.raw.bug_35763994);
     }
@@ -183,6 +187,11 @@
      ***********************************************************/
 
     @SecurityTest
+    public void testStagefright_bug_34097672() throws Exception {
+        doStagefrightTest(R.raw.bug_34097672);
+    }
+
+    @SecurityTest
     public void testStagefright_bug_33818508() throws Exception {
         doStagefrightTest(R.raw.bug_33818508);
     }
diff --git a/tests/tests/transition/src/android/transition/cts/ActivityTransitionTest.java b/tests/tests/transition/src/android/transition/cts/ActivityTransitionTest.java
index 872820a..3920bcf 100644
--- a/tests/tests/transition/src/android/transition/cts/ActivityTransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ActivityTransitionTest.java
@@ -88,18 +88,18 @@
     }
 
     @After
-    public void cleanup() {
+    public void cleanup() throws Throwable {
         if (TargetActivity.sLastCreated != null) {
-            mInstrumentation.runOnMainSync(() -> TargetActivity.sLastCreated.finish());
+            mActivityRule.runOnUiThread(() -> TargetActivity.sLastCreated.finish());
         }
         TargetActivity.sLastCreated = null;
     }
 
     // When using ActivityOptions.makeBasic(), no transitions should run
     @Test
-    public void testMakeBasic() {
+    public void testMakeBasic() throws Throwable {
         assertFalse(mActivity.isActivityTransitionRunning());
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             Intent intent = new Intent(mActivity, TargetActivity.class);
             ActivityOptions activityOptions =
                     ActivityOptions.makeBasic();
@@ -110,7 +110,7 @@
 
         TargetActivity targetActivity = waitForTargetActivity();
         assertFalse(targetActivity.isActivityTransitionRunning());
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             targetActivity.finish();
         });
 
@@ -123,7 +123,7 @@
     @Test
     public void viewsNotStripped() throws Throwable {
         enterScene(R.layout.scene10);
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             View sharedElement = mActivity.findViewById(R.id.blueSquare);
             Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
                     sharedElement, "holder").toBundle();
@@ -156,7 +156,7 @@
         assertEquals(1, targetActivity.findViewById(R.id.greenSquare).getAlpha(), 0.01f);
         assertEquals(1, targetActivity.findViewById(R.id.holder).getAlpha(), 0.01f);
 
-        mInstrumentation.runOnMainSync(() -> targetActivity.finishAfterTransition());
+        mActivityRule.runOnUiThread(() -> targetActivity.finishAfterTransition());
         verify(mReenterListener, within(3000)).onTransitionEnd(any());
         verify(mSharedElementReenterListener, within(3000)).onTransitionEnd(any());
         verify(targetActivity.returnListener, times(1)).onTransitionEnd(any());
@@ -195,7 +195,7 @@
     @Test
     public void viewsStripped() throws Throwable {
         enterScene(R.layout.scene13);
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             View sharedElement = mActivity.findViewById(R.id.redSquare);
             Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
                     sharedElement, "redSquare").toBundle();
@@ -227,7 +227,7 @@
         assertEquals(1, targetActivity.findViewById(R.id.greenSquare).getAlpha(), 0.01f);
         assertEquals(1, targetActivity.findViewById(R.id.holder).getAlpha(), 0.01f);
 
-        mInstrumentation.runOnMainSync(() -> targetActivity.finishAfterTransition());
+        mActivityRule.runOnUiThread(() -> targetActivity.finishAfterTransition());
         verify(mReenterListener, within(3000)).onTransitionEnd(any());
         verify(mSharedElementReenterListener, within(3000)).onTransitionEnd(any());
         verify(targetActivity.returnListener, times(1)).onTransitionEnd(any());
@@ -267,7 +267,7 @@
         final View hello = mActivity.findViewById(R.id.hello);
         final View red = mActivity.findViewById(R.id.redSquare);
         final View green = mActivity.findViewById(R.id.greenSquare);
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             Fade fade = new Fade();
             fade.setDuration(10000);
             fade.addListener(mExitListener);
@@ -282,7 +282,7 @@
         verify(targetActivity.enterListener, within(3000)).onTransitionEnd(any());
         verify(mExitListener, within(3000)).onTransitionEnd(any());
 
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             // Verify that the exited views have an alpha of 1 and are visible
             assertEquals(1.0f, hello.getAlpha(), 0.01f);
             assertEquals(1.0f, red.getAlpha(), 0.01f);
@@ -296,9 +296,9 @@
     }
 
     @Test
-    public void testAnimationQuery() {
+    public void testAnimationQuery() throws Throwable {
         assertFalse(mActivity.isActivityTransitionRunning());
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             mActivity.getWindow().setExitTransition(new Fade());
             Intent intent = new Intent(mActivity, TargetActivity.class);
             ActivityOptions activityOptions =
@@ -310,12 +310,19 @@
 
         TargetActivity targetActivity = waitForTargetActivity();
         assertTrue(targetActivity.isActivityTransitionRunning());
-        mInstrumentation.runOnMainSync(() -> {
-            targetActivity.finish();
+        mActivityRule.runOnUiThread(() -> { });
+        PollingCheck.waitFor(() -> !targetActivity.isActivityTransitionRunning());
+
+        assertFalse(mActivity.isActivityTransitionRunning());
+        mActivityRule.runOnUiThread(() -> {
+            targetActivity.finishAfterTransition();
+            // The target activity transition should start right away
+            assertTrue(targetActivity.isActivityTransitionRunning());
         });
 
-        assertTrue(targetActivity.isActivityTransitionRunning());
-        assertTrue(mActivity.isActivityTransitionRunning());
+        // The source activity transition should start sometime later
+        PollingCheck.waitFor(() -> mActivity.isActivityTransitionRunning());
+        PollingCheck.waitFor(() -> !mActivity.isActivityTransitionRunning());
     }
 
     // Views that are excluded from the exit/enter transition shouldn't change visibility
@@ -380,10 +387,10 @@
         TargetActivity.sLastCreated = null;
     }
 
-    private TargetActivity waitForTargetActivity() {
+    private TargetActivity waitForTargetActivity() throws Throwable {
         PollingCheck.waitFor(() -> TargetActivity.sLastCreated != null);
         // Just make sure that we're not in the middle of running on the UI thread.
-        mInstrumentation.runOnMainSync(() -> {});
+        mActivityRule.runOnUiThread(() -> { });
         return TargetActivity.sLastCreated;
     }
 
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java b/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
index 4b55057..d11051f 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
@@ -77,7 +77,7 @@
 
         startTransition(R.layout.scene6);
         // The update listener will validate that it is changing throughout the animation
-        waitForEnd(400);
+        waitForEnd(800);
 
         validateInScene6();
     }
@@ -96,7 +96,7 @@
         startTransition(R.layout.scene6);
 
         // The update listener will validate that it is changing throughout the animation
-        waitForEnd(400);
+        waitForEnd(800);
 
         validateInScene6();
     }
@@ -112,7 +112,7 @@
         startTransition(R.layout.scene1);
 
         // The update listener will validate that it is changing throughout the animation
-        waitForEnd(400);
+        waitForEnd(800);
 
         validateInScene1();
     }
@@ -131,7 +131,7 @@
         startTransition(R.layout.scene6);
 
         assertFalse(isRestartingAnimation());
-        waitForEnd(500);
+        waitForEnd(1000);
         validateInScene6();
     }
 
@@ -153,7 +153,7 @@
 
         assertFalse(isRestartingAnimation());
         assertFalse(isRestartingClip());
-        waitForEnd(500);
+        waitForEnd(1000);
         validateInScene6();
     }
 
@@ -172,7 +172,7 @@
         startTransition(R.layout.scene1);
 
         assertFalse(isRestartingAnimation());
-        waitForEnd(500);
+        waitForEnd(1000);
         validateInScene1();
     }
 
@@ -195,7 +195,7 @@
 
         assertFalse(isRestartingAnimation());
         assertFalse(isRestartingClip());
-        waitForEnd(500);
+        waitForEnd(1000);
         validateInScene1();
     }
 
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java b/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java
index b27364e..6ae8a9f 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java
@@ -236,7 +236,7 @@
         });
         waitForStart();
         verify(mListener, (startScale == endScale) ? times(1) : never()).onTransitionEnd(any());
-        waitForEnd(200);
+        waitForEnd(1000);
     }
 
     private ImageView enterImageViewScene(final ScaleType scaleType) throws Throwable {
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java b/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java
index fb231fa..38474a2 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java
@@ -66,7 +66,7 @@
         verify(mListener, never()).onTransitionEnd(any()); // still running
         // There is no way to validate the intermediate matrix because it uses
         // hidden properties of the View to execute.
-        waitForEnd(400);
+        waitForEnd(800);
         assertEquals(500f, redSquare.getTranslationX(), 0.0f);
         assertEquals(600f, redSquare.getTranslationY(), 0.0f);
     }
@@ -86,7 +86,7 @@
         verify(mListener, never()).onTransitionEnd(any()); // still running
         // There is no way to validate the intermediate matrix because it uses
         // hidden properties of the View to execute.
-        waitForEnd(400);
+        waitForEnd(800);
         assertEquals(45f, redSquare.getRotation(), 0.0f);
     }
 
@@ -106,7 +106,7 @@
         verify(mListener, never()).onTransitionEnd(any()); // still running
         // There is no way to validate the intermediate matrix because it uses
         // hidden properties of the View to execute.
-        waitForEnd(400);
+        waitForEnd(800);
         assertEquals(2f, redSquare.getScaleX(), 0.0f);
         assertEquals(3f, redSquare.getScaleY(), 0.0f);
     }
@@ -117,7 +117,7 @@
         enterScene(R.layout.scene5);
         startTransition(R.layout.scene9);
         verify(mListener, never()).onTransitionEnd(any()); // still running
-        waitForEnd(400);
+        waitForEnd(800);
 
         resetListener();
         mChangeTransform.setReparent(false);
@@ -142,7 +142,7 @@
             mSceneRoot.getOverlay().remove(view);
             assertTrue(mActivity.findViewById(R.id.text).getVisibility() != View.VISIBLE);
         });
-        waitForEnd(400);
+        waitForEnd(800);
 
         mChangeTransform.setReparentWithOverlay(false);
         assertEquals(false, mChangeTransform.getReparentWithOverlay());
@@ -159,7 +159,7 @@
             mSceneRoot.getOverlay().remove(view);
             assertEquals(View.VISIBLE, mActivity.findViewById(R.id.text).getVisibility());
         });
-        waitForEnd(400);
+        waitForEnd(800);
     }
 }
 
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
index d4375cc..f48f780 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
@@ -54,7 +54,7 @@
         });
 
         waitForStart();
-        waitForEnd(300);
+        waitForEnd(800);
         verify(mListener, never()).onTransitionResume(any());
         verify(mListener, never()).onTransitionPause(any());
         verify(mListener, never()).onTransitionCancel(any());
@@ -109,7 +109,7 @@
     public void testGo() throws Throwable {
         startTransition(R.layout.scene1);
         waitForStart();
-        waitForEnd(300);
+        waitForEnd(800);
 
         verify(mListener, never()).onTransitionResume(any());
         verify(mListener, never()).onTransitionPause(any());
@@ -156,7 +156,7 @@
         });
 
         waitForStart();
-        waitForEnd(300);
+        waitForEnd(800);
         verify(mListener, never()).onTransitionResume(any());
         verify(mListener, never()).onTransitionPause(any());
         verify(mListener, never()).onTransitionCancel(any());
@@ -195,7 +195,7 @@
         mActivityRule.runOnUiThread(() -> transitionManager.transitionTo(scenes[1]));
 
         waitForStart();
-        waitForEnd(300);
+        waitForEnd(800);
         verify(mListener, never()).onTransitionResume(any());
         verify(mListener, never()).onTransitionPause(any());
         verify(mListener, never()).onTransitionCancel(any());
@@ -220,7 +220,7 @@
         startTransition(R.layout.scene1);
         waitForStart();
         endTransition();
-        waitForEnd(100);
+        waitForEnd(400);
     }
 
     @Test
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionTest.java b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
index 9aaaeec..cc13eda 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
@@ -605,7 +605,7 @@
 
         enterScene(scene1);
 
-        mInstrumentation.runOnMainSync(() -> {
+        mActivityRule.runOnUiThread(() -> {
             // scene1
             assertSame(layout1, mActivity.findViewById(R.id.holder));
             assertNotNull(mActivity.findViewById(R.id.hello));
diff --git a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
index a71748a..6b608e4 100644
--- a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
+++ b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
@@ -61,19 +61,19 @@
         enterScene(R.layout.scene4);
         startTransition(R.layout.scene1);
         verify(mListener, never()).onTransitionEnd(any());
-        waitForEnd(400);
+        waitForEnd(800);
 
         resetListener();
         startTransition(R.layout.scene4);
         verify(mListener, never()).onTransitionEnd(any());
-        waitForEnd(400);
+        waitForEnd(800);
 
         // Now only animate in
         resetListener();
         mVisibilityTransition.setMode(Visibility.MODE_IN);
         startTransition(R.layout.scene1);
         verify(mListener, never()).onTransitionEnd(any());
-        waitForEnd(400);
+        waitForEnd(800);
 
         // No animation since it should only animate in
         resetListener();
@@ -90,7 +90,7 @@
         resetListener();
         startTransition(R.layout.scene4);
         verify(mListener, never()).onTransitionEnd(any());
-        waitForEnd(400);
+        waitForEnd(800);
     }
 
     @Test
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
index c47b4b1..aac14e6 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
@@ -77,6 +77,8 @@
     /** It is defined in R.anim.decelerate_alpha */
     private static final int DECELERATE_ALPHA_DURATION = 2000;
 
+    private static final int CANCELATION_TIMEOUT = 1000;
+
     private Instrumentation mInstrumentation;
     private Activity mActivity;
 
@@ -658,7 +660,7 @@
         MyAnimation anim = new MyAnimation();
         final CountDownLatch latch1 = new CountDownLatch(1);
         runCanceledAnimation(anim, latch1, false, false);
-        assertTrue(latch1.await(200, TimeUnit.MILLISECONDS));
+        assertTrue(latch1.await(CANCELATION_TIMEOUT, TimeUnit.MILLISECONDS));
         assertFalse(anim.isStillAnimating());
     }
 
@@ -667,7 +669,7 @@
         MyAnimation anim = new MyAnimation();
         final CountDownLatch latch2 = new CountDownLatch(1);
         runCanceledAnimation(anim, latch2, true, false);
-        assertTrue(latch2.await(200, TimeUnit.MILLISECONDS));
+        assertTrue(latch2.await(CANCELATION_TIMEOUT, TimeUnit.MILLISECONDS));
         assertFalse(anim.isStillAnimating());
     }
 
@@ -676,7 +678,7 @@
         MyAnimation anim = new MyAnimation();
         final CountDownLatch latch3 = new CountDownLatch(1);
         runCanceledAnimation(anim, latch3, false, true);
-        assertTrue(latch3.await(250, TimeUnit.MILLISECONDS));
+        assertTrue(latch3.await(CANCELATION_TIMEOUT, TimeUnit.MILLISECONDS));
         assertFalse(anim.isStillAnimating());
     }
 
@@ -685,7 +687,7 @@
         MyAnimation anim = new MyAnimation();
         final CountDownLatch latch4 = new CountDownLatch(1);
         runCanceledAnimation(anim, latch4, true, true);
-        assertTrue(latch4.await(250, TimeUnit.MILLISECONDS));
+        assertTrue(latch4.await(CANCELATION_TIMEOUT, TimeUnit.MILLISECONDS));
         assertFalse(anim.isStillAnimating());
     }
 
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index e912981..1d86477 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -190,4 +190,7 @@
     <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf1280x0720" />
     <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf1920x1080" />
 
+    <!-- b/37105075 -->
+    <option name="compatibility:exclude-filter" value="CtsIncidentHostTestCases com.android.server.cts.BatteryStatsValidationTest#testWifiUpload" />
+
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-sts.xml b/tools/cts-tradefed/res/config/security-bulletin.xml
similarity index 95%
rename from tools/cts-tradefed/res/config/cts-sts.xml
rename to tools/cts-tradefed/res/config/security-bulletin.xml
index 8e4c030..02175a9 100644
--- a/tools/cts-tradefed/res/config/cts-sts.xml
+++ b/tools/cts-tradefed/res/config/security-bulletin.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Runs Security Patch test cases">
 
-    <option name="plan" value="cts-sts" />
+    <option name="plan" value="security-bulletin" />
 
     <include name="cts"/>