Merge "CTS: WifiLockState"
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
index 343c960..dd7ef21 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
@@ -12,20 +12,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import its.image
+import math
+import os.path
 import its.caps
 import its.device
+import its.image
 import its.objects
 import its.target
-import os.path
-import math
+
+NAME = os.path.basename(__file__).split(".")[0]
+THRESHOLD_MAX_RMS_DIFF = 0.035
+
 
 def main():
-    """Test capturing a single frame as both RAW and YUV outputs.
-    """
-    NAME = os.path.basename(__file__).split(".")[0]
-
-    THRESHOLD_MAX_RMS_DIFF = 0.035
+    """Test capturing a single frame as both RAW and YUV outputs."""
 
     with its.device.ItsSession() as cam:
         props = cam.get_camera_properties()
@@ -38,34 +38,35 @@
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
         req = its.objects.manual_capture_request(s, e, 0.0, True, props)
 
-        if 0 in props['android.shading.availableModes']:
-            req["android.shading.mode"] = 0
+        mode = req["android.shading.mode"]
+        print "shading mode:", mode
 
-        max_raw_size = \
-                its.objects.get_available_output_sizes("raw", props)[0]
-        w,h = its.objects.get_available_output_sizes(
+        max_raw_size = its.objects.get_available_output_sizes("raw", props)[0]
+        w, h = its.objects.get_available_output_sizes(
                 "yuv", props, (1920, 1080), max_raw_size)[0]
-        out_surfaces = [{"format":"raw"},
-                        {"format":"yuv", "width":w, "height":h}]
+        out_surfaces = [{"format": "raw"},
+                        {"format": "yuv", "width": w, "height": h}]
         cap_raw, cap_yuv = cam.do_capture(req, out_surfaces)
 
         img = its.image.convert_capture_to_rgb_image(cap_yuv)
-        its.image.write_image(img, "%s_yuv.jpg" % (NAME), True)
+        its.image.write_image(img, "%s_shading=%d_yuv.jpg" % (NAME, mode), True)
         tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb0 = its.image.compute_image_means(tile)
 
         # Raw shots are 1/2 x 1/2 smaller after conversion to RGB, but tile
         # cropping is relative.
         img = its.image.convert_capture_to_rgb_image(cap_raw, props=props)
-        its.image.write_image(img, "%s_raw.jpg" % (NAME), True)
+        its.image.write_image(img, "%s_shading=%d_raw.jpg" % (NAME, mode), True)
         tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb1 = its.image.compute_image_means(tile)
 
         rms_diff = math.sqrt(
                 sum([pow(rgb0[i] - rgb1[i], 2.0) for i in range(3)]) / 3.0)
-        print "RMS difference:", rms_diff
-        assert(rms_diff < THRESHOLD_MAX_RMS_DIFF)
+        msg = "RMS difference: %.4f, spec: %.3f" % (rms_diff,
+                                                    THRESHOLD_MAX_RMS_DIFF)
+        print msg
+        assert rms_diff < THRESHOLD_MAX_RMS_DIFF, msg
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
 
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
index 6ecdca7..9c0c69b 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
@@ -12,20 +12,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import its.image
+import math
+import os.path
 import its.caps
 import its.device
+import its.image
 import its.objects
 import its.target
-import os.path
-import math
+
+NAME = os.path.basename(__file__).split(".")[0]
+THRESHOLD_MAX_RMS_DIFF = 0.035
+
 
 def main():
-    """Test capturing a single frame as both RAW10 and YUV outputs.
-    """
-    NAME = os.path.basename(__file__).split(".")[0]
-
-    THRESHOLD_MAX_RMS_DIFF = 0.035
+    """Test capturing a single frame as both RAW10 and YUV outputs."""
 
     with its.device.ItsSession() as cam:
         props = cam.get_camera_properties()
@@ -38,34 +38,36 @@
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
         req = its.objects.manual_capture_request(s, e, 0.0, True, props)
 
-        if 0 in props['android.shading.availableModes']:
-            req["android.shading.mode"] = 0
+        mode = req["android.shading.mode"]
+        print "shading mode:", mode
 
-        max_raw10_size = \
-                its.objects.get_available_output_sizes("raw10", props)[0]
-        w,h = its.objects.get_available_output_sizes(
+        max_raw10_size = its.objects.get_available_output_sizes("raw10",
+                                                                props)[0]
+        w, h = its.objects.get_available_output_sizes(
                 "yuv", props, (1920, 1080), max_raw10_size)[0]
-        cap_raw, cap_yuv = cam.do_capture(req,
-                [{"format":"raw10"},
-                 {"format":"yuv", "width":w, "height":h}])
+        out_surfaces = [{"format": "raw10"},
+                        {"format": "yuv", "width": w, "height": h}]
+        cap_raw, cap_yuv = cam.do_capture(req, out_surfaces)
 
         img = its.image.convert_capture_to_rgb_image(cap_yuv)
-        its.image.write_image(img, "%s_yuv.jpg" % (NAME), True)
+        its.image.write_image(img, "%s_shading=%d_yuv.jpg" % (NAME, mode), True)
         tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb0 = its.image.compute_image_means(tile)
 
         # Raw shots are 1/2 x 1/2 smaller after conversion to RGB, but tile
         # cropping is relative.
         img = its.image.convert_capture_to_rgb_image(cap_raw, props=props)
-        its.image.write_image(img, "%s_raw.jpg" % (NAME), True)
+        its.image.write_image(img, "%s_shading=%d_raw.jpg" % (NAME, mode), True)
         tile = its.image.get_image_patch(img, 0.45, 0.45, 0.1, 0.1)
         rgb1 = its.image.compute_image_means(tile)
 
         rms_diff = math.sqrt(
                 sum([pow(rgb0[i] - rgb1[i], 2.0) for i in range(3)]) / 3.0)
-        print "RMS difference:", rms_diff
-        assert(rms_diff < THRESHOLD_MAX_RMS_DIFF)
+        msg = "RMS difference: %.4f, spec: %.3f" % (rms_diff,
+                                                    THRESHOLD_MAX_RMS_DIFF)
+        print msg
+        assert rms_diff < THRESHOLD_MAX_RMS_DIFF, msg
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
 
diff --git a/hostsidetests/backup/src/android/cts/backup/SuccessNotificationHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/SuccessNotificationHostSideTest.java
index 0e2abb8..414e3bc 100644
--- a/hostsidetests/backup/src/android/cts/backup/SuccessNotificationHostSideTest.java
+++ b/hostsidetests/backup/src/android/cts/backup/SuccessNotificationHostSideTest.java
@@ -168,11 +168,13 @@
     private void addBackupFinishedNotificationReceiver()
             throws DeviceNotAvailableException {
         mOriginalBackupManagerConstants = getDevice().executeShellCommand(String.format(
-                "settings get secure %s", BACKUP_MANAGER_CONSTANTS_PREF));
+                "settings get secure %s", BACKUP_MANAGER_CONSTANTS_PREF)).trim();
+        if ("null".equals(mOriginalBackupManagerConstants)) {
+            mOriginalBackupManagerConstants = null;
+        }
         String backupManagerConstants = null;
 
-        if (mOriginalBackupManagerConstants == null ||
-                mOriginalBackupManagerConstants.trim().isEmpty()) {
+        if (mOriginalBackupManagerConstants == null || mOriginalBackupManagerConstants.isEmpty()) {
             backupManagerConstants =
                     BACKUP_FINISHED_NOTIFICATION_RECEIVERS + "=" + SUCCESS_NOTIFICATION_APP_PACKAGE;
         } else {
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PasswordBlacklistTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PasswordBlacklistTest.java
index 6d7af3b..7856aff 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PasswordBlacklistTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PasswordBlacklistTest.java
@@ -17,12 +17,14 @@
 package com.android.cts.deviceandprofileowner;
 
 import android.app.admin.DevicePolicyManager;
+import android.util.Log;
 
 import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.List;
 
 public final class PasswordBlacklistTest extends BaseDeviceAdminTest {
+    private static final String TAG = "PasswordBlacklistTest";
     private static final byte[] TOKEN = "abcdefghijklmnopqrstuvwxyz0123456789".getBytes();
 
     private boolean mShouldRun = true;
@@ -40,6 +42,7 @@
                     TOKEN));
         } catch (SecurityException e) {
             if (e.getMessage().equals("Escrow token is disabled on the current user")) {
+                Log.i(TAG, "Skip some password blacklist test because escrow token is disabled");
                 mShouldRun = false;
             } else {
                 throw e;
@@ -132,17 +135,11 @@
     }
 
     public void testMaxBlacklistSize() {
-        if (!mShouldRun) {
-            return;
-        }
         assertTrue(mDevicePolicyManager.setPasswordBlacklist(
                 ADMIN_RECEIVER_COMPONENT, "max size", generateMaxBlacklist()));
     }
 
     public void testBlacklistTooBig() {
-        if (!mShouldRun) {
-            return;
-        }
         try {
             mDevicePolicyManager.setPasswordBlacklist(
                     ADMIN_RECEIVER_COMPONENT, "too big", generateJustTooBigBlacklist());
@@ -202,9 +199,6 @@
     }
 
     public void testPasswordBlacklistWithEmptyName() {
-        if (!mShouldRun) {
-            return;
-        }
         final String emptyName = "";
         assertTrue(mDevicePolicyManager.setPasswordBlacklist(
                 ADMIN_RECEIVER_COMPONENT, emptyName, Arrays.asList("test", "empty", "name")));
@@ -213,9 +207,6 @@
     }
 
     public void testBlacklistNameCanBeChanged() {
-        if (!mShouldRun) {
-            return;
-        }
         final String firstName = "original";
         assertTrue(mDevicePolicyManager.setPasswordBlacklist(
                 ADMIN_RECEIVER_COMPONENT, firstName, Arrays.asList("a")));
@@ -230,9 +221,6 @@
     }
 
     public void testCannotNameClearedBlacklist() {
-        if (!mShouldRun) {
-            return;
-        }
         final String name = "empty!";
         assertTrue(mDevicePolicyManager.setPasswordBlacklist(
                 ADMIN_RECEIVER_COMPONENT, name, null));
@@ -240,9 +228,6 @@
     }
 
     public void testClearingBlacklistClearsName() {
-        if (!mShouldRun) {
-            return;
-        }
         final String firstName = "gotone";
         assertTrue(mDevicePolicyManager.setPasswordBlacklist(
                 ADMIN_RECEIVER_COMPONENT, firstName, Arrays.asList("something")));
@@ -256,9 +241,6 @@
     }
 
     public void testNullAdminWhenGettingBlacklistName() {
-        if (!mShouldRun) {
-            return;
-        }
         try {
             mDevicePolicyManager.getPasswordBlacklistName(null);
             fail("Did not throw NullPointerException");
@@ -268,6 +250,9 @@
     }
 
     public void testBlacklistNotConsideredByIsActivePasswordSufficient() {
+        if (!mShouldRun) {
+            return;
+        }
         mDevicePolicyManager.setPasswordQuality(ADMIN_RECEIVER_COMPONENT,
                 DevicePolicyManager.PASSWORD_QUALITY_COMPLEX);
         final String complexPassword = ".password123";
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
index 196dc4c..85e369b 100644
--- a/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
+++ b/hostsidetests/devicepolicy/app/LauncherTests/Android.mk
@@ -30,7 +30,6 @@
 	android-support-v4 \
 	ctstestrunner \
 	android-support-test \
-	legacy-android-test \
 	compatibility-device-util \
 	ShortcutManagerTestUtils \
 	testng
diff --git a/hostsidetests/seccomp/Android.mk b/hostsidetests/seccomp/Android.mk
new file mode 100644
index 0000000..2c1c077
--- /dev/null
+++ b/hostsidetests/seccomp/Android.mk
@@ -0,0 +1,32 @@
+# 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, src)
+
+LOCAL_MODULE_TAGS := tests
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+LOCAL_MODULE := CtsSeccompHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/seccomp/AndroidTest.xml b/hostsidetests/seccomp/AndroidTest.xml
new file mode 100644
index 0000000..cbfd1c4
--- /dev/null
+++ b/hostsidetests/seccomp/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?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 Sseccomp host test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="misc" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsSeccompDeviceApp.apk" />
+    </target_preparer>
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsSeccompHostTestCases.jar" />
+    </test>
+</configuration>
diff --git a/hostsidetests/seccomp/app/Android.mk b/hostsidetests/seccomp/app/Android.mk
new file mode 100644
index 0000000..726e64b
--- /dev/null
+++ b/hostsidetests/seccomp/app/Android.mk
@@ -0,0 +1,56 @@
+# 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)
+
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+          android-support-test \
+          compatibility-device-util \
+
+LOCAL_JNI_SHARED_LIBRARIES := \
+          libctsseccomp_jni \
+          libcts_jni \
+          libnativehelper_compat_libc++ \
+          libnativehelper \
+          libcutils \
+          libc++ \
+          libpackagelistparser \
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+LOCAL_PACKAGE_NAME := CtsSeccompDeviceApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/seccomp/app/AndroidManifest.xml b/hostsidetests/seccomp/app/AndroidManifest.xml
new file mode 100644
index 0000000..b8e97e3
--- /dev/null
+++ b/hostsidetests/seccomp/app/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.seccomp.cts.app">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.seccomp.cts.app" />
+
+</manifest>
diff --git a/hostsidetests/seccomp/app/jni/Android.mk b/hostsidetests/seccomp/app/jni/Android.mk
new file mode 100644
index 0000000..a0604a1
--- /dev/null
+++ b/hostsidetests/seccomp/app/jni/Android.mk
@@ -0,0 +1,41 @@
+# 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_MODULE := libctsseccomp_jni
+
+# Don't include this package in any configuration by default.
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+		CtsSeccompJniOnLoad.cpp \
+		android_seccomp_cts_app_SeccompDeviceTest.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+		libnativehelper \
+		liblog \
+		libcutils \
+		libc++ \
+		libpackagelistparser \
+
+
+LOCAL_C_INCLUDES += ndk/sources/cpufeatures
+LOCAL_STATIC_LIBRARIES := cpufeatures
+
+LOCAL_CFLAGS := -Wall -Werror
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/hostsidetests/seccomp/app/jni/CtsSeccompJniOnLoad.cpp b/hostsidetests/seccomp/app/jni/CtsSeccompJniOnLoad.cpp
new file mode 100644
index 0000000..928b8c5
--- /dev/null
+++ b/hostsidetests/seccomp/app/jni/CtsSeccompJniOnLoad.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+#include <stdio.h>
+
+extern int register_android_seccomp_cts_app_SeccompTest(JNIEnv*);
+
+jint JNI_OnLoad(JavaVM *vm, void * /*reserved*/) {
+    JNIEnv *env = NULL;
+
+    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
+        return JNI_ERR;
+    }
+
+    if (register_android_seccomp_cts_app_SeccompTest(env)) {
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_4;
+}
diff --git a/tests/tests/security/jni/android_security_cts_SeccompTest.cpp b/hostsidetests/seccomp/app/jni/android_seccomp_cts_app_SeccompDeviceTest.cpp
similarity index 91%
rename from tests/tests/security/jni/android_security_cts_SeccompTest.cpp
rename to hostsidetests/seccomp/app/jni/android_seccomp_cts_app_SeccompDeviceTest.cpp
index ee36cdd..de82b44 100644
--- a/tests/tests/security/jni/android_security_cts_SeccompTest.cpp
+++ b/hostsidetests/seccomp/app/jni/android_seccomp_cts_app_SeccompDeviceTest.cpp
@@ -36,7 +36,7 @@
     int pid = fork();
     if (pid == 0) {
         ALOGI("Calling syscall %d", nr);
-        int ret = syscall(nr);
+        syscall(nr);
         return false;
     } else {
         int status;
@@ -72,9 +72,9 @@
             (void*) testSyscallBlocked },
 };
 
-int register_android_security_cts_SeccompTest(JNIEnv* env)
+int register_android_seccomp_cts_app_SeccompTest(JNIEnv* env)
 {
-    jclass clazz = env->FindClass("android/security/cts/SeccompTest");
+    jclass clazz = env->FindClass("android/seccomp/cts/app/SeccompDeviceTest");
 
     return env->RegisterNatives(clazz, gMethods,
             sizeof(gMethods) / sizeof(JNINativeMethod));
diff --git a/tests/tests/security/src/android/security/cts/SeccompTest.java b/hostsidetests/seccomp/app/src/android/seccomp/cts/app/SeccompDeviceTest.java
similarity index 81%
rename from tests/tests/security/src/android/security/cts/SeccompTest.java
rename to hostsidetests/seccomp/app/src/android/seccomp/cts/app/SeccompDeviceTest.java
index 745aa87..2a7bcb3 100644
--- a/tests/tests/security/src/android/security/cts/SeccompTest.java
+++ b/hostsidetests/seccomp/app/src/android/seccomp/cts/app/SeccompDeviceTest.java
@@ -14,23 +14,28 @@
  * limitations under the License.
  */
 
-package android.security.cts;
+package android.seccomp.cts.app;
 
-import android.test.AndroidTestCase;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
+import android.support.test.runner.AndroidJUnit4;
 import com.android.compatibility.common.util.CpuFeatures;
 
-import junit.framework.TestCase;
-
 /**
- * Verify that the seccomp policy is enforced
+ * Device-side tests for CtsSeccompHostTestCases
  */
-public class SeccompTest extends AndroidTestCase {
-
+@RunWith(AndroidJUnit4.class)
+public class SeccompDeviceTest {
     static {
-        System.loadLibrary("ctssecurity_jni");
+        System.loadLibrary("ctsseccomp_jni");
     }
 
+    @Test
     public void testCTSSyscallBlocked() {
         if (CpuFeatures.isArm64Cpu()) {
             testBlocked(217); // __NR_add_key
@@ -63,10 +68,11 @@
             testBlocked(4282); // __NR_keyctl
             testAllowed(4288); // __NR_openat
         } else {
-            fail("Unsupported OS");
+            Assert.fail("Unsupported OS");
         }
     }
 
+    @Test
     public void testCTSSwapOnOffBlocked() {
         if (CpuFeatures.isArm64Cpu()) {
             testBlocked(224); // __NR_swapon
@@ -87,16 +93,16 @@
             testBlocked(4087); // __NR_swapon
             testBlocked(4115); // __NR_swapoff
         } else {
-            fail("Unsupported OS");
+            Assert.fail("Unsupported OS");
         }
     }
 
     private void testBlocked(int nr) {
-        assertTrue("Syscall " + nr + " allowed", testSyscallBlocked(nr));
+        Assert.assertTrue("Syscall " + nr + " not blocked", testSyscallBlocked(nr));
     }
 
     private void testAllowed(int nr) {
-        assertFalse("Syscall " + nr + " blocked", testSyscallBlocked(nr));
+        Assert.assertFalse("Syscall " + nr + " blocked", testSyscallBlocked(nr));
     }
 
     private static final native boolean testSyscallBlocked(int nr);
diff --git a/hostsidetests/seccomp/src/android/seccomp/cts/SeccompHostJUnit4DeviceTest.java b/hostsidetests/seccomp/src/android/seccomp/cts/SeccompHostJUnit4DeviceTest.java
new file mode 100644
index 0000000..63258e3
--- /dev/null
+++ b/hostsidetests/seccomp/src/android/seccomp/cts/SeccompHostJUnit4DeviceTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.seccomp.cts;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test that collects test results from test package android.seccomp.cts.app.
+ *
+ * When this test builds, it also builds a support APK containing
+ * {@link android.seccomp.cts.app.SeccompDeviceTest}, the results of which are
+ * collected from the hostside and reported accordingly.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class SeccompHostJUnit4DeviceTest extends BaseHostJUnit4Test {
+
+    private static final String TEST_PKG = "android.seccomp.cts.app";
+    private static final String TEST_CLASS = TEST_PKG + "." + "SeccompDeviceTest";
+    private static final String TEST_APP = "CtsSeccompDeviceApp.apk";
+
+    private static final String TEST_CTS_SYSCALL_BLOCKED = "testCTSSyscallBlocked";
+    private static final String TEST_CTS_SWAP_ON_OFF_BLOCKED = "testCTSSwapOnOffBlocked";
+
+    @Before
+    public void setUp() throws Exception {
+        installPackage(TEST_APP);
+    }
+
+    @Test
+    public void testCTSSyscallBlocked() throws Exception {
+        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, TEST_CTS_SYSCALL_BLOCKED));
+    }
+
+    @Test
+    public void testCTSSwapOnOffBlocked() throws Exception {
+        Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, TEST_CTS_SWAP_ON_OFF_BLOCKED));
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        uninstallPackage(getDevice(), TEST_PKG);
+    }
+
+}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/HostAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/HostAtomTests.java
index cbf3cc0..5ef6deb 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/HostAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/HostAtomTests.java
@@ -32,6 +32,7 @@
 import com.android.os.AtomsProto.BatterySaverModeStateChanged;
 import com.android.os.AtomsProto.ChargingStateChanged;
 import com.android.os.AtomsProto.CpuTimePerUid;
+import com.android.os.AtomsProto.CpuTimePerFreq;
 import com.android.os.AtomsProto.CpuTimePerUidFreq;
 import com.android.os.AtomsProto.DeviceIdleModeStateChanged;
 import com.android.os.AtomsProto.KernelWakelock;
@@ -598,6 +599,31 @@
         assertTrue(atom.getKernelWakelock().hasTime());
     }
 
+    public void testCpuTimePerFreq() throws Exception {
+        if (!TESTS_ENABLED) {return;}
+        StatsdConfig.Builder config = getPulledAndAnomalyConfig();
+        FieldMatcher.Builder dimension = FieldMatcher.newBuilder()
+                .setField(Atom.CPU_TIME_PER_FREQ_FIELD_NUMBER)
+                .addChild(FieldMatcher.newBuilder()
+                        .setField(CpuTimePerFreq.CLUSTER_FIELD_NUMBER));
+        addGaugeAtom(config, Atom.CPU_TIME_PER_FREQ_FIELD_NUMBER, dimension);
+
+        turnScreenOff();
+
+        uploadConfig(config);
+
+        Thread.sleep(2000);
+        turnScreenOn();
+        Thread.sleep(2000);
+
+        List<Atom> data = getGaugeMetricDataList();
+
+        Atom atom = data.get(0);
+        assertTrue(atom.getCpuTimePerFreq().getCluster() >= 0);
+        assertTrue(atom.getCpuTimePerFreq().getFreqIndex() >= 0);
+        assertTrue(atom.getCpuTimePerFreq().getTimeMs() > 0);
+    }
+
     public void testCpuTimePerUidFreq() throws Exception {
         if (!TESTS_ENABLED) {return;}
         StatsdConfig.Builder config = getPulledAndAnomalyConfig();
diff --git a/tests/framework/base/activitymanager/AndroidManifest.xml b/tests/framework/base/activitymanager/AndroidManifest.xml
index 4ca4a5d..15c07be 100644
--- a/tests/framework/base/activitymanager/AndroidManifest.xml
+++ b/tests/framework/base/activitymanager/AndroidManifest.xml
@@ -22,6 +22,7 @@
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
     <uses-permission android:name="android.permission.ACTIVITY_EMBEDDING" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
 
     <application android:label="CtsActivityManagerDeviceTestCases">
         <uses-library android:name="android.test.runner" />
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityAndWindowManagerOverrideConfigTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityAndWindowManagerOverrideConfigTests.java
index 12bfb78..116c026 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityAndWindowManagerOverrideConfigTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityAndWindowManagerOverrideConfigTests.java
@@ -18,6 +18,8 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.server.am.StateLogger.log;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -71,21 +73,23 @@
 
         launchActivity(TEST_ACTIVITY_NAME, WINDOWING_MODE_FREEFORM);
 
-        setDeviceRotation(0);
-        String logSeparator = clearLogcat();
-        resizeActivityTask(TEST_ACTIVITY_NAME, 0, 0, 100, 100);
-        ConfigurationChangeObserver c = new ConfigurationChangeObserver();
-        final boolean reportedSizeAfterResize = c.findConfigurationChange(TEST_ACTIVITY_NAME,
-                logSeparator);
-        assertTrue("Expected to observe configuration change when resizing",
-                reportedSizeAfterResize);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(ROTATION_0);
+            String logSeparator = clearLogcat();
+            resizeActivityTask(TEST_ACTIVITY_NAME, 0, 0, 100, 100);
+            ConfigurationChangeObserver c = new ConfigurationChangeObserver();
+            final boolean reportedSizeAfterResize = c.findConfigurationChange(TEST_ACTIVITY_NAME,
+                    logSeparator);
+            assertTrue("Expected to observe configuration change when resizing",
+                    reportedSizeAfterResize);
 
-        logSeparator = clearLogcat();
-        setDeviceRotation(2);
-        final boolean reportedSizeAfterRotation = c.findConfigurationChange(TEST_ACTIVITY_NAME,
-                logSeparator);
-        assertFalse("Not expected to observe configuration change after flip rotation",
-                reportedSizeAfterRotation);
+            logSeparator = clearLogcat();
+            rotationSession.set(ROTATION_180);
+            final boolean reportedSizeAfterRotation = c.findConfigurationChange(TEST_ACTIVITY_NAME,
+                    logSeparator);
+            assertFalse("Not expected to observe configuration change after flip rotation",
+                    reportedSizeAfterRotation);
+        }
     }
 }
 
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
index d32180a..404e5c7 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
@@ -24,6 +24,10 @@
 import static android.server.am.ActivityManagerState.STATE_RESUMED;
 import static android.server.am.StateLogger.log;
 import static android.server.am.StateLogger.logE;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -119,14 +123,17 @@
     public void testConfigurationUpdatesWhenRotatingWhileFullscreen() throws Exception {
         assumeTrue("Skipping test: no rotation support", supportsRotation());
 
-        setDeviceRotation(0);
-        final String logSeparator = clearLogcat();
-        launchActivity(RESIZEABLE_ACTIVITY_NAME,
-                WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
-        final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
-                logSeparator);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(ROTATION_0);
 
-        rotateAndCheckSizes(initialSizes);
+            final String logSeparator = clearLogcat();
+            launchActivity(RESIZEABLE_ACTIVITY_NAME,
+                    WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+                    logSeparator);
+
+            rotateAndCheckSizes(rotationSession, initialSizes);
+        }
     }
 
     /**
@@ -138,17 +145,20 @@
     public void testConfigurationUpdatesWhenRotatingWhileDocked() throws Exception {
         assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
 
-        setDeviceRotation(0);
-        final String logSeparator = clearLogcat();
-        // Launch our own activity to side in case Recents (or other activity to side) doesn't
-        // support rotation.
-        launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
-        // Launch target activity in docked stack.
-        getLaunchActivityBuilder().setTargetActivityName(RESIZEABLE_ACTIVITY_NAME).execute();
-        final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
-                logSeparator);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(ROTATION_0);
 
-        rotateAndCheckSizes(initialSizes);
+            final String logSeparator = clearLogcat();
+            // Launch our own activity to side in case Recents (or other activity to side) doesn't
+            // support rotation.
+            launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME);
+            // Launch target activity in docked stack.
+            getLaunchActivityBuilder().setTargetActivityName(RESIZEABLE_ACTIVITY_NAME).execute();
+            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+                    logSeparator);
+
+            rotateAndCheckSizes(rotationSession, initialSizes);
+        }
     }
 
     /**
@@ -160,23 +170,27 @@
     public void testConfigurationUpdatesWhenRotatingToSideFromDocked() throws Exception {
         assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
 
-        setDeviceRotation(0);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(ROTATION_0);
 
-        final String logSeparator = clearLogcat();
-        launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, RESIZEABLE_ACTIVITY_NAME);
-        final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
-                logSeparator);
+            final String logSeparator = clearLogcat();
+            launchActivitiesInSplitScreen(LAUNCHING_ACTIVITY, RESIZEABLE_ACTIVITY_NAME);
+            final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
+                    logSeparator);
 
-        rotateAndCheckSizes(initialSizes);
+            rotateAndCheckSizes(rotationSession, initialSizes);
+        }
     }
 
-    private void rotateAndCheckSizes(ReportedSizes prevSizes) throws Exception {
-        for (int rotation = 3; rotation >= 0; --rotation) {
+    private void rotateAndCheckSizes(RotationSession rotationSession, ReportedSizes prevSizes)
+            throws Exception {
+        final int[] rotations = { ROTATION_270, ROTATION_180, ROTATION_90, ROTATION_0 };
+        for (final int rotation : rotations) {
             final String logSeparator = clearLogcat();
             final int actualStackId = mAmWmState.getAmState().getTaskByActivityName(
                     RESIZEABLE_ACTIVITY_NAME).mStackId;
             final int displayId = mAmWmState.getAmState().getStackById(actualStackId).mDisplayId;
-            setDeviceRotation(rotation);
+            rotationSession.set(rotation);
             final int newDeviceRotation = getDeviceRotation(displayId);
             if (newDeviceRotation == INVALID_DEVICE_ROTATION) {
                 logE("Got an invalid device rotation value. "
@@ -356,14 +370,16 @@
 
     @Test
     public void testNonFullscreenActivityPermitted() throws Exception {
-        setDeviceRotation(0);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(ROTATION_0);
 
-        launchActivity(SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY);
-        mAmWmState.assertResumedActivity(
-                "target SDK <= 26 non-fullscreen activity should be allowed to launch",
-                SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY);
-        assertEquals("non-fullscreen activity requested landscape orientation",
-                0 /* landscape */, mAmWmState.getWmState().getLastOrientation());
+            launchActivity(SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY);
+            mAmWmState.assertResumedActivity(
+                    "target SDK <= 26 non-fullscreen activity should be allowed to launch",
+                    SDK26_TRANSLUCENT_LANDSCAPE_ACTIVITY);
+            assertEquals("non-fullscreen activity requested landscape orientation",
+                    0 /* landscape */, mAmWmState.getWmState().getLastOrientation());
+        }
     }
 
     /**
@@ -428,11 +444,12 @@
     @Presubmit
     @Test
     public void testSplitscreenPortraitAppOrientationRequests() throws Exception {
-        if (!supportsSplitScreenMultiWindow()) {
-          log("Skipping test: no multi-window support");
-          return;
+        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
+
+        try (final RotationSession rotationSession = new RotationSession()) {
+            requestOrientationInSplitScreen(rotationSession,
+                    ROTATION_90 /* portrait */, LANDSCAPE_ACTIVITY_NAME);
         }
-        requestOrientationInSplitScreen(1 /* portrait */, LANDSCAPE_ACTIVITY_NAME);
     }
 
     /**
@@ -441,23 +458,24 @@
     @Presubmit
     @Test
     public void testSplitscreenLandscapeAppOrientationRequests() throws Exception {
-        if (!supportsSplitScreenMultiWindow()) {
-          log("Skipping test: no multi-window support");
-          return;
+        assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
+
+        try (final RotationSession rotationSession = new RotationSession()) {
+            requestOrientationInSplitScreen(rotationSession,
+                    ROTATION_0 /* landscape */, PORTRAIT_ACTIVITY_NAME);
         }
-        requestOrientationInSplitScreen(0 /* landscape */, PORTRAIT_ACTIVITY_NAME);
     }
 
     /**
      * Rotate the device and launch specified activity in split-screen, checking if orientation
      * didn't change.
      */
-    private void requestOrientationInSplitScreen(int orientation, String activity)
-            throws Exception {
+    private void requestOrientationInSplitScreen(RotationSession rotationSession, int orientation,
+            String activity) throws Exception {
         assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
 
         // Set initial orientation.
-        setDeviceRotation(orientation);
+        rotationSession.set(orientation);
 
         // Launch activities that request orientations and check that device doesn't rotate.
         launchActivitiesInSplitScreen(
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
index 3320944..718fe85 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
@@ -30,6 +30,8 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.server.am.settings.SettingsSession;
 import android.support.test.filters.FlakyTest;
 
 import org.junit.Test;
@@ -66,17 +68,19 @@
     @Presubmit
     public void testLaunchingAssistantActivityIntoAssistantStack() throws Exception {
         // Enable the assistant and launch an assistant activity
-        enableAssistant();
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
-        mAmWmState.waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
+        try (final AssistantSession assistantSession = new AssistantSession()) {
+            assistantSession.set(getActivityComponentName(VOICE_INTERACTION_SERVICE));
 
-        // Ensure that the activity launched in the fullscreen assistant stack
-        assertAssistantStackExists();
-        assertTrue("Expected assistant stack to be fullscreen",
-                mAmWmState.getAmState().getStackByActivityType(
-                        ACTIVITY_TYPE_ASSISTANT).isFullscreen());
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
+            mAmWmState.waitForValidStateWithActivityType(ASSISTANT_ACTIVITY,
+                    ACTIVITY_TYPE_ASSISTANT);
 
-        disableAssistant();
+            // Ensure that the activity launched in the fullscreen assistant stack
+            assertAssistantStackExists();
+            assertTrue("Expected assistant stack to be fullscreen",
+                    mAmWmState.getAmState().getStackByActivityType(
+                            ACTIVITY_TYPE_ASSISTANT).isFullscreen());
+        }
     }
 
     @FlakyTest(bugId = 69573940)
@@ -100,25 +104,25 @@
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
 
         // Enable the assistant and launch an assistant activity, ensure it is on top
-        enableAssistant();
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
-        mAmWmState.waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
-        assertAssistantStackExists();
+        try (final AssistantSession assistantSession = new AssistantSession()) {
+            assistantSession.set(getActivityComponentName(VOICE_INTERACTION_SERVICE));
 
-        mAmWmState.assertFrontStack("Pinned stack should be on top.",
-                WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
-        mAmWmState.assertFocusedStack("Assistant stack should be focused.",
-                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
+            mAmWmState.waitForValidStateWithActivityType(ASSISTANT_ACTIVITY,
+                    ACTIVITY_TYPE_ASSISTANT);
+            assertAssistantStackExists();
 
-        disableAssistant();
+            mAmWmState.assertFrontStack("Pinned stack should be on top.",
+                    WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
+            mAmWmState.assertFocusedStack("Assistant stack should be focused.",
+                    WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
+        }
     }
 
     @Test
     @Presubmit
     public void testAssistantStackLaunchNewTask() throws Exception {
-        enableAssistant();
         assertAssistantStackCanLaunchAndReturnFromNewTask();
-        disableAssistant();
     }
 
     @Test
@@ -133,9 +137,7 @@
         mAmWmState.assertContainsStack("Must contain docked stack.",
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
 
-        enableAssistant();
         assertAssistantStackCanLaunchAndReturnFromNewTask();
-        disableAssistant();
     }
 
     private void assertAssistantStackCanLaunchAndReturnFromNewTask() throws Exception {
@@ -143,10 +145,12 @@
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
 
         // Enable the assistant and launch an assistant activity which will launch a new task
-        enableAssistant();
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
-                EXTRA_LAUNCH_NEW_TASK, TEST_ACTIVITY);
-        disableAssistant();
+        try (final AssistantSession assistantSession = new AssistantSession()) {
+            assistantSession.set(getActivityComponentName(VOICE_INTERACTION_SERVICE));
+
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
+                    EXTRA_LAUNCH_NEW_TASK, TEST_ACTIVITY);
+        }
 
         final int expectedWindowingMode = inSplitScreenMode
                 ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
@@ -174,10 +178,12 @@
         // Launch an assistant activity on top of an existing fullscreen activity, and ensure that
         // the fullscreen activity is still visible and on top after the assistant activity finishes
         launchActivity(TEST_ACTIVITY);
-        enableAssistant();
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
-                EXTRA_FINISH_SELF, "true");
-        disableAssistant();
+        try (final AssistantSession assistantSession = new AssistantSession()) {
+            assistantSession.set(getActivityComponentName(VOICE_INTERACTION_SERVICE));
+
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
+                    EXTRA_FINISH_SELF, "true");
+        }
         mAmWmState.waitForValidState(TEST_ACTIVITY,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         mAmWmState.waitForActivityState(TEST_ACTIVITY, STATE_RESUMED);
@@ -191,10 +197,12 @@
     @Test
     @Presubmit
     public void testDisallowEnterPiPFromAssistantStack() throws Exception {
-        enableAssistant();
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
-                EXTRA_ENTER_PIP, "true");
-        disableAssistant();
+        try (final AssistantSession assistantSession = new AssistantSession()) {
+            assistantSession.set(getActivityComponentName(VOICE_INTERACTION_SERVICE));
+
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
+                    EXTRA_ENTER_PIP, "true");
+        }
         mAmWmState.waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
         mAmWmState.assertDoesNotContainStack("Must not contain pinned stack.",
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
@@ -204,102 +212,107 @@
     @Presubmit
     @Test
     public void testTranslucentAssistantActivityStackVisibility() throws Exception {
-        enableAssistant();
-        // Go home, launch the assistant and check to see that home is visible
-        removeStacksInWindowingModes(WINDOWING_MODE_FULLSCREEN,
-                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
-        launchHomeActivity();
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
-                EXTRA_IS_TRANSLUCENT, String.valueOf(true));
-        mAmWmState.waitForValidStateWithActivityType(
-                TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
-        assertAssistantStackExists();
-        mAmWmState.waitForHomeActivityVisible();
-        if (hasHomeScreen()) {
-            mAmWmState.assertHomeActivityVisible(true);
-        }
+        try (final AssistantSession assistantSession = new AssistantSession()) {
+            assistantSession.set(getActivityComponentName(VOICE_INTERACTION_SERVICE));
 
-        // Launch a fullscreen app and then launch the assistant and check to see that it is
-        // also visible
-        removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
-        launchActivity(TEST_ACTIVITY);
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
-                EXTRA_IS_TRANSLUCENT, String.valueOf(true));
-        mAmWmState.waitForValidStateWithActivityType(
-                TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
-        assertAssistantStackExists();
-        mAmWmState.assertVisibility(TEST_ACTIVITY, true);
-
-        // Go home, launch assistant, launch app into fullscreen with activity present, and go back.
-        // Ensure home is visible.
-        removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
-        launchHomeActivity();
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
-                EXTRA_IS_TRANSLUCENT, String.valueOf(true), EXTRA_LAUNCH_NEW_TASK,
-                TEST_ACTIVITY);
-        mAmWmState.waitForValidState(TEST_ACTIVITY,
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        mAmWmState.assertHomeActivityVisible(false);
-        pressBackButton();
-        mAmWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
-        assertAssistantStackExists();
-        mAmWmState.waitForHomeActivityVisible();
-        if (hasHomeScreen()) {
-            mAmWmState.assertHomeActivityVisible(true);
-        }
-
-        // Launch a fullscreen and docked app and then launch the assistant and check to see that it
-        // is also visible
-        if (supportsSplitScreenMultiWindow()) {
-            removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
-            launchActivitiesInSplitScreen(DOCKED_ACTIVITY, TEST_ACTIVITY);
-            mAmWmState.assertContainsStack("Must contain docked stack.",
-                    WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
+            // Go home, launch the assistant and check to see that home is visible
+            removeStacksInWindowingModes(WINDOWING_MODE_FULLSCREEN,
+                    WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+            launchHomeActivity();
             launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
                     EXTRA_IS_TRANSLUCENT, String.valueOf(true));
             mAmWmState.waitForValidStateWithActivityType(
                     TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
             assertAssistantStackExists();
-            mAmWmState.assertVisibility(DOCKED_ACTIVITY, true);
+            mAmWmState.waitForHomeActivityVisible();
+            if (hasHomeScreen()) {
+                mAmWmState.assertHomeActivityVisible(true);
+            }
+
+            // Launch a fullscreen app and then launch the assistant and check to see that it is
+            // also visible
+            removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
+            launchActivity(TEST_ACTIVITY);
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
+                    EXTRA_IS_TRANSLUCENT, String.valueOf(true));
+            mAmWmState.waitForValidStateWithActivityType(
+                    TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
+            assertAssistantStackExists();
             mAmWmState.assertVisibility(TEST_ACTIVITY, true);
+
+            // Go home, launch assistant, launch app into fullscreen with activity present, and go back.
+
+            // Ensure home is visible.
+            removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
+            launchHomeActivity();
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
+                    EXTRA_IS_TRANSLUCENT, String.valueOf(true), EXTRA_LAUNCH_NEW_TASK,
+                    TEST_ACTIVITY);
+            mAmWmState.waitForValidState(TEST_ACTIVITY,
+                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+            mAmWmState.assertHomeActivityVisible(false);
+            pressBackButton();
+            mAmWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
+            assertAssistantStackExists();
+            mAmWmState.waitForHomeActivityVisible();
+            if (hasHomeScreen()) {
+                mAmWmState.assertHomeActivityVisible(true);
+            }
+
+            // Launch a fullscreen and docked app and then launch the assistant and check to see
+            // that it
+            // is also visible
+            if (supportsSplitScreenMultiWindow()) {
+                removeStacksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
+                launchActivitiesInSplitScreen(DOCKED_ACTIVITY, TEST_ACTIVITY);
+                mAmWmState.assertContainsStack("Must contain docked stack.",
+                        WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
+                launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
+                        EXTRA_IS_TRANSLUCENT, String.valueOf(true));
+                mAmWmState.waitForValidStateWithActivityType(
+                        TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
+                assertAssistantStackExists();
+                mAmWmState.assertVisibility(DOCKED_ACTIVITY, true);
+                mAmWmState.assertVisibility(TEST_ACTIVITY, true);
+            }
         }
-        disableAssistant();
     }
 
     @FlakyTest(bugId = 69229402)
     @Test
     @Presubmit
     public void testLaunchIntoSameTask() throws Exception {
-        enableAssistant();
+        try (final AssistantSession assistantSession = new AssistantSession()) {
+            assistantSession.set(getActivityComponentName(VOICE_INTERACTION_SERVICE));
 
-        // Launch the assistant
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
-        assertAssistantStackExists();
-        mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
-        mAmWmState.assertFocusedStack("Expected assistant stack focused",
-                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
-        assertEquals(1, mAmWmState.getAmState().getStackByActivityType(
-                ACTIVITY_TYPE_ASSISTANT).getTasks().size());
-        final int taskId = mAmWmState.getAmState().getTaskByActivityName(ASSISTANT_ACTIVITY)
-                .mTaskId;
+            // Launch the assistant
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
+            assertAssistantStackExists();
+            mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
+            mAmWmState.assertFocusedStack("Expected assistant stack focused",
+                    WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
+            assertEquals(1, mAmWmState.getAmState().getStackByActivityType(
+                    ACTIVITY_TYPE_ASSISTANT).getTasks().size());
+            final int taskId = mAmWmState.getAmState().getTaskByActivityName(ASSISTANT_ACTIVITY)
+                    .mTaskId;
 
-        // Launch a new fullscreen activity
-        // Using Animation Test Activity because it is opaque on all devices.
-        launchActivity(ANIMATION_TEST_ACTIVITY);
-        mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, false);
+            // Launch a new fullscreen activity
+            // Using Animation Test Activity because it is opaque on all devices.
+            launchActivity(ANIMATION_TEST_ACTIVITY);
+            mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, false);
 
-        // Launch the assistant again and ensure that it goes into the same task
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
-        assertAssistantStackExists();
-        mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
-        mAmWmState.assertFocusedStack("Expected assistant stack focused",
-                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
-        assertEquals(1, mAmWmState.getAmState().getStackByActivityType(
-                ACTIVITY_TYPE_ASSISTANT).getTasks().size());
-        assertEquals(taskId,
-                mAmWmState.getAmState().getTaskByActivityName(ASSISTANT_ACTIVITY).mTaskId);
+            // Launch the assistant again and ensure that it goes into the same task
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
+            assertAssistantStackExists();
+            mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
+            mAmWmState.assertFocusedStack("Expected assistant stack focused",
+                    WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
+            assertEquals(1, mAmWmState.getAmState().getStackByActivityType(
+                    ACTIVITY_TYPE_ASSISTANT).getTasks().size());
+            assertEquals(taskId,
+                    mAmWmState.getAmState().getTaskByActivityName(ASSISTANT_ACTIVITY).mTaskId);
 
-        disableAssistant();
+        }
     }
 
     @Test
@@ -307,22 +320,24 @@
         assumeTrue(supportsPip());
         assumeTrue(supportsSplitScreenMultiWindow());
 
-        enableAssistant();
+        try (final AssistantSession assistantSession = new AssistantSession()) {
+            assistantSession.set(getActivityComponentName(VOICE_INTERACTION_SERVICE));
 
-        // Launch a fullscreen activity and a PIP activity, then launch the assistant, and ensure
-        // that the test activity is still visible
-        launchActivity(TEST_ACTIVITY);
-        launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
-        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
-                EXTRA_IS_TRANSLUCENT, String.valueOf(true));
-        mAmWmState.waitForValidStateWithActivityType(
-                TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
-        assertAssistantStackExists();
-        mAmWmState.assertVisibility(TRANSLUCENT_ASSISTANT_ACTIVITY, true);
-        mAmWmState.assertVisibility(PIP_ACTIVITY, true);
-        mAmWmState.assertVisibility(TEST_ACTIVITY, true);
+            // Launch a fullscreen activity and a PIP activity, then launch the assistant, and ensure
 
-        disableAssistant();
+            // that the test activity is still visible
+            launchActivity(TEST_ACTIVITY);
+            launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
+            launchActivity(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
+                    EXTRA_IS_TRANSLUCENT, String.valueOf(true));
+            mAmWmState.waitForValidStateWithActivityType(
+                    TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
+            assertAssistantStackExists();
+            mAmWmState.assertVisibility(TRANSLUCENT_ASSISTANT_ACTIVITY, true);
+            mAmWmState.assertVisibility(PIP_ACTIVITY, true);
+            mAmWmState.assertVisibility(TEST_ACTIVITY, true);
+
+        }
     }
 
     /**
@@ -333,18 +348,13 @@
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
     }
 
-    /**
-     * Sets the system voice interaction service.
+    /** Helper class to save, set, and restore
+     * {@link Settings.Secure#VOICE_INTERACTION_SERVICE} system preference.
      */
-    private void enableAssistant() throws Exception {
-        executeShellCommand("settings put secure voice_interaction_service " +
-                getActivityComponentName(VOICE_INTERACTION_SERVICE));
-    }
-
-    /**
-     * Resets the system voice interaction service.
-     */
-    private void disableAssistant() throws Exception {
-        executeShellCommand("settings delete secure voice_interaction_service");
+    private static class AssistantSession extends SettingsSession<String> {
+        AssistantSession() {
+            super(Settings.Secure.getUriFor(Settings.Secure.VOICE_INTERACTION_SERVICE),
+                    Settings.Secure::getString, Settings.Secure::putString);
+        }
     }
 }
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
index 19b8399..a6760c3 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
@@ -24,6 +24,8 @@
 import static org.junit.Assert.fail;
 
 import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.server.am.settings.SettingsSession;
 
 import org.junit.Test;
 
@@ -82,60 +84,73 @@
         testChangeFontScale(FONT_SCALE_NO_RELAUNCH_ACTIVITY_NAME, false /* relaunch */);
     }
 
-    private void testRotation(
-            String activityName, int rotationStep, int numRelaunch, int numConfigChange)
-                    throws Exception {
+    private void testRotation(String activityName, int rotationStep, int numRelaunch,
+            int numConfigChange) throws Exception {
         launchActivity(activityName);
 
         final String[] waitForActivitiesVisible = new String[] {activityName};
         mAmWmState.computeState(waitForActivitiesVisible);
 
         final int initialRotation = 4 - rotationStep;
-        setDeviceRotation(initialRotation);
-        mAmWmState.computeState(waitForActivitiesVisible);
-        final int actualStackId = mAmWmState.getAmState().getTaskByActivityName(
-                activityName).mStackId;
-        final int displayId = mAmWmState.getAmState().getStackById(actualStackId).mDisplayId;
-        final int newDeviceRotation = getDeviceRotation(displayId);
-        if (newDeviceRotation == INVALID_DEVICE_ROTATION) {
-            logE("Got an invalid device rotation value. "
-                    + "Continuing the test despite of that, but it is likely to fail.");
-        } else if (newDeviceRotation != initialRotation) {
-            log("This device doesn't support user rotation "
-                    + "mode. Not continuing the rotation checks.");
-            return;
-        }
-
-        for (int rotation = 0; rotation < 4; rotation += rotationStep) {
-            final String logSeparator = clearLogcat();
-            setDeviceRotation(rotation);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(initialRotation);
             mAmWmState.computeState(waitForActivitiesVisible);
-            assertRelaunchOrConfigChanged(activityName, numRelaunch, numConfigChange, logSeparator);
+            final int actualStackId = mAmWmState.getAmState().getTaskByActivityName(
+                    activityName).mStackId;
+            final int displayId = mAmWmState.getAmState().getStackById(actualStackId).mDisplayId;
+            final int newDeviceRotation = getDeviceRotation(displayId);
+            if (newDeviceRotation == INVALID_DEVICE_ROTATION) {
+                logE("Got an invalid device rotation value. "
+                        + "Continuing the test despite of that, but it is likely to fail.");
+            } else if (newDeviceRotation != initialRotation) {
+                log("This device doesn't support user rotation "
+                        + "mode. Not continuing the rotation checks.");
+                return;
+            }
+
+            for (int rotation = 0; rotation < 4; rotation += rotationStep) {
+                final String logSeparator = clearLogcat();
+                rotationSession.set(rotation);
+                mAmWmState.computeState(waitForActivitiesVisible);
+                assertRelaunchOrConfigChanged(activityName, numRelaunch, numConfigChange,
+                        logSeparator);
+            }
+        }
+    }
+
+    /** Helper class to save, set, and restore font_scale preferences. */
+    private static class FontScaleSession extends SettingsSession<Float> {
+        FontScaleSession() {
+            super(Settings.System.getUriFor(Settings.System.FONT_SCALE),
+                    Settings.System::getFloat,
+                    Settings.System::putFloat);
         }
     }
 
     private void testChangeFontScale(
             String activityName, boolean relaunch) throws Exception {
-        setFontScale(1.0f);
-        String logSeparator = clearLogcat();
-        launchActivity(activityName);
-        final String[] waitForActivitiesVisible = new String[] {activityName};
-        mAmWmState.computeState(waitForActivitiesVisible);
-
-        final int densityDpi = getActivityDensityDpi(activityName, logSeparator);
-
-        for (float fontScale = 0.85f; fontScale <= 1.3f; fontScale += 0.15f) {
-            logSeparator = clearLogcat();
-            setFontScale(fontScale);
+        try (final FontScaleSession fontScaleSession = new FontScaleSession()) {
+            fontScaleSession.set(1.0f);
+            String logSeparator = clearLogcat();
+            launchActivity(activityName);
+            final String[] waitForActivitiesVisible = new String[]{activityName};
             mAmWmState.computeState(waitForActivitiesVisible);
-            assertRelaunchOrConfigChanged(activityName, relaunch ? 1 : 0, relaunch ? 0 : 1,
-                    logSeparator);
 
-            // Verify that the display metrics are updated, and therefore the text size is also
-            // updated accordingly.
-            assertExpectedFontPixelSize(activityName,
-                    scaledPixelsToPixels(EXPECTED_FONT_SIZE_SP, fontScale, densityDpi),
-                    logSeparator);
+            final int densityDpi = getActivityDensityDpi(activityName, logSeparator);
+
+            for (float fontScale = 0.85f; fontScale <= 1.3f; fontScale += 0.15f) {
+                logSeparator = clearLogcat();
+                fontScaleSession.set(fontScale);
+                mAmWmState.computeState(waitForActivitiesVisible);
+                assertRelaunchOrConfigChanged(activityName, relaunch ? 1 : 0, relaunch ? 0 : 1,
+                        logSeparator);
+
+                // Verify that the display metrics are updated, and therefore the text size is also
+                // updated accordingly.
+                assertExpectedFontPixelSize(activityName,
+                        scaledPixelsToPixels(EXPECTED_FONT_SIZE_SP, fontScale, densityDpi),
+                        logSeparator);
+            }
         }
     }
 
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
index 58143db..3229905 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerDisplayTests.java
@@ -1487,7 +1487,7 @@
      */
     @Test
     public void testMoveToEmptyDisplayOnLaunch() throws Exception {
-        if (!supportsMultiDisplay()) { return; }
+        assumeTrue(supportsMultiDisplay());
 
         // Launch activity with unique affinity, so it will the only one in its task.
         launchActivity(LAUNCHING_ACTIVITY);
@@ -1550,28 +1550,32 @@
                 RESIZEABLE_ACTIVITY_NAME, logSeparator);
         assertNotNull("Test activity must have reported initial sizes on launch", initialSizes);
 
-        // Rotate primary display and check that activity on secondary display is not affected.
-        rotateAndCheckSameSizes(RESIZEABLE_ACTIVITY_NAME);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            // Rotate primary display and check that activity on secondary display is not affected.
+            rotateAndCheckSameSizes(rotationSession, RESIZEABLE_ACTIVITY_NAME);
 
-        // Launch activity to secondary display when primary one is rotated.
-        final int initialRotation = mAmWmState.getWmState().getRotation();
-        setDeviceRotation((initialRotation + 1) % 4);
+            // Launch activity to secondary display when primary one is rotated.
+            final int initialRotation = mAmWmState.getWmState().getRotation();
+            rotationSession.set((initialRotation + 1) % 4);
 
-        logSeparator = clearLogcat();
-        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
-        mAmWmState.waitForActivityState(TEST_ACTIVITY_NAME, STATE_RESUMED);
-        mAmWmState.assertFocusedActivity("Focus must be on secondary display",
-                TEST_ACTIVITY_NAME);
-        final ReportedSizes testActivitySizes = getLastReportedSizesForActivity(
-                TEST_ACTIVITY_NAME, logSeparator);
-        assertEquals("Sizes of secondary display must not change after rotation of primary display",
-                initialSizes, testActivitySizes);
+            logSeparator = clearLogcat();
+            launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mId);
+            mAmWmState.waitForActivityState(TEST_ACTIVITY_NAME, STATE_RESUMED);
+            mAmWmState.assertFocusedActivity("Focus must be on secondary display",
+                    TEST_ACTIVITY_NAME);
+            final ReportedSizes testActivitySizes = getLastReportedSizesForActivity(
+                    TEST_ACTIVITY_NAME, logSeparator);
+            assertEquals(
+                    "Sizes of secondary display must not change after rotation of primary display",
+                    initialSizes, testActivitySizes);
+        }
     }
 
-    private void rotateAndCheckSameSizes(String activityName) throws Exception {
+    private void rotateAndCheckSameSizes(RotationSession rotationSession, String activityName)
+            throws Exception {
         for (int rotation = 3; rotation >= 0; --rotation) {
             final String logSeparator = clearLogcat();
-            setDeviceRotation(rotation);
+            rotationSession.set(rotation);
             final ReportedSizes rotatedSizes = getLastReportedSizesForActivity(activityName,
                     logSeparator);
             assertNull("Sizes must not change after rotation", rotatedSizes);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
index 22f1de0..5ba794d 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerPinnedStackTests.java
@@ -38,8 +38,10 @@
 
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
 import android.server.am.ActivityManagerState.ActivityStack;
 import android.server.am.ActivityManagerState.ActivityTask;
+import android.server.am.settings.SettingsSession;
 import android.support.test.filters.FlakyTest;
 
 import org.junit.Test;
@@ -196,22 +198,24 @@
         // Launch a PIP activity
         launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
 
-        setDeviceRotation(ROTATION_0);
-        WindowManagerState wmState = mAmWmState.getWmState();
-        wmState.computeState();
-        Rect defaultPipBounds = wmState.getDefaultPinnedStackBounds();
-        Rect stableBounds = wmState.getStableBounds();
-        assertTrue(defaultPipBounds.width() > 0 && defaultPipBounds.height() > 0);
-        assertTrue(stableBounds.contains(defaultPipBounds));
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(ROTATION_0);
 
-        setDeviceRotation(ROTATION_90);
-        wmState = mAmWmState.getWmState();
-        wmState.computeState();
-        defaultPipBounds = wmState.getDefaultPinnedStackBounds();
-        stableBounds = wmState.getStableBounds();
-        assertTrue(defaultPipBounds.width() > 0 && defaultPipBounds.height() > 0);
-        assertTrue(stableBounds.contains(defaultPipBounds));
-        setDeviceRotation(ROTATION_0);
+            WindowManagerState wmState = mAmWmState.getWmState();
+            wmState.computeState();
+            Rect defaultPipBounds = wmState.getDefaultPinnedStackBounds();
+            Rect stableBounds = wmState.getStableBounds();
+            assertTrue(defaultPipBounds.width() > 0 && defaultPipBounds.height() > 0);
+            assertTrue(stableBounds.contains(defaultPipBounds));
+
+            rotationSession.set(ROTATION_90);
+            wmState = mAmWmState.getWmState();
+            wmState.computeState();
+            defaultPipBounds = wmState.getDefaultPinnedStackBounds();
+            stableBounds = wmState.getStableBounds();
+            assertTrue(defaultPipBounds.width() > 0 && defaultPipBounds.height() > 0);
+            assertTrue(stableBounds.contains(defaultPipBounds));
+        }
     }
 
     @Test
@@ -221,22 +225,23 @@
         // Launch a PIP activity
         launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
 
-        setDeviceRotation(ROTATION_0);
-        WindowManagerState wmState = mAmWmState.getWmState();
-        wmState.computeState();
-        Rect pipMovementBounds = wmState.getPinnedStackMomentBounds();
-        Rect stableBounds = wmState.getStableBounds();
-        assertTrue(pipMovementBounds.width() > 0 && pipMovementBounds.height() > 0);
-        assertTrue(stableBounds.contains(pipMovementBounds));
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(ROTATION_0);
+            WindowManagerState wmState = mAmWmState.getWmState();
+            wmState.computeState();
+            Rect pipMovementBounds = wmState.getPinnedStackMomentBounds();
+            Rect stableBounds = wmState.getStableBounds();
+            assertTrue(pipMovementBounds.width() > 0 && pipMovementBounds.height() > 0);
+            assertTrue(stableBounds.contains(pipMovementBounds));
 
-        setDeviceRotation(ROTATION_90);
-        wmState = mAmWmState.getWmState();
-        wmState.computeState();
-        pipMovementBounds = wmState.getPinnedStackMomentBounds();
-        stableBounds = wmState.getStableBounds();
-        assertTrue(pipMovementBounds.width() > 0 && pipMovementBounds.height() > 0);
-        assertTrue(stableBounds.contains(pipMovementBounds));
-        setDeviceRotation(ROTATION_0);
+            rotationSession.set(ROTATION_90);
+            wmState = mAmWmState.getWmState();
+            wmState.computeState();
+            pipMovementBounds = wmState.getPinnedStackMomentBounds();
+            stableBounds = wmState.getStableBounds();
+            assertTrue(pipMovementBounds.width() > 0 && pipMovementBounds.height() > 0);
+            assertTrue(stableBounds.contains(pipMovementBounds));
+        }
     }
 
     @Test
@@ -282,15 +287,16 @@
         mAmWmState.waitForValidState(PIP_ACTIVITY, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
 
         // Ensure that the PIP stack is fully visible in each orientation
-        setDeviceRotation(ROTATION_0);
-        assertPinnedStackActivityIsInDisplayBounds(PIP_ACTIVITY);
-        setDeviceRotation(ROTATION_90);
-        assertPinnedStackActivityIsInDisplayBounds(PIP_ACTIVITY);
-        setDeviceRotation(ROTATION_180);
-        assertPinnedStackActivityIsInDisplayBounds(PIP_ACTIVITY);
-        setDeviceRotation(ROTATION_270);
-        assertPinnedStackActivityIsInDisplayBounds(PIP_ACTIVITY);
-        setDeviceRotation(ROTATION_0);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(ROTATION_0);
+            assertPinnedStackActivityIsInDisplayBounds(PIP_ACTIVITY);
+            rotationSession.set(ROTATION_90);
+            assertPinnedStackActivityIsInDisplayBounds(PIP_ACTIVITY);
+            rotationSession.set(ROTATION_180);
+            assertPinnedStackActivityIsInDisplayBounds(PIP_ACTIVITY);
+            rotationSession.set(ROTATION_270);
+            assertPinnedStackActivityIsInDisplayBounds(PIP_ACTIVITY);
+        }
     }
 
     @Test
@@ -836,38 +842,48 @@
         assertValidPictureInPictureCallbackOrder(PIP_ACTIVITY, logSeparator);
     }
 
+    /** Helper class to save, set, and restore transition_animation_scale preferences. */
+    private static class TransitionAnimationScaleSession extends SettingsSession<Float> {
+        TransitionAnimationScaleSession() {
+            super(Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE),
+                    Settings.Global::getFloat,
+                    Settings.Global::putFloat);
+        }
+    }
+
     @Test
     public void testEnterPipInterruptedCallbacks() throws Exception {
         assumeTrue(supportsPip());
 
-        // Slow down the transition animations for this test
-        setWindowTransitionAnimationDurationScale(20);
+        try (final TransitionAnimationScaleSession transitionAnimationScaleSession =
+                new TransitionAnimationScaleSession()) {
+            // Slow down the transition animations for this test
+            transitionAnimationScaleSession.set(20f);
 
-        // Launch a PiP activity
-        launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
-        // Wait until the PiP activity has moved into the pinned stack (happens before the
-        // transition has started)
-        mAmWmState.waitForValidState(PIP_ACTIVITY, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
-        assertPinnedStackExists();
+            // Launch a PiP activity
+            launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
+            // Wait until the PiP activity has moved into the pinned stack (happens before the
+            // transition has started)
+            mAmWmState.waitForValidState(PIP_ACTIVITY, WINDOWING_MODE_PINNED,
+                    ACTIVITY_TYPE_STANDARD);
+            assertPinnedStackExists();
 
-        // Relaunch the PiP activity back into fullscreen
-        String logSeparator = clearLogcat();
-        launchActivity(PIP_ACTIVITY);
-        // Wait until the PiP activity is reparented into the fullscreen stack (happens after the
-        // transition has finished)
-        mAmWmState.waitForValidState(
-                PIP_ACTIVITY, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+            // Relaunch the PiP activity back into fullscreen
+            String logSeparator = clearLogcat();
+            launchActivity(PIP_ACTIVITY);
+            // Wait until the PiP activity is reparented into the fullscreen stack (happens after
+            // the transition has finished)
+            mAmWmState.waitForValidState(
+                    PIP_ACTIVITY, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
 
-        // Ensure that we get the callbacks indicating that PiP/MW mode was cancelled, but no
-        // configuration change (since none was sent)
-        final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(
-                PIP_ACTIVITY, logSeparator);
-        assertTrue(lifecycleCounts.mConfigurationChangedCount == 0);
-        assertTrue(lifecycleCounts.mPictureInPictureModeChangedCount == 1);
-        assertTrue(lifecycleCounts.mMultiWindowModeChangedCount == 1);
-
-        // Reset the animation scale
-        setWindowTransitionAnimationDurationScale(1);
+            // Ensure that we get the callbacks indicating that PiP/MW mode was cancelled, but no
+            // configuration change (since none was sent)
+            final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(
+                    PIP_ACTIVITY, logSeparator);
+            assertTrue(lifecycleCounts.mConfigurationChangedCount == 0);
+            assertTrue(lifecycleCounts.mPictureInPictureModeChangedCount == 1);
+            assertTrue(lifecycleCounts.mMultiWindowModeChangedCount == 1);
+        }
     }
 
     @FlakyTest(bugId = 71564769)
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
index 2e3209e..8c793b9 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
@@ -27,6 +27,10 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.server.am.WindowManagerState.TRANSIT_WALLPAPER_OPEN;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -348,22 +352,24 @@
         // Each time we compute the state we implicitly assert valid bounds.
         String[] waitForActivitiesVisible =
             new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
-        for (int i = 0; i < 4; i++) {
-            setDeviceRotation(i);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            for (int i = 0; i < 4; i++) {
+                rotationSession.set(i);
+                mAmWmState.computeState(waitForActivitiesVisible);
+            }
+            // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for
+            // double step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side.
+            rotationSession.set(ROTATION_90);
+            mAmWmState.computeState(waitForActivitiesVisible);
+            rotationSession.set(ROTATION_270);
+            mAmWmState.computeState(waitForActivitiesVisible);
+            rotationSession.set(ROTATION_0);
+            mAmWmState.computeState(waitForActivitiesVisible);
+            rotationSession.set(ROTATION_180);
+            mAmWmState.computeState(waitForActivitiesVisible);
+            rotationSession.set(ROTATION_0);
             mAmWmState.computeState(waitForActivitiesVisible);
         }
-        // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for double
-        // step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side.
-        setDeviceRotation(1);
-        mAmWmState.computeState(waitForActivitiesVisible);
-        setDeviceRotation(3);
-        mAmWmState.computeState(waitForActivitiesVisible);
-        setDeviceRotation(0);
-        mAmWmState.computeState(waitForActivitiesVisible);
-        setDeviceRotation(2);
-        mAmWmState.computeState(waitForActivitiesVisible);
-        setDeviceRotation(0);
-        mAmWmState.computeState(waitForActivitiesVisible);
     }
 
     @Test
@@ -377,27 +383,31 @@
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD);
 
         String[] waitForActivitiesVisible =
-            new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
-        for (int i = 0; i < 4; i++) {
-            sleepDevice();
-            setDeviceRotation(i);
-            wakeUpAndUnlockDevice();
-            mAmWmState.computeState(waitForActivitiesVisible);
+                new String[] {LAUNCHING_ACTIVITY, TEST_ACTIVITY_NAME};
+        try (final RotationSession rotationSession = new RotationSession()) {
+            for (int i = 0; i < 4; i++) {
+                sleepDevice();
+                rotationSession.set(i);
+                wakeUpAndUnlockDevice();
+                mAmWmState.computeState(waitForActivitiesVisible);
+            }
         }
     }
 
     @Test
     public void testMinimizedFromEachDockedSide() throws Exception {
-        for (int i = 0; i < 2; i++) {
-            setDeviceRotation(i);
-            launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME);
-            if (!mAmWmState.isScreenPortrait() && isTablet()) {
-                // Test minimize to the right only on tablets in landscape
+        try (final RotationSession rotationSession = new RotationSession()) {
+            for (int i = 0; i < 2; i++) {
+                rotationSession.set(i);
+                launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME);
+                if (!mAmWmState.isScreenPortrait() && isTablet()) {
+                    // Test minimize to the right only on tablets in landscape
+                    removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
+                    launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME,
+                            SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
+                }
                 removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
-                launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME,
-                        SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
             }
-            removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
         }
     }
 
@@ -409,50 +419,55 @@
         // Rotate device single steps (90°) 0-1-2-3.
         // Each time we compute the state we implicitly assert valid bounds in minimized mode.
         String[] waitForActivitiesVisible = new String[] {TEST_ACTIVITY_NAME};
-        for (int i = 0; i < 4; i++) {
-            setDeviceRotation(i);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            for (int i = 0; i < 4; i++) {
+                rotationSession.set(i);
+                mAmWmState.computeState(waitForActivitiesVisible);
+            }
+
+            // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for
+            // double step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side in
+            // minimized mode.
+            rotationSession.set(ROTATION_90);
+            mAmWmState.computeState(waitForActivitiesVisible);
+            rotationSession.set(ROTATION_270);
+            mAmWmState.computeState(waitForActivitiesVisible);
+            rotationSession.set(ROTATION_0);
+            mAmWmState.computeState(waitForActivitiesVisible);
+            rotationSession.set(ROTATION_180);
+            mAmWmState.computeState(waitForActivitiesVisible);
+            rotationSession.set(ROTATION_0);
             mAmWmState.computeState(waitForActivitiesVisible);
         }
-
-        // Double steps (180°) We ended the single step at 3. So, we jump directly to 1 for double
-        // step. So, we are testing 3-1-3 for one side and 0-2-0 for the other side in minimized
-        // mode.
-        setDeviceRotation(1);
-        mAmWmState.computeState(waitForActivitiesVisible);
-        setDeviceRotation(3);
-        mAmWmState.computeState(waitForActivitiesVisible);
-        setDeviceRotation(0);
-        mAmWmState.computeState(waitForActivitiesVisible);
-        setDeviceRotation(2);
-        mAmWmState.computeState(waitForActivitiesVisible);
-        setDeviceRotation(0);
-        mAmWmState.computeState(waitForActivitiesVisible);
     }
 
     @Test
     public void testMinimizeAndUnminimizeThenGoingHome() throws Exception {
         // Rotate the screen to check that minimize, unminimize, dismiss the docked stack and then
         // going home has the correct app transition
-        for (int i = 0; i < 4; i++) {
-            setDeviceRotation(i);
-            launchActivityInDockStackAndMinimize(DOCKED_ACTIVITY_NAME);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            for (int i = 0; i < 4; i++) {
+                rotationSession.set(i);
+                launchActivityInDockStackAndMinimize(DOCKED_ACTIVITY_NAME);
 
-            // Unminimize the docked stack
-            pressAppSwitchButton();
-            waitForDockNotMinimized();
-            assertDockNotMinimized();
+                // Unminimize the docked stack
+                pressAppSwitchButton();
+                waitForDockNotMinimized();
+                assertDockNotMinimized();
 
-            // Dismiss the dock stack
-            launchActivity(TEST_ACTIVITY_NAME, WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
-            setActivityTaskWindowingMode(DOCKED_ACTIVITY_NAME,
-                    WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
-            mAmWmState.computeState(new String[]{DOCKED_ACTIVITY_NAME});
+                // Dismiss the dock stack
+                launchActivity(TEST_ACTIVITY_NAME,
+                        WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+                setActivityTaskWindowingMode(DOCKED_ACTIVITY_NAME,
+                        WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+                mAmWmState.computeState(new String[]{DOCKED_ACTIVITY_NAME});
 
-            // Go home and check the app transition
-            assertNotSame(TRANSIT_WALLPAPER_OPEN, mAmWmState.getWmState().getLastTransition());
-            pressHomeButton();
-            mAmWmState.computeState();
-            assertEquals(TRANSIT_WALLPAPER_OPEN, mAmWmState.getWmState().getLastTransition());
+                // Go home and check the app transition
+                assertNotSame(TRANSIT_WALLPAPER_OPEN, mAmWmState.getWmState().getLastTransition());
+                pressHomeButton();
+                mAmWmState.computeState();
+                assertEquals(TRANSIT_WALLPAPER_OPEN, mAmWmState.getWmState().getLastTransition());
+            }
         }
     }
 
diff --git a/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java b/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java
index 7a20d1f..2c7c554 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/KeyguardTests.java
@@ -18,7 +18,9 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.view.Surface.ROTATION_90;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -284,16 +286,18 @@
         mAmWmState.waitForKeyguardShowingAndNotOccluded();
         mAmWmState.assertKeyguardShowingAndNotOccluded();
         executeShellCommand(getAmStartCmd("ShowWhenLockedActivity"));
-        mAmWmState.computeState(new WaitForValidActivityState.Builder("ShowWhenLockedActivity").build());
+        mAmWmState.computeState(new WaitForValidActivityState("ShowWhenLockedActivity"));
         mAmWmState.assertVisibility("ShowWhenLockedActivity", true);
-        setDeviceRotation(1);
-        pressHomeButton();
-        mAmWmState.waitForKeyguardShowingAndNotOccluded();
-        mAmWmState.waitForDisplayUnfrozen();
-        mAmWmState.assertSanity();
-        mAmWmState.assertHomeActivityVisible(false);
-        mAmWmState.assertKeyguardShowingAndNotOccluded();
-        mAmWmState.assertVisibility("ShowWhenLockedActivity", false);
+        try (final RotationSession rotationSession = new RotationSession()) {
+            rotationSession.set(ROTATION_90);
+            pressHomeButton();
+            mAmWmState.waitForKeyguardShowingAndNotOccluded();
+            mAmWmState.waitForDisplayUnfrozen();
+            mAmWmState.assertSanity();
+            mAmWmState.assertHomeActivityVisible(false);
+            mAmWmState.assertKeyguardShowingAndNotOccluded();
+            mAmWmState.assertVisibility("ShowWhenLockedActivity", false);
+        }
     }
 
     private void assertWallpaperShowing() {
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
index 2acd049..7fe707a 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
@@ -44,10 +44,12 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.ParcelFileDescriptor;
+import android.provider.Settings;
+import android.server.am.settings.SettingsSession;
+import android.support.annotation.NonNull;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.UiDevice;
 import android.view.Display;
-import android.view.Surface;
 
 import com.android.compatibility.common.util.SystemUtil;
 
@@ -236,10 +238,6 @@
 
     protected ActivityAndWindowManagersState mAmWmState = new ActivityAndWindowManagersState();
 
-    private int mInitialAccelerometerRotation;
-    private int mUserRotation;
-    private float mFontScale;
-
     private SurfaceTraceReceiver mSurfaceTraceReceiver;
     private Thread mSurfaceTraceThread;
 
@@ -276,10 +274,6 @@
         wakeUpAndUnlockDevice();
         pressHomeButton();
         removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
-        // Store rotation settings.
-        mInitialAccelerometerRotation = getAccelerometerRotation();
-        mUserRotation = getUserRotation();
-        mFontScale = getFontScale();
         mLockCredentialsSet = false;
         mLockDisabled = isLockDisabled();
     }
@@ -290,11 +284,6 @@
         executeShellCommand(AM_FORCE_STOP_TEST_PACKAGE);
         executeShellCommand(AM_FORCE_STOP_SECOND_TEST_PACKAGE);
         executeShellCommand(AM_FORCE_STOP_THIRD_TEST_PACKAGE);
-        // Restore rotation settings to the state they were before test.
-        setAccelerometerRotation(mInitialAccelerometerRotation);
-        setUserRotation(mUserRotation);
-        setFontScale(mFontScale);
-            setWindowTransitionAnimationDurationScale(1);
         removeStacksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME);
         wakeUpAndUnlockDevice();
         pressHomeButton();
@@ -782,14 +771,34 @@
         runCommandAndPrintOutput("locksettings set-disabled " + lockDisabled);
     }
 
-    /**
-     * Sets the device rotation, value corresponds to one of {@link Surface#ROTATION_0},
-     * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}.
-     */
-    protected void setDeviceRotation(int rotation) throws Exception {
-        setAccelerometerRotation(0);
-        setUserRotation(rotation);
-        mAmWmState.waitForRotation(rotation);
+    /** Helper class to save, set & wait, and restore rotation related preferences. */
+    protected class RotationSession extends SettingsSession<Integer> {
+        private final SettingsSession<Integer> mUserRotation;
+
+        RotationSession() throws Exception {
+            // Save accelerometer_rotation preference.
+            super(Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION),
+                    Settings.System::getInt, Settings.System::putInt);
+            mUserRotation = new SettingsSession<>(
+                    Settings.System.getUriFor(Settings.System.USER_ROTATION),
+                    Settings.System::getInt, Settings.System::putInt);
+            // Disable accelerometer_rotation.
+            super.set(0);
+        }
+
+        @Override
+        public void set(@NonNull Integer value) throws Exception {
+            mUserRotation.set(value);
+            // Wait for settling rotation.
+            mAmWmState.waitForRotation(value);
+        }
+
+        @Override
+        public void close() throws Exception {
+            mUserRotation.close();
+            // Restore accelerometer_rotation preference.
+            super.close();
+        }
     }
 
     protected int getDeviceRotation(int displayId) {
@@ -798,7 +807,7 @@
                 "(mDisplayId=" + displayId + ")([\\s\\S]*)(mOverrideDisplayInfo)(.*)"
                         + "(rotation)(\\s+)(\\d+)");
         Matcher matcher = pattern.matcher(displays);
-        while (matcher.find()) {
+        if (matcher.find()) {
             final String match = matcher.group(7);
             return Integer.parseInt(match);
         }
@@ -806,63 +815,6 @@
         return INVALID_DEVICE_ROTATION;
     }
 
-    private int getAccelerometerRotation() {
-        final String rotation =
-                runCommandAndPrintOutput("settings get system accelerometer_rotation");
-        return Integer.parseInt(rotation.trim());
-    }
-
-    private void setAccelerometerRotation(int rotation) {
-        runCommandAndPrintOutput(
-                "settings put system accelerometer_rotation " + rotation);
-    }
-
-    protected int getUserRotation() {
-        final String rotation =
-                runCommandAndPrintOutput("settings get system user_rotation").trim();
-        if ("null".equals(rotation)) {
-            return -1;
-        }
-        return Integer.parseInt(rotation);
-    }
-
-    private void setUserRotation(int rotation) {
-        if (rotation == -1) {
-            runCommandAndPrintOutput(
-                    "settings delete system user_rotation");
-        } else {
-            runCommandAndPrintOutput(
-                    "settings put system user_rotation " + rotation);
-        }
-    }
-
-    protected void setFontScale(float fontScale) {
-        if (fontScale == 0.0f) {
-            runCommandAndPrintOutput(
-                    "settings delete system font_scale");
-        } else {
-            runCommandAndPrintOutput(
-                    "settings put system font_scale " + fontScale);
-        }
-    }
-
-    protected void setWindowTransitionAnimationDurationScale(float animDurationScale) {
-        runCommandAndPrintOutput(
-                "settings put global transition_animation_scale " + animDurationScale);
-    }
-
-    protected float getFontScale() {
-        try {
-            final String fontScale =
-                    runCommandAndPrintOutput("settings get system font_scale").trim();
-            return Float.parseFloat(fontScale);
-        } catch (NumberFormatException e) {
-            // If we don't have a valid font scale key, return 0.0f now so
-            // that we delete the key in tearDown().
-            return 0.0f;
-        }
-    }
-
     protected String runCommandAndPrintOutput(String command) {
         final String output = executeShellCommand(command);
         log(output);
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/settings/SettingsSession.java b/tests/framework/base/activitymanager/util/src/android/server/am/settings/SettingsSession.java
new file mode 100644
index 0000000..9877209
--- /dev/null
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/settings/SettingsSession.java
@@ -0,0 +1,164 @@
+package android.server.am.settings;
+
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.provider.Settings.SettingNotFoundException;
+import android.support.annotation.NonNull;
+import android.support.test.InstrumentationRegistry;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Helper class to save, set, and restore global system-level preferences.
+ * <p>
+ * To use this class, testing APK must be self-instrumented and have
+ * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}.
+ * <p>
+ * A test that changes system-level preferences can be written easily and reliably.
+ * <pre>
+ * static class PrefSession extends SettingsSession<String> {
+ *     PrefSession() {
+ *         super(android.provider.Settings.Secure.getUriFor(
+ *                       android.provider.Settings.Secure.PREFERENCE_KEY),
+ *               android.provider.Settings.Secure::getString,
+ *               android.provider.Settings.Secure::putString);
+ *     }
+ * }
+ *
+ * @Test
+ * public void doTest() throws Exception {
+ *     try (final PrefSession prefSession = new PrefSession()) {
+ *         prefSession.set("value 1");
+ *         doTest1();
+ *         prefSession.set("value 2");
+ *         doTest2();
+ *     }
+ * }
+ * </pre>
+ */
+public class SettingsSession<T> implements AutoCloseable {
+    private static final String TAG = SettingsSession.class.getSimpleName();
+    private static final boolean DEBUG = false;
+
+    @FunctionalInterface
+    public interface SettingsGetter<T> {
+        T get(ContentResolver cr, String key) throws SettingNotFoundException;
+    }
+
+    @FunctionalInterface
+    public interface SettingsSetter<T> {
+        void set(ContentResolver cr, String key, T value);
+    }
+
+    /**
+     * To debug to detect nested sessions for the same key. Enabled when {@link #DEBUG} is true.
+     * Note that nested sessions can be merged into one session.
+     */
+    private static final SessionCounters sSessionCounters = new SessionCounters();
+
+    private final Uri mUri;
+    private final SettingsGetter<T> mGetter;
+    private final SettingsSetter<T> mSetter;
+    private final boolean mHasInitialValue;
+    private final T mInitialValue;
+
+    public SettingsSession(final Uri uri, final SettingsGetter<T> getter,
+            final SettingsSetter<T> setter) {
+        mUri = uri;
+        mGetter = getter;
+        mSetter = setter;
+        T initialValue;
+        boolean hasInitialValue;
+        try {
+            initialValue = get(uri, getter);
+            hasInitialValue = true;
+        } catch (SettingNotFoundException e) {
+            initialValue = null;
+            hasInitialValue = false;
+        }
+        mInitialValue = initialValue;
+        mHasInitialValue = hasInitialValue;
+        if (DEBUG) {
+            Log.i(TAG, "start: uri=" + uri
+                    + (mHasInitialValue ? " value=" + mInitialValue : " undefined"));
+            sSessionCounters.open(uri);
+        }
+    }
+
+    public void set(final @NonNull T value) throws Exception {
+        put(mUri, mSetter, value);
+        if (DEBUG) {
+            Log.i(TAG, "  set: uri=" + mUri + " value=" + value);
+        }
+    }
+
+    public T get() throws SettingNotFoundException {
+        return get(mUri, mGetter);
+    }
+
+    @Override
+    public void close() throws Exception {
+        if (mHasInitialValue) {
+            put(mUri, mSetter, mInitialValue);
+            if (DEBUG) {
+                Log.i(TAG, "close: uri=" + mUri + " value=" + mInitialValue);
+            }
+        } else {
+            try {
+                delete(mUri);
+                if (DEBUG) {
+                    Log.i(TAG, "close: uri=" + mUri + " deleted");
+                }
+            } catch (IllegalArgumentException e) {
+                Log.w(TAG, "Can't delete settings " + mUri, e);
+            }
+        }
+        if (DEBUG) {
+            sSessionCounters.close(mUri);
+        }
+    }
+
+    private static <T> void put(final Uri uri, final SettingsSetter<T> setter, T value)
+            throws SettingNotFoundException {
+        setter.set(getContentResolver(), uri.getLastPathSegment(), value);
+    }
+
+    private static <T> T get(final Uri uri, final SettingsGetter<T> getter)
+            throws SettingNotFoundException {
+        return getter.get(getContentResolver(), uri.getLastPathSegment());
+    }
+
+    private static void delete(final Uri uri) throws IllegalArgumentException {
+        getContentResolver().delete(uri, null, null);
+    }
+
+    private static ContentResolver getContentResolver() {
+        return InstrumentationRegistry.getTargetContext().getContentResolver();
+    }
+
+    private static class SessionCounters {
+        private final Map<Uri, Integer> mOpenSessions = new HashMap<>();
+
+        void open(final Uri uri) {
+            final Integer count = mOpenSessions.get(uri);
+            if (count == null) {
+                mOpenSessions.put(uri, 1);
+                return;
+            }
+            mOpenSessions.put(uri, count + 1);
+            Log.w(TAG, "Open nested session for " + uri, new Throwable());
+        }
+
+        void close(final Uri uri) {
+            final int count = mOpenSessions.get(uri);
+            if (count == 1) {
+                mOpenSessions.remove(uri);
+                return;
+            }
+            mOpenSessions.put(uri, count - 1);
+            Log.w(TAG, "Close nested session for " + uri, new Throwable());
+        }
+    }
+}
diff --git a/tests/signature/api-check/src/android/signature/cts/api/BootClassPathClassesProvider.java b/tests/signature/api-check/src/android/signature/cts/api/BootClassPathClassesProvider.java
new file mode 100644
index 0000000..e2c92b3
--- /dev/null
+++ b/tests/signature/api-check/src/android/signature/cts/api/BootClassPathClassesProvider.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.signature.cts.api;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.stream.Stream;
+
+import android.signature.cts.ClassProvider;
+import dalvik.system.DexFile;
+
+@SuppressWarnings("deprecation")
+public class BootClassPathClassesProvider extends ClassProvider {
+    private Stream<Class<?>> allClasses = null;
+
+    @Override
+    public Stream<Class<?>> getAllClasses() {
+        Stream.Builder<Class<?>> builder = Stream.builder();
+        if (allClasses == null) {
+            for (String file : getBootJarPaths()) {
+                try {
+                    DexFile dexFile = new DexFile(file);
+                    Enumeration<String> entries = dexFile.entries();
+                    while (entries.hasMoreElements()) {
+                        String className = entries.nextElement();
+                        Class<?> clazz = getClass(className);
+                        if (clazz != null) {
+                            builder.add(clazz);
+                        }
+                    }
+                } catch (IOException e) {
+                    throw new RuntimeException("Failed to parse dex in " + file, e);
+                } catch (ClassNotFoundException e) {
+                    throw new RuntimeException("Error while loading class in " + file, e);
+                }
+            }
+            allClasses = builder.build();
+        }
+        return allClasses;
+    }
+
+    private String[] getBootJarPaths() {
+        return System.getProperty("java.boot.class.path").split(":");
+    }
+
+}
diff --git a/tests/signature/api-check/src/android/signature/cts/api/SignatureTest.java b/tests/signature/api-check/src/android/signature/cts/api/SignatureTest.java
index 1ec58d7..4240588 100644
--- a/tests/signature/api-check/src/android/signature/cts/api/SignatureTest.java
+++ b/tests/signature/api-check/src/android/signature/cts/api/SignatureTest.java
@@ -18,8 +18,10 @@
 
 import android.os.Bundle;
 import android.signature.cts.ApiDocumentParser;
+import android.signature.cts.ClassProvider;
 import android.signature.cts.ApiComplianceChecker;
 import android.signature.cts.FailureType;
+import android.signature.cts.ExcludingClassProvider;
 import android.signature.cts.JDiffClassDescription;
 import android.signature.cts.ReflectionHelper;
 import android.signature.cts.ResultObserver;
@@ -30,6 +32,8 @@
 import java.util.HashSet;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.function.Predicate;
+
 import org.xmlpull.v1.XmlPullParserException;
 import repackaged.android.test.InstrumentationTestCase;
 import repackaged.android.test.InstrumentationTestRunner;
@@ -114,9 +118,16 @@
      */
     public void testSignature() {
         try {
+
+            // Prepare for a class provider that loads classes from bootclasspath but filters
+            // out known inaccessible classes
+            ClassProvider classProvider = new ExcludingClassProvider(
+                    new BootClassPathClassesProvider(),
+                    KNOWN_INACCESSIBLE_CLASSES::contains);
+
             Set<JDiffClassDescription> unexpectedClasses = loadUnexpectedClasses();
             for (JDiffClassDescription classDescription : unexpectedClasses) {
-                Class<?> unexpectedClass = findUnexpectedClass(classDescription);
+                Class<?> unexpectedClass = findUnexpectedClass(classDescription, classProvider);
                 if (unexpectedClass != null) {
                     mResultObserver.notifyFailure(
                             FailureType.UNEXPECTED_CLASS,
@@ -125,7 +136,8 @@
                 }
             }
 
-            ApiComplianceChecker complianceChecker = new ApiComplianceChecker(mResultObserver);
+            ApiComplianceChecker complianceChecker = new ApiComplianceChecker(mResultObserver,
+                    classProvider);
             ApiDocumentParser apiDocumentParser = new ApiDocumentParser(
                     TAG, new ApiDocumentParser.Listener() {
                 @Override
@@ -162,9 +174,10 @@
         }
     }
 
-    private Class<?> findUnexpectedClass(JDiffClassDescription classDescription) {
+    private Class<?> findUnexpectedClass(JDiffClassDescription classDescription,
+            ClassProvider classProvider) {
         try {
-            return ReflectionHelper.findMatchingClass(classDescription);
+            return ReflectionHelper.findMatchingClass(classDescription, classProvider);
         } catch (ClassNotFoundException e) {
             return null;
         }
diff --git a/tests/signature/api-check/system-current-api/Android.mk b/tests/signature/api-check/system-current-api/Android.mk
index 1c10d2c..34c6c22 100644
--- a/tests/signature/api-check/system-current-api/Android.mk
+++ b/tests/signature/api-check/system-current-api/Android.mk
@@ -20,6 +20,7 @@
 
 LOCAL_SIGNATURE_API_FILES := \
     system-current.api \
+    system-removed.api \
     android-test-mock-current.api \
     android-test-runner-current.api \
 
diff --git a/tests/signature/api-check/system-current-api/AndroidTest.xml b/tests/signature/api-check/system-current-api/AndroidTest.xml
index 31ee887..6c574ea 100644
--- a/tests/signature/api-check/system-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/system-current-api/AndroidTest.xml
@@ -24,6 +24,9 @@
         <option name="push" value="system-current.api->/data/local/tmp/signature-test/system-current.api" />
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="system-removed.api->/data/local/tmp/signature-test/system-removed.api" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="push" value="android-test-mock-current.api->/data/local/tmp/signature-test/android-test-mock-current.api" />
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
@@ -36,7 +39,7 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.signature.cts.api.system_current" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
-        <option name="instrumentation-arg" key="expected-api-files" value="system-current.api" />
+        <option name="instrumentation-arg" key="expected-api-files" value="system-current.api,system-removed.api" />
         <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-mock-current.api,android-test-runner-current.api" />
         <option name="runtime-hint" value="30s" />
     </test>
diff --git a/tests/signature/src/android/signature/cts/ApiComplianceChecker.java b/tests/signature/src/android/signature/cts/ApiComplianceChecker.java
index 8dbf5e7..b27624b 100644
--- a/tests/signature/src/android/signature/cts/ApiComplianceChecker.java
+++ b/tests/signature/src/android/signature/cts/ApiComplianceChecker.java
@@ -71,9 +71,11 @@
 
 
     private final ResultObserver resultObserver;
+    private final ClassProvider classProvider;
 
-    public ApiComplianceChecker(ResultObserver resultObserver) {
+    public ApiComplianceChecker(ResultObserver resultObserver, ClassProvider classProvider) {
         this.resultObserver = resultObserver;
+        this.classProvider = classProvider;
     }
 
     private static void loge(String message, Exception exception) {
@@ -188,7 +190,7 @@
 
     private Class<?> findRequiredClass(JDiffClassDescription classDescription) {
         try {
-            return ReflectionHelper.findMatchingClass(classDescription);
+            return ReflectionHelper.findMatchingClass(classDescription, classProvider);
         } catch (ClassNotFoundException e) {
             loge("ClassNotFoundException for " + classDescription.getAbsoluteClassName(), e);
             return null;
diff --git a/tests/signature/src/android/signature/cts/ClassProvider.java b/tests/signature/src/android/signature/cts/ClassProvider.java
new file mode 100644
index 0000000..2461f26
--- /dev/null
+++ b/tests/signature/src/android/signature/cts/ClassProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.signature.cts;
+
+import java.util.stream.Stream;
+
+/**
+ * Generic class for getting runtime classes that will be matched against
+ * {@link JDiffClassDescription}. {@link ApiComplianceChecker} is using this
+ * when it needs runtime classes.
+ */
+public abstract class ClassProvider {
+    /**
+     * Get a specific class with the given name.
+     *
+     * @throws ClassNotFoundException
+     */
+    public Class<?> getClass(String name) throws ClassNotFoundException {
+        return Class.forName(name, false, this.getClass().getClassLoader());
+    }
+
+    /**
+     * Gets all classes available to this provider.
+     */
+    public abstract Stream<Class<?>> getAllClasses();
+}
diff --git a/tests/signature/src/android/signature/cts/ExcludingClassProvider.java b/tests/signature/src/android/signature/cts/ExcludingClassProvider.java
new file mode 100644
index 0000000..290cbf5
--- /dev/null
+++ b/tests/signature/src/android/signature/cts/ExcludingClassProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.signature.cts;
+
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+/**
+ * A filtered class provider which excludes classes by their canonical names
+ */
+public class ExcludingClassProvider extends ClassProvider {
+    private final ClassProvider base;
+    private final Predicate<String> testForExclusion;
+
+    public ExcludingClassProvider(ClassProvider base,
+            Predicate<String> testForExclusion) {
+        this.base = base;
+        this.testForExclusion = testForExclusion;
+    }
+
+    @Override
+    public Class<?> getClass(String name) throws ClassNotFoundException {
+        if (!testForExclusion.test(name)) {
+            return base.getClass(name);
+        }
+        // a filtered-out class is the same as non-existing class
+        throw new ClassNotFoundException("Cannot find class " + name);
+    }
+
+    @Override
+    public Stream<Class<?>> getAllClasses() {
+        return base.getAllClasses()
+                .filter(clazz -> !testForExclusion.test(clazz.getCanonicalName()));
+    }
+}
diff --git a/tests/signature/src/android/signature/cts/ReflectionHelper.java b/tests/signature/src/android/signature/cts/ReflectionHelper.java
index 54640a3..d87037d 100644
--- a/tests/signature/src/android/signature/cts/ReflectionHelper.java
+++ b/tests/signature/src/android/signature/cts/ReflectionHelper.java
@@ -42,7 +42,7 @@
      * @return the reflected class, or null if not found.
      */
     @SuppressWarnings("unchecked")
-    public static Class<?> findMatchingClass(JDiffClassDescription classDescription)
+    public static Class<?> findMatchingClass(JDiffClassDescription classDescription, ClassProvider classProvider)
             throws ClassNotFoundException {
         // even if there are no . in the string, split will return an
         // array of length 1
@@ -51,8 +51,7 @@
         String packageName = classDescription.getPackageName();
         String currentName = packageName + "." + classNameParts[0];
 
-        Class<?> clz = Class.forName(
-                currentName, false, ReflectionHelper.class.getClassLoader());
+        Class<?> clz = classProvider.getClass(currentName);
         String absoluteClassName = classDescription.getAbsoluteClassName();
         if (clz.getCanonicalName().equals(absoluteClassName)) {
             return clz;
diff --git a/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
index 71d2e37..45e14a9 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
@@ -20,7 +20,6 @@
 import android.signature.cts.FailureType;
 import android.signature.cts.JDiffClassDescription;
 import android.signature.cts.ResultObserver;
-
 import junit.framework.Assert;
 import junit.framework.TestCase;
 
@@ -74,7 +73,8 @@
 
     private void checkSignatureCompliance(JDiffClassDescription classDescription,
             ResultObserver resultObserver) {
-        ApiComplianceChecker complianceChecker = new ApiComplianceChecker(resultObserver);
+        ApiComplianceChecker complianceChecker = new ApiComplianceChecker(resultObserver,
+                new TestClassesProvider());
         complianceChecker.checkSignatureCompliance(classDescription);
     }
 
diff --git a/tests/signature/tests/src/android/signature/cts/tests/TestClassesProvider.java b/tests/signature/tests/src/android/signature/cts/tests/TestClassesProvider.java
new file mode 100644
index 0000000..2cb614c
--- /dev/null
+++ b/tests/signature/tests/src/android/signature/cts/tests/TestClassesProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.signature.cts.tests;
+
+import java.util.stream.Stream;
+
+import android.signature.cts.ClassProvider;
+import android.signature.cts.tests.data.AbstractClass;
+import android.signature.cts.tests.data.FinalClass;
+import android.signature.cts.tests.data.NormalClass;
+import android.signature.cts.tests.data.NormalException;
+import android.signature.cts.tests.data.NormalInterface;
+
+public class TestClassesProvider extends ClassProvider {
+    @Override
+    public Stream<Class<?>> getAllClasses() {
+        Stream.Builder<Class<?>> builder = Stream.builder();
+        builder.add(AbstractClass.class);
+        builder.add(FinalClass.class);
+        builder.add(NormalClass.class);
+        builder.add(NormalException.class);
+        builder.add(NormalInterface.class);
+        return builder.build();
+    }
+
+}
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
index d7cf703..7ba7191 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
index fc39cf4..37a0d21 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
index d1b1f86..b011284 100644
--- a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java b/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
index 2b7dccb..5afb71d 100644
--- a/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
+++ b/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
@@ -642,14 +642,6 @@
 
             setStringProperty(drm, LISTENER_TEST_SUPPORT_PROPERTY_KEY, listenerTestSupport);
 
-            // Test setting new string property
-            setStringProperty(drm, "NewStringPropertyKeyTest", "test value");
-
-            value = getStringProperty(drm, "NewStringPropertyKeyTest");
-            if (!value.equals("test value")) {
-                throw new Error("Failed to set property: NewStringPropertyKeyTest");
-            }
-
             // Test setting immutable properties
             HashMap<String, String> defaultImmutableProperties = new HashMap<String, String>();
             defaultImmutableProperties.put(ALGORITHMS_PROPERTY_KEY,
@@ -679,19 +671,11 @@
                 }
             }
 
-            // Test setPropertyByteArray
+            // Test setPropertyByteArray for immutable property
             final byte[] bytes = new byte[] {
                     0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8,
                     0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0};
 
-            setByteArrayProperty(drm, "someBytes", bytes);
-
-            // Verify new property value
-            if (!Arrays.equals(bytes, getByteArrayProperty(drm, "someBytes"))) {
-                throw new Error("Failed to set byte array for key=" + "someBytes");
-            }
-
-            // Test setPropertyByteArray for immutable property
             final byte[] deviceId = getByteArrayProperty(drm, DEVICEID_PROPERTY_KEY);
 
             setByteArrayProperty(drm, DEVICEID_PROPERTY_KEY, bytes);
diff --git a/tests/tests/permission/src/android/permission/cts/AppOpsTest.java b/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
index 8b1b9c9..7a97434 100644
--- a/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
+++ b/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
@@ -22,6 +22,7 @@
 import static android.app.AppOpsManager.MODE_IGNORED;
 import static android.app.AppOpsManager.OPSTR_READ_SMS;
 
+import android.Manifest.permission;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.os.Process;
@@ -33,16 +34,59 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 public class AppOpsTest extends InstrumentationTestCase {
-    static final Class<?>[] sSetModeSignature = new Class[] {
-            Context.class, AttributeSet.class};
-
     private AppOpsManager mAppOps;
     private Context mContext;
     private String mOpPackageName;
     private int mMyUid;
 
+    // These permissions and opStrs must map to the same op codes.
+    private static Map<String, String> permissionToOpStr = new HashMap<>();
+
+    static {
+        permissionToOpStr.put(permission.ACCESS_COARSE_LOCATION,
+                AppOpsManager.OPSTR_COARSE_LOCATION);
+        permissionToOpStr.put(permission.ACCESS_FINE_LOCATION, AppOpsManager.OPSTR_FINE_LOCATION);
+        permissionToOpStr.put(permission.READ_CONTACTS, AppOpsManager.OPSTR_READ_CONTACTS);
+        permissionToOpStr.put(permission.WRITE_CONTACTS, AppOpsManager.OPSTR_WRITE_CONTACTS);
+        permissionToOpStr.put(permission.READ_CALL_LOG, AppOpsManager.OPSTR_READ_CALL_LOG);
+        permissionToOpStr.put(permission.WRITE_CALL_LOG, AppOpsManager.OPSTR_WRITE_CALL_LOG);
+        permissionToOpStr.put(permission.READ_CALENDAR, AppOpsManager.OPSTR_READ_CALENDAR);
+        permissionToOpStr.put(permission.WRITE_CALENDAR, AppOpsManager.OPSTR_WRITE_CALENDAR);
+        permissionToOpStr.put(permission.CALL_PHONE, AppOpsManager.OPSTR_CALL_PHONE);
+        permissionToOpStr.put(permission.READ_SMS, AppOpsManager.OPSTR_READ_SMS);
+        permissionToOpStr.put(permission.RECEIVE_SMS, AppOpsManager.OPSTR_RECEIVE_SMS);
+        permissionToOpStr.put(permission.RECEIVE_MMS, AppOpsManager.OPSTR_RECEIVE_MMS);
+        permissionToOpStr.put(permission.RECEIVE_WAP_PUSH, AppOpsManager.OPSTR_RECEIVE_WAP_PUSH);
+        permissionToOpStr.put(permission.SEND_SMS, AppOpsManager.OPSTR_SEND_SMS);
+        permissionToOpStr.put(permission.READ_SMS, AppOpsManager.OPSTR_READ_SMS);
+        permissionToOpStr.put(permission.WRITE_SETTINGS, AppOpsManager.OPSTR_WRITE_SETTINGS);
+        permissionToOpStr.put(permission.SYSTEM_ALERT_WINDOW,
+                AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW);
+        permissionToOpStr.put(permission.ACCESS_NOTIFICATIONS,
+                AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS);
+        permissionToOpStr.put(permission.CAMERA, AppOpsManager.OPSTR_CAMERA);
+        permissionToOpStr.put(permission.RECORD_AUDIO, AppOpsManager.OPSTR_RECORD_AUDIO);
+        permissionToOpStr.put(permission.READ_PHONE_STATE, AppOpsManager.OPSTR_READ_PHONE_STATE);
+        permissionToOpStr.put(permission.ADD_VOICEMAIL, AppOpsManager.OPSTR_ADD_VOICEMAIL);
+        permissionToOpStr.put(permission.USE_SIP, AppOpsManager.OPSTR_USE_SIP);
+        permissionToOpStr.put(permission.PROCESS_OUTGOING_CALLS,
+                AppOpsManager.OPSTR_PROCESS_OUTGOING_CALLS);
+        permissionToOpStr.put(permission.BODY_SENSORS, AppOpsManager.OPSTR_BODY_SENSORS);
+        permissionToOpStr.put(permission.READ_CELL_BROADCASTS,
+                AppOpsManager.OPSTR_READ_CELL_BROADCASTS);
+        permissionToOpStr.put(permission.READ_EXTERNAL_STORAGE,
+                AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE);
+        permissionToOpStr.put(permission.WRITE_EXTERNAL_STORAGE,
+                AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE);
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -115,6 +159,46 @@
         }
     }
 
+    @SmallTest
+    public void testAllOpsHaveOpString() {
+        Set<String> opStrs = new HashSet<>();
+        for (String opStr : AppOpsManager.getOpStrs()) {
+            assertNotNull("Each app op must have an operation string defined", opStr);
+            opStrs.add(opStr);
+        }
+        assertEquals("Not all op strings are unique", AppOpsManager._NUM_OP, opStrs.size());
+    }
+
+    @SmallTest
+    public void testOpCodesUnique() {
+        String[] opStrs = AppOpsManager.getOpStrs();
+        Set<Integer> opCodes = new HashSet<>();
+        for (String opStr : opStrs) {
+            opCodes.add(AppOpsManager.strOpToOp(opStr));
+        }
+        assertEquals("Not all app op codes are unique", opStrs.length, opCodes.size());
+    }
+
+    @SmallTest
+    public void testPermissionMapping() {
+        for (String permission : permissionToOpStr.keySet()) {
+            testPermissionMapping(permission, permissionToOpStr.get(permission));
+        }
+    }
+
+    private void testPermissionMapping(String permission, String opStr) {
+        // Do the public value => internal op code lookups.
+        String mappedOpStr = AppOpsManager.permissionToOp(permission);
+        assertEquals(mappedOpStr, opStr);
+        int mappedOpCode = AppOpsManager.permissionToOpCode(permission);
+        int mappedOpCode2 = AppOpsManager.strOpToOp(opStr);
+        assertEquals(mappedOpCode, mappedOpCode2);
+
+        // Do the internal op code => public value lookup (reverse lookup).
+        String permissionMappedBack = AppOpsManager.opToPermission(mappedOpCode);
+        assertEquals(permission, permissionMappedBack);
+    }
+
     /**
      * Test that the app can not change the app op mode for itself.
      */
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index fe4f779..4fefdab 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -28,7 +28,6 @@
 		android_security_cts_LinuxRngTest.cpp \
 		android_security_cts_NativeCodeTest.cpp \
 		android_security_cts_SELinuxTest.cpp \
-		android_security_cts_SeccompTest.cpp \
 		android_security_cts_MMapExecutableTest.cpp \
 		android_security_cts_EncryptionTest.cpp \
 
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 835d1a6..2014591 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -49,11 +49,7 @@
         return JNI_ERR;
     }
 
-    if (register_android_security_cts_SeccompTest(env)) {
-        return JNI_ERR;
-    }
-
-     if (register_android_security_cts_KernelSettingsTest(env)) {
+    if (register_android_security_cts_KernelSettingsTest(env)) {
         return JNI_ERR;
     }
 
diff --git a/tests/tests/widget/res/layout/textview_fallbacklinespacing_layout.xml b/tests/tests/widget/res/layout/textview_fallbacklinespacing_layout.xml
new file mode 100644
index 0000000..684d821
--- /dev/null
+++ b/tests/tests/widget/res/layout/textview_fallbacklinespacing_layout.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/layout_textviewtest"
+        android:orientation="vertical">
+
+    <TextView android:id="@+id/textview_true"
+              android:fallbackLineSpacing="true"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"/>
+
+    <TextView android:id="@+id/textview_false"
+              android:fallbackLineSpacing="false"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"/>
+
+    <TextView android:id="@+id/textview_default"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"/>
+
+    <TextView android:id="@+id/textview_style_true"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              style="@style/TextAppearance.FallbackLineSpacingTrue"/>
+
+    <TextView android:id="@+id/textview_style_false"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              style="@style/TextAppearance.FallbackLineSpacingFalse"/>
+
+    <TextView android:id="@+id/textview_style_default"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              style="@style/TextAppearance"/>
+
+</LinearLayout>
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
index 8d44c7a..abb85ad 100644
--- a/tests/tests/widget/res/values/styles.xml
+++ b/tests/tests/widget/res/values/styles.xml
@@ -141,6 +141,15 @@
         <item name="android:elegantTextHeight">false</item>
     </style>
 
+
+    <style name="TextAppearance.FallbackLineSpacingFalse">
+        <item name="android:fallbackLineSpacing">false</item>
+    </style>
+
+    <style name="TextAppearance.FallbackLineSpacingTrue">
+        <item name="android:fallbackLineSpacing">true</item>
+    </style>
+
     <style name="AllCapsPassword">
         <item name="android:textAllCaps">true</item>
         <item name="android:password">true</item>
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index ca1c9a1..cc4d023 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -7817,6 +7817,70 @@
         assertEquals(Typeface.DEFAULT, mTextView.getTypeface());
     }
 
+    @UiThreadTest
+    @Test
+    public void testFallbackLineSpacing_readsFromLayoutXml() {
+        mActivity.setContentView(R.layout.textview_fallbacklinespacing_layout);
+        mTextView = findTextView(R.id.textview_true);
+        assertTrue(mTextView.isFallbackLineSpacing());
+
+        mTextView = findTextView(R.id.textview_default);
+        assertTrue(mTextView.isFallbackLineSpacing());
+
+        mTextView = findTextView(R.id.textview_false);
+        assertFalse(mTextView.isFallbackLineSpacing());
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFallbackLineSpacing_set_get() {
+        mActivity.setContentView(R.layout.textview_fallbacklinespacing_layout);
+        mTextView = findTextView(R.id.textview_true);
+        assertTrue(mTextView.isFallbackLineSpacing());
+
+        mTextView.setFallbackLineSpacing(false);
+        assertFalse(mTextView.isFallbackLineSpacing());
+
+        mTextView.setFallbackLineSpacing(true);
+        assertTrue(mTextView.isFallbackLineSpacing());
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFallbackLineSpacing_readsFromStyleXml() {
+        mActivity.setContentView(R.layout.textview_fallbacklinespacing_layout);
+        mTextView = findTextView(R.id.textview_style_true);
+        assertTrue(mTextView.isFallbackLineSpacing());
+
+        mTextView = findTextView(R.id.textview_style_default);
+        assertTrue(mTextView.isFallbackLineSpacing());
+
+        mTextView = findTextView(R.id.textview_style_false);
+        assertFalse(mTextView.isFallbackLineSpacing());
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFallbackLineSpacing_textAppearance_set_get() {
+        mActivity.setContentView(R.layout.textview_fallbacklinespacing_layout);
+        mTextView = findTextView(R.id.textview_default);
+        assertTrue(mTextView.isFallbackLineSpacing());
+
+        mTextView.setTextAppearance(R.style.TextAppearance_FallbackLineSpacingFalse);
+        assertFalse(mTextView.isFallbackLineSpacing());
+
+        mTextView.setTextAppearance(R.style.TextAppearance_FallbackLineSpacingTrue);
+        assertTrue(mTextView.isFallbackLineSpacing());
+
+        mTextView.setFallbackLineSpacing(false);
+        mTextView.setTextAppearance(R.style.TextAppearance);
+        assertFalse(mTextView.isFallbackLineSpacing());
+
+        mTextView.setFallbackLineSpacing(true);
+        mTextView.setTextAppearance(R.style.TextAppearance);
+        assertTrue(mTextView.isFallbackLineSpacing());
+    }
+
     private void initializeTextForSmartSelection(CharSequence text) throws Throwable {
         assertTrue(text.length() >= SMARTSELECT_END);
         mActivityRule.runOnUiThread(() -> {