Merge "Test for removing a shared element during activity transition" into oc-dev
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 1787b42..ce6c76f 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -70,17 +70,17 @@
     <!-- Needed by the Audio Quality Verifier to store the sound samples that will be mailed. -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
+    <!-- Needed for Telecom self-managed ConnectionService tests. -->
+    <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
+
     <application android:label="@string/app_name"
             android:icon="@drawable/icon"
-            android:backupAgent="VerifierBackupAgent"
             android:debuggable="true"
             android:largeHeap="true"
             android:theme="@android:style/Theme.DeviceDefault">
 
         <meta-data android:name="SuiteName" android:value="CTS_VERIFIER" />
-
-        <meta-data android:name="com.google.android.backup.api_key"
-                android:value="AEdPqrEAAAAIbK6ldcOzoeRtQ1u1dFVJ1A7KetRhit-a1Xa82Q" />
+        
         <meta-data android:name="android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU"
             android:value="true"/>
         <uses-library android:name="android.test.runner"/>
@@ -118,6 +118,32 @@
                        android:value="android.software.device_admin" />
         </activity>
 
+        <activity android:name=".admin.tapjacking.DeviceAdminTapjackingTestActivity"
+                  android:label="@string/da_tapjacking_test"
+                  android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_device_admin" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.software.device_admin" />
+        </activity>
+
+        <receiver android:name=".admin.tapjacking.EmptyDeviceAdminReceiver"
+                  android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                       android:resource="@xml/tapjacking_device_admin" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
+            </intent-filter>
+        </receiver>
+
+        <activity
+            android:name=".admin.tapjacking.OverlayingActivity"
+            android:theme="@style/OverlayTheme"
+            android:label="Overlaying Activity"/>
+
         <activity android:name=".companion.CompanionDeviceTestActivity"
                   android:label="@string/companion_test"
                   android:configChanges="keyboardHidden|orientation|screenSize">
@@ -171,25 +197,6 @@
                     android:value="android.software.device_admin" />
         </activity>
 
-        <activity android:name=".backup.BackupTestActivity" android:label="@string/backup_test">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.cts.intent.category.MANUAL_TEST" />
-            </intent-filter>
-            <meta-data android:name="test_required_features"
-                    android:value="android.software.backup" />
-        </activity>
-
-	<!-- Further work is required for this test, b/32798562  -->
-        <!-- activity android:name=".backup.BackupAccessibilityTestActivity" android:label="@string/backup_accessibility_test">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.cts.intent.category.MANUAL_TEST" />
-            </intent-filter>
-            <meta-data android:name="test_required_features"
-                    android:value="android.software.backup" />
-        </activity -->
-
 <!--            CTS Verifier Bluetooth Test Top Screen -->
         <activity
             android:name=".bluetooth.BluetoothTestActivity"
@@ -1059,6 +1066,17 @@
             <meta-data android:name="test_required_features" android:value="android.hardware.location.gps" />
         </activity>
 
+        <activity android:name=".location.GnssTtffTestsActivity"
+            android:label="@string/location_gnss_ttff_test"
+            android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.cts.intent.category.MANUAL_TEST"/>
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_hardware"/>
+            <meta-data android:name="test_required_features" android:value="android.hardware.location.gps" />
+        </activity>
+
         <activity android:name=".location.GnssMeasurementWhenNoLocationTestsActivity"
             android:label="@string/location_gnss_measure_no_location_test"
             android:screenOrientation="locked">
@@ -3092,6 +3110,22 @@
             <meta-data
                 android:name="test_required_features"
                 android:value="android.hardware.telephony"/>
+            </activity>
+
+        <activity
+            android:name=".telecom.SelfManagedIncomingCallTestActivity"
+            android:label="@string/telecom_incoming_self_mgd_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.cts.intent.category.MANUAL_TEST"/>
+            </intent-filter>
+
+            <meta-data
+                android:name="test_category"
+                android:value="@string/test_category_telecom"/>
+            <meta-data
+                android:name="test_required_features"
+                android:value="android.hardware.telephony"/>
         </activity>
 
         <activity
diff --git a/apps/CtsVerifier/res/drawable/border.xml b/apps/CtsVerifier/res/drawable/border.xml
new file mode 100644
index 0000000..b419618
--- /dev/null
+++ b/apps/CtsVerifier/res/drawable/border.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <corners
+        android:radius="4dp"/>
+    <stroke
+        android:width="4dp"
+        android:color="@android:color/black" />
+</shape>
diff --git a/apps/CtsVerifier/res/layout/bu_main.xml b/apps/CtsVerifier/res/layout/bu_main.xml
deleted file mode 100644
index 2289fee..0000000
--- a/apps/CtsVerifier/res/layout/bu_main.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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:orientation="vertical"
-         android:layout_width="match_parent"
-         android:layout_height="match_parent"
-         >
-         
-    <ListView android:id="@+id/android:list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            />
-            
-    <TextView android:id="@id/android:empty"
-           android:gravity="center"
-           android:layout_width="match_parent"
-           android:layout_height="wrap_content"
-           android:layout_weight="1"
-           android:text="@string/bu_loading"
-           />
-
-    <Button android:id="@+id/generate_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bu_generate"
-            />
-
-    <include layout="@layout/pass_fail_buttons" />
-
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/bua_main.xml b/apps/CtsVerifier/res/layout/bua_main.xml
deleted file mode 100644
index e2d5ef1..0000000
--- a/apps/CtsVerifier/res/layout/bua_main.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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:orientation="vertical"
-         android:layout_width="match_parent"
-         android:layout_height="match_parent"
-         >
-
-    <ListView android:id="@+id/android:list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            />
-
-    <TextView android:id="@id/android:empty"
-           android:gravity="center"
-           android:layout_width="match_parent"
-           android:layout_height="wrap_content"
-           android:layout_weight="1"
-           android:text="@string/bu_loading"
-           />
-
-    <Button android:id="@+id/generate_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bua_read_settings"
-            />
-
-    <Button android:id="@+id/show_instructions_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/bua_show_instructions"
-            />
-
-    <include layout="@layout/pass_fail_buttons" />
-
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/da_tapjacking_overlay_activity.xml b/apps/CtsVerifier/res/layout/da_tapjacking_overlay_activity.xml
new file mode 100644
index 0000000..5583fce
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/da_tapjacking_overlay_activity.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:background="@drawable/border"
+              android:padding="8dp" >
+
+    <TextView android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:textColor="@android:color/black"
+              android:text="@string/da_tapjacking_overlay_app_description" />
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/da_tapjacking_test_main.xml b/apps/CtsVerifier/res/layout/da_tapjacking_test_main.xml
new file mode 100644
index 0000000..2ee9ea9
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/da_tapjacking_test_main.xml
@@ -0,0 +1,55 @@
+<?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.
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/RootLayoutPadding"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <!-- Enable device admin -->
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" >
+
+            <TextView
+                android:id="@+id/admin_tapjacking_instructions"
+                style="@style/InstructionsSmallFont"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:layout_alignParentTop="true"
+                android:text="@string/da_tapjacking_instructions" />
+
+            <Button
+                android:id="@+id/enable_admin_overlay_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:layout_below="@id/admin_tapjacking_instructions"
+                android:layout_marginLeft="20dip"
+                android:layout_marginRight="20dip"
+                android:text="@string/da_tapjacking_button_text" />
+        </RelativeLayout>
+
+        <include layout="@layout/pass_fail_buttons" />
+    </LinearLayout>
+
+</ScrollView>
diff --git a/apps/CtsVerifier/res/layout/telecom_self_managed_answer.xml b/apps/CtsVerifier/res/layout/telecom_self_managed_answer.xml
new file mode 100644
index 0000000..27aa55a
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/telecom_self_managed_answer.xml
@@ -0,0 +1,133 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/telecom_incoming_self_mgd_info"/>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+
+        <ImageView
+            android:id="@+id/step_1_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true" />
+        <TextView
+            android:id="@+id/step_1_instructions"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/telecom_incoming_self_mgd_step_1"
+            android:textSize="16dp"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentTop="true"
+            android:layout_toRightOf="@id/step_1_status" />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_below="@id/step_1_instructions"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_toRightOf="@id/step_1_status"
+            android:id="@+id/telecom_incoming_self_mgd_register_button"
+            android:text="@string/telecom_incoming_self_mgd_register_button"/>
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+
+        <ImageView
+            android:id="@+id/step_2_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true" />
+        <TextView
+            android:id="@+id/step_2_instructions"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/telecom_incoming_self_mgd_step_2"
+            android:textSize="16dp"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentTop="true"
+            android:layout_toRightOf="@id/step_2_status" />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_below="@id/step_2_instructions"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_toRightOf="@id/step_2_status"
+            android:id="@+id/telecom_incoming_self_mgd_show_ui_button"
+            android:text="@string/telecom_incoming_self_mgd_show_ui_button"/>
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+
+        <ImageView
+            android:id="@+id/step_3_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true" />
+        <TextView
+            android:id="@+id/step_3_instructions"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/telecom_incoming_self_mgd_step_3"
+            android:textSize="16dp"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentTop="true"
+            android:layout_toRightOf="@id/step_3_status" />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_below="@id/step_3_instructions"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_toRightOf="@id/step_3_status"
+            android:id="@+id/telecom_incoming_self_mgd_confirm_answer_button"
+            android:text="@string/telecom_incoming_self_mgd_confirm_answer_button"/>
+    </RelativeLayout>
+
+    <include layout="@layout/pass_fail_buttons" />
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index d9b87d16..3f4e18e 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -66,71 +66,6 @@
     <string name="bu_generate_error">Error occurred while generating test data...</string>
     <string name="bu_settings">Settings</string>
 
-    <!-- Strings for BackupTestActivity -->
-    <string name="backup_test">Data Backup Test</string>
-    <string name="backup_info">This test checks that data backup and automatic restore works
-        properly. The test activity lists some preferences and files that are backed up and
-        restored by the CTS Verifier. If backup and restore is working properly, these values
-        should be restored after running the backup manager, uninstalling the app, and reinstalling
-        the CTS Verifier.
-        \n\nPress the \"Generate Test Data\" to populate these values
-        and then follow the on screen instructions to finish the test.
-    </string>
-    <string name="bu_generate">Generate Test Data</string>
-    <string name="bu_preferences">Preferences</string>
-    <string name="bu_files">Files</string>
-    <string name="bu_instructions">Random values for the preferences and files have been saved.
-        \n\nFollow the instructions below to check that the data backup and restore works:
-        \n\n1. Make sure backup and automatic restore are enabled in settings. Depending on the
-        backup transport supported by the device you may need to do additional steps. For instance
-        you may need to set a Google account as the backup account for the device. If you cannot
-        find the corresponding setting options on your device, run \"adb shell bmgr enable true\"
-        to enable the backup manager. You can check its status by executing \"adb shell bmgr
-        enabled\".
-        \n\n2. Run the backup manager: adb shell bmgr run
-        \n\n3. Uninstall the program: adb uninstall com.android.cts.verifier
-        \n\n4. Reinstall the CTS Verifier and verify that the values are still the same.
-    </string>
-
-    <!-- Strings for BackupAccessibilityTestActivity -->
-    <string name="backup_accessibility_test">Backup Accessibility Settings Test</string>
-    <string name="backup_accessibility_info">This test checks that data backup and automatic restore
-        of Accessibility-related settings works properly. If backup and restore is working properly,
-        these values should be restored after running the backup manager, removing your Google
-        account, changing the accessibility settings values, and re-adding your Google account.
-        \n\nPress \"Generate Test Data\" to generate test values for accessibility settings and then
-        follow the on screen instructions to finish the test.
-    </string>
-    <string name="bua_settings">General Accessibility Settings</string>
-    <string name="bua_settings_color_correction">Color Correction Settings</string>
-    <string name="bua_settings_accessibility_services">Accessibility Service Settings</string>
-    <string name="bua_settings_captions">Captions Settings</string>
-    <string name="bua_settings_tts">TTS Settings</string>
-    <string name="bua_settings_system">Other System Settings</string>
-    <string name="bua_instructions">You will need two devices for this test.
-        \n\nFollow the instructions below to check that the data backup and restore of
-        accessibility-related settings works properly:
-        \n\n1. Make sure backup and automatic restore are enabled in settings. If you cannot find
-        the corresponding setting options on your device, run \"adb shell bmgr enable true\" to
-        enable the backup manager. You can check its status by executing \"adb shell bmgr enabled\".
-        You will also need to set a Google account as the backup account for the device.
-        \n\n2. Press \"Read Current Values\" and note the default values for the listed settings.
-        Values that are either \"0\" or \"null\" will appear in green. Note: Some default values are
-        neither \"0\", nor \"null\", so you still need to pay attention to the default setting
-        values that are not highlighted.
-        \n\n3. Change the values of the listed settings to something other than their default value.
-        \n\n4. Return to the CtsVerifier and press \"Read Current Values\". Make sure that you have
-        changed all of the settings.
-        \n\n5. Run the backup manager: adb shell bmgr run
-        \n\n6. Factory reset data on the second device. While going through the Setup Wizard,
-        restore all data from the account on your first device. When prompted, choose to restore all
-        settings from your first device.
-        \n\n7. Install CtsVerifier on your new device and make sure that the values read on the
-        second device match the values on your first device.
-    </string>
-    <string name="bua_show_instructions">Show Instructions</string>
-    <string name="bua_read_settings">Read Current Values</string>
-
     <!-- Strings for Device Administration tests -->
     <string name="da_policy_serialization_test">Policy Serialization Test</string>
     <string name="da_policy_serialization_info">This test checks that a device policy is properly
@@ -144,6 +79,10 @@
         can be easily uninstalled from the application details screen in a way similar to other
         apps.
     </string>
+    <string name="da_tapjacking_test">Device Admin Tapjacking Test</string>
+    <string name="da_tapjacking_test_info">This test checks that an activity cannot tapjack the
+        user by obscuring the device admin details while prompting the user to activate the admin.
+    </string>
     <string name="car_dock_test">Car Dock Test</string>
     <string name="car_dock_test_desc">This test ensures that car mode opens the app associated with
         car dock when going into car mode.\n\n
@@ -199,6 +138,18 @@
     </string>
     <string name="da_uninstall_admin_button_text">Launch settings</string>
 
+    <string name="da_tapjacking_overlay_app_description">This activity attempts to tapjack the activity below.\n
+        Any security sensitive controls below should not respond to taps as long as this activity is visible.</string>
+    <string name="da_tapjacking_instructions">
+        1. Launch the device admin add screen by pressing the button below.\n
+        2. Wait for an overlaying transparent activity to show up obscuring the device admin details window.\n
+        3. Attempt to activate the admin with the transparent activity still obscuring the window.
+        The button should discard any taps while showing a toast warning to the user.\n
+        4. Return to this screen and pass the test if the device admin could not be activated while the details
+        window was being obscured.
+    </string>
+    <string name="da_tapjacking_button_text">Enable device admin</string>
+
     <!-- Strings for lock bound keys test -->
     <string name="sec_lock_bound_key_test">Lock Bound Keys Test</string>
     <string name="sec_lock_bound_key_test_info">
@@ -604,6 +555,7 @@
     <string name="location_gnss_measure_no_location_test">GNSS Measurement Before Location Test</string>
     <string name="location_gnss_reg_test">GNSS Measurement Registration Test</string>
     <string name="location_gnss_value_test">GNSS Measurement Values Test</string>
+    <string name="location_gnss_ttff_test">GNSS TTFF Test</string>
     <string name="location_gnss_nav_msg_test">GNSS Navigation Message Test</string>
     <string name="location_gnss_status_test">GNSS Status Test</string>
     <string name="location_gnss_test_info">This test verifies basic GNSS behavior.
@@ -3952,4 +3904,22 @@
         that audio is audible.
     </string>
     <string name="telecom_incoming_call_confirm_button">Confirm</string>
+    <string name="telecom_incoming_self_mgd_test"> Incoming Self-Managed Connection Test</string>
+    <string name="telecom_incoming_self_mgd_info">
+        This test verifies that incoming calls from a Self-Managed Connection Service will trigger
+        a Telecom-managed incoming call UI when there is already an ongoing call on the device.
+    </string>
+    <string name="telecom_incoming_self_mgd_step_1">
+        Click the button below to register a test self-managed ConnectionService.
+    </string>
+    <string name="telecom_incoming_self_mgd_register_button">Register Self-Managed ConnectionService</string>
+    <string name="telecom_incoming_self_mgd_step_2">
+        Click the button below to test that the system incoming call notification shows.  When the
+        notification shows, "answer" the call.
+    </string>
+    <string name="telecom_incoming_self_mgd_show_ui_button">Show System Incoming UI</string>
+    <string name="telecom_incoming_self_mgd_step_3">
+        Click the button below to confirm that the incoming call was answered.
+    </string>
+    <string name="telecom_incoming_self_mgd_confirm_answer_button">Confirm Answer</string>
 </resources>
diff --git a/apps/CtsVerifier/res/values/styles.xml b/apps/CtsVerifier/res/values/styles.xml
index 0e05817..64fd4fe 100644
--- a/apps/CtsVerifier/res/values/styles.xml
+++ b/apps/CtsVerifier/res/values/styles.xml
@@ -13,4 +13,9 @@
     <style name="RootLayoutPadding">
         <item name="android:padding">10dip</item>
     </style>
+    <style name="OverlayTheme" parent="android:Theme.Dialog">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+    </style>
 </resources>
diff --git a/apps/CtsVerifier/res/xml/tapjacking_device_admin.xml b/apps/CtsVerifier/res/xml/tapjacking_device_admin.xml
new file mode 100644
index 0000000..d884663
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/tapjacking_device_admin.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-policies>
+        <limit-password />
+        <watch-login />
+        <encrypted-storage />
+        <wipe-data />
+        <reset-password />
+        <disable-keyguard-features />
+        <force-lock />
+        <limit-password />
+    </uses-policies>
+</device-admin>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java
deleted file mode 100644
index 2527d57..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestResultsBackupHelper.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier;
-
-import com.android.cts.verifier.backup.BackupTestActivity;
-
-import android.app.backup.BackupDataInputStream;
-import android.app.backup.BackupDataOutput;
-import android.app.backup.BackupHelper;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-/** {@link BackupHelper} for the test results database. */
-class TestResultsBackupHelper implements BackupHelper {
-
-    private static final String TAG = TestResultsBackupHelper.class.getSimpleName();
-
-    private static final String DB_BACKUP_KEY = "db";
-
-    private final Context mContext;
-
-    TestResultsBackupHelper(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
-            ParcelFileDescriptor newState) {
-        ContentResolver resolver = mContext.getContentResolver();
-        Cursor cursor = null;
-        try {
-            cursor = resolver.query(TestResultsProvider.getResultContentUri(mContext),
-                    null, null, null, null);
-            int nameIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_NAME);
-            int resultIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_RESULT);
-            int infoSeenIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_INFO_SEEN);
-            int detailsIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_DETAILS);
-            int metricsIndex = cursor.getColumnIndex(TestResultsProvider.COLUMN_TEST_METRICS);
-
-            ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
-            DataOutputStream dataOutput = new DataOutputStream(byteOutput);
-
-            dataOutput.writeInt(cursor.getCount());
-            while (cursor.moveToNext()) {
-                String name = cursor.getString(nameIndex);
-                int result = cursor.getInt(resultIndex);
-                int infoSeen = cursor.getInt(infoSeenIndex);
-                String details = cursor.getString(detailsIndex);
-                byte[] metricsData = cursor.getBlob(metricsIndex);
-
-                dataOutput.writeUTF(name);
-                dataOutput.writeInt(result);
-                dataOutput.writeInt(infoSeen);
-                dataOutput.writeUTF(details != null ? details : "");
-                dataOutput.writeInt(metricsData.length);
-                if (metricsData.length > 0) {
-                    dataOutput.write(metricsData);
-                }
-            }
-
-            byte[] rawBytes = byteOutput.toByteArray();
-            data.writeEntityHeader(DB_BACKUP_KEY, rawBytes.length);
-            data.writeEntityData(rawBytes, rawBytes.length);
-        } catch (IOException e) {
-            Log.e(TAG, "Couldn't backup test results...", e);
-            failBackupTest();
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-    }
-
-    @Override
-    public void restoreEntity(BackupDataInputStream data) {
-        try {
-            if (DB_BACKUP_KEY.equals(data.getKey())) {
-                byte[] rawBytes = new byte[data.size()];
-                data.read(rawBytes, 0, data.size());
-
-                ByteArrayInputStream byteInput = new ByteArrayInputStream(rawBytes);
-                DataInputStream dataInput = new DataInputStream(byteInput);
-
-                int numRows = dataInput.readInt();
-                ContentValues[] values = new ContentValues[numRows];
-                for (int i = 0; i < numRows; i++) {
-                    String name = dataInput.readUTF();
-                    int result = dataInput.readInt();
-                    int infoSeen = dataInput.readInt();
-                    String details = dataInput.readUTF();
-                    int metricsDataSize = dataInput.readInt();
-
-                    values[i] = new ContentValues();
-                    values[i].put(TestResultsProvider.COLUMN_TEST_NAME, name);
-                    values[i].put(TestResultsProvider.COLUMN_TEST_RESULT, result);
-                    values[i].put(TestResultsProvider.COLUMN_TEST_INFO_SEEN, infoSeen);
-                    values[i].put(TestResultsProvider.COLUMN_TEST_DETAILS, details);
-
-                    if (metricsDataSize > 0) {
-                        byte[] metrics = new byte[metricsDataSize];
-                        dataInput.readFully(metrics);
-                        values[i].put(TestResultsProvider.COLUMN_TEST_METRICS, metrics);
-                    }
-                }
-
-                ContentResolver resolver = mContext.getContentResolver();
-                resolver.bulkInsert(TestResultsProvider.getResultContentUri(mContext), values);
-            } else {
-                Log.e(TAG, "Skipping key: " + data.getKey());
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "Couldn't restore test results...", e);
-            failBackupTest();
-        }
-    }
-
-    private void failBackupTest() {
-        TestResultsProvider.setTestResult(mContext, BackupTestActivity.class.getName(),
-                TestResult.TEST_RESULT_FAILED, null /*testDetails*/, null /*testMetrics*/);
-    }
-
-    @Override
-    public void writeNewStateDescription(ParcelFileDescriptor newState) {
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/VerifierBackupAgent.java b/apps/CtsVerifier/src/com/android/cts/verifier/VerifierBackupAgent.java
deleted file mode 100644
index 3c980b9..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/VerifierBackupAgent.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier;
-
-import com.android.cts.verifier.backup.BackupTestActivity;
-
-import android.app.backup.BackupAgentHelper;
-
-public class VerifierBackupAgent extends BackupAgentHelper {
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        addHelper("test-results", new TestResultsBackupHelper(this));
-        addHelper("backup-test-prefs", BackupTestActivity.getSharedPreferencesBackupHelper(this));
-        addHelper("backup-test-files", BackupTestActivity.getFileBackupHelper(this));
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/DeviceAdminTapjackingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/DeviceAdminTapjackingTestActivity.java
new file mode 100644
index 0000000..6a81cba
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/DeviceAdminTapjackingTestActivity.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.admin.tapjacking;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+/**
+ * Test that checks that device admin activate button does not allow taps when another window
+ * is obscuring the device admin details
+ */
+public class DeviceAdminTapjackingTestActivity extends PassFailButtons.Activity implements
+        View.OnClickListener {
+
+    private static final String TAG = DeviceAdminTapjackingTestActivity.class.getSimpleName();
+    private static final String ADMIN_ACTIVATED_BUNDLE_KEY = "admin_activated";
+    private static final String ACTIVITIES_FINISHED_IN_ORDER_KEY = "activities_finished_in_order";
+    private static final int REQUEST_ENABLE_ADMIN = 0;
+    private static final int REQUEST_OVERLAY_ACTIVITY = 1;
+    private static final long REMOVE_ADMIN_TIMEOUT = 5000;
+
+    private DevicePolicyManager mDevicePolicyManager;
+    private Button mAddDeviceAdminButton;
+    private boolean mAdminActivated;
+    private boolean mActivitiesFinishedInOrder;
+    private boolean mOverlayFinished;
+    private ComponentName mAdmin;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.da_tapjacking_test_main);
+        setInfoResources(R.string.da_tapjacking_test, R.string.da_tapjacking_test_info, -1);
+        setPassFailButtonClickListeners();
+
+        mAdmin = new ComponentName(this, EmptyDeviceAdminReceiver.class);
+        mDevicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
+
+        if (savedInstanceState != null) {
+            mAdminActivated = savedInstanceState.getBoolean(ADMIN_ACTIVATED_BUNDLE_KEY, false);
+            mActivitiesFinishedInOrder = savedInstanceState.getBoolean(ACTIVITIES_FINISHED_IN_ORDER_KEY, false);
+        } else if (isActiveAdminAfterTimeout()) {
+            Log.e(TAG, "Could not remove active admin. Cannot proceed with test");
+            finish();
+        }
+        mAddDeviceAdminButton = findViewById(R.id.enable_admin_overlay_button);
+        mAddDeviceAdminButton.setOnClickListener(this);
+    }
+
+    private boolean isActiveAdminAfterTimeout() {
+        final long startTime = SystemClock.uptimeMillis();
+        while (mDevicePolicyManager.isAdminActive(mAdmin)
+                && SystemClock.uptimeMillis() < startTime + REMOVE_ADMIN_TIMEOUT) {
+            try {
+                Thread.sleep(1000);
+            } catch(InterruptedException exc) {
+            }
+        }
+        return mDevicePolicyManager.isAdminActive(mAdmin);
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v == mAddDeviceAdminButton) {
+            Intent securitySettingsIntent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
+            securitySettingsIntent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdmin);
+            startActivityForResult(securitySettingsIntent, REQUEST_ENABLE_ADMIN);
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException exc) {
+            }
+            startActivityForResult(new Intent(this, OverlayingActivity.class), REQUEST_OVERLAY_ACTIVITY);
+        }
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQUEST_ENABLE_ADMIN) {
+            mActivitiesFinishedInOrder = mOverlayFinished;
+            if (resultCode == RESULT_OK) {
+                mAdminActivated = true;
+                Log.e(TAG, "Admin was activated. Restart the Test");
+            }
+        }
+        else if (requestCode == REQUEST_OVERLAY_ACTIVITY) {
+            mOverlayFinished = true;
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateWidgets();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle icicle) {
+        icicle.putBoolean(ADMIN_ACTIVATED_BUNDLE_KEY, mAdminActivated);
+        icicle.putBoolean(ACTIVITIES_FINISHED_IN_ORDER_KEY, mActivitiesFinishedInOrder);
+    }
+
+    private void updateWidgets() {
+        mAddDeviceAdminButton.setEnabled(!mActivitiesFinishedInOrder && !mAdminActivated);
+        getPassButton().setEnabled(!mAdminActivated && mActivitiesFinishedInOrder);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/EmptyDeviceAdminReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/EmptyDeviceAdminReceiver.java
new file mode 100644
index 0000000..42dd9ac
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/EmptyDeviceAdminReceiver.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.admin.tapjacking;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+
+public class EmptyDeviceAdminReceiver extends DeviceAdminReceiver {
+
+    @Override
+    public void onEnabled(Context context, Intent intent) {
+        DevicePolicyManager dpm =
+                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        dpm.removeActiveAdmin(new ComponentName(context, this.getClass()));
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/OverlayingActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/OverlayingActivity.java
new file mode 100644
index 0000000..52c7ed5
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/OverlayingActivity.java
@@ -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.
+ */
+
+package com.android.cts.verifier.admin.tapjacking;
+
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import com.android.cts.verifier.R;
+
+
+public class OverlayingActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.da_tapjacking_overlay_activity);
+        WindowManager.LayoutParams params = getWindow().getAttributes();
+        params.flags = FLAG_LAYOUT_NO_LIMITS | FLAG_NOT_TOUCH_MODAL | FLAG_NOT_TOUCHABLE
+                | FLAG_KEEP_SCREEN_ON;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupAccessibilityTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupAccessibilityTestActivity.java
deleted file mode 100644
index 157a71c..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupAccessibilityTestActivity.java
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.backup;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.backup.BackupManager;
-import android.app.backup.FileBackupHelper;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.graphics.Color;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.Scanner;
-
-/**
- * Test for checking whether Accessibility Settings are being backed up properly. It lists the
- * values of the accessibility preferences that should get backed up and restored after running the
- * backup manager and reinstalling the CTS verifier.
- */
-public class BackupAccessibilityTestActivity extends PassFailButtons.ListActivity {
-
-    private static final String TAG = BackupAccessibilityTestActivity.class.getSimpleName();
-
-    private static final int INSTRUCTIONS_DIALOG_ID = 1;
-
-    private static final List<String> ACCESSIBILITY_SETTINGS = new ArrayList();
-    private static final List<String> COLOR_CORRECTION_SETTINGS = new ArrayList();
-    private static final List<String> ACCESSIBILITY_SERVICE_SETTINGS = new ArrayList();
-    private static final List<String> CAPTIONS_SETTINGS = new ArrayList();
-    private static final List<String> TTS_SETTINGS = new ArrayList();
-    private static final List<String> SYSTEM_SETTINGS = new ArrayList();
-
-    static {
-        ACCESSIBILITY_SETTINGS.add("accessibility_display_magnification_enabled");
-        ACCESSIBILITY_SETTINGS.add("accessibility_autoclick_enabled");
-        ACCESSIBILITY_SETTINGS.add("accessibility_autoclick_delay");
-        ACCESSIBILITY_SETTINGS.add("high_text_contrast_enabled");
-        ACCESSIBILITY_SETTINGS.add("incall_power_button_behavior");
-        ACCESSIBILITY_SETTINGS.add(Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD);
-        ACCESSIBILITY_SETTINGS.add("accessibility_large_pointer_icon");
-        ACCESSIBILITY_SETTINGS.add("long_press_timeout");
-        ACCESSIBILITY_SETTINGS.add(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
-
-        COLOR_CORRECTION_SETTINGS.add("accessibility_display_daltonizer");
-        COLOR_CORRECTION_SETTINGS.add("accessibility_display_daltonizer_enabled");
-
-        CAPTIONS_SETTINGS.add("accessibility_captioning_preset");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_enabled");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_locale");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_background_color");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_foreground_color");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_edge_type");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_edge_color");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_typeface");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_font_scale");
-        CAPTIONS_SETTINGS.add("accessibility_captioning_window_color");
-
-        TTS_SETTINGS.add(Settings.Secure.TTS_DEFAULT_RATE);
-        TTS_SETTINGS.add("tts_default_locale");
-
-        ACCESSIBILITY_SERVICE_SETTINGS.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
-        ACCESSIBILITY_SERVICE_SETTINGS.add("touch_exploration_granted_accessibility_services");
-        ACCESSIBILITY_SERVICE_SETTINGS.add(Settings.Secure.TOUCH_EXPLORATION_ENABLED);
-
-        SYSTEM_SETTINGS.add(Settings.System.FONT_SCALE);
-        SYSTEM_SETTINGS.add(Settings.System.STAY_ON_WHILE_PLUGGED_IN);
-        SYSTEM_SETTINGS.add(Settings.System.SCREEN_OFF_TIMEOUT);
-        SYSTEM_SETTINGS.add(Settings.System.SCREEN_BRIGHTNESS);
-        SYSTEM_SETTINGS.add(Settings.System.SCREEN_BRIGHTNESS_MODE);
-        SYSTEM_SETTINGS.add(Settings.System.TEXT_SHOW_PASSWORD);
-        SYSTEM_SETTINGS.add(Settings.System.HAPTIC_FEEDBACK_ENABLED);
-        SYSTEM_SETTINGS.add("power_sounds_enabled");
-        SYSTEM_SETTINGS.add("lockscreen_sounds_enabled");
-        SYSTEM_SETTINGS.add("pointer_speed");
-        SYSTEM_SETTINGS.add(Settings.System.VIBRATE_WHEN_RINGING);
-        SYSTEM_SETTINGS.add(Settings.System.ACCELEROMETER_ROTATION);
-    }
-
-    private BackupAdapter mAdapter;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-        setContentView(R.layout.bua_main);
-        setPassFailButtonClickListeners();
-        setInfoResources(R.string.backup_accessibility_test, R.string.backup_accessibility_info, 0);
-
-        mAdapter = new BackupAdapter(this);
-        setListAdapter(mAdapter);
-
-        new ReadCurrentSettingsValuesTask().execute();
-
-        findViewById(R.id.generate_button).setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                new ReadCurrentSettingsValuesTask().execute();
-            }
-        });
-
-        findViewById(R.id.show_instructions_button).setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                showDialog(INSTRUCTIONS_DIALOG_ID);
-            }
-        });
-    }
-
-    class ReadCurrentSettingsValuesTask extends AsyncTask<Void, Void, List<BackupItem>> {
-
-        @Override
-        protected void onPreExecute() {
-            super.onPreExecute();
-            setProgressBarIndeterminateVisibility(true);
-        }
-
-        @Override
-        protected List<BackupItem> doInBackground(Void... params) {
-            List<BackupItem> items = new ArrayList<BackupItem>();
-
-            items.add(new CategoryBackupItem(R.string.bua_settings));
-            addSecureSettings(items, ACCESSIBILITY_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_color_correction));
-            addSecureSettings(items, COLOR_CORRECTION_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_captions));
-            addSecureSettings(items, CAPTIONS_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_tts));
-            addSecureSettings(items, TTS_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_accessibility_services));
-            addSecureSettings(items, ACCESSIBILITY_SERVICE_SETTINGS);
-
-            items.add(new CategoryBackupItem(R.string.bua_settings_system));
-            addSystemSettings(items, SYSTEM_SETTINGS);
-
-            return items;
-        }
-
-        private void addSecureSettings(List<BackupItem> items, List<String> settings) {
-            for (String setting : settings) {
-                String value = Settings.Secure.getString(getContentResolver(), setting);
-                items.add(new PreferenceBackupItem(setting, value));
-            }
-        }
-
-        private void addSystemSettings(List<BackupItem> items, List<String> settings) {
-            for (String setting : settings) {
-                String value = Settings.System.getString(getContentResolver(), setting);
-                items.add(new PreferenceBackupItem(setting, value));
-            }
-        }
-
-        @Override
-        protected void onPostExecute(List<BackupItem> result) {
-            super.onPostExecute(result);
-            setProgressBarIndeterminateVisibility(false);
-            mAdapter.clear();
-            mAdapter.addAll(result);
-        }
-    }
-
-    @Override
-    public Dialog onCreateDialog(int id, Bundle args) {
-        switch (id) {
-            case INSTRUCTIONS_DIALOG_ID:
-                return new AlertDialog.Builder(this)
-                    .setIcon(android.R.drawable.ic_dialog_info)
-                    .setTitle(R.string.backup_accessibility_test)
-                    .setMessage(R.string.bua_instructions)
-                    .setPositiveButton(android.R.string.ok, null)
-                    .setNeutralButton(R.string.bu_settings, new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            startActivity(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
-                        }
-                    }).create();
-
-            default:
-                return super.onCreateDialog(id, args);
-        }
-    }
-
-    interface BackupItem {
-        int getViewType();
-        View getView(LayoutInflater inflater, int position, View convertView, ViewGroup parent);
-    }
-
-    static class CategoryBackupItem implements BackupItem {
-
-        private final int mTitleResId;
-
-        CategoryBackupItem(int titleResId) {
-            mTitleResId = titleResId;
-        }
-
-        @Override
-        public int getViewType() {
-            return 0;
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.test_category_row, parent, false);
-            }
-            view.setText(mTitleResId);
-            view.setAllCaps(true);
-            view.setTextAppearance(1);  // Bold
-            return view;
-        }
-    }
-
-    static class PreferenceBackupItem implements BackupItem {
-
-        private final String mName;
-        private final String mValue;
-
-        PreferenceBackupItem(String name, String value) {
-            mName = name;
-            mValue = value;
-        }
-
-        @Override
-        public int getViewType() {
-            if (mValue == null || mValue.equals("0")) {
-                return 1;
-            } else {
-                return 2;
-            }
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.bu_preference_row, parent, false);
-            }
-            view.setText(mName + " : " + mValue);
-            if (mValue == null || mValue.equals("0")) {
-                view.setTextColor(Color.GREEN);
-            }
-            return view;
-        }
-    }
-
-    class BackupAdapter extends BaseAdapter {
-
-        private final LayoutInflater mLayoutInflater;
-
-        private final List<BackupItem> mItems = new ArrayList<BackupItem>();
-
-        public BackupAdapter(Context context) {
-            mLayoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
-        }
-
-        public void clear() {
-            mItems.clear();
-        }
-
-        public void addAll(List<BackupItem> items) {
-            mItems.addAll(items);
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public int getCount() {
-            return mItems.size();
-        }
-
-        @Override
-        public BackupItem getItem(int position) {
-            return mItems.get(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public boolean isEnabled(int position) {
-            return false;
-        }
-
-        @Override
-        public int getViewTypeCount() {
-            return 3;
-        }
-
-        @Override
-        public int getItemViewType(int position) {
-            return getItem(position).getViewType();
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            return getItem(position).getView(mLayoutInflater, position, convertView, parent);
-        }
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupTestActivity.java
deleted file mode 100644
index cccc1c2..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/backup/BackupTestActivity.java
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.backup;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.backup.BackupManager;
-import android.app.backup.FileBackupHelper;
-import android.app.backup.SharedPreferencesBackupHelper;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.Scanner;
-
-/**
- * Test for checking whether the BackupManager is working properly. It lists the values of
- * several preferences and contents of files that should get backed up and restored after
- * running the backup manager and reinstalling the CTS verifier.
- */
-public class BackupTestActivity extends PassFailButtons.ListActivity {
-
-    private static final String TAG = BackupTestActivity.class.getSimpleName();
-
-    private static final int INSTRUCTIONS_DIALOG_ID = 1;
-
-    private static final String TEST_PREFS_1 = "test-prefs-1";
-    private static final String INT_PREF = "int-pref";
-    private static final String BOOL_PREF = "bool-pref";
-
-    private static final String TEST_PREFS_2 = "test-prefs-2";
-    private static final String FLOAT_PREF = "float-pref";
-    private static final String LONG_PREF = "long-pref";
-    private static final String STRING_PREF = "string-pref";
-
-    private static final String TEST_FILE_1 = "test-file-1";
-    private static final String TEST_FILE_2 = "test-file-2";
-
-    private BackupAdapter mAdapter;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
-        setContentView(R.layout.bu_main);
-        setPassFailButtonClickListeners();
-        setInfoResources(R.string.backup_test, R.string.backup_info, 0);
-
-        mAdapter = new BackupAdapter(this);
-        setListAdapter(mAdapter);
-
-        new LoadBackupItemsTask().execute();
-
-        findViewById(R.id.generate_button).setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                new GenerateValuesTask().execute();
-            }
-        });
-    }
-
-    public static SharedPreferencesBackupHelper getSharedPreferencesBackupHelper(Context context) {
-        return new SharedPreferencesBackupHelper(context, TEST_PREFS_1, TEST_PREFS_2);
-    }
-
-    public static FileBackupHelper getFileBackupHelper(Context context) {
-        return new FileBackupHelper(context, TEST_FILE_1, TEST_FILE_2);
-    }
-
-    class LoadBackupItemsTask extends AsyncTask<Void, Void, List<BackupItem>> {
-
-        @Override
-        protected void onPreExecute() {
-            super.onPreExecute();
-            setProgressBarIndeterminateVisibility(true);
-        }
-
-        @Override
-        protected List<BackupItem> doInBackground(Void... params) {
-            List<BackupItem> items = new ArrayList<BackupItem>();
-
-            items.add(new CategoryBackupItem(R.string.bu_preferences));
-            loadPreferenceGroup1(items);
-            loadPreferenceGroup2(items);
-
-            items.add(new CategoryBackupItem(R.string.bu_files));
-            loadFile(TEST_FILE_1, items);
-            loadFile(TEST_FILE_2, items);
-
-            return items;
-        }
-
-        private void loadPreferenceGroup1(List<BackupItem> items) {
-            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
-
-            int intValue = prefs.getInt(INT_PREF, 0);
-            items.add(new PreferenceBackupItem(TEST_PREFS_1, INT_PREF, "" + intValue));
-
-            boolean boolValue = prefs.getBoolean(BOOL_PREF, false);
-            items.add(new PreferenceBackupItem(TEST_PREFS_1, BOOL_PREF, "" + boolValue));
-        }
-
-        private void loadPreferenceGroup2(List<BackupItem> items) {
-            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
-
-            float floatValue = prefs.getFloat(FLOAT_PREF, 0.0f);
-            items.add(new PreferenceBackupItem(TEST_PREFS_2, FLOAT_PREF, "" + floatValue));
-
-            long longValue = prefs.getLong(LONG_PREF, 0L);
-            items.add(new PreferenceBackupItem(TEST_PREFS_2, LONG_PREF, "" + longValue));
-
-            String stringValue = prefs.getString(STRING_PREF, null);
-            items.add(new PreferenceBackupItem(TEST_PREFS_2, STRING_PREF, stringValue));
-        }
-
-        private void loadFile(String fileName, List<BackupItem> items) {
-            StringBuilder contents = new StringBuilder();
-            Scanner scanner = null;
-            try {
-                scanner = new Scanner(new File(getFilesDir(), fileName));
-                while (scanner.hasNext()) {
-                    contents.append(scanner.nextLine());
-                }
-                scanner.close();
-            } catch (FileNotFoundException e) {
-                Log.e(TAG, "Couldn't find test file but this may be fine...", e);
-            } finally {
-                if (scanner != null) {
-                    scanner.close();
-                }
-            }
-            items.add(new FileBackupItem(fileName, contents.toString()));
-        }
-
-        @Override
-        protected void onPostExecute(List<BackupItem> result) {
-            super.onPostExecute(result);
-            setProgressBarIndeterminateVisibility(false);
-            mAdapter.clear();
-            mAdapter.addAll(result);
-        }
-    }
-
-    class GenerateValuesTask extends AsyncTask<Void, Void, Exception> {
-
-        @Override
-        protected Exception doInBackground(Void... params) {
-            Random random = new Random();
-            generatePreferenceGroup1(random);
-            generatePreferenceGroup2(random);
-            try {
-                generateTestFile(TEST_FILE_1, random);
-                generateTestFile(TEST_FILE_2, random);
-            } catch (FileNotFoundException e) {
-                return e;
-            }
-            return null;
-        }
-
-        private void generatePreferenceGroup1(Random random) {
-            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
-            SharedPreferences.Editor editor = prefs.edit();
-            editor.putInt(INT_PREF, (random.nextInt(100) + 1));
-            editor.putBoolean(BOOL_PREF, random.nextBoolean());
-            editor.commit();
-        }
-
-        private void generatePreferenceGroup2(Random random) {
-            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
-            SharedPreferences.Editor editor = prefs.edit();
-            editor.putFloat(FLOAT_PREF, random.nextFloat());
-            editor.putLong(LONG_PREF, random.nextLong());
-            editor.putString(STRING_PREF, "Random number: " + (random.nextInt(100) + 1));
-            editor.commit();
-        }
-
-        private void generateTestFile(String fileName, Random random)
-                throws FileNotFoundException {
-            File file = new File(getFilesDir(), fileName);
-            PrintWriter writer = new PrintWriter(file);
-            writer.write("Random number: " + (random.nextInt(100) + 1));
-            writer.close();
-        }
-
-        @Override
-        protected void onPostExecute(Exception exception) {
-            super.onPostExecute(exception);
-            if (exception != null) {
-                Log.e(TAG, "Couldn't generate test data...", exception);
-                Toast.makeText(BackupTestActivity.this, R.string.bu_generate_error,
-                        Toast.LENGTH_LONG).show();
-            } else {
-                showDialog(INSTRUCTIONS_DIALOG_ID);
-
-                BackupManager backupManager = new BackupManager(BackupTestActivity.this);
-                backupManager.dataChanged();
-
-                new LoadBackupItemsTask().execute();
-            }
-        }
-    }
-
-    @Override
-    public Dialog onCreateDialog(int id, Bundle args) {
-        switch (id) {
-            case INSTRUCTIONS_DIALOG_ID:
-                return new AlertDialog.Builder(this)
-                    .setIcon(android.R.drawable.ic_dialog_info)
-                    .setTitle(R.string.backup_test)
-                    .setMessage(R.string.bu_instructions)
-                    .setPositiveButton(android.R.string.ok, null)
-                    .setNeutralButton(R.string.bu_settings, new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            startActivity(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
-                        }
-                    })
-                    .create();
-
-            default:
-                return super.onCreateDialog(id, args);
-        }
-    }
-
-    interface BackupItem {
-        int getViewType();
-        View getView(LayoutInflater inflater, int position, View convertView, ViewGroup parent);
-    }
-
-    static class CategoryBackupItem implements BackupItem {
-
-        private final int mTitleResId;
-
-        CategoryBackupItem(int titleResId) {
-            mTitleResId = titleResId;
-        }
-
-        @Override
-        public int getViewType() {
-            return 0;
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.test_category_row, parent, false);
-            }
-            view.setText(mTitleResId);
-            return view;
-        }
-    }
-
-    static class PreferenceBackupItem implements BackupItem {
-
-        private final String mGroup;
-
-        private final String mName;
-
-        private final String mValue;
-
-        PreferenceBackupItem(String group, String name, String value) {
-            mGroup = group;
-            mName = name;
-            mValue = value;
-        }
-
-        @Override
-        public int getViewType() {
-            return 1;
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.bu_preference_row, parent, false);
-            }
-            view.setText(mGroup + "/" + mName + " : " + mValue);
-            return view;
-        }
-    }
-
-    static class FileBackupItem implements BackupItem {
-
-        private final String mName;
-
-        private final String mContents;
-
-        FileBackupItem(String name, String contents) {
-            mName = name;
-            mContents = contents;
-        }
-
-        @Override
-        public int getViewType() {
-            return 2;
-        }
-
-        @Override
-        public View getView(LayoutInflater inflater, int position, View convertView,
-                ViewGroup parent) {
-            TextView view = (TextView) convertView;
-            if (convertView == null) {
-                view = (TextView) inflater.inflate(R.layout.bu_preference_row, parent, false);
-            }
-            view.setText(mName + " : " + mContents);
-            return view;
-        }
-    }
-
-    class BackupAdapter extends BaseAdapter {
-
-        private final LayoutInflater mLayoutInflater;
-
-        private final List<BackupItem> mItems = new ArrayList<BackupItem>();
-
-        public BackupAdapter(Context context) {
-            mLayoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
-        }
-
-        public void clear() {
-            mItems.clear();
-        }
-
-        public void addAll(List<BackupItem> items) {
-            mItems.addAll(items);
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public int getCount() {
-            return mItems.size();
-        }
-
-        @Override
-        public BackupItem getItem(int position) {
-            return mItems.get(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public boolean isEnabled(int position) {
-            return false;
-        }
-
-        @Override
-        public int getViewTypeCount() {
-            return 3;
-        }
-
-        @Override
-        public int getItemViewType(int position) {
-            return getItem(position).getViewType();
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            return getItem(position).getView(mLayoutInflater, position, convertView, parent);
-        }
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/location/GnssTtffTestsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/location/GnssTtffTestsActivity.java
new file mode 100644
index 0000000..1ba925c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/location/GnssTtffTestsActivity.java
@@ -0,0 +1,15 @@
+package com.android.cts.verifier.location;
+
+import com.android.cts.verifier.location.base.GnssCtsTestActivity;
+import android.location.cts.GnssTtffTests;
+
+/**
+ * Activity to execute CTS GnssStatusTest.
+ * It is a wrapper for {@link GnssTtffTests} running with AndroidJUnitRunner.
+ */
+
+public class GnssTtffTestsActivity extends GnssCtsTestActivity {
+  public GnssTtffTestsActivity() {
+    super(GnssTtffTests.class);
+  }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
index 0355cb4..23744c7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
@@ -32,7 +32,6 @@
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
-import android.provider.Settings;
 import android.service.notification.NotificationListenerService;
 import android.util.Log;
 import android.view.View;
@@ -101,7 +100,7 @@
         tests.add(new SetModeAllTest());
         tests.add(new AllInterceptsNothingTest());
         tests.add(new DefaultOrderTest());
-        tests.add(new PrioritytOrderTest());
+        tests.add(new PriorityOrderTest());
         tests.add(new InterruptionOrderTest());
         tests.add(new AmbientBitsTest());
         tests.add(new LookupUriOrderTest());
@@ -113,13 +112,11 @@
 
     private void createChannels() {
         NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
-                NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+                NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_MIN);
         mNm.createNotificationChannel(channel);
         NotificationChannel noisyChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID_NOISY,
                 NOTIFICATION_CHANNEL_ID_NOISY, NotificationManager.IMPORTANCE_HIGH);
         noisyChannel.enableVibration(true);
-        noisyChannel.setSound(
-                Settings.System.DEFAULT_RINGTONE_URI, Notification.AUDIO_ATTRIBUTES_DEFAULT);
         mNm.createNotificationChannel(noisyChannel);
     }
 
@@ -528,7 +525,7 @@
     }
 
     // ordered by priority: B, C, A
-    protected class PrioritytOrderTest extends InteractiveTestCase {
+    protected class PriorityOrderTest extends InteractiveTestCase {
         @Override
         View inflate(ViewGroup parent) {
             return createAutoItem(parent, R.string.attention_priority_order);
@@ -585,8 +582,8 @@
         @Override
         void setUp() {
             createChannels();
-            // send B & C noisy
-            sendNotifications(SEND_B | SEND_C, MODE_NONE, false, true);
+            // send B & C noisy with contact affinity
+            sendNotifications(SEND_B | SEND_C, MODE_URI, false, true);
             status = READY;
             // wait for then to not be recently noisy any more
             delay(15000);
@@ -595,7 +592,7 @@
         @Override
         void test() {
             if (status == READY) {
-                // send A noisy
+                // send A noisy but no contact affinity
                 sendNotifications(SEND_A, MODE_NONE, false, true);
                 status = RETEST;
                 delay();
@@ -650,7 +647,8 @@
         @Override
         void setUp() {
             createChannels();
-            sendNotifications(MODE_NONE, true, false);
+            sendNotifications(SEND_B | SEND_C, MODE_NONE, true, true);
+            sendNotifications(SEND_A, MODE_NONE, true, false);
             status = READY;
             // wait for notifications to move through the system
             delay();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java
index 8d1bb7a..d311faa 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java
@@ -170,8 +170,10 @@
                 } else if (SERVICE_SNOOZE_DURATION.equals(action)) {
                     String tag = intent.getStringExtra(EXTRA_TAG);
                     String key = mNotificationKeys.get(tag);
-                    MockListener.this.snoozeNotification(key,
-                            intent.getLongExtra(EXTRA_LONG, (long) 0));
+                    if (key != null) {
+                        MockListener.this.snoozeNotification(key,
+                                intent.getLongExtra(EXTRA_LONG, (long) 0));
+                    }
                 } else if (SERVICE_GET_SNOOZED.equals(action)) {
                     mSnoozed.clear();
                     StatusBarNotification[] snoozed = MockListener.this.getSnoozedNotifications();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
index 5bad113..20e7d1e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
@@ -84,11 +84,13 @@
         tests.add(new DismissOneWithReasonTest());
         tests.add(new DismissAllTest());
         tests.add(new SnoozeNotificationForTimeTest());
+        tests.add(new SnoozeNotificationForTimeCancelTest());
         tests.add(new GetSnoozedNotificationTest());
         tests.add(new EnableHintsTest());
         tests.add(new SnoozeTest());
         tests.add(new UnsnoozeTest());
         tests.add(new MessageBundleTest());
+        tests.add(new EnableHintsTest());
         tests.add(new IsDisabledTest());
         tests.add(new ServiceStoppedTest());
         tests.add(new NotificationNotReceivedTest());
@@ -792,6 +794,85 @@
         }
     }
 
+    /**
+     * Posts notifications, snoozes one of them. Verifies that it is snoozed. Cancels all
+     * notifications and reposts them. Confirms that the original notification is still snoozed.
+     */
+    private class SnoozeNotificationForTimeCancelTest extends InteractiveTestCase {
+
+        final static int READY_TO_SNOOZE = 0;
+        final static int SNOOZED = 1;
+        final static int READY_TO_CHECK_FOR_SNOOZE = 2;
+        int state = -1;
+        long snoozeTime = 10000;
+        private String tag;
+        @Override
+        View inflate(ViewGroup parent) {
+            return createAutoItem(parent, R.string.nls_snooze_one_time);
+        }
+
+        @Override
+        void setUp() {
+            createChannel();
+            sendNotifications();
+            tag = mTag1;
+            status = READY;
+            state = READY_TO_SNOOZE;
+            delay();
+        }
+
+        @Override
+        void test() {
+            status = RETEST;
+            if (state == READY_TO_SNOOZE) {
+                MockListener.snoozeOneFor(mContext, tag, snoozeTime);
+                state = SNOOZED;
+            } else if (state == SNOOZED){
+                MockListener.probeListenerSnoozed(mContext,
+                        new MockListener.StringListResultCatcher() {
+                            @Override
+                            public void accept(List<String> result) {
+                                if (result != null && result.size() >= 1
+                                        && result.contains(tag)) {
+                                    // cancel and repost
+                                    sendNotifications();
+                                    state = READY_TO_CHECK_FOR_SNOOZE;
+                                    delay();
+                                } else {
+                                    logFail();
+                                    status = FAIL;
+                                    next();
+                                }
+                            }
+                        });
+            } else {
+                MockListener.probeListenerSnoozed(mContext,
+                        new MockListener.StringListResultCatcher() {
+                            @Override
+                            public void accept(List<String> result) {
+                                if (result != null && result.size() >= 1
+                                        && result.contains(tag)) {
+                                    status = PASS;
+                                } else {
+                                    logFail();
+                                    status = FAIL;
+                                }
+                                next();
+                            }
+                        });
+            }
+            delay();
+        }
+
+        @Override
+        void tearDown() {
+            mNm.cancelAll();
+            deleteChannel();
+            MockListener.resetListenerData(mContext);
+            delay();
+        }
+    }
+
     private class GetSnoozedNotificationTest extends InteractiveTestCase {
         final static int READY_TO_SNOOZE = 0;
         final static int SNOOZED = 1;
@@ -858,7 +939,7 @@
                         new MockListener.StringListResultCatcher() {
                             @Override
                             public void accept(List<String> result) {
-                                if (result != null && result.size() == 2
+                                if (result != null && result.size() >= 2
                                         && result.contains(mTag1)
                                         && result.contains(mTag2)) {
                                     status = PASS;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java
index c935841..c004b73 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java
@@ -20,12 +20,16 @@
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
+import android.telecom.CallAudioState;
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 import android.telecom.VideoProfile;
 
 import com.android.cts.verifier.R;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
  * An implementation of the {@link android.telecom.Connection} class used by the
  * {@link CtsConnectionService}.
@@ -51,6 +55,7 @@
     private final Listener mListener;
     private final MediaPlayer mMediaPlayer;
     private final Context mContext;
+    private CountDownLatch mWaitForCallAudioStateChanged = new CountDownLatch(1);
 
     public CtsConnection(Context context, boolean isIncomingCall,
             Listener listener, boolean hasAudio) {
@@ -131,6 +136,20 @@
         }
     }
 
+    public void onCallAudioStateChanged(CallAudioState state) {
+        mWaitForCallAudioStateChanged.countDown();
+        mWaitForCallAudioStateChanged = new CountDownLatch(1);
+
+    }
+
+    public void waitForAudioStateChanged() {
+        try {
+            mWaitForCallAudioStateChanged.await(CtsConnectionService.TIMEOUT_MILLIS,
+                    TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+        }
+    }
+
     private void setDisconnectedAndDestroy(DisconnectCause cause) {
         setDisconnected(cause);
         destroy();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
index 528c221..7cfcbf8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
@@ -26,35 +26,74 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * CTS Verifier ConnectionService implementation.
  */
 public class CtsConnectionService extends ConnectionService {
+    static final int TIMEOUT_MILLIS = 10000;
 
     private CtsConnection.Listener mConnectionListener =
             new CtsConnection.Listener() {
                 @Override
                 void onDestroyed(CtsConnection connection) {
-                    mConnections.remove(connection);
+                    synchronized (mConnectionsLock) {
+                        mConnections.remove(connection);
+                    }
                 }
             };
 
     private static CtsConnectionService sConnectionService;
+    private static CountDownLatch sBindingLatch = new CountDownLatch(1);
 
     private List<CtsConnection> mConnections = new ArrayList<>();
+    private Object mConnectionsLock = new Object();
+    private CountDownLatch mConnectionLatch = new CountDownLatch(1);
 
     public static CtsConnectionService getConnectionService() {
         return sConnectionService;
     }
 
+    public static CtsConnectionService waitForAndGetConnectionService() {
+        if (sConnectionService == null) {
+            try {
+                sBindingLatch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+            }
+        }
+        return sConnectionService;
+    }
+
     public CtsConnectionService() throws Exception {
         super();
         sConnectionService = this;
+        if (sBindingLatch != null) {
+            sBindingLatch.countDown();
+        }
+        sBindingLatch = new CountDownLatch(1);
     }
 
     public List<CtsConnection> getConnections() {
-        return mConnections;
+        synchronized (mConnectionsLock) {
+            return new ArrayList<CtsConnection>(mConnections);
+        }
+    }
+
+    public CtsConnection waitForAndGetConnection() {
+        try {
+            mConnectionLatch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+        }
+        mConnectionLatch = new CountDownLatch(1);
+        synchronized (mConnectionsLock) {
+            if (mConnections.size() > 0) {
+                return mConnections.get(0);
+            } else {
+                return null;
+            }
+        }
     }
 
     @Override
@@ -109,7 +148,12 @@
         connection.putExtras(moreExtras);
         connection.setVideoState(request.getVideoState());
 
-        mConnections.add(connection);
+        synchronized (mConnectionsLock) {
+            mConnections.add(connection);
+        }
+        if (mConnectionLatch != null) {
+            mConnectionLatch.countDown();
+        }
         return connection;
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java
index cdc8665..6b0b3da 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java
@@ -57,6 +57,19 @@
             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
             .build();
 
+    public static final String TEST_SELF_MAANGED_PHONE_ACCOUNT2_ID = "selfMgdTest2";
+    public static final String TEST_SELF_MANAGED_PHONE_ACCOUNT2_LABEL = "CTSVerifier2";
+
+    public static final PhoneAccountHandle TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2 =
+            new PhoneAccountHandle(new ComponentName(
+                    PassFailButtons.class.getPackage().getName(),
+                    CtsConnectionService.class.getName()), TEST_SELF_MAANGED_PHONE_ACCOUNT2_ID);
+    public static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT_2 = new PhoneAccount.Builder(
+            TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2, TEST_SELF_MANAGED_PHONE_ACCOUNT2_LABEL)
+            .setAddress(TEST_SELF_MANAGED_PHONE_ACCOUNT_ADDRESS)
+            .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
+            .build();
+
     /**
      * Registers the test phone account.
      * @param context The context.
@@ -89,13 +102,25 @@
     }
 
     /**
-     * Registers the test self-managed phone account.
+     * Registers the test self-managed phone accounts.
      * @param context The context.
      */
     public static void registerTestSelfManagedPhoneAccount(Context context) {
         TelecomManager telecomManager = (TelecomManager) context.getSystemService(
                 Context.TELECOM_SERVICE);
         telecomManager.registerPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT);
+        telecomManager.registerPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT_2);
+    }
+
+    /**
+     * Unregisters the test self-managed phone accounts.
+     * @param context The context.
+     */
+    public static void unRegisterTestSelfManagedPhoneAccount(Context context) {
+        TelecomManager telecomManager = (TelecomManager) context.getSystemService(
+                Context.TELECOM_SERVICE);
+        telecomManager.unregisterPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE);
+        telecomManager.unregisterPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2);
     }
 
     /**
@@ -119,4 +144,15 @@
                 Context.TELECOM_SERVICE);
         return telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
     }
+
+    /**
+     * Retrieves the test phone account, or null if not registered.
+     * @param context The context.
+     * @return The Phone Account.
+     */
+    public static PhoneAccount getSelfManagedPhoneAccount2(Context context) {
+        TelecomManager telecomManager = (TelecomManager) context.getSystemService(
+                Context.TELECOM_SERVICE);
+        return telecomManager.getPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2);
+    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java
new file mode 100644
index 0000000..2b06446
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.cts.verifier.telecom;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.telecom.Connection;
+import android.telecom.PhoneAccount;
+import android.telecom.TelecomManager;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import java.util.List;
+
+/**
+ * This test verifies functionality associated with the Self-Managed
+ * {@link android.telecom.ConnectionService} APIs.  It ensures that Telecom will show an incoming
+ * call UI when a new incoming self-managed call is added when there is already an ongoing managed
+ * call or when there is an ongoing self-managed call in another app.
+ */
+public class SelfManagedIncomingCallTestActivity extends PassFailButtons.Activity {
+    private Uri TEST_DIAL_NUMBER_1 = Uri.fromParts("tel", "6505551212", null);
+    private Uri TEST_DIAL_NUMBER_2 = Uri.fromParts("tel", "4085551212", null);
+
+    private ImageView mStep1Status;
+    private Button mRegisterPhoneAccount;
+    private ImageView mStep2Status;
+    private Button mShowUi;
+    private ImageView mStep3Status;
+    private Button mConfirm;
+
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        View view = getLayoutInflater().inflate(R.layout.telecom_self_managed_answer, null);
+        setContentView(view);
+        setInfoResources(R.string.telecom_incoming_self_mgd_test,
+                R.string.telecom_incoming_self_mgd_info, -1);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+
+        mStep1Status = view.findViewById(R.id.step_1_status);
+        mRegisterPhoneAccount = view.findViewById(R.id.telecom_incoming_self_mgd_register_button);
+        mRegisterPhoneAccount.setOnClickListener(v -> {
+            PhoneAccountUtils.registerTestSelfManagedPhoneAccount(this);
+            PhoneAccount account = PhoneAccountUtils.getSelfManagedPhoneAccount(this);
+            PhoneAccount account2 = PhoneAccountUtils.getSelfManagedPhoneAccount2(this);
+            if (account != null &&
+                    account.isEnabled() &&
+                    account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) &&
+                    account2 != null &&
+                    account2.isEnabled() &&
+                    account2.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
+                mRegisterPhoneAccount.setEnabled(false);
+                mShowUi.setEnabled(true);
+                mStep1Status.setImageResource(R.drawable.fs_good);
+            } else {
+                mStep1Status.setImageResource(R.drawable.fs_error);
+            }
+        });
+
+        mStep2Status = view.findViewById(R.id.step_2_status);
+        mShowUi = view.findViewById(R.id.telecom_incoming_self_mgd_show_ui_button);
+        mShowUi.setOnClickListener(v -> {
+            (new AsyncTask<Void, Void, Throwable>() {
+                @Override
+                protected Throwable doInBackground(Void... params) {
+                    try {
+                        Bundle extras = new Bundle();
+                        extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
+                                TEST_DIAL_NUMBER_1);
+                        TelecomManager telecomManager =
+                                (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
+                        if (telecomManager == null) {
+                            mStep2Status.setImageResource(R.drawable.fs_error);
+                            return new Throwable("Could not get telecom service.");
+                        }
+                        telecomManager.addNewIncomingCall(
+                                PhoneAccountUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE, extras);
+
+                        CtsConnectionService ctsConnectionService =
+                                CtsConnectionService.waitForAndGetConnectionService();
+                        if (ctsConnectionService == null) {
+                            mStep2Status.setImageResource(R.drawable.fs_error);
+                            return new Throwable("Could not get connection service.");
+                        }
+
+                        CtsConnection connection = ctsConnectionService.waitForAndGetConnection();
+                        if (connection == null) {
+                            mStep2Status.setImageResource(R.drawable.fs_error);
+                            return new Throwable("Could not get connection.");
+                        }
+                        // Wait until the connection knows its audio state changed; at this point
+                        // Telecom knows about the connection and can answer.
+                        connection.waitForAudioStateChanged();
+                        // Make it active to simulate an answer.
+                        connection.setActive();
+
+                        // Place the second call. It should trigger the incoming call UX.
+                        Bundle extras2 = new Bundle();
+                        extras2.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
+                                TEST_DIAL_NUMBER_2);
+                        telecomManager.addNewIncomingCall(
+                                PhoneAccountUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2,
+                                extras2);
+
+                        return null;
+                    } catch (Throwable t) {
+                        return  t;
+                    }
+                }
+
+                @Override
+                protected void onPostExecute(Throwable t) {
+                    if (t == null) {
+                        mStep2Status.setImageResource(R.drawable.fs_good);
+                        mShowUi.setEnabled(false);
+                        mConfirm.setEnabled(true);
+                    } else {
+                        mStep2Status.setImageResource(R.drawable.fs_error);
+                    }
+                }
+            }).execute();
+
+
+        });
+
+        mStep3Status = view.findViewById(R.id.step_3_status);
+        mConfirm = view.findViewById(R.id.telecom_incoming_self_mgd_confirm_answer_button);
+        mConfirm.setOnClickListener(v -> {
+            CtsConnectionService ctsConnectionService = CtsConnectionService.getConnectionService();
+            if (ctsConnectionService == null) {
+                mStep3Status.setImageResource(R.drawable.fs_error);
+                return;
+            }
+            List<CtsConnection> connections = ctsConnectionService.getConnections();
+            if (connections.size() != 1) {
+                mStep3Status.setImageResource(R.drawable.fs_error);
+                return;
+            }
+
+            if (connections.get(0).getState() == Connection.STATE_ACTIVE) {
+                connections
+                        .stream()
+                        .forEach((c) -> c.onDisconnect());
+                mStep3Status.setImageResource(R.drawable.fs_good);
+                getPassButton().setEnabled(true);
+            } else {
+                mStep3Status.setImageResource(R.drawable.fs_error);
+            }
+
+            PhoneAccountUtils.unRegisterTestSelfManagedPhoneAccount(this);
+        });
+
+        mShowUi.setEnabled(false);
+        mConfirm.setEnabled(false);
+    }
+}
diff --git a/build/device_info_package.mk b/build/device_info_package.mk
index b91c264..dcc81d3 100644
--- a/build/device_info_package.mk
+++ b/build/device_info_package.mk
@@ -26,7 +26,6 @@
   $(DEVICE_INFO_PACKAGE).GenericDeviceInfo \
   $(DEVICE_INFO_PACKAGE).GlesStubActivity \
   $(DEVICE_INFO_PACKAGE).GraphicsDeviceInfo \
-  $(DEVICE_INFO_PACKAGE).LibraryDeviceInfo \
   $(DEVICE_INFO_PACKAGE).LocaleDeviceInfo \
   $(DEVICE_INFO_PACKAGE).MediaDeviceInfo \
   $(DEVICE_INFO_PACKAGE).MemoryDeviceInfo \
@@ -34,7 +33,8 @@
   $(DEVICE_INFO_PACKAGE).PropertyDeviceInfo \
   $(DEVICE_INFO_PACKAGE).ScreenDeviceInfo \
   $(DEVICE_INFO_PACKAGE).StorageDeviceInfo \
-  $(DEVICE_INFO_PACKAGE).UserDeviceInfo
+  $(DEVICE_INFO_PACKAGE).UserDeviceInfo \
+  $(DEVICE_INFO_PACKAGE).VintfDeviceInfo
 
 ifeq ($(DEVICE_INFO_MIN_SDK),)
 DEVICE_INFO_MIN_SDK := 8
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LibraryDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LibraryDeviceInfo.java
deleted file mode 100644
index 792c88a..0000000
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/LibraryDeviceInfo.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.compatibility.common.deviceinfo;
-
-import android.util.Log;
-
-import com.android.compatibility.common.util.DeviceInfoStore;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Formatter;
-
-/**
- * Library device info collector.
- */
-public final class LibraryDeviceInfo extends DeviceInfo {
-
-    private static final String TAG = "LibraryDeviceInfo";
-    private static final int BUFFER_SIZE_BYTES = 4096;
-
-    @Override
-    protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
-        collectSystemLibs(store);
-        collectVendorLibs(store);
-        collectFrameworkJars(store);
-    }
-
-    private void collectSystemLibs(DeviceInfoStore store) throws Exception {
-        store.startArray("lib");
-        collectFileDetails(store, "/system/lib", ".so");
-        store.endArray();
-    }
-
-    private void collectVendorLibs(DeviceInfoStore store) throws Exception {
-        store.startArray("vendor_lib");
-        collectFileDetails(store, "/system/vendor/lib", ".so");
-        store.endArray();
-    }
-
-    private void collectFrameworkJars(DeviceInfoStore store) throws Exception {
-        store.startArray("framework_jar");
-        collectFileDetails(store, "/system/framework", ".jar");
-        store.endArray();
-    }
-
-    private void collectFileDetails(DeviceInfoStore store, String path, String suffix)
-            throws Exception {
-        File dir = new File(path);
-        File[] files = dir.listFiles();
-        if (files == null) {
-            return;
-        }
-        for (File file : files) {
-            String name = file.getName();
-            if (file.isFile() && name.endsWith(suffix)) {
-                String sha1 = "unknown";
-                try {
-                    sha1 = getSha1sum(file);
-                } catch (IOException e) {
-                    Log.e(TAG, "Failed to hash " + file + ": ", e);
-                }
-                store.startGroup();
-                store.addResult("name", name);
-                store.addResult("sha1", sha1);
-                store.endGroup();
-            }
-        }
-    }
-
-    private static String getSha1sum(File file) throws IOException {
-        InputStream in = null;
-        try {
-            in = new FileInputStream(file);
-            return sha1(in);
-        } finally {
-            close(in);
-        }
-    }
-
-    private static void close(Closeable s) throws IOException {
-        if (s == null) {
-            return;
-        }
-        s.close();
-    }
-
-    /**
-     * @return the SHA-1 digest of input as a hex string
-     */
-    public static String sha1(InputStream input) throws IOException {
-        try {
-            return toHexString(digest(input, "sha1"));
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private static byte[] digest(InputStream in, String algorithm)
-        throws NoSuchAlgorithmException, IOException {
-        MessageDigest digest = MessageDigest.getInstance(algorithm);
-        byte[] buffer = new byte[BUFFER_SIZE_BYTES];
-        while (true) {
-            int read = in.read(buffer);
-            if (read < 0) {
-                break;
-            }
-            digest.update(buffer, 0, read);
-        }
-        return digest.digest();
-    }
-
-    private static String toHexString(byte[] buffer) {
-        Formatter formatter = new Formatter();
-        try {
-            for (byte b : buffer) {
-                formatter.format("%02X", b);
-            }
-            return formatter.toString();
-        } finally {
-            formatter.close();
-        }
-    }
-}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
new file mode 100644
index 0000000..c38628d
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import android.os.VintfObject;
+import android.os.VintfRuntimeInfo;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import com.android.compatibility.common.util.DeviceInfoStore;
+
+/**
+ * VINTF device info collector.
+ */
+public final class VintfDeviceInfo extends DeviceInfo {
+
+    private static final String[] sEmptyStringArray = new String[0];
+
+    @Override
+    protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
+        store.addResult("cpu_info", VintfRuntimeInfo.getCpuInfo());
+        store.addResult("os_name", VintfRuntimeInfo.getOsName());
+        store.addResult("node_name", VintfRuntimeInfo.getNodeName());
+        store.addResult("os_release", VintfRuntimeInfo.getOsRelease());
+        store.addResult("os_version", VintfRuntimeInfo.getOsVersion());
+        store.addResult("hardware_id", VintfRuntimeInfo.getHardwareId());
+        store.addResult("kernel_version", VintfRuntimeInfo.getKernelVersion());
+        store.addResult("kernel_sepolicy_version", VintfRuntimeInfo.getKernelSepolicyVersion());
+        store.addResult("sepolicy_version", VintfObject.getSepolicyVersion());
+
+        String[] hals = VintfObject.getHalNamesAndVersions();
+        store.addListResult("hals", hals == null
+                ? Collections.emptyList() : Arrays.<String>asList(hals));
+
+        Map<String, String[]> vndks = VintfObject.getVndkSnapshots();
+        if (vndks == null) vndks = Collections.emptyMap();
+        store.startArray("vndk_snapshots");
+        for (Map.Entry<String, String[]> e : vndks.entrySet()) {
+            store.startGroup();
+            store.addResult("version", e.getKey());
+            String[] libraries = e.getValue();
+            store.addListResult("libraries", libraries == null
+                    ? Collections.emptyList() : Arrays.<String>asList(libraries));
+            store.endGroup();
+        }
+        store.endArray();
+    }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
index ad7cf47..7ea8a36 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
@@ -380,6 +380,7 @@
             // Forward module results to the master.
             mMasterResultReporter.mergeModuleResult(mCurrentModuleResult);
             mCurrentModuleResult.resetTestRuns();
+            mCurrentModuleResult.resetRuntime();
         }
     }
 
@@ -595,9 +596,11 @@
         }
 
         FileInputStream fis = null;
+        LogFile logFile = null;
         try {
             fis = new FileInputStream(resultFile);
-            mLogSaver.saveLogData("log-result", LogDataType.XML, fis);
+            logFile = mLogSaver.saveLogData("log-result", LogDataType.XML, fis);
+            debug("Result XML URL: %s", logFile.getUrl());
         } catch (IOException ioe) {
             CLog.e("[%s] error saving XML with log saver", mDeviceSerial);
             CLog.e(ioe);
@@ -609,7 +612,8 @@
             FileInputStream zipResultStream = null;
             try {
                 zipResultStream = new FileInputStream(zippedResults);
-                mLogSaver.saveLogData("results", LogDataType.ZIP, zipResultStream);
+                logFile = mLogSaver.saveLogData("results", LogDataType.ZIP, zipResultStream);
+                debug("Result zip URL: %s", logFile.getUrl());
             } finally {
                 StreamUtil.close(zipResultStream);
             }
@@ -790,7 +794,7 @@
      *  Log debug to the console.
      */
     private static void debug(String format, Object... args) {
-        CLog.d(format, args);
+        log(LogLevel.DEBUG, format, args);
     }
 
     /**
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceFileCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceFileCollector.java
new file mode 100644
index 0000000..0e8426f
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceFileCollector.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.tradefed.targetprep;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import java.nio.file.Paths;
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * An {@link PreconditionPreparer} that collects one device file.
+ */
+public class DeviceFileCollector extends PreconditionPreparer {
+
+    @Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION,
+            shortName = 'd',
+            description = "Whether device info collection should be skipped")
+    private boolean mSkipDeviceInfo = false;
+
+    @Option(name= "src-file", description = "The file path to copy to the results dir")
+    private String mSrcFile;
+
+    @Option(name = "dest-file", description = "The destination file path under the result")
+    private String mDestFile;
+
+    private File mResultFile;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void run(ITestDevice device, IBuildInfo buildInfo) {
+        if (mSkipDeviceInfo)
+            return;
+
+        createResultDir(buildInfo);
+        if (mResultFile != null && !mResultFile.isDirectory() &&
+            mSrcFile != null && !mSrcFile.isEmpty()) {
+
+            try {
+                if (device.doesFileExist(mSrcFile)) {
+                    device.pullFile(mSrcFile, mResultFile);
+                } else {
+                    CLog.w(String.format("File does not exist on device: \"%s\"", mSrcFile));
+                }
+            } catch (DeviceNotAvailableException e) {
+                CLog.e("Caught exception during pull.");
+                CLog.e(e);
+            }
+        }
+    }
+
+    private void createResultDir(IBuildInfo buildInfo) {
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
+        try {
+            File resultDir = buildHelper.getResultDir();
+            if (mDestFile == null || mDestFile.isEmpty()) {
+                mDestFile = Paths.get(mSrcFile).getFileName().toString();
+            }
+            mResultFile = Paths.get(resultDir.getAbsolutePath(), mDestFile).toFile();
+            resultDir = mResultFile.getParentFile();
+            resultDir.mkdirs();
+            if (!resultDir.isDirectory()) {
+                CLog.e("%s is not a directory", resultDir.getAbsolutePath());
+                return;
+            }
+        } catch (FileNotFoundException fnfe) {
+            fnfe.printStackTrace();
+        }
+    }
+}
diff --git a/common/util/src/com/android/compatibility/common/util/IModuleResult.java b/common/util/src/com/android/compatibility/common/util/IModuleResult.java
index 06d66c0..2ebf181 100644
--- a/common/util/src/com/android/compatibility/common/util/IModuleResult.java
+++ b/common/util/src/com/android/compatibility/common/util/IModuleResult.java
@@ -30,6 +30,8 @@
 
     void addRuntime(long elapsedTime);
 
+    void resetRuntime();
+
     long getRuntime();
 
     /**
diff --git a/common/util/src/com/android/compatibility/common/util/ModuleResult.java b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
index 60038cf..60500a2 100644
--- a/common/util/src/com/android/compatibility/common/util/ModuleResult.java
+++ b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
@@ -191,6 +191,14 @@
      * {@inheritDoc}
      */
     @Override
+    public void resetRuntime() {
+        mRuntime = 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public long getRuntime() {
         return mRuntime;
     }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 3a282bf..6a6c27d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -47,8 +47,13 @@
     private static final String MODE_EMULATED = "emulated";
     private static final String MODE_NONE = "none";
 
+    private static final String FEATURE_DEVICE_ADMIN = "feature:android.software.device_admin\n";
+    private static final String FEATURE_AUTOMOTIVE = "feature:android.hardware.type.automotive\n";
+
     private static final long SHUTDOWN_TIME_MS = 30 * 1000;
 
+    private String mFeatureList = null;
+
     private IAbi mAbi;
     private IBuildInfo mCtsBuild;
 
@@ -82,6 +87,22 @@
     }
 
     /**
+     * Automotive devices MUST support native FBE.
+     */
+    public void testAutomotiveNativeFbe() throws Exception {
+        if (!isSupportedDevice()) {
+            Log.v(TAG, "Device not supported; skipping test");
+            return;
+        } else if (!isAutomotiveDevice()) {
+            Log.v(TAG, "Device not automotive; skipping test");
+            return;
+        }
+
+        assertTrue("Automotive devices must support native FBE",
+            MODE_NATIVE.equals(getFbeMode()));
+    }
+
+    /**
      * If device has native FBE, verify lifecycle.
      */
     public void testDirectBootNative() throws Exception {
@@ -227,9 +248,20 @@
         return "1".equals(output);
     }
 
+    private boolean hasSystemFeature(final String feature) throws Exception {
+        if (mFeatureList == null) {
+            mFeatureList = getDevice().executeShellCommand("pm list features");
+        }
+
+        return mFeatureList.contains(feature);
+    }
+
     private boolean isSupportedDevice() throws Exception {
-        final String featureList = getDevice().executeShellCommand("pm list features");
-        return featureList.contains("feature:android.software.device_admin\n");
+        return hasSystemFeature(FEATURE_DEVICE_ADMIN);
+    }
+
+    private boolean isAutomotiveDevice() throws Exception {
+        return hasSystemFeature(FEATURE_AUTOMOTIVE);
     }
 
     private void waitForBootCompleted() throws Exception {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 77513c5..915f147 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -102,20 +102,47 @@
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartNormal");
     }
 
-    public void testEphemeralStartExposed() throws Exception {
-        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed");
+    // each connection to an exposed component needs to run in its own test to
+    // avoid sharing state. once an instant app is exposed to a component, it's
+    // exposed until the device restarts or the instant app is removed.
+    public void testEphemeralStartExposed01() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed01");
+    }
+    public void testEphemeralStartExposed02() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed02");
+    }
+    public void testEphemeralStartExposed03() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed03");
+    }
+    public void testEphemeralStartExposed04() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed04");
+    }
+    public void testEphemeralStartExposed05() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed05");
+    }
+    public void testEphemeralStartExposed06() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed06");
+    }
+    public void testEphemeralStartExposed07() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed07");
+    }
+    public void testEphemeralStartExposed08() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed08");
+    }
+    public void testEphemeralStartExposed09() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed09");
+    }
+    public void testEphemeralStartExposed10() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed10");
     }
 
     public void testEphemeralStartEphemeral() throws Exception {
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartEphemeral");
     }
 
-    /*
-     * Disabled pending drops of updated prebuilts
     public void testExposedSystemActivities() throws Exception {
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testExposedSystemActivities");
     }
-    */
 
     public void testBuildSerialUnknown() throws Exception {
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testBuildSerialUnknown");
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
index 04fbd70..f679e83 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
@@ -182,6 +182,8 @@
         getDevice().executeShellCommand("settings put global sys_storage_cache_max_bytes 0");
         try {
             for (int user : mUsers) {
+                waitForIdle();
+
                 // Clear all other cached data to give ourselves a clean slate
                 getDevice().executeShellCommand("pm trim-caches 4096G");
                 runDeviceTests(PKG_STATS, CLASS_STATS, "testCacheClearing", user);
@@ -196,6 +198,8 @@
     }
 
     public void doFullDisk() throws Exception {
+        waitForIdle();
+
         // Clear all other cached and external storage data to give ourselves a
         // clean slate to test against
         getDevice().executeShellCommand("pm trim-caches 4096G");
@@ -234,6 +238,14 @@
         }
     }
 
+    public void waitForIdle() throws Exception {
+        // Try getting all pending events flushed out
+        for (int i = 0; i < 5; i++) {
+            getDevice().executeShellCommand("am wait-for-broadcast-idle");
+            Thread.sleep(1000);
+        }
+    }
+
     public void runDeviceTests(String packageName, String testClassName, String testMethodName,
             int userId) throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName, userId);
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index 8f44f89..c9d0e45 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -97,9 +97,6 @@
                 ContactsContract.CommonDataKinds.Email.CONTENT_TYPE, null),
         makeIntent(Intent.ACTION_PICK, null,
                 ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_TYPE, null),
-        makeIntent(Intent.ACTION_INSERT, null, ContactsContract.Contacts.CONTENT_TYPE, null),
-        // Email
-        makeIntent(Intent.ACTION_SEND, null, "text/plain", Uri.parse("mailto:")),
         // File Storage
         makeIntent(Intent.ACTION_OPEN_DOCUMENT, Intent.CATEGORY_OPENABLE, "*/*", null),
         makeIntent(Intent.ACTION_OPEN_DOCUMENT, null, "*/*", null),
@@ -108,13 +105,8 @@
         makeIntent(Intent.ACTION_OPEN_DOCUMENT_TREE, null, null, null),
         makeIntent(Intent.ACTION_CREATE_DOCUMENT, Intent.CATEGORY_OPENABLE, "text/plain", null),
         makeIntent(Intent.ACTION_CREATE_DOCUMENT, null, "text/plain", null),
-        // Phone call
-        makeIntent(Intent.ACTION_DIAL, null, null, Uri.parse("tel:")),
-        // SMS
-        makeIntent(Intent.ACTION_SEND, null, "text/plain", Uri.parse("sms:")),
-        makeIntent(Intent.ACTION_SEND, null, "text/plain", Uri.parse("smsto:")),
-        // Web
-        makeIntent(Intent.ACTION_VIEW, null, "text/html", Uri.parse("https://example.com")),
+        // Framework
+        makeIntent(Intent.ACTION_CHOOSER, null, null, null),
     };
 
     private BroadcastReceiver mReceiver;
@@ -150,13 +142,13 @@
                     is("com.android.cts.ephemeralapp1"));
             assertThat(resolveInfo.get(0).activityInfo.name,
                     is("com.android.cts.ephemeralapp1.EphemeralActivity"));
-            assertThat(resolveInfo.get(0).instantAppAvailable,
+            assertThat(resolveInfo.get(0).isInstantAppAvailable,
                     is(true));
             assertThat(resolveInfo.get(1).activityInfo.packageName,
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).activityInfo.name,
                     is("com.android.cts.normalapp.ExposedActivity"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -173,13 +165,13 @@
                     is("com.android.cts.ephemeralapp1"));
             assertThat(resolveInfo.get(0).activityInfo.name,
                     is("com.android.cts.ephemeralapp1.EphemeralActivity"));
-            assertThat(resolveInfo.get(0).instantAppAvailable,
+            assertThat(resolveInfo.get(0).isInstantAppAvailable,
                     is(true));
             assertThat(resolveInfo.get(1).activityInfo.packageName,
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).activityInfo.name,
                     is("com.android.cts.normalapp.ExposedActivity"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -196,13 +188,13 @@
                     is("com.android.cts.ephemeralapp1"));
             assertThat(resolveInfo.get(0).activityInfo.name,
                     is("com.android.cts.ephemeralapp1.EphemeralActivity"));
-            assertThat(resolveInfo.get(0).instantAppAvailable,
+            assertThat(resolveInfo.get(0).isInstantAppAvailable,
                     is(true));
             assertThat(resolveInfo.get(1).activityInfo.packageName,
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).activityInfo.name,
                     is("com.android.cts.normalapp.ExposedActivity"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -222,7 +214,7 @@
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).serviceInfo.name,
                     is("com.android.cts.normalapp.ExposedService"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -276,7 +268,7 @@
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).providerInfo.name,
                     is("com.android.cts.normalapp.ExposedProvider"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -454,217 +446,224 @@
     }
 
     @Test
-    public void testStartExposed() throws Exception {
+    public void testStartExposed01() throws Exception {
         // start the explicitly exposed activity
-        {
-            final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
-            InstrumentationRegistry
-                    .getContext().startActivity(startExposedIntent, null /*options*/);
-            final TestResult testResult = getResult();
-            assertThat(testResult.getPackageName(),
-                    is("com.android.cts.normalapp"));
-            assertThat(testResult.getComponentName(),
-                    is("ExposedActivity"));
-            assertThat(testResult.getStatus(),
-                    is("PASS"));
-            assertThat(testResult.getEphemeralPackageInfoExposed(),
-                    is(true));
-            assertThat(testResult.getException(),
-                    is(nullValue()));
-        }
+        final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
+        InstrumentationRegistry
+                .getContext().startActivity(startExposedIntent, null /*options*/);
+        final TestResult testResult = getResult();
+        assertThat(testResult.getPackageName(),
+                is("com.android.cts.normalapp"));
+        assertThat(testResult.getComponentName(),
+                is("ExposedActivity"));
+        assertThat(testResult.getStatus(),
+                is("PASS"));
+        assertThat(testResult.getEphemeralPackageInfoExposed(),
+                is(true));
+        assertThat(testResult.getException(),
+                is(nullValue()));
+    }
 
+    @Test
+    public void testStartExposed02() throws Exception {
         // start the explicitly exposed activity; directed package
-        {
-            final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
-            startExposedIntent.setPackage("com.android.cts.normalapp");
-            InstrumentationRegistry
-                    .getContext().startActivity(startExposedIntent, null /*options*/);
-            final TestResult testResult = getResult();
-            assertThat(testResult.getPackageName(),
-                    is("com.android.cts.normalapp"));
-            assertThat(testResult.getComponentName(),
-                    is("ExposedActivity"));
-            assertThat(testResult.getStatus(),
-                    is("PASS"));
-            assertThat(testResult.getEphemeralPackageInfoExposed(),
-                    is(true));
-            assertThat(testResult.getException(),
-                    is(nullValue()));
-        }
+        final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
+        startExposedIntent.setPackage("com.android.cts.normalapp");
+        InstrumentationRegistry
+                .getContext().startActivity(startExposedIntent, null /*options*/);
+        final TestResult testResult = getResult();
+        assertThat(testResult.getPackageName(),
+                is("com.android.cts.normalapp"));
+        assertThat(testResult.getComponentName(),
+                is("ExposedActivity"));
+        assertThat(testResult.getStatus(),
+                is("PASS"));
+        assertThat(testResult.getEphemeralPackageInfoExposed(),
+                is(true));
+        assertThat(testResult.getException(),
+                is(nullValue()));
+    }
 
+    @Test
+    public void testStartExposed03() throws Exception {
         // start the explicitly exposed activity; directed component
-        {
-            final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
-            startExposedIntent.setComponent(new ComponentName(
-                    "com.android.cts.normalapp", "com.android.cts.normalapp.ExposedActivity"));
+        final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
+        startExposedIntent.setComponent(new ComponentName(
+                "com.android.cts.normalapp", "com.android.cts.normalapp.ExposedActivity"));
+        InstrumentationRegistry
+                .getContext().startActivity(startExposedIntent, null /*options*/);
+        final TestResult testResult = getResult();
+        assertThat(testResult.getPackageName(),
+                is("com.android.cts.normalapp"));
+        assertThat(testResult.getComponentName(),
+                is("ExposedActivity"));
+        assertThat(testResult.getStatus(),
+                is("PASS"));
+        assertThat(testResult.getEphemeralPackageInfoExposed(),
+                is(true));
+        assertThat(testResult.getException(),
+                is(nullValue()));
+    }
+
+    @Test
+    public void testStartExposed04() throws Exception {
+        // start the implicitly exposed activity; directed package
+        try {
+            final Intent startExposedIntent = new Intent(Intent.ACTION_VIEW);
+            startExposedIntent.setPackage("com.android.cts.implicitapp");
+            startExposedIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+            startExposedIntent.setData(Uri.parse("https://cts.google.com/implicit"));
             InstrumentationRegistry
                     .getContext().startActivity(startExposedIntent, null /*options*/);
-            final TestResult testResult = getResult();
-            assertThat(testResult.getPackageName(),
-                    is("com.android.cts.normalapp"));
-            assertThat(testResult.getComponentName(),
-                    is("ExposedActivity"));
-            assertThat(testResult.getStatus(),
-                    is("PASS"));
-            assertThat(testResult.getEphemeralPackageInfoExposed(),
-                    is(true));
-            assertThat(testResult.getException(),
-                    is(nullValue()));
-        }
+            fail("activity started");
+        } catch (ActivityNotFoundException expected) { }
+    }
 
-        // start the implicitly exposed activity; directed package
-        {
-            try {
-                final Intent startExposedIntent = new Intent(Intent.ACTION_VIEW);
-                startExposedIntent.setPackage("com.android.cts.implicitapp");
-                startExposedIntent.addCategory(Intent.CATEGORY_BROWSABLE);
-                startExposedIntent.setData(Uri.parse("https://cts.google.com/implicit"));
-                InstrumentationRegistry
-                        .getContext().startActivity(startExposedIntent, null /*options*/);
-                fail("activity started");
-            } catch (ActivityNotFoundException expected) { }
-        }
-
+    @Test
+    public void testStartExposed05() throws Exception {
         // start the implicitly exposed activity; directed component
-        {
-            try {
-                final Intent startExposedIntent = new Intent(Intent.ACTION_VIEW);
-                startExposedIntent.setComponent(new ComponentName(
-                        "com.android.cts.implicitapp",
-                        "com.android.cts.implicitapp.ImplicitActivity"));
-                startExposedIntent.addCategory(Intent.CATEGORY_BROWSABLE);
-                startExposedIntent.setData(Uri.parse("https://cts.google.com/implicit"));
-                InstrumentationRegistry
-                        .getContext().startActivity(startExposedIntent, null /*options*/);
-                fail("activity started");
-            } catch (ActivityNotFoundException expected) { }
-        }
-
-        // start the exposed service; directed package
-        {
-            final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
-            startExposedIntent.setPackage("com.android.cts.normalapp");
-            InstrumentationRegistry.getContext().startService(startExposedIntent);
-            final TestResult testResult = getResult();
-            assertThat(testResult.getPackageName(),
-                    is("com.android.cts.normalapp"));
-            assertThat(testResult.getComponentName(),
-                    is("ExposedService"));
-            assertThat(testResult.getStatus(),
-                    is("PASS"));
-            assertThat(testResult.getEphemeralPackageInfoExposed(),
-                    is(true));
-            assertThat(testResult.getException(),
-                    is(nullValue()));
-        }
-
-        // start the exposed service; directed component
-        {
-            final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
+        try {
+            final Intent startExposedIntent = new Intent(Intent.ACTION_VIEW);
             startExposedIntent.setComponent(new ComponentName(
-                    "com.android.cts.normalapp", "com.android.cts.normalapp.ExposedService"));
-            InstrumentationRegistry.getContext().startService(startExposedIntent);
+                    "com.android.cts.implicitapp",
+                    "com.android.cts.implicitapp.ImplicitActivity"));
+            startExposedIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+            startExposedIntent.setData(Uri.parse("https://cts.google.com/implicit"));
+            InstrumentationRegistry
+                    .getContext().startActivity(startExposedIntent, null /*options*/);
+            fail("activity started");
+        } catch (ActivityNotFoundException expected) { }
+    }
+
+    @Test
+    public void testStartExposed06() throws Exception {
+        // start the exposed service; directed package
+        final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
+        startExposedIntent.setPackage("com.android.cts.normalapp");
+        InstrumentationRegistry.getContext().startForegroundService(startExposedIntent);
+        final TestResult testResult = getResult();
+        assertThat(testResult.getPackageName(),
+                is("com.android.cts.normalapp"));
+        assertThat(testResult.getComponentName(),
+                is("ExposedService"));
+        assertThat(testResult.getStatus(),
+                is("PASS"));
+        assertThat(testResult.getEphemeralPackageInfoExposed(),
+                is(true));
+        assertThat(testResult.getException(),
+                is(nullValue()));
+    }
+
+    @Test
+    public void testStartExposed07() throws Exception {
+        // start the exposed service; directed component
+        final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
+        startExposedIntent.setComponent(new ComponentName(
+                "com.android.cts.normalapp", "com.android.cts.normalapp.ExposedService"));
+        InstrumentationRegistry.getContext().startForegroundService(startExposedIntent);
+        final TestResult testResult = getResult();
+        assertThat(testResult.getPackageName(),
+                is("com.android.cts.normalapp"));
+        assertThat(testResult.getComponentName(),
+                is("ExposedService"));
+        assertThat(testResult.getMethodName(),
+                is("onStartCommand"));
+        assertThat(testResult.getStatus(),
+                is("PASS"));
+        assertThat(testResult.getEphemeralPackageInfoExposed(),
+                is(true));
+        assertThat(testResult.getException(),
+                is(nullValue()));
+    }
+
+    @Test
+    public void testStartExposed08() throws Exception {
+        // bind to the exposed service; directed package
+        final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
+        startExposedIntent.setPackage("com.android.cts.normalapp");
+        final TestServiceConnection connection = new TestServiceConnection();
+        try {
+            assertThat(InstrumentationRegistry.getContext().bindService(
+                    startExposedIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
+                    is(true));
             final TestResult testResult = getResult();
             assertThat(testResult.getPackageName(),
                     is("com.android.cts.normalapp"));
             assertThat(testResult.getComponentName(),
                     is("ExposedService"));
             assertThat(testResult.getMethodName(),
-                    is("onStartCommand"));
+                    is("onBind"));
             assertThat(testResult.getStatus(),
                     is("PASS"));
             assertThat(testResult.getEphemeralPackageInfoExposed(),
                     is(true));
             assertThat(testResult.getException(),
                     is(nullValue()));
+        } finally {
+            InstrumentationRegistry.getContext().unbindService(connection);
         }
+    }
 
-        // bind to the exposed service; directed package
-        {
-            final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
-            startExposedIntent.setPackage("com.android.cts.normalapp");
-            final TestServiceConnection connection = new TestServiceConnection();
-            try {
-                assertThat(InstrumentationRegistry.getContext().bindService(
-                        startExposedIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
-                        is(true));
-                final TestResult testResult = getResult();
-                assertThat(testResult.getPackageName(),
-                        is("com.android.cts.normalapp"));
-                assertThat(testResult.getComponentName(),
-                        is("ExposedService"));
-                assertThat(testResult.getMethodName(),
-                        is("onBind"));
-                assertThat(testResult.getStatus(),
-                        is("PASS"));
-                assertThat(testResult.getEphemeralPackageInfoExposed(),
-                        is(true));
-                assertThat(testResult.getException(),
-                        is(nullValue()));
-            } finally {
-                InstrumentationRegistry.getContext().unbindService(connection);
-            }
-        }
-
+    @Test
+    public void testStartExposed09() throws Exception {
         // bind to the exposed service; directed component
-        {
-            final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
-            startExposedIntent.setComponent(new ComponentName(
-                    "com.android.cts.normalapp", "com.android.cts.normalapp.ExposedService"));
-            final TestServiceConnection connection = new TestServiceConnection();
-            try {
-                assertThat(InstrumentationRegistry.getContext().bindService(
-                        startExposedIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
-                        is(true));
-                final TestResult testResult = getResult();
-                assertThat(testResult.getPackageName(),
-                        is("com.android.cts.normalapp"));
-                assertThat(testResult.getComponentName(),
-                        is("ExposedService"));
-                assertThat(testResult.getMethodName(),
-                        is("onBind"));
-                assertThat(testResult.getStatus(),
-                        is("PASS"));
-                assertThat(testResult.getEphemeralPackageInfoExposed(),
-                        is(true));
-                assertThat(testResult.getException(),
-                        is(nullValue()));
-            } finally {
-                InstrumentationRegistry.getContext().unbindService(connection);
-            }
-        }
-
-        // connect to exposed provider
-        {
-            final String provider = "content://com.android.cts.normalapp.exposed.provider/table";
-            final Cursor testCursor = InstrumentationRegistry
-                    .getContext().getContentResolver().query(
-                            Uri.parse(provider),
-                            null /*projection*/,
-                            null /*selection*/,
-                            null /*selectionArgs*/,
-                            null /*sortOrder*/);
-            assertThat(testCursor, is(notNullValue()));
-            assertThat(testCursor.getCount(), is(1));
-            assertThat(testCursor.getColumnCount(), is(2));
-            assertThat(testCursor.moveToFirst(), is(true));
-            assertThat(testCursor.getInt(0), is(1));
-            assertThat(testCursor.getString(1), is("ExposedProvider"));
+        final Intent startExposedIntent = new Intent(ACTION_START_EXPOSED);
+        startExposedIntent.setComponent(new ComponentName(
+                "com.android.cts.normalapp", "com.android.cts.normalapp.ExposedService"));
+        final TestServiceConnection connection = new TestServiceConnection();
+        try {
+            assertThat(InstrumentationRegistry.getContext().bindService(
+                    startExposedIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
+                    is(true));
             final TestResult testResult = getResult();
             assertThat(testResult.getPackageName(),
                     is("com.android.cts.normalapp"));
             assertThat(testResult.getComponentName(),
-                    is("ExposedProvider"));
+                    is("ExposedService"));
+            assertThat(testResult.getMethodName(),
+                    is("onBind"));
             assertThat(testResult.getStatus(),
                     is("PASS"));
             assertThat(testResult.getEphemeralPackageInfoExposed(),
                     is(true));
             assertThat(testResult.getException(),
                     is(nullValue()));
+        } finally {
+            InstrumentationRegistry.getContext().unbindService(connection);
         }
     }
 
     @Test
+    public void testStartExposed10() throws Exception {
+        // connect to exposed provider
+        final String provider = "content://com.android.cts.normalapp.exposed.provider/table";
+        final Cursor testCursor = InstrumentationRegistry
+                .getContext().getContentResolver().query(
+                        Uri.parse(provider),
+                        null /*projection*/,
+                        null /*selection*/,
+                        null /*selectionArgs*/,
+                        null /*sortOrder*/);
+        assertThat(testCursor, is(notNullValue()));
+        assertThat(testCursor.getCount(), is(1));
+        assertThat(testCursor.getColumnCount(), is(2));
+        assertThat(testCursor.moveToFirst(), is(true));
+        assertThat(testCursor.getInt(0), is(1));
+        assertThat(testCursor.getString(1), is("ExposedProvider"));
+        final TestResult testResult = getResult();
+        assertThat(testResult.getPackageName(),
+                is("com.android.cts.normalapp"));
+        assertThat(testResult.getComponentName(),
+                is("ExposedProvider"));
+        assertThat(testResult.getStatus(),
+                is("PASS"));
+        assertThat(testResult.getEphemeralPackageInfoExposed(),
+                is(true));
+        assertThat(testResult.getException(),
+                is(nullValue()));
+    }
+
+    @Test
     public void testStartEphemeral() throws Exception {
         // start the ephemeral activity
         {
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
index 22b8c25..cd5ac0e 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
@@ -99,13 +99,13 @@
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(0).activityInfo.name,
                     is("com.android.cts.normalapp.ExposedActivity"));
-            assertThat(resolveInfo.get(0).instantAppAvailable,
+            assertThat(resolveInfo.get(0).isInstantAppAvailable,
                     is(false));
             assertThat(resolveInfo.get(1).activityInfo.packageName,
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).activityInfo.name,
                     is("com.android.cts.normalapp.NormalActivity"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -124,13 +124,13 @@
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(0).activityInfo.name,
                     is("com.android.cts.normalapp.ExposedActivity"));
-            assertThat(resolveInfo.get(0).instantAppAvailable,
+            assertThat(resolveInfo.get(0).isInstantAppAvailable,
                     is(false));
             assertThat(resolveInfo.get(1).activityInfo.packageName,
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).activityInfo.name,
                     is("com.android.cts.normalapp.NormalActivity"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -167,13 +167,13 @@
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(0).serviceInfo.name,
                     is("com.android.cts.normalapp.ExposedService"));
-            assertThat(resolveInfo.get(0).instantAppAvailable,
+            assertThat(resolveInfo.get(0).isInstantAppAvailable,
                     is(false));
             assertThat(resolveInfo.get(1).serviceInfo.packageName,
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).serviceInfo.name,
                     is("com.android.cts.normalapp.NormalService"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -192,13 +192,13 @@
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(0).serviceInfo.name,
                     is("com.android.cts.normalapp.ExposedService"));
-            assertThat(resolveInfo.get(0).instantAppAvailable,
+            assertThat(resolveInfo.get(0).isInstantAppAvailable,
                     is(false));
             assertThat(resolveInfo.get(1).serviceInfo.packageName,
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).serviceInfo.name,
                     is("com.android.cts.normalapp.NormalService"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -240,7 +240,7 @@
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).providerInfo.name,
                     is("com.android.cts.normalapp.NormalProvider"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
@@ -264,7 +264,7 @@
                     is("com.android.cts.normalapp"));
             assertThat(resolveInfo.get(1).providerInfo.name,
                     is("com.android.cts.normalapp.NormalProvider"));
-            assertThat(resolveInfo.get(1).instantAppAvailable,
+            assertThat(resolveInfo.get(1).isInstantAppAvailable,
                     is(false));
         }
 
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/Utils.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/Utils.java
index 2e43a14..bf7f958 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/Utils.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/Utils.java
@@ -57,6 +57,8 @@
     public static final long CACHE_EXT = (11) * MB_IN_BYTES;
     public static final long CACHE_ALL = CACHE_INT + CACHE_EXT; // 78MB
 
+    public static final long CODE_ALL = 29 * MB_IN_BYTES;
+
     public static void useSpace(Context c) throws Exception {
         // We use prime numbers for all values so that we can easily identify
         // which file(s) are missing from broken test results.
@@ -72,6 +74,8 @@
         final File subdir = makeUniqueFile(c.getCacheDir());
         Os.mkdir(subdir.getAbsolutePath(), 0700);
         useFallocate(makeUniqueFile(subdir), 23 * MB_IN_BYTES);
+
+        useWrite(makeUniqueFile(c.getObbDir()), 29 * MB_IN_BYTES);
     }
 
     public static void assertAtLeast(long expected, long actual) {
@@ -125,10 +129,19 @@
     }
 
     public static long getSizeManual(File dir) throws Exception {
+        return getSizeManual(dir, false);
+    }
+
+    public static long getSizeManual(File dir, boolean excludeObb) throws Exception {
         long size = getAllocatedSize(dir);
         for (File f : dir.listFiles()) {
             if (f.isDirectory()) {
-                size += getSizeManual(f);
+                if (excludeObb && f.getName().equalsIgnoreCase("obb")
+                        && f.getParentFile().getName().equalsIgnoreCase("Android")) {
+                    Log.d(TAG, "Ignoring OBB directory " + f);
+                } else {
+                    size += getSizeManual(f, excludeObb);
+                }
             } else {
                 size += getAllocatedSize(f);
             }
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java
index 2845185..927968c 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java
@@ -19,6 +19,7 @@
 import static com.android.cts.storageapp.Utils.TAG;
 import static com.android.cts.storageapp.Utils.makeUniqueFile;
 import static com.android.cts.storageapp.Utils.useFallocate;
+import static com.android.cts.storageapp.Utils.useWrite;
 
 import android.app.Activity;
 import android.content.BroadcastReceiver;
@@ -30,6 +31,8 @@
 import android.util.Log;
 
 import java.io.File;
+import java.util.Objects;
+import java.util.UUID;
 
 public class UtilsReceiver extends BroadcastReceiver {
     public static final String EXTRA_FRACTION = "fraction";
@@ -52,15 +55,37 @@
 
         long allocated = 0;
         try {
+            // When shared storage is backed by internal, then pivot our cache
+            // files between the two locations to ensure clearing logic works.
+            final File intDir = context.getCacheDir();
+            final File extDir = context.getExternalCacheDir();
+            final UUID intUuid = sm.getUuidForPath(intDir);
+            final UUID extUuid = sm.getUuidForPath(extDir);
+
+            Log.d(TAG, "Found internal " + intUuid + " and external " + extUuid);
+            final boolean doPivot = Objects.equals(intUuid, extUuid);
+
             final double fraction = extras.getDouble(EXTRA_FRACTION, 0);
-            final long quota = sm.getCacheQuotaBytes(sm.getUuidForPath(context.getCacheDir()));
+            final long quota = sm.getCacheQuotaBytes(intUuid);
             final long bytes = (long) (quota * fraction);
             final long time = extras.getLong(EXTRA_TIME, System.currentTimeMillis());
 
+            int i = 0;
             while (allocated < bytes) {
-                final File f = makeUniqueFile(context.getCacheDir());
+                final File target;
+                if (doPivot) {
+                    target = (i++ % 2) == 0 ? intDir : extDir;
+                } else {
+                    target = intDir;
+                }
+
+                final File f = makeUniqueFile(target);
                 final long size = 1024 * 1024;
-                useFallocate(f, size);
+                if (target == intDir) {
+                    useFallocate(f, size);
+                } else {
+                    useWrite(f, size);
+                }
                 f.setLastModified(time);
                 allocated += Os.stat(f.getAbsolutePath()).st_blocks * 512;
             }
diff --git a/hostsidetests/appsecurity/test-apps/StorageStatsApp/Android.mk b/hostsidetests/appsecurity/test-apps/StorageStatsApp/Android.mk
index 8b6d680..abee640 100644
--- a/hostsidetests/appsecurity/test-apps/StorageStatsApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/StorageStatsApp/Android.mk
@@ -18,7 +18,7 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_SDK_VERSION := test_current
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
 	$(call all-java-files-under, ../StorageApp/src)
diff --git a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
index de13476..ebc2946 100644
--- a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
@@ -19,6 +19,7 @@
 import static android.os.storage.StorageManager.UUID_DEFAULT;
 
 import static com.android.cts.storageapp.Utils.CACHE_ALL;
+import static com.android.cts.storageapp.Utils.CODE_ALL;
 import static com.android.cts.storageapp.Utils.DATA_ALL;
 import static com.android.cts.storageapp.Utils.MB_IN_BYTES;
 import static com.android.cts.storageapp.Utils.PKG_A;
@@ -49,6 +50,7 @@
 import android.os.Environment;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
+import android.support.test.uiautomator.UiDevice;
 import android.system.Os;
 import android.system.StructUtsname;
 import android.test.InstrumentationTestCase;
@@ -57,6 +59,8 @@
 
 import com.android.cts.storageapp.UtilsReceiver;
 
+import junit.framework.AssertionFailedError;
+
 import java.io.File;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
@@ -110,6 +114,10 @@
         final StorageStats afterApp = stats.queryStatsForUid(UUID_DEFAULT, uid);
         final StorageStats afterUser = stats.queryStatsForUser(UUID_DEFAULT, user);
 
+        final long deltaCode = CODE_ALL;
+        assertMostlyEquals(deltaCode, afterApp.getAppBytes() - beforeApp.getAppBytes());
+        assertMostlyEquals(deltaCode, afterUser.getAppBytes() - beforeUser.getAppBytes());
+
         final long deltaData = DATA_ALL;
         assertMostlyEquals(deltaData, afterApp.getDataBytes() - beforeApp.getDataBytes());
         assertMostlyEquals(deltaData, afterUser.getDataBytes() - beforeUser.getDataBytes());
@@ -134,6 +142,16 @@
 
         assertMostlyEquals(DATA_ALL, bs.getDataBytes());
         assertMostlyEquals(CACHE_ALL, bs.getCacheBytes());
+
+        // Since OBB storage space may be shared or isolated between users,
+        // we'll accept either expected or double usage.
+        try {
+            assertMostlyEquals(CODE_ALL * 2, as.getAppBytes(), 5 * MB_IN_BYTES);
+            assertMostlyEquals(CODE_ALL * 1, bs.getAppBytes(), 5 * MB_IN_BYTES);
+        } catch (AssertionFailedError e) {
+            assertMostlyEquals(CODE_ALL * 4, as.getAppBytes(), 5 * MB_IN_BYTES);
+            assertMostlyEquals(CODE_ALL * 2, bs.getAppBytes(), 5 * MB_IN_BYTES);
+        }
     }
 
     /**
@@ -205,7 +223,7 @@
         // TODO: remove this once 34723223 is fixed
         logCommand("sync");
 
-        final long manualSize = getSizeManual(Environment.getExternalStorageDirectory());
+        final long manualSize = getSizeManual(Environment.getExternalStorageDirectory(), true);
         final long statsSize = stats.queryExternalStatsForUser(UUID_DEFAULT, user).getTotalBytes();
 
         assertMostlyEquals(manualSize, statsSize);
@@ -228,9 +246,11 @@
 
         final File filesDir = context.getFilesDir();
         final UUID filesUuid = sm.getUuidForPath(filesDir);
+        final String pmUuid = filesUuid.equals(StorageManager.UUID_DEFAULT) ? "internal"
+                : filesUuid.toString();
 
         final long beforeAllocatable = sm.getAllocatableBytes(filesUuid);
-        final long beforeFree = stats.getFreeBytes(UUID_DEFAULT);
+        final long beforeFree = stats.getFreeBytes(filesUuid);
         final long beforeRaw = filesDir.getUsableSpace();
 
         Log.d(TAG, "Before raw " + beforeRaw + ", free " + beforeFree + ", allocatable "
@@ -247,16 +267,16 @@
         // Apps using up some cache space shouldn't change how much we can
         // allocate, or how much we think is free; but it should decrease real
         // disk space.
-        if (stats.isQuotaSupported(UUID_DEFAULT)) {
+        if (stats.isQuotaSupported(filesUuid)) {
             assertMostlyEquals(beforeAllocatable,
                     sm.getAllocatableBytes(filesUuid), 10 * MB_IN_BYTES);
             assertMostlyEquals(beforeFree,
-                    stats.getFreeBytes(UUID_DEFAULT), 10 * MB_IN_BYTES);
+                    stats.getFreeBytes(filesUuid), 10 * MB_IN_BYTES);
         } else {
             assertMostlyEquals(beforeAllocatable - totalAllocated,
                     sm.getAllocatableBytes(filesUuid), 10 * MB_IN_BYTES);
             assertMostlyEquals(beforeFree - totalAllocated,
-                    stats.getFreeBytes(UUID_DEFAULT), 10 * MB_IN_BYTES);
+                    stats.getFreeBytes(filesUuid), 10 * MB_IN_BYTES);
         }
         assertMostlyEquals(beforeRaw - totalAllocated,
                 filesDir.getUsableSpace(), 10 * MB_IN_BYTES);
@@ -267,7 +287,12 @@
         // Allocate some space for ourselves, which should trim away at
         // over-quota app first, even though its files are newer.
         final long clear1 = filesDir.getUsableSpace() + (targetB / 2);
-        sm.allocateBytes(filesUuid, clear1);
+        if (stats.isQuotaSupported(filesUuid)) {
+            sm.allocateBytes(filesUuid, clear1);
+        } else {
+            UiDevice.getInstance(getInstrumentation())
+                    .executeShellCommand("pm trim-caches " + clear1 + " " + pmUuid);
+        }
 
         assertMostlyEquals(targetA, getCacheBytes(PKG_A, user));
         assertMostlyEquals(targetB / 2, getCacheBytes(PKG_B, user), 2 * MB_IN_BYTES);
@@ -277,7 +302,12 @@
         // they're tied for cache ratios, we expect to clear about half of the
         // remaining space from each of them.
         final long clear2 = filesDir.getUsableSpace() + (targetB / 2);
-        sm.allocateBytes(filesUuid, clear2);
+        if (stats.isQuotaSupported(filesUuid)) {
+            sm.allocateBytes(filesUuid, clear2);
+        } else {
+            UiDevice.getInstance(getInstrumentation())
+                    .executeShellCommand("pm trim-caches " + clear2 + " " + pmUuid);
+        }
 
         assertMostlyEquals(targetA / 2, getCacheBytes(PKG_A, user), 2 * MB_IN_BYTES);
         assertMostlyEquals(targetA / 2, getCacheBytes(PKG_B, user), 2 * MB_IN_BYTES);
@@ -286,6 +316,11 @@
     public void testCacheBehavior() throws Exception {
         final Context context = getContext();
         final StorageManager sm = context.getSystemService(StorageManager.class);
+        final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class);
+
+        final UUID filesUuid = sm.getUuidForPath(context.getFilesDir());
+        final String pmUuid = filesUuid.equals(StorageManager.UUID_DEFAULT) ? "internal"
+                : filesUuid.toString();
 
         final File normal = new File(context.getCacheDir(), "normal");
         final File group = new File(context.getCacheDir(), "group");
@@ -321,7 +356,12 @@
         tomb.setLastModified(tombTime);
 
         final long clear1 = group.getUsableSpace() + (8 * MB_IN_BYTES);
-        sm.allocateBytes(sm.getUuidForPath(group), clear1);
+        if (stats.isQuotaSupported(filesUuid)) {
+            sm.allocateBytes(filesUuid, clear1);
+        } else {
+            UiDevice.getInstance(getInstrumentation())
+                    .executeShellCommand("pm trim-caches " + clear1 + " " + pmUuid);
+        }
 
         assertTrue(a.exists());
         assertTrue(b.exists());
diff --git a/hostsidetests/backup/Android.mk b/hostsidetests/backup/Android.mk
new file mode 100644
index 0000000..3ed8e99
--- /dev/null
+++ b/hostsidetests/backup/Android.mk
@@ -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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_RESOURCE_DIRS := assets/
+
+LOCAL_MODULE_TAGS := tests
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_MODULE := CtsBackupHostTestCases
+
+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/backup/AndroidTest.xml b/hostsidetests/backup/AndroidTest.xml
new file mode 100644
index 0000000..4675ed0
--- /dev/null
+++ b/hostsidetests/backup/AndroidTest.xml
@@ -0,0 +1,24 @@
+<?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 Backup host test cases">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsBackupRestoreDeviceApp.apk" />
+    </target_preparer>
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsBackupHostTestCases.jar" />
+    </test>
+</configuration>
diff --git a/hostsidetests/backup/app/Android.mk b/hostsidetests/backup/app/Android.mk
new file mode 100644
index 0000000..248207c
--- /dev/null
+++ b/hostsidetests/backup/app/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsBackupRestoreDeviceApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/backup/app/AndroidManifest.xml b/hostsidetests/backup/app/AndroidManifest.xml
new file mode 100644
index 0000000..32e8e4e
--- /dev/null
+++ b/hostsidetests/backup/app/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?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.backup.cts.backuprestoreapp">
+
+    <application
+        android:backupAgent="CtsBackupRestoreBackupAgent">
+        <uses-library android:name="android.test.runner" />
+
+        <activity
+            android:name=".KeyValueBackupRandomDataActivity"
+            android:launchMode="singleInstance">
+            <intent-filter>
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.backup.cts.backuprestoreapp" />
+
+</manifest>
diff --git a/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/CtsBackupRestoreBackupAgent.java b/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/CtsBackupRestoreBackupAgent.java
new file mode 100644
index 0000000..e692fdd
--- /dev/null
+++ b/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/CtsBackupRestoreBackupAgent.java
@@ -0,0 +1,33 @@
+/*
+ * 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.backup.cts.backuprestoreapp;
+
+import android.app.backup.BackupAgentHelper;
+
+public class CtsBackupRestoreBackupAgent extends BackupAgentHelper {
+    private static final String KEY_BACKUP_TEST_PREFS_PREFIX = "backup-test-prefs";
+    private static final String KEY_BACKUP_TEST_FILES_PREFIX = "backup-test-files";
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        addHelper(KEY_BACKUP_TEST_PREFS_PREFIX,
+                KeyValueBackupRandomDataActivity.getSharedPreferencesBackupHelper(this));
+        addHelper(KEY_BACKUP_TEST_FILES_PREFIX,
+                KeyValueBackupRandomDataActivity.getFileBackupHelper(this));
+    }
+}
diff --git a/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/KeyValueBackupRandomDataActivity.java b/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/KeyValueBackupRandomDataActivity.java
new file mode 100644
index 0000000..92db3f3
--- /dev/null
+++ b/hostsidetests/backup/app/src/android/backup/cts/backuprestoreapp/KeyValueBackupRandomDataActivity.java
@@ -0,0 +1,228 @@
+/*
+ * 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.backup.cts.backuprestoreapp;
+
+import android.app.Activity;
+import android.app.backup.BackupManager;
+import android.app.backup.FileBackupHelper;
+import android.app.backup.SharedPreferencesBackupHelper;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.Random;
+import java.util.Scanner;
+
+/**
+ * Test activity that reads/writes to shared preferences and files.
+ *
+ * It uses logcat messages to send the data to the host side of the test.
+ * The format of logcat messages: "DATA_PREF: VALUE".
+ * VALUES_LOADED_MESSAGE is logged after all the values.
+ *
+ * Workflow onCreate:
+ * - Read shared preferences and files
+ * - If the values are default ones:
+ *      - Randomly generate new values
+ *      - Save new values to shared preferences and files
+ *      - Load the new values.
+ *
+ * Migrated from BackupTestActivity in former BackupTest CTS Verfifier test.
+ */
+public class KeyValueBackupRandomDataActivity extends Activity {
+    private static final String TAG = KeyValueBackupRandomDataActivity.class.getSimpleName();
+
+    private static final String TEST_PREFS_1 = "test-prefs-1";
+    private static final String INT_PREF = "int-pref";
+    private static final String BOOL_PREF = "bool-pref";
+
+    private static final String TEST_PREFS_2 = "test-prefs-2";
+    private static final String FLOAT_PREF = "float-pref";
+    private static final String LONG_PREF = "long-pref";
+    private static final String STRING_PREF = "string-pref";
+
+    private static final String TEST_FILE_1 = "test-file-1";
+    private static final String TEST_FILE_2 = "test-file-2";
+
+    private static final int DEFAULT_INT_VALUE = 0;
+    private static final boolean DEFAULT_BOOL_VALUE = false;
+    private static final float DEFAULT_FLOAT_VALUE = 0.0f;
+    private static final long DEFAULT_LONG_VALUE = 0L;
+    private static final String DEFAULT_STRING_VALUE = null;
+
+    private static final String VALUES_LOADED_MESSAGE = "ValuesLoaded";
+    private static final String EMPTY_STRING_LOG = "empty";
+
+    private boolean mDefaultValues = true;
+    private boolean mValuesWereGenerated;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        new LoadBackupItemsTask().execute();
+    }
+
+    public static SharedPreferencesBackupHelper getSharedPreferencesBackupHelper(Context context) {
+        return new SharedPreferencesBackupHelper(context, TEST_PREFS_1, TEST_PREFS_2);
+    }
+
+    public static FileBackupHelper getFileBackupHelper(Context context) {
+        return new FileBackupHelper(context, TEST_FILE_1, TEST_FILE_2);
+    }
+
+    class LoadBackupItemsTask extends AsyncTask<Void, Void, Void> {
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            loadPreferenceGroup1();
+            loadPreferenceGroup2();
+            loadFile(TEST_FILE_1);
+            loadFile(TEST_FILE_2);
+            return null;
+        }
+
+        private void loadPreferenceGroup1() {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
+
+            int intValue = prefs.getInt(INT_PREF, DEFAULT_INT_VALUE);
+            Log.i(TAG, INT_PREF + ":" + intValue);
+
+            boolean boolValue = prefs.getBoolean(BOOL_PREF, DEFAULT_BOOL_VALUE);
+            Log.i(TAG, BOOL_PREF + ":" + boolValue);
+
+            mDefaultValues = mDefaultValues
+                    && intValue == DEFAULT_INT_VALUE
+                    && boolValue == DEFAULT_BOOL_VALUE;
+        }
+
+        private void loadPreferenceGroup2() {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
+
+            float floatValue = prefs.getFloat(FLOAT_PREF, DEFAULT_FLOAT_VALUE);
+            Log.i(TAG, FLOAT_PREF + ":" + floatValue);
+
+            long longValue = prefs.getLong(LONG_PREF, DEFAULT_LONG_VALUE);
+            Log.i(TAG, LONG_PREF + ":" + longValue);
+
+            String stringValue = prefs.getString(STRING_PREF, DEFAULT_STRING_VALUE);
+            Log.i(TAG, STRING_PREF + ":" + stringValue);
+
+            mDefaultValues = mDefaultValues
+                            && floatValue == DEFAULT_FLOAT_VALUE
+                            && longValue == DEFAULT_LONG_VALUE
+                            && stringValue == DEFAULT_STRING_VALUE;
+        }
+
+        private void loadFile(String fileName) {
+            StringBuilder contents = new StringBuilder();
+            Scanner scanner = null;
+            try {
+                scanner = new Scanner(new File(getFilesDir(), fileName));
+                while (scanner.hasNext()) {
+                    contents.append(scanner.nextLine());
+                }
+                scanner.close();
+            } catch (FileNotFoundException e) {
+                Log.i(TAG, "Couldn't find test file but this may be fine...");
+            } finally {
+                if (scanner != null) {
+                    scanner.close();
+                }
+            }
+            String logString = contents.toString();
+            logString = logString.isEmpty() ? EMPTY_STRING_LOG : logString;
+            Log.i(TAG, fileName + ":" + logString);
+
+            mDefaultValues = mDefaultValues && contents.toString().isEmpty();
+        }
+
+        @Override
+        protected void onPostExecute(Void param) {
+            super.onPostExecute(param);
+
+            if (mDefaultValues && !mValuesWereGenerated) {
+                new GenerateValuesTask().execute();
+            } else {
+                Log.i(TAG, VALUES_LOADED_MESSAGE);
+            }
+        }
+    }
+
+    class GenerateValuesTask extends AsyncTask<Void, Void, Exception> {
+
+        @Override
+        protected Exception doInBackground(Void... params) {
+            Random random = new Random();
+            generatePreferenceGroup1(random);
+            generatePreferenceGroup2(random);
+            try {
+                generateTestFile(TEST_FILE_1, random);
+                generateTestFile(TEST_FILE_2, random);
+            } catch (FileNotFoundException e) {
+                return e;
+            }
+            return null;
+        }
+
+        private void generatePreferenceGroup1(Random random) {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_1, MODE_PRIVATE);
+            SharedPreferences.Editor editor = prefs.edit();
+            editor.putInt(INT_PREF, (random.nextInt(100) + 1));
+            editor.putBoolean(BOOL_PREF, random.nextBoolean());
+            editor.commit();
+        }
+
+        private void generatePreferenceGroup2(Random random) {
+            SharedPreferences prefs = getSharedPreferences(TEST_PREFS_2, MODE_PRIVATE);
+            SharedPreferences.Editor editor = prefs.edit();
+            editor.putFloat(FLOAT_PREF, random.nextFloat());
+            editor.putLong(LONG_PREF, random.nextLong());
+            editor.putString(STRING_PREF, "Random number " + (random.nextInt(100) + 1));
+            editor.commit();
+        }
+
+        private void generateTestFile(String fileName, Random random)
+                throws FileNotFoundException {
+            File file = new File(getFilesDir(), fileName);
+            PrintWriter writer = new PrintWriter(file);
+            writer.write("Random number " + (random.nextInt(100) + 1));
+            writer.close();
+        }
+
+        @Override
+        protected void onPostExecute(Exception exception) {
+            super.onPostExecute(exception);
+            mValuesWereGenerated = true;
+
+            if (exception != null) {
+                Log.e(TAG, "Couldn't generate test data...", exception);
+            } else {
+                BackupManager backupManager = new BackupManager(
+                        KeyValueBackupRandomDataActivity.this);
+                backupManager.dataChanged();
+
+                new LoadBackupItemsTask().execute();
+            }
+        }
+    }
+}
diff --git a/hostsidetests/backup/src/android/backup/cts/BackupRestoreHostSideTest.java b/hostsidetests/backup/src/android/backup/cts/BackupRestoreHostSideTest.java
new file mode 100644
index 0000000..86cecbb
--- /dev/null
+++ b/hostsidetests/backup/src/android/backup/cts/BackupRestoreHostSideTest.java
@@ -0,0 +1,342 @@
+/*
+ * 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.backup.cts.backup;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.compatibility.common.tradefed.testtype.CompatibilityHostTestBase;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Test for checking that key/value backup and restore works correctly.
+ * It interacts with the app that generates random values and saves them in different shared
+ * preferences and files. The app uses BackupAgentHelper to do key/value backup of those values.
+ * The tests verifies that the values are restored after the app is uninstalled and reinstalled.
+ *
+ * NB: The tests uses "bmgr backupnow" for backup, which works on N+ devices.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class BackupRestoreHostSideTest extends CompatibilityHostTestBase {
+
+    /** Value of PackageManager.FEATURE_BACKUP */
+    private static final String FEATURE_BACKUP = "android.software.backup";
+
+    private static final String LOCAL_TRANSPORT =
+            "android/com.android.internal.backup.LocalTransport";
+
+    /** The name of the APK of the app under test */
+    private static final String TEST_APP_APK = "CtsBackupRestoreDeviceApp.apk";
+
+    /** The package name of the APK */
+    private static final String PACKAGE_UNDER_TEST = "android.backup.cts.backuprestoreapp";
+
+    /** The class name of the main activity in the APK */
+    private static final String CLASS_UNDER_TEST = "KeyValueBackupRandomDataActivity";
+
+    /** The command to launch the main activity */
+    private static final String START_ACTIVITY_UNDER_TEST_COMMAND = String.format(
+            "am start -W -a android.intent.action.MAIN -n %s/%s.%s", PACKAGE_UNDER_TEST,
+            PACKAGE_UNDER_TEST,
+            CLASS_UNDER_TEST);
+
+    /** The command to clear the user data of the package */
+    private static final String CLEAR_DATA_IN_PACKAGE_UNDER_TEST_COMMAND = String.format(
+            "pm clear %s", PACKAGE_UNDER_TEST);
+
+    /**
+     * Time we wait before reading the logcat again if the message we want is not logged by the
+     * app yet.
+     */
+    private static final int SMALL_LOGCAT_DELAY_MS = 1000;
+
+    /**
+     * Message logged by the app after all the values were loaded from SharedPreferences and files.
+     */
+    private static final String VALUES_LOADED_MESSAGE = "ValuesLoaded";
+
+    /**
+     * Keys for various shared preferences and files saved/read by the app.
+     */
+    private static final String INT_PREF = "int-pref";
+    private static final String BOOL_PREF = "bool-pref";
+    private static final String FLOAT_PREF = "float-pref";
+    private static final String LONG_PREF = "long-pref";
+    private static final String STRING_PREF = "string-pref";
+    private static final String TEST_FILE_1 = "test-file-1";
+    private static final String TEST_FILE_2 = "test-file-2";
+
+    /** Number of the values saved/restored by the app (keys listed above) */
+    private static final int NUMBER_OF_VALUES = 7;
+
+    /**
+     * String equivalents of the default values of the shared preferences logged by the app.
+     * These values are logged by the app by default if it fails to generate or restore values.
+     */
+    private static final String DEFAULT_INT_STRING = Integer.toString(0);
+    private static final String DEFAULT_BOOL_STRING = Boolean.toString(false);
+    private static final String DEFAULT_FLOAT_STRING = Float.toString(0.0f);
+    private static final String DEFAULT_LONG_STRING = Long.toString(0L);
+    private static final String DEFAULT_STRING_STRING = "null";
+    private static final String DEFAULT_FILE_STRING = "empty";
+
+    private boolean mIsBackupSupported;
+    private boolean mWasBackupEnabled;
+    private String mOldTransport;
+
+    /**
+     * Map of the shared preferences/files values reported by the app.
+     * Format example: INT_PREF -> 17 (string, as found in the logcat).
+     */
+    private Map<String, String> mSavedValues;
+
+    @Before
+    public void setUp() throws DeviceNotAvailableException, Exception {
+        mIsBackupSupported = mDevice.hasFeature("feature:" + FEATURE_BACKUP);
+        assumeTrue(mIsBackupSupported);
+        // Enable backup and select local backup transport
+        assertTrue("LocalTransport should be available.", hasBackupTransport(LOCAL_TRANSPORT));
+        mWasBackupEnabled = enableBackup(true);
+        mOldTransport = setBackupTransport(LOCAL_TRANSPORT);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        if (mIsBackupSupported) {
+            setBackupTransport(mOldTransport);
+            enableBackup(mWasBackupEnabled);
+        }
+    }
+
+    @Test
+    public void testKeyValueBackupAndRestore() throws Exception {
+        // Clear app data if any
+        mDevice.executeShellCommand(CLEAR_DATA_IN_PACKAGE_UNDER_TEST_COMMAND);
+        // Clear logcat
+        mDevice.executeAdbCommand("logcat", "-c");
+        // Start the main activity of the app
+        mDevice.executeShellCommand(START_ACTIVITY_UNDER_TEST_COMMAND);
+
+        // The app will generate some random values onCreate. Save them to mSavedValues
+        saveDataValuesReportedByApp();
+
+        // If all the values are default, there is something wrong with the app
+        assertNotAllValuesAreDefault();
+
+        // Run backup
+        // TODO: make this compatible with N-, potentially by replacing 'backupnow' with 'run'.
+        String backupnowOutput = mDevice.executeShellCommand(
+                "bmgr backupnow " + PACKAGE_UNDER_TEST);
+
+        assertBackupIsSuccessful(backupnowOutput);
+
+        assertNull(uninstallPackage(PACKAGE_UNDER_TEST));
+
+        installPackage(TEST_APP_APK);
+
+        mDevice.executeAdbCommand("logcat", "-c");
+
+        // Start the reinstalled app
+        mDevice.executeShellCommand(START_ACTIVITY_UNDER_TEST_COMMAND);
+
+        // If the app data was restored successfully, the app should not generate new values and
+        // the values reported by the app should match values saved in mSavedValues
+        assertValuesAreRestored();
+    }
+
+    /**
+     * Saves the data values reported by the app in {@code mSavedValues}.
+     */
+    private void saveDataValuesReportedByApp()
+            throws InterruptedException, DeviceNotAvailableException {
+        mSavedValues = readDataValuesFromLogcat();
+        assertEquals(NUMBER_OF_VALUES, mSavedValues.size());
+    }
+
+    /**
+     * Checks that at least some values in {@code mSavedValues} are different from corresponding
+     * default values.
+     */
+    private void assertNotAllValuesAreDefault() {
+        boolean allValuesAreDefault = mSavedValues.get(INT_PREF).equals(DEFAULT_INT_STRING)
+                && mSavedValues.get(BOOL_PREF).equals(DEFAULT_BOOL_STRING)
+                && mSavedValues.get(FLOAT_PREF).equals(DEFAULT_FLOAT_STRING)
+                && mSavedValues.get(LONG_PREF).equals(DEFAULT_LONG_STRING)
+                && mSavedValues.get(STRING_PREF).equals(DEFAULT_STRING_STRING)
+                && mSavedValues.get(TEST_FILE_1).equals(DEFAULT_FILE_STRING)
+                && mSavedValues.get(TEST_FILE_2).equals(DEFAULT_FILE_STRING);
+
+        assertFalse("The values were not changed from default.", allValuesAreDefault);
+    }
+
+    /**
+     * Parsing the output of "bmgr backupnow" command and checking that the package under test
+     * was backed up successfully.
+     *
+     * Expected format: "Package android.backup.cts.backuprestoreapp with result: Success"
+     */
+    private void assertBackupIsSuccessful(String backupnowOutput) {
+        // Assert backup was successful.
+        Scanner in = new Scanner(backupnowOutput);
+        while (in.hasNextLine()) {
+            String line = in.nextLine();
+
+            if (line.contains(PACKAGE_UNDER_TEST)) {
+                String result = line.split(":")[1].trim();
+
+                assertEquals(result, "Success");
+            }
+        }
+        in.close();
+    }
+
+    /**
+     * Reads the values logged by the app and verifies that they are the same as the ones we saved
+     * in {@code mSavedValues}.
+     */
+    private void assertValuesAreRestored()
+            throws InterruptedException, DeviceNotAvailableException {
+        Map<String, String> restoredValues = readDataValuesFromLogcat();
+
+        // Iterating through mSavedValues (vs. restoredValues) keyset to make sure all of the
+        // keys are reported in restored data
+        for (String dataType : mSavedValues.keySet()) {
+            assertEquals(mSavedValues.get(dataType), restoredValues.get(dataType));
+        }
+    }
+
+    /**
+     * Reads the values that app has reported via logcat and saves them in a map.
+     *
+     * The app logs the values once they are read from shared preferences or a file.
+     * If the values are default ones (i.e., it's the first run of the application), the app then
+     * generates random values and saves them in shared preferences or a file.
+     * Finally, the app reads the values from shared preferences or a file again and logs them.
+     * We are only interested in the final (generated or restored) values.
+     * The format of the log messages is "INT_PREF:17".
+     *
+     * @return Map of the values found in logcat.
+     */
+    private Map<String, String> readDataValuesFromLogcat()
+            throws InterruptedException, DeviceNotAvailableException {
+        Map<String, String> result = new HashMap<>();
+
+        long timeout = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(30);
+
+        // The app generates reads, generates and reads values in async tasks fired onCreate.
+        // It may take some time for all tasks to finish and for logs to appear, so we check logcat
+        // repeatedly until we read VALUES_LOADED_MESSAGE, which is the last message the app logs.
+        search:
+        while (timeout >= System.currentTimeMillis()) {
+            String logs = getLogcatForClass(CLASS_UNDER_TEST);
+
+            Scanner in = new Scanner(logs);
+            while (in.hasNextLine()) {
+                String line = in.nextLine();
+                // Filter by TAG.
+                if (line.startsWith("I/" + CLASS_UNDER_TEST)) {
+                    // Get rid of the TAG.
+                    String message = line.split(":", 2)[1].trim();
+
+                    // VALUES_LOADED_MESSAGE is logged by the app when all the values are loaded and
+                    // logged so we can stop expecting more lines at this point.
+                    if (message.equals(VALUES_LOADED_MESSAGE)) {
+                        break search;
+                    }
+
+                    // Values are logged by the app in the format "INT_PREF:17".
+                    String[] values = message.split(":");
+                    if (values.length == 2) {
+                        result.put(values[0], values[1]);
+                    }
+                }
+            }
+            in.close();
+
+            // In case the key has not been found, wait for the log to update before
+            // performing the next search.
+            Thread.sleep(SMALL_LOGCAT_DELAY_MS);
+        }
+        assertTrue("Timeout while reading the app values", timeout > System.currentTimeMillis());
+        return result;
+    }
+
+    /**
+     * Returns the logcat string with the tag {@param className} and clears everything else.
+     */
+    private String getLogcatForClass(String className) throws DeviceNotAvailableException {
+        return mDevice.executeAdbCommand("logcat", "-v", "brief", "-d",
+                className + ":I", "*:S");
+    }
+
+    // Copied over from BackupQuotaTest
+    private boolean enableBackup(boolean enable) throws Exception {
+        boolean previouslyEnabled;
+        String output = mDevice.executeShellCommand("bmgr enabled");
+        Pattern pattern = Pattern.compile("^Backup Manager currently (enabled|disabled)$");
+        Matcher matcher = pattern.matcher(output.trim());
+        if (matcher.find()) {
+            previouslyEnabled = "enabled".equals(matcher.group(1));
+        } else {
+            throw new RuntimeException("non-parsable output setting bmgr enabled: " + output);
+        }
+
+        mDevice.executeShellCommand("bmgr enable " + enable);
+        return previouslyEnabled;
+    }
+
+    // Copied over from BackupQuotaTest
+    private String setBackupTransport(String transport) throws Exception {
+        String output = mDevice.executeShellCommand("bmgr transport " + transport);
+        Pattern pattern = Pattern.compile("\\(formerly (.*)\\)$");
+        Matcher matcher = pattern.matcher(output);
+        if (matcher.find()) {
+            return matcher.group(1);
+        } else {
+            throw new RuntimeException("non-parsable output setting bmgr transport: " + output);
+        }
+    }
+
+    // Copied over from BackupQuotaTest
+    private boolean hasBackupTransport(String transport) throws Exception {
+        String output = mDevice.executeShellCommand("bmgr list transports");
+        for (String t : output.split(" ")) {
+            if (transport.equals(t.trim())) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java
index 73956c6..98bf3b7 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AutofillRestrictionsTest.java
@@ -28,6 +28,10 @@
     private static final String AUTOFILL_PACKAGE_NAME = "com.android.cts.devicepolicy.autofillapp";
     private static final String AUTOFILL_ACTIVITY_NAME = AUTOFILL_PACKAGE_NAME + ".SimpleActivity";
 
+    // Currently, autofill_service is a cloned service, so it's only set in the default user.
+    // That might change, so we're using a guard to decide how to set it
+    private final boolean USES_CLONED_SETTINGS = true;
+
     int mUserId;
 
     @Override
@@ -76,26 +80,39 @@
     }
 
     private void enableService() throws Exception {
-        runShellCommand("settings put --user %d secure %s %s default",
-                mUserId, AUTOFILL_SERVICE, SERVICE_NAME);
+        if (USES_CLONED_SETTINGS) {
+            runShellCommand("settings put secure %s %s default", AUTOFILL_SERVICE, SERVICE_NAME);
+        } else {
+            runShellCommand("settings put --user %d secure %s %s default",
+                    mUserId, AUTOFILL_SERVICE, SERVICE_NAME);
+        }
         waitForServiceSettingSaved(SERVICE_NAME);
     }
 
     private void disableService() {
-        runShellCommand("settings delete --user %d secure %s", mUserId, AUTOFILL_SERVICE);
+        if (USES_CLONED_SETTINGS) {
+            runShellCommand("settings delete secure %s", AUTOFILL_SERVICE);
+        } else {
+            runShellCommand("settings delete --user %d secure %s", mUserId, AUTOFILL_SERVICE);
+        }
     }
 
     private void waitForServiceSettingSaved(String expected) throws Exception {
         String actual = null;
-        // Wait up to 0.5 second until setting is saved.
+        // Wait up to 0.5 seconds until setting is saved.
         for (int i = 0; i < 5; i++) {
-            actual = runShellCommand("settings get --user %d secure %s", mUserId, AUTOFILL_SERVICE);
+            if (USES_CLONED_SETTINGS) {
+                actual = runShellCommand("settings get secure %s", AUTOFILL_SERVICE);
+            } else {
+                actual = runShellCommand("settings get --user %d secure %s", mUserId,
+                        AUTOFILL_SERVICE);
+            }
             if (expected.equals(actual)) {
                 return;
             }
             Thread.sleep(100);
         }
-        fail("Expected service status: " + expected
+        fail("Expected service status for user " + mUserId + ": " + expected
                 + "; actual: " + actual + " after 0.5 seconds");
     }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java
index b8cc99d..f0b8279 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminServiceTest.java
@@ -105,68 +105,91 @@
         }
 
         // Install
+        CLog.i("Installing apk1...");
         installAppAsUser(OWNER_APK_1, getUserId());
+
+        CLog.i("Making it a device/profile owner...");
         setAsOwnerOrFail(OWNER_COMPONENT);
 
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
 
         // Remove admin.
+        CLog.i("Removing admin...");
         removeAdmin(OWNER_COMPONENT, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
 
         // Overwrite -> update.
+        CLog.i("Re-installing apk1...");
         installAppAsUser(OWNER_APK_1, getUserId());
+
+        CLog.i("Making it a device/profile owner...");
         setAsOwnerOrFail(OWNER_COMPONENT);
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
 
+        CLog.i("Installing apk2...");
         installAppAsUser(OWNER_APK_2, getUserId());
         withRetry(() -> assertServiceBound(OWNER_SERVICE)); // Should still be bound.
 
         // Service exported -> not bound.
+        CLog.i("Installing apk3...");
         installAppAsUser(OWNER_APK_3, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
 
         // Recover.
+        CLog.i("Installing apk2 again...");
         installAppAsUser(OWNER_APK_2, getUserId());
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
 
         // Multiple service found -> not bound.
+        CLog.i("Installing apk4...");
         installAppAsUser(OWNER_APK_4, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE2));
 
         // Disable service1 -> now there's only one service, so should be bound.
+        CLog.i("Running testDisableService1...");
         executeDeviceTestMethod(".ComponentController", "testDisableService1");
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceBound(OWNER_SERVICE2));
 
+        CLog.i("Running testDisableService2...");
         executeDeviceTestMethod(".ComponentController", "testDisableService2");
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE2));
 
+        CLog.i("Running testEnableService1...");
         executeDeviceTestMethod(".ComponentController", "testEnableService1");
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE2));
 
+        CLog.i("Running testEnableService2...");
         executeDeviceTestMethod(".ComponentController", "testEnableService2");
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE2));
 
         // Remove admin.
+        CLog.i("Removing admin again...");
         removeAdmin(OWNER_COMPONENT, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
 
         // Retry with package 1 and remove admin.
+        CLog.i("Installing apk1 again...");
         installAppAsUser(OWNER_APK_1, getUserId());
+
+        CLog.i("Making it a device/profile owner again...");
         setAsOwnerOrFail(OWNER_COMPONENT);
         withRetry(() -> assertServiceBound(OWNER_SERVICE));
 
+        CLog.i("Removing admin again...");
         removeAdmin(OWNER_COMPONENT, getUserId());
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
 
         // Now install package B and make it the owner.  OWNER_APK_1 still exists, but it shouldn't
         // interfere.
+        CLog.i("Installing apk B...");
         installAppAsUser(OWNER_APK_B, getUserId());
+
+        CLog.i("Making it a device/profile owner...");
         setAsOwnerOrFail(OWNER_COMPONENT_B);
         withRetry(() -> assertServiceNotBound(OWNER_SERVICE));
         withRetry(() -> assertServiceBound(OWNER_SERVICE_B));
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
index fd3e85d..ea00512 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
@@ -272,26 +272,29 @@
     }
 
     private void checkWakelock(String[] parts) {
-        assertEquals(20, parts.length);
+        assertEquals(23, parts.length);
         assertNotNull(parts[4]);      // wakelock
 
         assertInteger(parts[5]);      // full totalTime
         assertEquals("f", parts[6]);  // full
         long full_count = assertInteger(parts[7]);      // full count
-        assertInteger(parts[8]);      // current
-        assertInteger(parts[9]);      // max
+        assertInteger(parts[8]);      // current duration
+        assertInteger(parts[9]);      // max duration
+        assertInteger(parts[10]);     // total duration
 
-        assertInteger(parts[10]);      // partial totalTime
-        assertEquals("p", parts[11]);  // partial
-        long partial_count = assertInteger(parts[12]);     // partial count
-        assertInteger(parts[13]);      // current
-        assertInteger(parts[14]);      // max
+        assertInteger(parts[11]);      // partial totalTime
+        assertEquals("p", parts[12]);  // partial
+        long partial_count = assertInteger(parts[13]);     // partial count
+        assertInteger(parts[14]);      // current duration
+        assertInteger(parts[15]);      // max duration
+        assertInteger(parts[16]);      // total duration
 
-        assertInteger(parts[15]);     // window totalTime
-        assertEquals("w", parts[16]); // window
-        long window_count = assertInteger(parts[17]);     // window count
-        assertInteger(parts[18]);      // current
-        assertInteger(parts[19]);     // max
+        assertInteger(parts[17]);     // window totalTime
+        assertEquals("w", parts[18]); // window
+        long window_count = assertInteger(parts[19]);     // window count
+        assertInteger(parts[20]);      // current duration
+        assertInteger(parts[21]);     // max duration
+        assertInteger(parts[22]);     // total duration
 
         // Sanity checks.
         assertTrue("full wakelock count must be >= 0", full_count >= 0);
@@ -387,7 +390,7 @@
     }
 
     private void checkBattery(String[] parts) {
-        assertEquals(13, parts.length);
+        assertEquals(15, parts.length);
         if (!parts[4].equals("N/A")) {
             assertInteger(parts[4]);  // startCount
         }
@@ -399,6 +402,9 @@
         long bOffReal = assertInteger(parts[10]); // batteryScreenOffRealtime
         long bOffUp = assertInteger(parts[11]); // batteryScreenOffUptime
         long bEstCap = assertInteger(parts[12]); // batteryEstimatedCapacity
+        assertInteger(parts[13]); // minLearnedBatteryCapacity
+        assertInteger(parts[14]); // maxLearnedBatteryCapacity
+
         // The device cannot be up more than there are real-world seconds.
         assertTrue("batteryRealtime must be >= batteryUptime", bReal >= bUp);
         assertTrue("totalRealtime must be >= totalUptime", tReal >= tUp);
@@ -612,12 +618,13 @@
     }
 
     private void checkBluetoothMisc(String[] parts) {
-        assertEquals(9, parts.length);
+        assertEquals(10, parts.length);
         assertInteger(parts[4]); // totalTime
         assertInteger(parts[5]); // count
         assertInteger(parts[6]); // countBg
         assertInteger(parts[7]); // actualTime
         assertInteger(parts[8]); // actualTimeBg
+        assertInteger(parts[9]); // resultsCount
     }
 
     /**
diff --git a/hostsidetests/edi/Android.mk b/hostsidetests/edi/Android.mk
new file mode 100644
index 0000000..efa093f
--- /dev/null
+++ b/hostsidetests/edi/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
+
+LOCAL_MODULE := CtsEdiHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/bu_preference_row.xml b/hostsidetests/edi/AndroidTest.xml
similarity index 67%
rename from apps/CtsVerifier/res/layout/bu_preference_row.xml
rename to hostsidetests/edi/AndroidTest.xml
index c37eece..94be6b6 100644
--- a/apps/CtsVerifier/res/layout/bu_preference_row.xml
+++ b/hostsidetests/edi/AndroidTest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- Copyright (C) 2017 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textSize="18sp"
-        android:padding="5dp"
-        />
+<configuration description="Config for CTS EDI host test cases">
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="CtsEdiHostTestCases.jar" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/hostsidetests/edi/src/android/edi/cts/LibraryDeviceInfo.java b/hostsidetests/edi/src/android/edi/cts/LibraryDeviceInfo.java
new file mode 100644
index 0000000..b9f83f4
--- /dev/null
+++ b/hostsidetests/edi/src/android/edi/cts/LibraryDeviceInfo.java
@@ -0,0 +1,88 @@
+/*
+ * 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.edi.cts;
+
+import com.android.compatibility.common.util.DeviceInfo;
+import com.android.compatibility.common.util.HostInfoStore;
+import com.android.ddmlib.FileListingService.FileEntry;
+import com.android.tradefed.device.IFileEntry;
+import com.android.tradefed.device.ITestDevice;
+
+import java.util.Arrays;
+
+public class LibraryDeviceInfo extends DeviceInfo {
+
+    private ITestDevice mDevice;
+
+    @Override
+    protected void collectDeviceInfo(HostInfoStore store) throws Exception {
+
+        mDevice = getDevice();
+
+        collectSystemLibs(store);
+        collectVendorLibs(store);
+        collectFrameworkJars(store);
+    }
+
+    private void collectSystemLibs(HostInfoStore store) throws Exception {
+        store.startArray("lib");
+        collectFileDetails(store, "/system/lib", ".so");
+        store.endArray();
+    }
+
+    private void collectVendorLibs(HostInfoStore store) throws Exception {
+        store.startArray("vendor_lib");
+        collectFileDetails(store, "/system/vendor/lib", ".so");
+        store.endArray();
+    }
+
+    private void collectFrameworkJars(HostInfoStore store) throws Exception {
+        store.startArray("framework_jar");
+        collectFileDetails(store, "/system/framework", ".jar");
+        store.endArray();
+    }
+
+    private void collectFileDetails(HostInfoStore store, String path, String suffix)
+            throws Exception {
+        IFileEntry dir = mDevice.getFileEntry(path);
+
+        if(dir == null || !dir.isDirectory()) {
+            return;
+        }
+
+        for (IFileEntry file : dir.getChildren(false)) {
+            String name = file.getName();
+            if (!file.isDirectory() && name.endsWith(suffix)) {
+                String sha1 = getSha1(file.getFullPath());
+                store.startGroup();
+                store.addResult("name", name);
+                store.addResult("sha1", sha1);
+                store.endGroup();
+            }
+        }
+    }
+
+    private String getSha1(String filePath) {
+        String sha1 = "unknown";
+        try {
+            String out = mDevice.executeShellCommand("sha1sum " + filePath);
+            sha1 = out.split(" ", 2)[0].toUpperCase();
+        } catch (Exception e) {
+            // Do nothing.
+        }
+        return sha1;
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBackgroundService.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBackgroundService.java
index 496e61a..bc28c07 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBackgroundService.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBackgroundService.java
@@ -17,6 +17,7 @@
 package com.android.server.cts.device.batterystats;
 
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_ACTION;
+import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_REQUEST_CODE;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.doAction;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.isAppInBackground;
 
@@ -45,7 +46,9 @@
             Log.w(TAG, "Couldn't determine if app is in background. Proceeding with test anyway.");
         }
 
-        Log.i(TAG, "Starting action from background service");
-        doAction(this, intent.getStringExtra(KEY_ACTION));
+        String action = intent.getStringExtra(KEY_ACTION);
+        String requestCode = intent.getStringExtra(KEY_REQUEST_CODE);
+        Log.i(TAG, "Starting " + action + " from background service as request " + requestCode);
+        doAction(this, action, requestCode);
     }
 }
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
index 480ca2f..e6e810f 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
@@ -55,9 +55,10 @@
     public static final String ACTION_WIFI_DOWNLOAD = "action.wifi_download";
     public static final String ACTION_WIFI_UPLOAD = "action.wifi_upload";
 
+    public static final String KEY_REQUEST_CODE = "request_code";
 
     /** Perform the action specified by the given action code (see constants above). */
-    public static void doAction(Context ctx, String actionCode) {
+    public static void doAction(Context ctx, String actionCode, String requestCode) {
         if (actionCode == null) {
             Log.e(TAG, "Intent was missing action.");
             return;
@@ -65,22 +66,22 @@
         sleep(100);
         switch(actionCode) {
             case ACTION_BLE_SCAN:
-                doBleScan(ctx);
+                doBleScan(ctx, requestCode);
                 break;
             case ACTION_JOB_SCHEDULE:
-                doScheduleJob(ctx);
+                doScheduleJob(ctx, requestCode);
                 break;
             case ACTION_SYNC:
-                doSync(ctx);
+                doSync(ctx, requestCode);
                 break;
             case ACTION_WIFI_SCAN:
-                doWifiScan(ctx);
+                doWifiScan(ctx, requestCode);
                 break;
             case ACTION_WIFI_DOWNLOAD:
-                doWifiDownload(ctx);
+                doWifiDownload(ctx, requestCode);
                 break;
             case ACTION_WIFI_UPLOAD:
-                doWifiUpload(ctx);
+                doWifiUpload(ctx, requestCode);
                 break;
             default:
                 Log.e(TAG, "Intent had invalid action");
@@ -88,7 +89,7 @@
         sleep(100);
     }
 
-    private static void doBleScan(Context ctx) {
+    private static void doBleScan(Context ctx, String requestCode) {
         BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
         if (bluetoothAdapter == null) {
             Log.e(TAG, "Device does not support Bluetooth");
@@ -128,9 +129,10 @@
         bleScanner.startScan(null, scanSettings, scanCallback);
         sleep(2_000);
         bleScanner.stopScan(scanCallback);
+        tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
     }
 
-    private static void doScheduleJob(Context ctx) {
+    private static void doScheduleJob(Context ctx, String requestCode) {
         final ComponentName JOB_COMPONENT_NAME =
                 new ComponentName("com.android.server.cts.device.batterystats",
                         SimpleJobService.class.getName());
@@ -148,13 +150,14 @@
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
-                waitForReceiver(null, 3_000, latch, null);
+                waitForReceiver(null, 60_000, latch, null);
+                tellHostActionFinished(ACTION_JOB_SCHEDULE, requestCode);
                 return null;
             }
         }.execute();
     }
 
-    private static void doSync(Context ctx) {
+    private static void doSync(Context ctx, String requestCode) {
         BatteryStatsAuthenticator.removeAllAccounts(ctx);
         final Account account = BatteryStatsAuthenticator.getTestAccount();
         // Create the test account.
@@ -185,36 +188,59 @@
                 if(ctx instanceof Activity){
                     ((Activity) ctx).finish();
                 }
+                tellHostActionFinished(ACTION_SYNC, requestCode);
             }
         }.execute();
     }
 
-    private static void doWifiScan(Context ctx) {
+    private static void doWifiScan(Context ctx, String requestCode) {
+        // Sometimes a scan was already running (from a different uid), so the first scan doesn't
+        // start when requested. Therefore, additionally wait for whatever scan is currently running
+        // to finish, then request a scan again - at least one of these two scans should be
+        // attributed to this app.
+        doWifiScanOnce(ctx);
+        doWifiScanOnce(ctx);
+        tellHostActionFinished(ACTION_WIFI_SCAN, requestCode);
+    }
+
+    private static void doWifiScanOnce(Context ctx) {
         IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
         CountDownLatch onReceiveLatch = new CountDownLatch(1);
         BroadcastReceiver receiver = registerReceiver(ctx, onReceiveLatch, intentFilter);
         ctx.getSystemService(WifiManager.class).startScan();
-        waitForReceiver(ctx, 3_000, onReceiveLatch, receiver);
+        waitForReceiver(ctx, 60_000, onReceiveLatch, receiver);
     }
 
-    private static void doWifiDownload(Context ctx) {
+    private static void doWifiDownload(Context ctx, String requestCode) {
+        CountDownLatch latch = new CountDownLatch(1);
+
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
-                BatteryStatsWifiTransferTests.download();
+                BatteryStatsWifiTransferTests.download(requestCode);
+                latch.countDown();
                 return null;
             }
         }.execute();
+
+        waitForReceiver(null, 60_000, latch, null);
+        tellHostActionFinished(ACTION_WIFI_DOWNLOAD, requestCode);
     }
 
-    private static void doWifiUpload(Context ctx) {
+    private static void doWifiUpload(Context ctx, String requestCode) {
+        CountDownLatch latch = new CountDownLatch(1);
+
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
                 BatteryStatsWifiTransferTests.upload();
+                latch.countDown();
                 return null;
             }
         }.execute();
+
+        waitForReceiver(null, 60_000, latch, null);
+        tellHostActionFinished(ACTION_WIFI_UPLOAD, requestCode);
     }
 
     /** Register receiver to determine when given action is complete. */
@@ -258,6 +284,12 @@
         }
     }
 
+    /** Communicates to hostside (via logcat) that action has completed (regardless of success). */
+    private static void tellHostActionFinished(String actionCode, String requestCode) {
+        String s = String.format("Completed performing %s for request %s", actionCode, requestCode);
+        Log.i(TAG, s);
+    }
+
     /** Determines whether the package is running as a background process. */
     public static boolean isAppInBackground(Context context) throws ReflectiveOperationException {
         String pkgName = context.getPackageName();
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
index c41b244..fab306d 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
@@ -16,10 +16,9 @@
 
 package com.android.server.cts.device.batterystats;
 
-import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions
-        .ACTION_JOB_SCHEDULE;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.ACTION_SYNC;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_ACTION;
+import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_REQUEST_CODE;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.doAction;
 import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.isAppInBackground;
 
@@ -53,7 +52,9 @@
         }
 
         String action = intent.getStringExtra(KEY_ACTION);
-        doAction(this, action);
+        String requestCode = intent.getStringExtra(KEY_REQUEST_CODE);
+        Log.i(TAG, "Starting " + action + " from foreground activity as request " + requestCode);
+        doAction(this, action, requestCode);
 
         // ACTION_SYNC will finish itself. Others get finished here.
         if (!ACTION_SYNC.equals(action)) {
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
index 1633301..aa5c018 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
@@ -15,35 +15,14 @@
  */
 package com.android.server.cts.device.batterystats;
 
-import static org.junit.Assert.assertTrue;
-
-import android.app.IntentService;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
 import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.util.Arrays;
-import java.util.Random;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
 
 public class BatteryStatsWifiTransferTests {
     private static final String TAG = "BatteryStatsWifiTransferTests";
@@ -53,7 +32,7 @@
     /** Server to send requests to. */
     private static final String SERVER_URL = "https://developer.android.com/index.html";
 
-    public static String download() {
+    public static String download(String requestCode) {
         HttpURLConnection conn = null;
         try {
             URL url = new URL(SERVER_URL);
@@ -69,7 +48,7 @@
             while ((count = in.read(data)) != -1) {
                 total += count;
             }
-            Log.i(TAG, Integer.toString(total));
+            Log.i(TAG, String.format("request %s d=%d", requestCode, total));
         } catch (IOException e) {
             Log.i(TAG, e.toString());
             return "Caught exception";
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java
index cccd9c9..2b9e5a6 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java
+++ b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java
@@ -147,6 +147,12 @@
         drawFrames(new int[frameCount]);
     }
 
+    public void waitForReady() throws InterruptedException, TimeoutException {
+        if (!mReady.await(4, TimeUnit.SECONDS)) {
+            throw new TimeoutException();
+        }
+    }
+
     public void drawFrames(final int[] framesToDraw) throws InterruptedException, TimeoutException {
         if (!mReady.await(4, TimeUnit.SECONDS)) {
             throw new TimeoutException();
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java
index 854649f..ff3e9eb 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java
+++ b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java
@@ -39,6 +39,7 @@
     @Test
     public void testDrawTenFrames() throws Throwable {
         DrawFramesActivity activity = mActivityRule.getActivity();
+        activity.waitForReady();
         assertEquals(1, activity.getRenderedFramesCount());
         assertEquals(0, activity.getDroppedReportsCount());
         activity.drawFrames(10);
@@ -49,6 +50,7 @@
     @Test
     public void testDrawJankyFrames() throws Throwable {
         DrawFramesActivity activity = mActivityRule.getActivity();
+        activity.waitForReady();
         assertEquals(1, activity.getRenderedFramesCount());
         assertEquals(0, activity.getDroppedReportsCount());
         int[] frames = new int[50];
@@ -67,6 +69,7 @@
     @Test
     public void testDrawDaveyFrames() throws Throwable {
         DrawFramesActivity activity = mActivityRule.getActivity();
+        activity.waitForReady();
         assertEquals(1, activity.getRenderedFramesCount());
         assertEquals(0, activity.getDroppedReportsCount());
         int[] frames = new int[40];
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
index 758c443..1c8ac57 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
@@ -15,8 +15,15 @@
  */
 package com.android.server.cts;
 
+import com.android.ddmlib.IShellOutputReceiver;
 import com.android.tradefed.log.LogUtil;
 
+import com.google.common.base.Charsets;
+
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 /**
  * Test for "dumpsys batterystats -c
  *
@@ -52,6 +59,9 @@
     public static final String ACTION_WIFI_DOWNLOAD = "action.wifi_download";
     public static final String ACTION_WIFI_UPLOAD = "action.wifi_upload";
 
+    public static final String KEY_REQUEST_CODE = "request_code";
+    public static final String BG_VS_FG_TAG = "BatteryStatsBgVsFgActions";
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -105,8 +115,8 @@
         runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".BatteryStatsWakeLockTests",
                 "testHoldLongWakeLock");
 
-        assertValueRange("wl", "BSShortWakeLock", 14, (long) (500 * 0.9), 500 * 2);
-        assertValueRange("wl", "BSLongWakeLock", 14, (long) (3000 * 0.9), 3000 * 2);
+        assertValueRange("wl", "BSShortWakeLock", 15, (long) (500 * 0.9), 500 * 2); // partial max duration
+        assertValueRange("wl", "BSLongWakeLock", 15, (long) (3000 * 0.9), 3000 * 2);  // partial max duration
 
         batteryOffScreenOn();
     }
@@ -130,14 +140,12 @@
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
         // Foreground test.
-        executeForeground(ACTION_BLE_SCAN);
-        Thread.sleep(2_500);
+        executeForeground(ACTION_BLE_SCAN, 30_000);
         assertValueRange("blem", "", 5, 1, 1); // ble_scan_count
         assertValueRange("blem", "", 6, 0, 0); // ble_scan_count_bg
 
         // Background test.
-        executeBackground(ACTION_BLE_SCAN);
-        Thread.sleep(2_500);
+        executeBackground(ACTION_BLE_SCAN, 30_000);
         assertValueRange("blem", "", 5, 2, 2); // ble_scan_count
         assertValueRange("blem", "", 6, 1, 1); // ble_scan_count_bg
 
@@ -149,14 +157,12 @@
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
         // Foreground test.
-        executeForeground(ACTION_JOB_SCHEDULE);
-        Thread.sleep(4_000);
+        executeForeground(ACTION_JOB_SCHEDULE, 60_000);
         assertValueRange("jb", "", 6, 1, 1); // count
         assertValueRange("jb", "", 8, 0, 0); // background_count
 
         // Background test.
-        executeBackground(ACTION_JOB_SCHEDULE);
-        Thread.sleep(4_000);
+        executeBackground(ACTION_JOB_SCHEDULE, 60_000);
         assertValueRange("jb", "", 6, 2, 2); // count
         assertValueRange("jb", "", 8, 1, 1); // background_count
 
@@ -168,15 +174,13 @@
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
         // Foreground test.
-        executeForeground(ACTION_SYNC);
-        Thread.sleep(3_000);
+        executeForeground(ACTION_SYNC, 60_000);
         // Allow one or two syncs in this time frame (not just one) due to unpredictable syncs.
         assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 6, 1, 2); // count
         assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 8, 0, 0); // background_count
 
         // Background test.
-        executeBackground(ACTION_SYNC);
-        Thread.sleep(3_000);
+        executeBackground(ACTION_SYNC, 60_000);
         assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 6, 2, 4); // count
         assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 8, 1, 2); // background_count
 
@@ -186,18 +190,23 @@
     public void testWifiScans() throws Exception {
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
+        // Whitelist this app against background wifi scan throttling
+        getDevice().executeShellCommand(String.format(
+                "settings put global wifi_scan_background_throttle_package_whitelist %s",
+                DEVICE_SIDE_TEST_PACKAGE));
 
         // Foreground count test.
-        executeForeground(ACTION_WIFI_SCAN);
-        Thread.sleep(4_000);
-        assertValueRange("wfl", "", 7, 1, 1); // scan_count
+        executeForeground(ACTION_WIFI_SCAN, 120_000);
+        // Allow one or two scans because we try scanning twice and because we allow for the
+        // possibility that, when the test is started, a scan from a different uid was already being
+        // performed (causing the test to 'miss' a scan).
+        assertValueRange("wfl", "", 7, 1, 2); // scan_count
         assertValueRange("wfl", "", 11, 0, 0); // scan_count_bg
 
         // Background count test.
-        executeBackground(ACTION_WIFI_SCAN);
-        Thread.sleep(6_000);
-        assertValueRange("wfl", "", 7, 2, 2); // scan_count
-        assertValueRange("wfl", "", 11, 1, 1); // scan_count_bg
+        executeBackground(ACTION_WIFI_SCAN, 120_000);
+        assertValueRange("wfl", "", 7, 2, 4); // scan_count
+        assertValueRange("wfl", "", 11, 1, 2); // scan_count_bg
 
         batteryOffScreenOn();
     }
@@ -275,8 +284,8 @@
 
         long prevBytes = getLongValue(getUid(), "nt", "", 6);
 
-        executeForeground(ACTION_WIFI_DOWNLOAD);
-        long downloadedBytes = getDownloadedBytes();
+        String requestCode = executeForeground(ACTION_WIFI_DOWNLOAD, 60_000);
+        long downloadedBytes = getDownloadedBytes(requestCode);
         assertTrue(downloadedBytes > 0);
         long min = prevBytes + downloadedBytes + MIN_HTTP_HEADER_BYTES;
         long max = prevBytes + downloadedBytes + FUZZ; // Add some fuzzing.
@@ -285,9 +294,8 @@
 
         // Do the background download
         long prevBgBytes = getLongValue(getUid(), "nt", "", 20);
-        executeBackground(ACTION_WIFI_DOWNLOAD);
-        Thread.sleep(4000);
-        downloadedBytes = getDownloadedBytes();
+        requestCode = executeBackground(ACTION_WIFI_DOWNLOAD, 60_000);
+        downloadedBytes = getDownloadedBytes(requestCode);
 
         long minBg = prevBgBytes + downloadedBytes + MIN_HTTP_HEADER_BYTES;
         long maxBg = prevBgBytes + downloadedBytes + FUZZ;
@@ -310,14 +318,12 @@
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
-        executeForeground(ACTION_WIFI_UPLOAD);
-        Thread.sleep(2000);
+        executeForeground(ACTION_WIFI_UPLOAD, 60_000);
         int min = MIN_HTTP_HEADER_BYTES + (2 * 1024);
         int max = min + (6 * 1024); // Add some fuzzing.
         assertValueRange("nt", "", 7, min, max); // wifi_bytes_tx
 
-        executeBackground(ACTION_WIFI_UPLOAD);
-        Thread.sleep(4000);
+        executeBackground(ACTION_WIFI_UPLOAD, 60_000);
         assertValueRange("nt", "", 21, min * 2, max * 2); // wifi_bytes_bg_tx
 
         batteryOffScreenOn();
@@ -371,15 +377,39 @@
     }
 
     /**
+     * Runs a (background) service to perform the given action, and waits for
+     * the device to report that the action has finished (via a logcat message) before returning.
+     * @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
+     *                    action to perform.
+     * @param maxTimeMs max time to wait (in ms) for action to report that it has completed.
+     * @return A string, representing a random integer, assigned to this particular request for the
+     *                     device to perform the given action. This value can be used to receive
+     *                     communications via logcat from the device about this action.
+     */
+    private String executeBackground(String actionValue, int maxTimeMs) throws Exception {
+        String requestCode = executeBackground(actionValue);
+        String searchString = getCompletedActionString(actionValue, requestCode);
+        checkLogcatForText(BG_VS_FG_TAG, searchString, maxTimeMs);
+        return requestCode;
+    }
+
+    /**
      * Runs a (background) service to perform the given action.
      * @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
      *                    action to perform.
+     * @return A string, representing a random integer, assigned to this particular request for the
+      *                     device to perform the given action. This value can be used to receive
+      *                     communications via logcat from the device about this action.
      */
-    private void executeBackground(String actionValue) throws Exception {
+    private String executeBackground(String actionValue) throws Exception {
         allowBackgroundServices();
+        String requestCode = Integer.toString(new Random().nextInt());
         getDevice().executeShellCommand(String.format(
-                "am startservice -n '%s' -e %s %s",
-                DEVICE_SIDE_BG_SERVICE_COMPONENT, KEY_ACTION, actionValue));
+                "am startservice -n '%s' -e %s %s -e %s %s",
+                DEVICE_SIDE_BG_SERVICE_COMPONENT,
+                KEY_ACTION, actionValue,
+                KEY_REQUEST_CODE, requestCode));
+        return requestCode;
     }
 
     /** Required to successfully start a background service from adb in O. */
@@ -389,26 +419,119 @@
     }
 
     /**
+     * Runs an activity (in the foreground) to perform the given action, and waits
+     * for the device to report that the action has finished (via a logcat message) before returning.
+     * @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
+     *                    action to perform.
+     * @param maxTimeMs max time to wait (in ms) for action to report that it has completed.
+     * @return A string, representing a random integer, assigned to this particular request for the
+     *                     device to perform the given action. This value can be used to receive
+     *                     communications via logcat from the device about this action.
+     */
+    private String executeForeground(String actionValue, int maxTimeMs) throws Exception {
+        String requestCode = executeForeground(actionValue);
+        String searchString = getCompletedActionString(actionValue, requestCode);
+        checkLogcatForText(BG_VS_FG_TAG, searchString, maxTimeMs);
+        return requestCode;
+    }
+
+    /**
      * Runs an activity (in the foreground) to perform the given action.
      * @param actionValue one of the constants in BatteryStatsBgVsFgActions indicating the desired
      *                    action to perform.
+     * @return A string, representing a random integer, assigned to this particular request for the
+     *                     device to perform the given action. This value can be used to receive
+     *                     communications via logcat from the device about this action.
      */
-    private void executeForeground(String actionValue) throws Exception {
+    private String executeForeground(String actionValue) throws Exception {
+        String requestCode = Integer.toString(new Random().nextInt());
         getDevice().executeShellCommand(String.format(
-                "am start -n '%s' -e %s %s",
-                DEVICE_SIDE_FG_ACTIVITY_COMPONENT, KEY_ACTION, actionValue));
+                "am start -n '%s' -e %s %s -e %s %s",
+                DEVICE_SIDE_FG_ACTIVITY_COMPONENT,
+                KEY_ACTION, actionValue,
+                KEY_REQUEST_CODE, requestCode));
+        return requestCode;
+    }
+
+    /**
+     * The string that will be printed in the logcat when the action completes. This needs to be
+     * identical to {@link com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions#tellHostActionFinished}.
+     */
+    private String getCompletedActionString(String actionValue, String requestCode) {
+        return String.format("Completed performing %s for request %s", actionValue, requestCode);
+    }
+
+    /**
+    * Runs logcat and waits (for a maximumum of maxTimeMs) until the desired text is displayed with
+    * the given tag.
+    * Logcat is not cleared, so make sure that text is unique (won't get false hits from old data).
+    * Note that, in practice, the actual max wait time seems to be about 10s longer than maxTimeMs.
+    */
+    private void checkLogcatForText(String logcatTag, String text, int maxTimeMs) {
+        IShellOutputReceiver receiver = new IShellOutputReceiver() {
+            private final StringBuilder mOutputBuffer = new StringBuilder();
+            private final AtomicBoolean mIsCanceled = new AtomicBoolean(false);
+
+            @Override
+            public void addOutput(byte[] data, int offset, int length) {
+                if (!isCancelled()) {
+                    synchronized (mOutputBuffer) {
+                        String s = new String(data, offset, length, Charsets.UTF_8);
+                        mOutputBuffer.append(s);
+                        if (checkBufferForText()) {
+                            mIsCanceled.set(true);
+                        }
+                    }
+                }
+            }
+
+            private boolean checkBufferForText() {
+                if (mOutputBuffer.indexOf(text) > -1) {
+                    return true;
+                } else {
+                    // delete all old data (except the last few chars) since they don't contain text
+                    // (presumably large chunks of data will be added at a time, so this is
+                    // sufficiently efficient.)
+                    int newStart = mOutputBuffer.length() - text.length();
+                    if (newStart > 0) {
+                        mOutputBuffer.delete(0, newStart);
+                    }
+                    return false;
+                }
+            }
+
+            @Override
+            public boolean isCancelled() {
+                return mIsCanceled.get();
+            }
+
+            @Override
+            public void flush() {
+            }
+        };
+
+        try {
+            // Wait for at most maxTimeMs for logcat to display the desired text.
+            getDevice().executeShellCommand(String.format("logcat -s %s -e '%s'", logcatTag, text),
+                    receiver, maxTimeMs, TimeUnit.MILLISECONDS, 0);
+        } catch (com.android.tradefed.device.DeviceNotAvailableException e) {
+            System.err.println(e);
+        }
     }
 
     /**
      * Returns the bytes downloaded for the wifi transfer download tests.
+     * @param requestCode the output of executeForeground() or executeBackground() to identify in
+     *                    the logcat the line associated with the desired download information
      */
-    private long getDownloadedBytes() throws Exception {
+    private long getDownloadedBytes(String requestCode) throws Exception {
         String log = getDevice().executeShellCommand(
-                "logcat -d -s BatteryStatsWifiTransferTests -e '\\d+'");
+                String.format("logcat -d -s BatteryStatsWifiTransferTests -e 'request %s d=\\d+'",
+                        requestCode));
         String[] lines = log.split("\n");
         long size = 0;
         for (int i = lines.length - 1; i >= 0; i--) {
-            String[] parts = lines[i].split(":");
+            String[] parts = lines[i].split("d=");
             String num = parts[parts.length - 1].trim();
             if (num.matches("\\d+")) {
                 size = Integer.parseInt(num);
diff --git a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
index ea64a25..2e04e80 100644
--- a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
@@ -88,9 +88,10 @@
         assertTrue(slowUiDelta >= 30);
         int missedVsyncDelta = summaryAfter.getMissedVsyncCount()
                 - summaryBefore.getMissedVsyncCount();
-        assertEquals(10, missedVsyncDelta);
+        assertTrue(missedVsyncDelta >= 10);
+        assertTrue(missedVsyncDelta <= 11);
 
-        int veryJankyDelta = countFramesAbove(statsAfter, 40) - countFramesAbove(statsBefore, 40);
+        int veryJankyDelta = countFramesAbove(statsAfter, 60) - countFramesAbove(statsBefore, 60);
         // The 1st frame could be >40ms, but nothing after that should be
         assertTrue(veryJankyDelta <= 1);
     }
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 577f62c..d43d8aa 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -817,29 +817,37 @@
     }
 
     protected void launchComponentAndAssertNetworkAccess(int type) throws Exception {
-        if (type == TYPE_COMPONENT_ACTIVTIY) {
+        if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) {
+            startForegroundService();
+            assertForegroundServiceNetworkAccess();
+            return;
+        } else if (type == TYPE_COMPONENT_ACTIVTIY) {
             turnScreenOn();
-        }
-        final CountDownLatch latch = new CountDownLatch(1);
-        final Intent launchIntent = getIntentForComponent(type);
-        final Bundle extras = new Bundle();
-        final String[] errors = new String[] {null};
-        extras.putBinder(KEY_NETWORK_STATE_OBSERVER, getNewNetworkStateObserver(latch, errors));
-        launchIntent.putExtras(extras);
-        if (type == TYPE_COMPONENT_ACTIVTIY) {
+            final CountDownLatch latch = new CountDownLatch(1);
+            final Intent launchIntent = getIntentForComponent(type);
+            final Bundle extras = new Bundle();
+            final String[] errors = new String[]{null};
+            extras.putBinder(KEY_NETWORK_STATE_OBSERVER, getNewNetworkStateObserver(latch, errors));
+            launchIntent.putExtras(extras);
             mContext.startActivity(launchIntent);
-        } else if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) {
-            mContext.startService(launchIntent);
-        }
-        if (latch.await(FOREGROUND_PROC_NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
-            if (!errors[0].isEmpty()) {
-                fail("Network is not available for app2 (" + mUid + "): " + errors[0]);
+            if (latch.await(FOREGROUND_PROC_NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                if (!errors[0].isEmpty()) {
+                    fail("Network is not available for app2 (" + mUid + "): " + errors[0]);
+                }
+            } else {
+                fail("Timed out waiting for network availability status from app2 (" + mUid + ")");
             }
         } else {
-            fail("Timed out waiting for network availability status from app2 (" + mUid + ")");
+            throw new IllegalArgumentException("Unknown type: " + type);
         }
     }
 
+    private void startForegroundService() throws Exception {
+        final Intent launchIntent = getIntentForComponent(TYPE_COMPONENT_FOREGROUND_SERVICE);
+        mContext.startForegroundService(launchIntent);
+        assertForegroundServiceState();
+    }
+
     private Intent getIntentForComponent(int type) {
         final Intent intent = new Intent();
         if (type == TYPE_COMPONENT_ACTIVTIY) {
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/Android.mk b/hostsidetests/services/activityandwindowmanager/activitymanager/app/Android.mk
index 9abafe9..2633c0a 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/Android.mk
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/Android.mk
@@ -19,6 +19,9 @@
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := tests
 
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-v4 \
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
                    ../../../../../apps/CtsVerifier/src/com/android/cts/verifier/vr/MockVrListenerService.java
 
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
index f406735..12ba159 100755
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
@@ -30,6 +30,12 @@
                 android:supportsPictureInPicture="true"
                 android:exported="true"
         />
+        <activity android:name=".TestActivityWithSameAffinity"
+                android:resizeableActivity="true"
+                android:supportsPictureInPicture="true"
+                android:exported="true"
+                android:taskAffinity="nobody.but.PipActivitySameAffinity"
+        />
         <activity android:name=".TranslucentTestActivity"
                 android:resizeableActivity="true"
                 android:supportsPictureInPicture="true"
@@ -103,7 +109,20 @@
                   android:exported="true"
                   android:taskAffinity="nobody.but.PipActivity2"
         />
-
+        <activity android:name=".PipOnStopActivity"
+                  android:resizeableActivity="false"
+                  android:supportsPictureInPicture="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+                  android:exported="true"
+                  android:taskAffinity="nobody.but.PipOnStopActivity"
+        />
+        <activity android:name=".PipActivityWithSameAffinity"
+                  android:resizeableActivity="false"
+                  android:supportsPictureInPicture="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+                  android:exported="true"
+                  android:taskAffinity="nobody.but.PipActivitySameAffinity"
+        />
         <activity android:name=".AlwaysFocusablePipActivity"
                   android:theme="@style/Theme.Transparent"
                   android:resizeableActivity="false"
@@ -134,19 +153,12 @@
                   android:exported="true"
         />
         <activity android:name=".LaunchImeWithPipActivity"
-            android:resizeableActivity="false"
-            android:supportsPictureInPicture="true"
-            androidprv:alwaysFocusable="true"
-            android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
-            android:exported="true"
-            android:windowSoftInputMode="stateAlwaysVisible"
-        />
-        <activity android:name=".PipOnStopActivity"
-            android:resizeableActivity="false"
-            android:supportsPictureInPicture="true"
-            android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
-            android:exported="true"
-            android:taskAffinity="nobody.but.PipOnStopActivity"
+                  android:resizeableActivity="false"
+                  android:supportsPictureInPicture="true"
+                  androidprv:alwaysFocusable="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+                  android:exported="true"
+                  android:windowSoftInputMode="stateAlwaysVisible"
         />
         <activity android:name=".FreeformActivity"
                   android:resizeableActivity="true"
@@ -345,6 +357,14 @@
             android:theme="@style/SplashscreenTheme"
             android:exported="true" />
 
+
+        <activity android:name=".SwipeRefreshActivity"
+                  android:exported="true" />
+
+        <activity android:name=".NoHistoryActivity"
+                  android:noHistory="true"
+                  android:exported="true" />
+
         <service android:name="com.android.cts.verifier.vr.MockVrListenerService"
                  android:exported="true"
                  android:enabled="true"
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/BroadcastReceiverActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/BroadcastReceiverActivity.java
index ed75f73..18f1fa8 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/BroadcastReceiverActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/BroadcastReceiverActivity.java
@@ -77,8 +77,8 @@
                 getWindow().addFlags(FLAG_DISMISS_KEYGUARD);
             }
             if (extras.getBoolean("dismissKeyguardMethod")) {
-                getSystemService(KeyguardManager.class).dismissKeyguard(
-                        BroadcastReceiverActivity.this, new KeyguardDismissLoggerCallback(), null);
+                getSystemService(KeyguardManager.class).requestDismissKeyguard(
+                        BroadcastReceiverActivity.this, new KeyguardDismissLoggerCallback());
             }
 
             ActivityLauncher.launchActivityFromExtras(BroadcastReceiverActivity.this, extras);
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/LaunchEnterPipActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/LaunchEnterPipActivity.java
index 322927e..e2b4786 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/LaunchEnterPipActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/LaunchEnterPipActivity.java
@@ -18,11 +18,12 @@
 
 import android.app.Activity;
 import android.graphics.Rect;
+import android.os.Bundle;
 
 public class LaunchEnterPipActivity extends Activity {
     @Override
-    protected void onResume() {
-        super.onResume();
+    protected void onCreate(Bundle bundle) {
+        super.onCreate(bundle);
         PipActivity.launchEnterPipActivity(this);
     }
 }
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/NoHistoryActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/NoHistoryActivity.java
new file mode 100644
index 0000000..6a84602
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/NoHistoryActivity.java
@@ -0,0 +1,29 @@
+/*
+ * 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.server.cts;
+
+/**
+ * An activity that has the noHistory flag set.
+ */
+public class NoHistoryActivity extends AbstractLifecycleLogActivity {
+    private static final String TAG = NoHistoryActivity.class.getSimpleName();
+
+    @Override
+    protected String getTag() {
+        return TAG;
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
index 79d3c3f..7e50331 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
@@ -299,11 +299,11 @@
     }
 
     /**
-     * Launches a new instance of the PipActivity that will automatically enter PiP.
+     * Launches a new instance of the PipActivity in the same task that will automatically enter
+     * PiP.
      */
     static void launchEnterPipActivity(Activity caller) {
         final Intent intent = new Intent(caller, PipActivity.class);
-        intent.setFlags(FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK);
         intent.putExtra(EXTRA_ENTER_PIP, "true");
         intent.putExtra(EXTRA_ASSERT_NO_ON_STOP_BEFORE_PIP, "true");
         caller.startActivity(intent);
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivityWithSameAffinity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivityWithSameAffinity.java
new file mode 100644
index 0000000..e97dc0e
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivityWithSameAffinity.java
@@ -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
+ */
+
+package android.server.cts;
+
+import android.app.Activity;
+import android.app.PictureInPictureParams;
+
+/**
+ * An activity that can enter PiP with a fixed affinity to match
+ * {@link TestActivityWithSameAffinity}.
+ */
+public class PipActivityWithSameAffinity extends Activity {
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SwipeRefreshActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SwipeRefreshActivity.java
new file mode 100644
index 0000000..5f36abc
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SwipeRefreshActivity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.server.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.server.cts.SwipeRefreshLayout;
+
+
+/**
+ * An activity containing a SwipeRefreshLayout which prevents activity idle.
+ */
+public class SwipeRefreshActivity extends AbstractLifecycleLogActivity {
+    private static final String TAG = SwipeRefreshActivity.class.getSimpleName();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(new SwipeRefreshLayout(this));
+    }
+
+    @Override
+    protected String getTag() {
+        return TAG;
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SwipeRefreshLayout.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SwipeRefreshLayout.java
new file mode 100644
index 0000000..a061d9e
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SwipeRefreshLayout.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.server.cts;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+/**
+ * An extension of {@link android.support.v4.widget.SwipeRefreshLayout} that calls
+ * {@link #setRefreshing} during construction, preventing activity idle.
+ */
+public class SwipeRefreshLayout extends android.support.v4.widget.SwipeRefreshLayout {
+    public SwipeRefreshLayout(Context context) {
+        super(context);
+        initialize();
+    }
+
+    public SwipeRefreshLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initialize();
+    }
+
+    private void initialize() {
+        setRefreshing(true);
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java
new file mode 100644
index 0000000..d835da7
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.cts;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.util.Log;
+
+public class TestActivityWithSameAffinity extends TestActivity {
+
+    private static final String TAG = TestActivityWithSameAffinity.class.getSimpleName();
+
+    // Starts the activity (component name) provided by the value at the end of onCreate
+    private static final String EXTRA_START_ACTIVITY = "start_activity";
+    // Finishes the activity at the end of onResume (after EXTRA_START_ACTIVITY is handled)
+    private static final String EXTRA_FINISH_SELF_ON_RESUME = "finish_self_on_resume";
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Launch a new activity if requested
+        String launchActivityComponent = getIntent().getStringExtra(EXTRA_START_ACTIVITY);
+        if (launchActivityComponent != null) {
+            Intent launchIntent = new Intent();
+            launchIntent.setComponent(ComponentName.unflattenFromString(launchActivityComponent));
+            startActivity(launchIntent);
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        // Finish self if requested
+        if (getIntent().hasExtra(EXTRA_FINISH_SELF_ON_RESUME)) {
+            finish();
+        }
+    }
+
+    @Override
+    protected String getTag() {
+        return TAG;
+    }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TurnScreenOnDismissKeyguardActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TurnScreenOnDismissKeyguardActivity.java
index 9d262a7..62948b6 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TurnScreenOnDismissKeyguardActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TurnScreenOnDismissKeyguardActivity.java
@@ -27,7 +27,7 @@
         super.onCreate(savedInstanceState);
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                 | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
-        getSystemService(KeyguardManager.class).dismissKeyguard(this,
-                new KeyguardDismissLoggerCallback(), null);
+        getSystemService(KeyguardManager.class).requestDismissKeyguard(this,
+                new KeyguardDismissLoggerCallback());
     }
 }
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
index 8374f7c..c04ef90 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
@@ -102,6 +102,9 @@
             case "destroy_display":
                 destroyVirtualDisplays();
                 break;
+            case "resize_display":
+                resizeDisplay();
+                break;
         }
     }
 
@@ -195,4 +198,12 @@
     @Override
     public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
     }
+
+    /** Resize virtual display to half of the surface frame size. */
+    private void resizeDisplay() {
+        final VirtualDisplayEntry vd = (VirtualDisplayEntry) mVirtualDisplays.values().toArray()[0];
+        final SurfaceHolder surfaceHolder = vd.surfaceView.getHolder();
+        vd.display.resize(surfaceHolder.getSurfaceFrame().width() / 2,
+                surfaceHolder.getSurfaceFrame().height() / 2, vd.density);
+    }
 }
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java
index d0db632..c647be4 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java
@@ -39,6 +39,9 @@
     private static final String DOCKED_ACTIVITY_NAME = "DockedActivity";
     private static final String TURN_SCREEN_ON_ACTIVITY_NAME = "TurnScreenOnActivity";
     private static final String MOVE_TASK_TO_BACK_ACTIVITY_NAME = "MoveTaskToBackActivity";
+    private static final String SWIPE_REFRESH_ACTIVITY = "SwipeRefreshActivity";
+    private static final String NOHISTORY_ACTIVITY = "NoHistoryActivity";
+
 
     public void testTranslucentActivityOnTopOfPinnedStack() throws Exception {
         if (!supportsPip()) {
@@ -250,6 +253,24 @@
         // Ensure launching activity was brought forward.
         mAmWmState.assertFocusedActivity("Launching Activity must be focused",
                 LAUNCHING_ACTIVITY);
+    }
 
+    /**
+     * Asserts that a nohistory activity is stopped and removed immediately after a resumed activity
+     * above becomes visible and does not idle.
+     */
+    public void testNoHistoryActivityFinishedResumedActivityNotIdle() throws Exception {
+        // Start with home on top
+        launchHomeActivity();
+
+        // Launch no history activity
+        launchActivity(NOHISTORY_ACTIVITY);
+
+        // Launch an activity with a swipe refresh layout configured to prevent idle.
+        launchActivity(SWIPE_REFRESH_ACTIVITY);
+
+        pressBackButton();
+        mAmWmState.waitForHomeActivityVisible(mDevice);
+        mAmWmState.assertHomeActivityVisible(true);
     }
 }
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAssistantStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAssistantStackTests.java
index af42e30..21146a4 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAssistantStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAssistantStackTests.java
@@ -17,7 +17,6 @@
 package android.server.cts;
 
 import static android.server.cts.ActivityManagerState.STATE_RESUMED;
-import static android.server.cts.ActivityManagerState.STATE_STOPPED;
 
 /**
  * Build: mmma -j32 cts/hostsidetests/services
@@ -186,6 +185,34 @@
         disableAssistant();
     }
 
+    public void testLaunchIntoSameTask() throws Exception {
+        enableAssistant();
+
+        // Launch the assistant
+        launchActivity(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
+        assertAssistantStackExists();
+        mAmWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
+        mAmWmState.assertFocusedStack("Expected assistant stack focused", ASSISTANT_STACK_ID);
+        assertEquals(1, mAmWmState.getAmState().getStackById(ASSISTANT_STACK_ID).getTasks().size());
+        final int taskId = mAmWmState.getAmState().getTaskByActivityName(ASSISTANT_ACTIVITY)
+                .mTaskId;
+
+        // Launch a new fullscreen activity
+        launchActivity(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", ASSISTANT_STACK_ID);
+        assertEquals(1, mAmWmState.getAmState().getStackById(ASSISTANT_STACK_ID).getTasks().size());
+        assertEquals(taskId,
+                mAmWmState.getAmState().getTaskByActivityName(ASSISTANT_ACTIVITY).mTaskId);
+
+        disableAssistant();
+    }
+
     /**
      * Asserts that the assistant stack exists.
      */
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
index 9ad9d29..dc37d9b 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
@@ -410,7 +410,7 @@
      * on the primary display. It should land on the primary display and dismiss docked stack.
      */
     public void testLaunchNonResizeableActivityWithSplitScreen() throws Exception {
-        if (!supportsMultiDisplay()) { return; }
+        if (!supportsMultiDisplay() || !supportsSplitScreenMultiWindow()) { return; }
 
         // Start launching activity.
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
@@ -540,10 +540,9 @@
         if (!supportsMultiDisplay()) { return; }
 
         // Start launching activity.
-        launchActivityInDockStack(LAUNCHING_ACTIVITY);
+        launchActivity(LAUNCHING_ACTIVITY);
         // Create new virtual display.
-        final DisplayState newDisplay =
-                new VirtualDisplayBuilder(this).setLaunchInSplitScreen(true).build();
+        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
 
         // Launch activity on secondary display from the app on primary display.
         getLaunchActivityBuilder().setTargetActivityName(TEST_ACTIVITY_NAME)
@@ -569,28 +568,21 @@
         if (!supportsMultiDisplay()) { return; }
 
         // Start launching activity.
-        launchActivityInDockStack(LAUNCHING_ACTIVITY);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
-
+        launchActivity(LAUNCHING_ACTIVITY);
         // Create new virtual display.
-        final DisplayState newDisplay =
-                new VirtualDisplayBuilder(this).setLaunchInSplitScreen(true).build();
+        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
         mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
         // Launch activity on primary display and check if it doesn't affect activity on secondary
         // display.
         getLaunchActivityBuilder().setTargetActivityName(RESIZEABLE_ACTIVITY_NAME).execute();
-        mAmWmState.waitForValidState(mDevice, RESIZEABLE_ACTIVITY_NAME,
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.waitForValidState(mDevice, RESIZEABLE_ACTIVITY_NAME);
         mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true /* visible */);
     }
 
@@ -606,46 +598,54 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
         mAmWmState.assertFocusedActivity("Focus must be on secondary display", TEST_ACTIVITY_NAME);
-        mAmWmState.assertNotFocusedStack("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        focusedStack = mAmWmState.getAmState().getStackById(focusedStackId);
+        assertEquals("Focused stack must be on secondary display",
+                newDisplay.mDisplayId, focusedStack.mDisplayId);
 
         // Move activity from secondary display to primary.
-        moveActivityToStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
-        mAmWmState.waitForFocusedStack(mDevice, FULLSCREEN_WORKSPACE_STACK_ID);
+        moveActivityToStack(TEST_ACTIVITY_NAME, defaultDisplayStackId);
+        mAmWmState.waitForFocusedStack(mDevice, defaultDisplayStackId);
         mAmWmState.assertFocusedActivity("Focus must be on moved activity", TEST_ACTIVITY_NAME);
-        mAmWmState.assertFocusedStack("Focus must return to primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        focusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        focusedStack = mAmWmState.getAmState().getStackById(focusedStackId);
+        assertEquals("Focus must return to primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
     }
 
     /**
      * Tests launching activities on secondary display and then removing it to see if stack focus
      * is moved correctly.
-     * This version launches virtual display creator to fullscreen stack.
+     * This version launches virtual display creator to fullscreen stack in split-screen.
      */
     @Presubmit
     public void testStackFocusSwitchOnDisplayRemoved() throws Exception {
-        if (!supportsMultiDisplay()) { return; }
+        if (!supportsMultiDisplay() || !supportsSplitScreenMultiWindow()) { return; }
 
         // Start launching activity into docked stack.
         launchActivityInDockStack(LAUNCHING_ACTIVITY);
         mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
-        tryCreatingAndRemovingDisplayWithActivity();
+        tryCreatingAndRemovingDisplayWithActivity(true /* splitScreen */,
+                FULLSCREEN_WORKSPACE_STACK_ID);
     }
 
     /**
      * Tests launching activities on secondary display and then removing it to see if stack focus
      * is moved correctly.
-     * This version launches virtual display creator to docked stack.
+     * This version launches virtual display creator to docked stack in split-screen.
      */
     public void testStackFocusSwitchOnDisplayRemoved2() throws Exception {
-        if (!supportsMultiDisplay()) { return; }
+        if (!supportsMultiDisplay() || !supportsSplitScreenMultiWindow()) { return; }
 
         // Setup split-screen.
         launchActivityInDockStack(RESIZEABLE_ACTIVITY_NAME);
@@ -654,21 +654,45 @@
         launchActivityInStack(LAUNCHING_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
         mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
-        tryCreatingAndRemovingDisplayWithActivity();
+        tryCreatingAndRemovingDisplayWithActivity(true /* splitScreen */,
+                FULLSCREEN_WORKSPACE_STACK_ID);
     }
 
     /**
-     * Create a virtual display to side from LaunchingActivity, launch a test activity there,
-     * destroy the display and check if test activity is moved to fullscreen stack.
+     * Tests launching activities on secondary display and then removing it to see if stack focus
+     * is moved correctly.
+     * This version works without split-screen.
      */
-    private void tryCreatingAndRemovingDisplayWithActivity() throws Exception {
+    public void testStackFocusSwitchOnDisplayRemoved3() throws Exception {
+        if (!supportsMultiDisplay()) { return; }
+
+        // Start an activity on default display to determine default stack.
+        launchActivity(BROADCAST_RECEIVER_ACTIVITY);
+        final int focusedStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
+        // Finish probing activity.
+        executeShellCommand(FINISH_ACTIVITY_BROADCAST);
+
+
+        tryCreatingAndRemovingDisplayWithActivity(false /* splitScreen */, focusedStackId);
+    }
+
+    /**
+     * Create a virtual display, launch a test activity there, destroy the display and check if test
+     * activity is moved to a stack on the default display.
+     */
+    private void tryCreatingAndRemovingDisplayWithActivity(boolean splitScreen, int defaultStackId)
+            throws Exception {
         // Create new virtual display.
-        final DisplayState newDisplay = new VirtualDisplayBuilder(this)
-                .setLaunchInSplitScreen(true)
-                .setPublicDisplay(true)
-                .build();
+        final VirtualDisplayBuilder builder = new VirtualDisplayBuilder(this)
+                .setPublicDisplay(true);
+        if (splitScreen) {
+            builder.setLaunchInSplitScreen(true);
+        }
+        final DisplayState newDisplay = builder.build();
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
+        if (splitScreen) {
+            mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
+        }
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
@@ -679,15 +703,17 @@
 
         // Destroy virtual display.
         destroyVirtualDisplays();
-        mAmWmState.waitForValidState(mDevice, TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.waitForValidState(mDevice, TEST_ACTIVITY_NAME, defaultStackId);
         mAmWmState.assertSanity();
         mAmWmState.assertValidBounds(true /* compareTaskAndStackBounds */);
 
         // Check if the focus is switched back to primary display.
         mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-        mAmWmState.assertFocusedStack("Fullscreen stack must be focused after display removed",
-                FULLSCREEN_WORKSPACE_STACK_ID);
-        mAmWmState.assertFocusedActivity("Focus must be switched back to primary display",
+        mAmWmState.assertFocusedStack(
+                "Default stack on primary display must be focused after display removed",
+                defaultStackId);
+        mAmWmState.assertFocusedActivity(
+                "Focus must be switched back to activity on primary display",
                 TEST_ACTIVITY_NAME);
     }
 
@@ -698,15 +724,10 @@
     public void testStackFocusSwitchOnStackEmptied() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
-        // Start launching activity.
-        launchActivityInDockStack(LAUNCHING_ACTIVITY);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
-
         // Create new virtual display.
-        final DisplayState newDisplay =
-                new VirtualDisplayBuilder(this).setLaunchInSplitScreen(true).build();
+        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
+        final int focusedStackId = mAmWmState.getAmState().getFrontStackId(DEFAULT_DISPLAY_ID);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(BROADCAST_RECEIVER_ACTIVITY, newDisplay.mDisplayId);
@@ -721,9 +742,8 @@
 
         // Unlock and check if the focus is switched back to primary display.
         wakeUpAndUnlockDevice();
-        mAmWmState.waitForFocusedStack(mDevice, FULLSCREEN_WORKSPACE_STACK_ID);
-        mAmWmState.waitForValidState(mDevice, LAUNCHING_ACTIVITY);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
+        mAmWmState.waitForFocusedStack(mDevice, focusedStackId);
+        mAmWmState.waitForValidState(mDevice, VIRTUAL_DISPLAY_ACTIVITY);
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Focus must be switched back to primary display",
                 VIRTUAL_DISPLAY_ACTIVITY);
@@ -767,16 +787,20 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
         mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                 TEST_ACTIVITY_NAME);
         final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
-        assertTrue("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID != externalFocusedStackId);
+        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
+        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
+                focusedStack.mDisplayId);
 
         // Launch other activity with different uid and check it is launched on dynamic stack on
         // secondary display.
@@ -801,8 +825,11 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch activity with different uid on secondary display.
         final String startCmd =  "am start -n " + SECOND_PACKAGE_NAME + "/." + SECOND_ACTIVITY_NAME;
@@ -814,8 +841,9 @@
         mAmWmState.assertFocusedActivity("Focus must be on newly launched app",
                 SECOND_PACKAGE_NAME, SECOND_ACTIVITY_NAME);
         final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
-        assertTrue("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID != externalFocusedStackId);
+        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
+        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
+                focusedStack.mDisplayId);
 
         // Launch another activity with third different uid from app on secondary display and check
         // it is launched on secondary display.
@@ -877,8 +905,11 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch other activity with different uid on secondary display.
         final String startCmd =  "am start -n " + SECOND_PACKAGE_NAME + "/." + SECOND_ACTIVITY_NAME;
@@ -890,8 +921,9 @@
         mAmWmState.assertFocusedActivity("Focus must be on newly launched app",
                 SECOND_PACKAGE_NAME, SECOND_ACTIVITY_NAME);
         final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
-        assertTrue("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID != externalFocusedStackId);
+        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
+        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
+                focusedStack.mDisplayId);
 
         // Check that owner uid can launch its own activity on secondary display.
         final String broadcastAction = componentName + ".LAUNCH_BROADCAST_ACTION";
@@ -917,16 +949,20 @@
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
         mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
                 VIRTUAL_DISPLAY_ACTIVITY);
-        mAmWmState.assertFocusedStack("Focus must remain on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(defaultDisplayFocusedStackId);
+        assertEquals("Focus must remain on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         // Launch activity on new secondary display.
         launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
         mAmWmState.assertFocusedActivity("Focus must be on secondary display",
                 TEST_ACTIVITY_NAME);
         final int externalFocusedStackId = mAmWmState.getAmState().getFocusedStackId();
-        assertTrue("Focused stack must be on secondary display",
-                FULLSCREEN_WORKSPACE_STACK_ID != externalFocusedStackId);
+        focusedStack = mAmWmState.getAmState().getStackById(externalFocusedStackId);
+        assertEquals("Focused stack must be on secondary display", newDisplay.mDisplayId,
+                focusedStack.mDisplayId);
 
         final String logSeparator = clearLogcat();
 
@@ -1052,15 +1088,9 @@
     public void testDisplayResize() throws Exception {
         if (!supportsMultiDisplay()) { return; }
 
-        // Start launching activity.
-        launchActivityInDockStack(LAUNCHING_ACTIVITY);
-
-        mAmWmState.waitForValidState(mDevice, LAUNCHING_ACTIVITY, DOCKED_STACK_ID);
         // Create new virtual display.
-        final DisplayState newDisplay =
-                new VirtualDisplayBuilder(this).setLaunchInSplitScreen(true).build();
+        final DisplayState newDisplay = new VirtualDisplayBuilder(this).build();
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true /* visible */);
 
         // Launch a resizeable activity on new secondary display.
         final String initialLogSeparator = clearLogcat();
@@ -1072,14 +1102,10 @@
         // Grab reported sizes and compute new with slight size change.
         final ReportedSizes initialSize = getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY_NAME,
                 initialLogSeparator);
-        final Rectangle initialBounds
-                = mAmWmState.getAmState().getStackById(DOCKED_STACK_ID).getBounds();
-        final Rectangle newBounds = new Rectangle(initialBounds.x, initialBounds.y,
-                initialBounds.width + SIZE_VALUE_SHIFT, initialBounds.height + SIZE_VALUE_SHIFT);
 
         // Resize the docked stack, so that activity with virtual display will also be resized.
         final String logSeparator = clearLogcat();
-        resizeDockedStack(newBounds.width, newBounds.height, newBounds.width, newBounds.height);
+        executeShellCommand(getResizeVirtualDisplayCommand());
 
         mAmWmState.waitForWithAmState(mDevice, amState -> {
             try {
@@ -1091,16 +1117,8 @@
             }
         }, "Wait for the configuration change to happen and for activity to be resumed.");
 
-        mAmWmState.computeState(mDevice, new String[] {RESIZEABLE_ACTIVITY_NAME, LAUNCHING_ACTIVITY,
+        mAmWmState.computeState(mDevice, new String[] {RESIZEABLE_ACTIVITY_NAME,
                 VIRTUAL_DISPLAY_ACTIVITY}, false /* compareTaskAndStackBounds */);
-        mAmWmState.assertDockedTaskBounds(newBounds.width, newBounds.height,
-                LAUNCHING_ACTIVITY);
-        mAmWmState.assertContainsStack("Must contain docked stack", DOCKED_STACK_ID);
-        mAmWmState.assertContainsStack("Must contain fullscreen stack",
-                FULLSCREEN_WORKSPACE_STACK_ID);
-        assertEquals(new Rectangle(0, 0, newBounds.width, newBounds.height),
-                mAmWmState.getAmState().getStackById(DOCKED_STACK_ID).getBounds());
-        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
         mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true);
         mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY_NAME, true);
 
@@ -1112,12 +1130,8 @@
                 logSeparator);
         assertTrue(updatedSize.widthDp <= initialSize.widthDp);
         assertTrue(updatedSize.heightDp <= initialSize.heightDp);
-        assertTrue(updatedSize.displayWidth <= initialSize.displayWidth);
-        assertTrue(updatedSize.displayHeight <= initialSize.displayHeight);
-        final boolean widthUpdated = updatedSize.metricsWidth < initialSize.metricsWidth;
-        final boolean heightUpdated = updatedSize.metricsHeight < initialSize.metricsHeight;
-        assertTrue("Either width or height must be updated after split-screen resize",
-                widthUpdated ^ heightUpdated);
+        assertTrue(updatedSize.displayWidth == initialSize.displayWidth / 2);
+        assertTrue(updatedSize.displayHeight == initialSize.displayHeight / 2);
     }
 
     /** Read the number of configuration changes sent to activity from logs. */
@@ -1174,7 +1188,7 @@
         // Check that task has moved from primary display to secondary.
         final int taskNumFinal = mAmWmState.getAmState().getStackById(defaultDisplayStackId)
                 .getTasks().size();
-        mAmWmState.assertEquals("Task number in fullscreen stack must be decremented.", taskNum - 1,
+        mAmWmState.assertEquals("Task number in default stack must be decremented.", taskNum - 1,
                 taskNumFinal);
         final int taskNumFinalOnSecondary = mAmWmState.getAmState().getStackById(frontStackId)
                 .getTasks().size();
@@ -1246,12 +1260,15 @@
                 null /* stackIds */, false /* compareTaskAndStackBounds */, componentName);
 
         // Check that second activity gets launched on the default display
-        final ActivityManagerState.ActivityStack fullscreenStack =
-                mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID);
+        final int defaultDisplayFrontStackId = mAmWmState.getAmState().getFrontStackId(
+                DEFAULT_DISPLAY_ID);
+        final ActivityManagerState.ActivityStack defaultDisplayFrontStack =
+                mAmWmState.getAmState().getStackById(defaultDisplayFrontStackId);
         assertEquals("Activity launched on default display must be resumed",
-                getActivityComponentName(ALT_LAUNCHING_ACTIVITY), fullscreenStack.mResumedActivity);
+                getActivityComponentName(ALT_LAUNCHING_ACTIVITY),
+                defaultDisplayFrontStack.mResumedActivity);
         mAmWmState.assertFocusedStack("Focus must be on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+                defaultDisplayFrontStackId);
 
         executeShellCommand("am start -n " + getActivityComponentName(LAUNCHING_ACTIVITY));
         mAmWmState.waitForFocusedStack(mDevice, frontStackId);
@@ -1293,13 +1310,14 @@
         mAmWmState.waitForValidState(mDevice, new String[] {TEST_ACTIVITY_NAME},
                 null /* stackIds */, false /* compareTaskAndStackBounds */, componentName);
 
-        // Check that the second activity is launched onto the fullscreen stack
-        final ActivityManagerState.ActivityStack fullscreenStack =
-                mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID);
+        // Check that the second activity is launched on the default display
+        final int focusedStackId = mAmWmState.getAmState().getFocusedStackId();
+        final ActivityManagerState.ActivityStack focusedStack
+                = mAmWmState.getAmState().getStackById(focusedStackId);
         assertEquals("Activity launched on default display must be resumed",
-                getActivityComponentName(TEST_ACTIVITY_NAME), fullscreenStack.mResumedActivity);
-        mAmWmState.assertFocusedStack("Focus must be on primary display",
-                FULLSCREEN_WORKSPACE_STACK_ID);
+                getActivityComponentName(TEST_ACTIVITY_NAME), focusedStack.mResumedActivity);
+        assertEquals("Focus must be on primary display", DEFAULT_DISPLAY_ID,
+                focusedStack.mDisplayId);
 
         executeShellCommand("am broadcast -a trigger_broadcast --ez launch_activity true "
                 + "--ez new_task true --es target_activity " + LAUNCHING_ACTIVITY);
@@ -1793,6 +1811,11 @@
                 " --es command destroy_display";
     }
 
+    private static String getResizeVirtualDisplayCommand() {
+        return getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY) + " -f 0x20000000" +
+                " --es command resize_display";
+    }
+
     /** Checks if the device supports multi-display. */
     private boolean supportsMultiDisplay() throws Exception {
         return hasDeviceFeature("android.software.activities_on_secondary_displays");
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
index d5ba74e..c7061d1 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -94,6 +94,33 @@
         mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
     }
 
+    public void testLaunchToSideMultiWindowCallbacks() throws Exception {
+        if (!supportsSplitScreenMultiWindow()) {
+            CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+            return;
+        }
+
+        // Launch two activities, one docked, one adjacent
+        launchActivityInDockStack(LAUNCHING_ACTIVITY);
+        mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
+        getLaunchActivityBuilder().setToSide(true).execute();
+        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
+        mAmWmState.assertContainsStack(
+                "Must contain fullscreen stack.", FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
+
+        // Remove the docked stack, and ensure that
+        final String logSeparator = clearLogcat();
+        removeStacks(DOCKED_STACK_ID);
+        final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(
+                TEST_ACTIVITY_NAME, logSeparator);
+        if (lifecycleCounts.mMultiWindowModeChangedCount != 1) {
+            fail(TEST_ACTIVITY_NAME + " has received "
+                    + lifecycleCounts.mMultiWindowModeChangedCount
+                    + " onMultiWindowModeChanged() calls, expecting 1");
+        }
+    }
+
     public void testLaunchToSideAndBringToFront() throws Exception {
         if (!supportsSplitScreenMultiWindow()) {
             CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 65f507e..dc94ba4 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -35,11 +35,13 @@
  */
 public class ActivityManagerPinnedStackTests extends ActivityManagerTestBase {
     private static final String TEST_ACTIVITY = "TestActivity";
+    private static final String TEST_ACTIVITY_WITH_SAME_AFFINITY = "TestActivityWithSameAffinity";
     private static final String TRANSLUCENT_TEST_ACTIVITY = "TranslucentTestActivity";
     private static final String NON_RESIZEABLE_ACTIVITY = "NonResizeableActivity";
     private static final String RESUME_WHILE_PAUSING_ACTIVITY = "ResumeWhilePausingActivity";
     private static final String PIP_ACTIVITY = "PipActivity";
     private static final String PIP_ACTIVITY2 = "PipActivity2";
+    private static final String PIP_ACTIVITY_WITH_SAME_AFFINITY = "PipActivityWithSameAffinity";
     private static final String ALWAYS_FOCUSABLE_PIP_ACTIVITY = "AlwaysFocusablePipActivity";
     private static final String LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY =
             "LaunchIntoPinnedStackPipActivity";
@@ -805,10 +807,10 @@
                     + " onStop() calls, expecting 1");
         } else if (lifecycleCounts.mPictureInPictureModeChangedCount != 1) {
             fail(PIP_ACTIVITY + " has received " + lifecycleCounts.mPictureInPictureModeChangedCount
-                    + " onMultiWindowModeChanged() calls, expecting 1");
+                    + " onPictureInPictureModeChanged() calls, expecting 1");
         } else if (lifecycleCounts.mMultiWindowModeChangedCount != 1) {
             fail(PIP_ACTIVITY + " has received " + lifecycleCounts.mMultiWindowModeChangedCount
-                    + " onPictureInPictureModeChanged() calls, expecting 1");
+                    + " onMultiWindowModeChanged() calls, expecting 1");
         } else {
             int lastStopLine = lifecycleCounts.mLastStopLineIndex;
             int lastPipLine = lifecycleCounts.mLastPictureInPictureModeChangedLineIndex;
@@ -914,6 +916,111 @@
         assertTrue(lifecycleCounts.mPauseCount == 0);
     }
 
+    public void testPinnedStackWithDockedStack() throws Exception {
+        if (!supportsPip() || !supportsSplitScreenMultiWindow()) return;
+
+        launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
+        launchActivityInDockStack(LAUNCHING_ACTIVITY);
+        launchActivityToSide(true, false, TEST_ACTIVITY);
+        mAmWmState.assertVisibility(PIP_ACTIVITY, true);
+        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
+        mAmWmState.assertVisibility(TEST_ACTIVITY, true);
+
+        // Launch the activities again to take focus and make sure nothing is hidden
+        launchActivityInDockStack(LAUNCHING_ACTIVITY);
+        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
+        mAmWmState.assertVisibility(TEST_ACTIVITY, true);
+
+        launchActivityToSide(true, false, TEST_ACTIVITY);
+        mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
+        mAmWmState.assertVisibility(TEST_ACTIVITY, true);
+
+        // Go to recents to make sure that fullscreen stack is invisible
+        // Some devices do not support recents or implement it differently (instead of using a
+        // separate stack id or as an activity), for those cases the visibility asserts will be
+        // ignored
+        pressAppSwitchButton();
+        if (mAmWmState.waitForRecentsActivityVisible(mDevice)) {
+            mAmWmState.assertVisibility(LAUNCHING_ACTIVITY, true);
+            mAmWmState.assertVisibility(TEST_ACTIVITY, false);
+        }
+    }
+
+    public void testLaunchTaskByComponentMatchMultipleTasks() throws Exception {
+        if (!supportsPip()) return;
+
+        // Launch a fullscreen activity which will launch a PiP activity in a new task with the same
+        // affinity
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
+        launchActivityInStack(PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
+        assertPinnedStackExists();
+
+        // Launch the root activity again...
+        int rootActivityTaskId = mAmWmState.getAmState().getTaskByActivityName(
+                TEST_ACTIVITY_WITH_SAME_AFFINITY).mTaskId;
+        launchHomeActivity();
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
+
+        // ...and ensure that the root activity task is found and reused, and that the pinned stack
+        // is unaffected
+        assertPinnedStackExists();
+        mAmWmState.assertFocusedActivity("Expected root activity focused",
+                TEST_ACTIVITY_WITH_SAME_AFFINITY);
+        assertTrue(rootActivityTaskId == mAmWmState.getAmState().getTaskByActivityName(
+                TEST_ACTIVITY_WITH_SAME_AFFINITY).mTaskId);
+    }
+
+    public void testLaunchTaskByAffinityMatchMultipleTasks() throws Exception {
+        if (!supportsPip()) return;
+
+        // Launch a fullscreen activity which will launch a PiP activity in a new task with the same
+        // affinity, and also launch another activity in the same task, while finishing itself. As
+        // a result, the task will not have a component matching the same activity as what it was
+        // started with
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY,
+                EXTRA_START_ACTIVITY, getActivityComponentName(TEST_ACTIVITY),
+                EXTRA_FINISH_SELF_ON_RESUME, "true");
+        mAmWmState.waitForValidState(mDevice, TEST_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
+        launchActivityInStack(PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
+        mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
+        assertPinnedStackExists();
+
+        // Launch the root activity again...
+        int rootActivityTaskId = mAmWmState.getAmState().getTaskByActivityName(
+                TEST_ACTIVITY).mTaskId;
+        launchHomeActivity();
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
+
+        // ...and ensure that even while matching purely by task affinity, the root activity task is
+        // found and reused, and that the pinned stack is unaffected
+        assertPinnedStackExists();
+        mAmWmState.assertFocusedActivity("Expected root activity focused", TEST_ACTIVITY);
+        assertTrue(rootActivityTaskId == mAmWmState.getAmState().getTaskByActivityName(
+                TEST_ACTIVITY).mTaskId);
+    }
+
+    public void testLaunchTaskByAffinityMatchSingleTask() throws Exception {
+        if (!supportsPip()) return;
+
+        // Launch an activity into the pinned stack with a fixed affinity
+        launchActivityInStack(TEST_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID,
+                EXTRA_START_ACTIVITY, getActivityComponentName(PIP_ACTIVITY),
+                EXTRA_FINISH_SELF_ON_RESUME, "true");
+        mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY, PINNED_STACK_ID);
+        assertPinnedStackExists();
+
+        // Launch the root activity again, of the matching task and ensure that we expand to
+        // fullscreen
+        int activityTaskId = mAmWmState.getAmState().getTaskByActivityName(
+                PIP_ACTIVITY).mTaskId;
+        launchHomeActivity();
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY);
+        mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
+        assertPinnedStackDoesNotExist();
+        assertTrue(activityTaskId == mAmWmState.getAmState().getTaskByActivityName(
+                PIP_ACTIVITY).mTaskId);
+    }
+
     /**
      * Called after the given {@param activityName} has been moved to the fullscreen stack. Ensures
      * that the {@param focusedStackId} is focused, and checks the top and/or bottom tasks in the
@@ -1014,10 +1121,10 @@
                     + " onConfigurationChanged() calls, expecting 1");
         } else if (lifecycleCounts.mPictureInPictureModeChangedCount != 1) {
             fail(activityName + " has received " + lifecycleCounts.mPictureInPictureModeChangedCount
-                    + " onMultiWindowModeChanged() calls, expecting 1");
+                    + " onPictureInPictureModeChanged() calls, expecting 1");
         } else if (lifecycleCounts.mMultiWindowModeChangedCount != 1) {
             fail(activityName + " has received " + lifecycleCounts.mMultiWindowModeChangedCount
-                    + " onPictureInPictureModeChanged() calls, expecting 1");
+                    + " onMultiWindowModeChanged() calls, expecting 1");
         } else {
             int lastPipLine = lifecycleCounts.mLastPictureInPictureModeChangedLineIndex;
             int lastMwLine = lifecycleCounts.mLastMultiWindowModeChangedLineIndex;
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java
index 9f4cf6c..b73cf1e 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java
@@ -214,6 +214,13 @@
                 "***Waiting for home activity to be visible...");
     }
 
+    /** @return true if recents activity is visible. Devices without recents will return false */
+    boolean waitForRecentsActivityVisible(ITestDevice device) throws Exception {
+        waitForWithAmState(device, ActivityManagerState::isRecentsActivityVisible,
+                "***Waiting for recents activity to be visible...");
+        return mAmState.isRecentsActivityVisible();
+    }
+
     void waitForKeyguardShowingAndNotOccluded(ITestDevice device) throws Exception {
         waitForWithAmState(device, state -> state.getKeyguardControllerState().keyguardShowing
                         && !state.getKeyguardControllerState().keyguardOccluded,
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
index 56fed31..cacfe23 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
@@ -34,6 +34,7 @@
 import java.util.regex.Matcher;
 
 import static android.server.cts.ActivityManagerTestBase.HOME_STACK_ID;
+import static android.server.cts.ActivityManagerTestBase.RECENTS_STACK_ID;
 import static android.server.cts.StateLogger.log;
 import static android.server.cts.StateLogger.logE;
 
@@ -309,6 +310,11 @@
         return homeActivity != null && homeActivity.visible;
     }
 
+    boolean isRecentsActivityVisible() {
+        final Activity recentsActivity = getRecentsActivity();
+        return recentsActivity != null && recentsActivity.visible;
+    }
+
     String getHomeActivityName() {
         Activity activity = getHomeActivity();
         if (activity == null) {
@@ -330,11 +336,30 @@
         return null;
     }
 
+    ActivityTask getRecentsTask() {
+        ActivityStack recentsStack = getStackById(RECENTS_STACK_ID);
+        if (recentsStack != null) {
+            for (ActivityTask task : recentsStack.mTasks) {
+                if (task.mTaskType == RECENTS_ACTIVITY_TYPE) {
+                    return task;
+                }
+            }
+            return null;
+        }
+        return null;
+    }
+
     private Activity getHomeActivity() {
         final ActivityTask homeTask = getHomeTask();
         return homeTask != null ? homeTask.mActivities.get(homeTask.mActivities.size() - 1) : null;
     }
 
+    private Activity getRecentsActivity() {
+        final ActivityTask recentsTask = getRecentsTask();
+        return recentsTask != null ? recentsTask.mActivities.get(recentsTask.mActivities.size() - 1)
+                : null;
+    }
+
     ActivityTask getTaskByActivityName(String activityName) {
         return getTaskByActivityName(activityName, -1);
     }
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
index 5e34c4b..3eebff9 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
@@ -29,9 +29,9 @@
 import org.mockito.MockitoAnnotations;
 
 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
+
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
@@ -76,20 +76,9 @@
     }
 
     @Test
-    public void testGetFingerprintManager_returnsManagerIfFeatureAvailable() {
-        if (!mIsHardwareAvailable) {
-            assertNull(mFingerprintGestureController);
-            return;
-        }
-        assertNotNull(mFingerprintGestureController);
-    }
-
-    @Test
     public void testGestureDetectionAvailable_initialState_shouldBeAvailable() {
-        if (!mIsHardwareAvailable) {
-            return;
-        }
-        assertTrue(mFingerprintGestureController.isGestureDetectionAvailable());
+        assertEquals(mIsHardwareAvailable,
+                mFingerprintGestureController.isGestureDetectionAvailable());
     }
 
     @Test
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
index 53eec5f..6bc2969 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
@@ -3928,6 +3928,10 @@
 
         // Set selection at the end.
         final int textLength = editText.getText().length();
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, textLength);
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, textLength);
+        assertTrue(text.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
+
         // Verify the selection position.
         assertEquals(textLength, Selection.getSelectionStart(editText.getText()));
         assertEquals(textLength, Selection.getSelectionEnd(editText.getText()));
diff --git a/tests/app/app/Android.mk b/tests/app/app/Android.mk
index 2e4bdf0..3c0a0c5 100644
--- a/tests/app/app/Android.mk
+++ b/tests/app/app/Android.mk
@@ -30,6 +30,7 @@
     ctstestrunner \
     ctstestserver \
     mockito-target-minus-junit4 \
+    android-support-v4 \
     legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
diff --git a/tests/app/src/android/app/cts/AlertWindowsTests.java b/tests/app/src/android/app/cts/AlertWindowsTests.java
index bd97727..e31c53b 100644
--- a/tests/app/src/android/app/cts/AlertWindowsTests.java
+++ b/tests/app/src/android/app/cts/AlertWindowsTests.java
@@ -131,38 +131,36 @@
     public void testAlertWindowOomAdj() throws Exception {
         setAlertWindowPermission(true /* allow */);
 
+
         assertPackageImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_PRE_26);
-        assertUidImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_PRE_26);
+
+        // TODO AM.getUidImportance() sometimes return a different value from what
+        // getPackageImportance() returns... b/37950472
+        // assertUidImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_PRE_26);
 
         addAlertWindow();
         // Process importance should be increased to visible when the service has an alert window.
         assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
-        assertUidImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
 
         addAlertWindow();
         assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
-        assertUidImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
 
         setAlertWindowPermission(false /* allow */);
         // Process importance should no longer be visible since its alert windows are not allowed to
         // be visible.
         assertPackageImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_PRE_26);
-        assertUidImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_PRE_26);
 
         setAlertWindowPermission(true /* allow */);
         // They can show again so importance should be visible again.
         assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
-        assertUidImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
 
         removeAlertWindow();
         assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
-        assertUidImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
 
         removeAlertWindow();
         // Process importance should no longer be visible when the service no longer as alert
         // windows.
         assertPackageImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_PRE_26);
-        assertUidImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_PRE_26);
     }
 
     private void addAlertWindow() throws Exception {
diff --git a/tests/autofillservice/Android.mk b/tests/autofillservice/Android.mk
index 37605af..f4437f7 100644
--- a/tests/autofillservice/Android.mk
+++ b/tests/autofillservice/Android.mk
@@ -16,8 +16,12 @@
 
 include $(CLEAR_VARS)
 
+# Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
 LOCAL_STATIC_JAVA_LIBRARIES := \
     compatibility-device-util \
     ctstestrunner \
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
index 32bf5a5..b762071 100644
--- a/tests/autofillservice/AndroidManifest.xml
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -39,7 +39,14 @@
         <activity android:name=".TimePickerClockActivity" />
         <activity android:name=".TimePickerSpinnerActivity" />
         <activity android:name=".FatActivity" />
-        <activity android:name=".VirtualContainerActivity" />
+        <activity android:name=".VirtualContainerActivity">
+            <intent-filter>
+                <!-- This intent filter is not really needed by CTS, but it maks easier to launch
+                     this app during CTS development... -->
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
         <activity android:name=".OptionalSaveActivity" />
         <activity android:name=".AllAutofillableViewsActivity" />
         <activity android:name=".GridActivity" >
diff --git a/tests/autofillservice/res/layout/login_activity.xml b/tests/autofillservice/res/layout/login_activity.xml
index 96caa46..e16d1c4 100644
--- a/tests/autofillservice/res/layout/login_activity.xml
+++ b/tests/autofillservice/res/layout/login_activity.xml
@@ -88,6 +88,12 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Login" />
+
+        <Button
+            android:id="@+id/cancel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Cancel" />
     </LinearLayout>
 
     <TextView
diff --git a/tests/autofillservice/res/layout/pre_filled_login_activity.xml b/tests/autofillservice/res/layout/pre_filled_login_activity.xml
index 3a32928..77d94dc 100644
--- a/tests/autofillservice/res/layout/pre_filled_login_activity.xml
+++ b/tests/autofillservice/res/layout/pre_filled_login_activity.xml
@@ -90,6 +90,12 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="Login" />
+
+        <Button
+            android:id="@+id/cancel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Cancel" />
     </LinearLayout>
 
     <TextView
diff --git a/tests/autofillservice/res/layout/view_attribute_test_activity.xml b/tests/autofillservice/res/layout/view_attribute_test_activity.xml
index 96c0186..d03d65c 100644
--- a/tests/autofillservice/res/layout/view_attribute_test_activity.xml
+++ b/tests/autofillservice/res/layout/view_attribute_test_activity.xml
@@ -16,17 +16,77 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent" android:layout_height="match_parent"
-    android:orientation="vertical" android:id="@+id/rootContainer">
-
-    <TextView android:id="@+id/textViewNoHint" android:layout_width="wrap_content"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:id="@+id/rootContainer">
+    <EditText android:id="@+id/editTextNoHint"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content" />
-    <TextView android:id="@+id/textViewHintCustom" android:layout_width="wrap_content"
-        android:layout_height="wrap_content" android:autofillHints="@string/new_password_label" />
-    <TextView android:id="@+id/textViewPassword" android:layout_width="wrap_content"
-        android:layout_height="wrap_content" android:autofillHints="password" />
-    <TextView android:id="@+id/textViewPhoneName" android:layout_width="wrap_content"
-        android:layout_height="wrap_content" android:autofillHints=" phone, username     " />
-    <TextView android:id="@+id/textViewHintsFromArray" android:layout_width="wrap_content"
-        android:layout_height="wrap_content" android:autofillHints="@array/cc_expiration_values" />
+
+    <EditText android:id="@+id/editTextHintCustom"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:autofillHints="@string/new_password_label" />
+
+    <EditText android:id="@+id/editTextPassword"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:autofillHints="password" />
+
+    <EditText android:id="@+id/editTextPhoneName"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:autofillHints=" phone, username     " />
+
+    <EditText android:id="@+id/editTextHintsFromArray"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:autofillHints="@array/cc_expiration_values" />
+
+    <!-- Use px instead of dp to not have to deal with screen resolution -->
+    <LinearLayout android:id="@+id/outerView"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:paddingTop="2px"
+        android:paddingBottom="5px"
+        android:paddingLeft="7px"
+        android:paddingRight="3px"
+        android:orientation="vertical"
+        android:background="#F00"
+        android:importantForAutofill="yes">
+        <LinearLayout android:id="@+id/nestedView"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:paddingTop="11px"
+            android:paddingBottom="17px"
+            android:paddingLeft="19px"
+            android:paddingRight="13px"
+            android:orientation="vertical"
+            android:background="#0F0"
+            android:importantForAutofill="no">
+            <LinearLayout android:id="@+id/doubleNestedView"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:paddingTop="23px"
+                android:paddingBottom="31px"
+                android:paddingLeft="37px"
+                android:paddingRight="29px"
+                android:orientation="vertical"
+                android:background="#00F"
+                android:importantForAutofill="yes">
+                <EditText android:id="@+id/tripleNestedView"
+                    android:layout_height="41px"
+                    android:layout_width="43px"
+                    android:background="#FF0"
+                    android:importantForAutofill="yes" />
+            </LinearLayout>
+
+            <EditText android:id="@+id/secondDoubleNestedView"
+                android:layout_height="47px"
+                android:layout_width="53px"
+                android:background="#F0F"
+                android:importantForAutofill="yes" />
+        </LinearLayout>
+    </LinearLayout>
 </LinearLayout>
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
index d1595ee..3956187 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
@@ -16,32 +16,74 @@
 
 package android.autofillservice.cts;
 
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.app.PendingIntent;
 import android.app.assist.AssistStructure;
+import android.autofillservice.cts.CannedFillResponse.CannedDataset;
+import android.content.Context;
 import android.content.Intent;
+import android.content.IntentSender;
 import android.os.Bundle;
 import android.os.Parcelable;
+import android.util.SparseArray;
 import android.view.autofill.AutofillManager;
 
-import static com.google.common.truth.Truth.assertWithMessage;
+import com.google.common.base.Preconditions;
 
 /**
  * This class simulates authentication at the dataset at reponse level
  */
 public class AuthenticationActivity extends AbstractAutoFillActivity {
+
+    private static final String EXTRA_DATASET_ID = "dataset_id";
+
     private static CannedFillResponse sResponse;
     private static CannedFillResponse.CannedDataset sDataset;
     private static Bundle sData;
+    private static final SparseArray<CannedDataset> sDatasets = new SparseArray<>();
+
+    static void resetStaticState() {
+        sDatasets.clear();
+    }
 
     public static void setResponse(CannedFillResponse response) {
         sResponse = response;
         sDataset = null;
     }
 
-    public static void setDataset(CannedFillResponse.CannedDataset dataset) {
+    /**
+     * @deprecated should use {@link #createSender(Context, int, CannedDataset)} instead.
+     */
+    @Deprecated
+    public static void setDataset(CannedDataset dataset) {
         sDataset = dataset;
         sResponse = null;
     }
 
+    /**
+     * Creates an {@link IntentSender} with the given unique id for the given dataset.
+     */
+    public static IntentSender createSender(Context context, int id,
+            CannedDataset dataset) {
+        Preconditions.checkArgument(id > 0, "id must be positive");
+        Preconditions.checkState(sDatasets.get(id) == null, "already have id");
+        sDatasets.put(id, dataset);
+        final Intent intent = new Intent(context, AuthenticationActivity.class);
+        intent.putExtra(EXTRA_DATASET_ID, id);
+        return PendingIntent.getActivity(context, id, intent, 0).getIntentSender();
+    }
+
+    /**
+     * Creates an {@link IntentSender} with the given unique id.
+     */
+    public static IntentSender createSender(Context context, int id) {
+        Preconditions.checkArgument(id > 0, "id must be positive");
+        return PendingIntent
+                .getActivity(context, id, new Intent(context, AuthenticationActivity.class), 0)
+                .getIntentSender();
+    }
+
     public static Bundle getData() {
         final Bundle data = sData;
         sData = null;
@@ -59,9 +101,13 @@
 
         // and the bundle
         sData = getIntent().getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE);
+        final CannedDataset dataset = sDatasets.get(getIntent().getIntExtra(EXTRA_DATASET_ID, 0));
 
         final Parcelable result;
-        if (sResponse != null) {
+
+        if (dataset != null) {
+            result = dataset.asDataset((id) -> Helper.findNodeByResourceId(structure, id));
+        } else if (sResponse != null) {
             result = sResponse.asFillResponse((id) -> Helper.findNodeByResourceId(structure, id));
         } else if (sDataset != null) {
             result = sDataset.asDataset((id) -> Helper.findNodeByResourceId(structure, id));
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index d18e621..a519e04 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -60,13 +60,18 @@
 
     @BeforeClass
     public static void setUiBot() throws Exception {
-        sUiBot = new UiBot(InstrumentationRegistry.getInstrumentation(), UI_TIMEOUT_MS);
+        sUiBot = new UiBot(InstrumentationRegistry.getInstrumentation());
     }
 
     @BeforeClass
     @AfterClass
     public static void disableService() {
+        if (!isServiceEnabled()) return;
+
+        final OneTimeSettingsListener observer = new OneTimeSettingsListener(getContext(),
+                AUTOFILL_SERVICE);
         runShellCommand("settings delete secure %s", AUTOFILL_SERVICE);
+        observer.assertCalled();
         assertServiceDisabled();
     }
 
@@ -75,6 +80,7 @@
         destroyAllSessions();
         sReplier.reset();
         InstrumentedAutoFillService.resetStaticState();
+        AuthenticationActivity.resetStaticState();
     }
 
     @After
@@ -84,11 +90,15 @@
     }
 
     /**
-     * Enables the {@link InstrumentedAutoFillService} for auto-fill for the default user.
+     * Enables the {@link InstrumentedAutoFillService} for autofill for the current user.
      */
     protected void enableService() {
-        runShellCommand(
-                "settings put secure %s %s default", AUTOFILL_SERVICE, SERVICE_NAME);
+        if (isServiceEnabled()) return;
+
+        final OneTimeSettingsListener observer = new OneTimeSettingsListener(getContext(),
+                AUTOFILL_SERVICE);
+        runShellCommand("settings put secure %s %s default", AUTOFILL_SERVICE, SERVICE_NAME);
+        observer.assertCalled();
         assertServiceEnabled();
     }
 
@@ -134,6 +144,11 @@
         return presentation;
     }
 
+    private static boolean isServiceEnabled() {
+        final String service = runShellCommand("settings get secure %s", AUTOFILL_SERVICE);
+        return SERVICE_NAME.equals(service);
+    }
+
     private static void assertServiceStatus(boolean enabled) {
         final String actual = runShellCommand("settings get secure %s", AUTOFILL_SERVICE);
         final String expected = enabled ? SERVICE_NAME : "null";
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index 9f5368f..7d2f7e2 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -17,8 +17,6 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
-import static android.autofillservice.cts.Helper.dumpStructure;
-import static android.autofillservice.cts.Helper.findNodeByResourceId;
 import static android.autofillservice.cts.Helper.getAutofillIds;
 import android.app.assist.AssistStructure;
 import android.app.assist.AssistStructure.ViewNode;
@@ -26,7 +24,6 @@
 import android.os.Bundle;
 import android.service.autofill.Dataset;
 import android.service.autofill.FillCallback;
-import android.service.autofill.FillContext;
 import android.service.autofill.FillResponse;
 import android.service.autofill.SaveInfo;
 import android.view.autofill.AutofillId;
@@ -124,10 +121,12 @@
         if (mIgnoredIds != null) {
             builder.setIgnoredIds(getAutofillIds(nodeResolver, mIgnoredIds));
         }
+        if (mAuthenticationIds != null) {
+            builder.setAuthentication(getAutofillIds(nodeResolver, mAuthenticationIds),
+                    mAuthentication, mPresentation);
+        }
         return builder
                 .setClientState(mExtras)
-                .setAuthentication(getAutofillIds(nodeResolver, mAuthenticationIds),
-                        mAuthentication, mPresentation)
                 .build();
     }
 
@@ -215,16 +214,9 @@
         /**
          * Sets the authentication intent.
          */
-        public Builder setAuthentication(IntentSender authentication) {
-            mAuthentication = authentication;
-            return this;
-        }
-
-        /**
-         * Sets the authentication ids.
-         */
-        public Builder setAuthenticationIds(String... ids) {
+        public Builder setAuthentication(IntentSender authentication, String... ids) {
             mAuthenticationIds = ids;
+            mAuthentication = authentication;
             return this;
         }
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CheckoutActivity.java b/tests/autofillservice/src/android/autofillservice/cts/CheckoutActivity.java
index b04b45f..0b8d938 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CheckoutActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CheckoutActivity.java
@@ -28,7 +28,6 @@
 import android.widget.RadioButton;
 import android.widget.RadioGroup;
 import android.widget.Spinner;
-import android.widget.SpinnerAdapter;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index f1491b4..7b2e7a5 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -16,34 +16,26 @@
 
 package android.autofillservice.cts;
 
-import static android.autofillservice.cts.Helper.dumpStructure;
-
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.app.assist.AssistStructure;
 import android.app.assist.AssistStructure.ViewNode;
 import android.app.assist.AssistStructure.WindowNode;
 import android.icu.util.Calendar;
-import android.os.Bundle;
 import android.os.UserManager;
-import android.service.autofill.Dataset;
 import android.service.autofill.FillContext;
-import android.service.autofill.FillResponse;
 import android.support.annotation.NonNull;
 import android.support.test.InstrumentationRegistry;
 import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.util.Log;
-import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillValue;
 import android.view.View;
 import android.view.ViewStructure.HtmlInfo;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
 
 import com.android.compatibility.common.util.SystemUtil;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.function.Function;
 
 /**
@@ -89,6 +81,11 @@
     static final long SAVE_TIMEOUT_MS = 5000;
 
     /**
+     * Time to wait if a UI change is not expected
+     */
+    static final long NOT_SHOWING_TIMEOUT_MS = 500;
+
+    /**
      * Timeout (in milliseconds) for UI operations. Typically used by {@link UiBot}.
      */
     static final int UI_TIMEOUT_MS = 2000;
@@ -239,7 +236,7 @@
     /**
      * Gets a node given its Android resource id, or {@code null} if not found.
      */
-    static ViewNode findNodeByResourceId(ArrayList<FillContext> contexts, String resourceId) {
+    static ViewNode findNodeByResourceId(List<FillContext> contexts, String resourceId) {
         for (FillContext context : contexts) {
             ViewNode node = findNodeByResourceId(context.getStructure(), resourceId);
             if (node != null) {
@@ -311,14 +308,17 @@
       final CharSequence text = node.getText();
       final String resourceId = node.getIdEntry();
       if (!TextUtils.isEmpty(text)) {
-        throw new AssertionError("text on sanitized field " + resourceId + ": " + text);
+          throw new AssertionError("text on sanitized field " + resourceId + ": " + text);
       }
       assertNodeHasNoAutofillValue(node);
     }
 
     static void assertNodeHasNoAutofillValue(ViewNode node) {
         final AutofillValue value = node.getAutofillValue();
-        assertWithMessage("node.getAutofillValue()").that(value).isNull();
+        if (value != null) {
+            final String text = value.isText() ? value.getTextValue().toString() : "N/A";
+            throw new AssertionError("node has value: " + value + " text=" + text);
+        }
     }
 
     /**
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index 61b47af..bfe438a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -38,7 +38,6 @@
 import android.service.autofill.SaveCallback;
 import android.util.Log;
 
-import java.util.ArrayList;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -149,13 +148,13 @@
      */
     static final class FillRequest {
         final AssistStructure structure;
-        final ArrayList<FillContext> contexts;
+        final List<FillContext> contexts;
         final Bundle data;
         final CancellationSignal cancellationSignal;
         final FillCallback callback;
         final int flags;
 
-        private FillRequest(ArrayList<FillContext> contexts, Bundle data,
+        private FillRequest(List<FillContext> contexts, Bundle data,
                 CancellationSignal cancellationSignal, FillCallback callback, int flags) {
             this.contexts = contexts;
             this.data = data;
@@ -282,7 +281,7 @@
             mSaveRequests.clear();
         }
 
-        private void onFillRequest(ArrayList<FillContext> contexts, Bundle data,
+        private void onFillRequest(List<FillContext> contexts, Bundle data,
                 CancellationSignal cancellationSignal, FillCallback callback, int flags) {
             try {
                 CannedFillResponse response = null;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivity.java
index 48efb32..d05728f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivity.java
@@ -58,6 +58,7 @@
     private TextView mOutput;
     private Button mLoginButton;
     private Button mSaveButton;
+    private Button mCancelButton;
     private Button mClearButton;
     private FillExpectation mExpectation;
 
@@ -81,6 +82,7 @@
         mLoginButton = (Button) findViewById(R.id.login);
         mSaveButton = (Button) findViewById(R.id.save);
         mClearButton = (Button) findViewById(R.id.clear);
+        mCancelButton = (Button) findViewById(R.id.cancel);
         mUsernameLabel = (TextView) findViewById(R.id.username_label);
         mUsernameEditText = (EditText) findViewById(R.id.username);
         mPasswordLabel = (TextView) findViewById(R.id.password_label);
@@ -108,6 +110,7 @@
                 getAutofillManager().cancel();
             }
         });
+        mCancelButton.setOnClickListener((OnClickListener) v -> finish());
     }
 
     protected int getContentView() {
@@ -156,7 +159,7 @@
     }
 
     /**
-     * Sets the expectation for an auto-fill request, so it can be asserted through
+     * Sets the expectation for an autofill request (for all fields), so it can be asserted through
      * {@link #assertAutoFilled()} later.
      */
     void expectAutoFill(String username, String password) {
@@ -166,13 +169,24 @@
     }
 
     /**
+     * Sets the expectation for an autofill request (for username only), so it can be asserted
+     * through {@link #assertAutoFilled()} later.
+     */
+    void expectAutoFill(String username) {
+        mExpectation = new FillExpectation(username);
+        mUsernameEditText.addTextChangedListener(mExpectation.ccUsernameWatcher);
+    }
+
+    /**
      * Asserts the activity was auto-filled with the values passed to
      * {@link #expectAutoFill(String, String)}.
      */
     void assertAutoFilled() throws Exception {
         assertWithMessage("expectAutoFill() not called").that(mExpectation).isNotNull();
         mExpectation.ccUsernameWatcher.assertAutoFilled();
-        mExpectation.ccPasswordWatcher.assertAutoFilled();
+        if (mExpectation.ccPasswordWatcher != null) {
+            mExpectation.ccPasswordWatcher.assertAutoFilled();
+        }
     }
 
     /**
@@ -278,5 +292,10 @@
             ccUsernameWatcher = new OneTimeTextWatcher("username", mUsernameEditText, username);
             ccPasswordWatcher = new OneTimeTextWatcher("password", mPasswordEditText, password);
         }
+
+        private FillExpectation(String username) {
+            ccUsernameWatcher = new OneTimeTextWatcher("username", mUsernameEditText, username);
+            ccPasswordWatcher = null;
+        }
     }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 8ce9596..b2b5d40 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -23,6 +23,7 @@
 import static android.autofillservice.cts.Helper.assertNumberOfChildren;
 import static android.autofillservice.cts.Helper.assertTextAndValue;
 import static android.autofillservice.cts.Helper.assertTextIsSanitized;
+import static android.autofillservice.cts.Helper.assertValue;
 import static android.autofillservice.cts.Helper.eventually;
 import static android.autofillservice.cts.Helper.findNodeByResourceId;
 import static android.autofillservice.cts.Helper.runShellCommand;
@@ -45,6 +46,7 @@
 import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_USERNAME;
 import static android.text.InputType.TYPE_NULL;
 import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
+import static android.view.View.IMPORTANT_FOR_AUTOFILL_NO;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -87,9 +89,6 @@
  */
 public class LoginActivityTest extends AutoFillServiceTestCase {
 
-    // TODO(b/37424539): remove when fixed
-    private static final boolean SUPPORTS_PARTITIONED_AUTH = false;
-
     @Rule
     public final ActivityTestRule<LoginActivity> mActivityRule = new ActivityTestRule<LoginActivity>(
             LoginActivity.class);
@@ -168,6 +167,100 @@
     }
 
     @Test
+    public void testAutoFillTwoDatasetsSameNumberOfFields() throws Exception {
+        // Set service.
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("The Dude"))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "DUDE")
+                        .setField(ID_PASSWORD, "SWEET")
+                        .setPresentation(createPresentation("THE DUDE"))
+                        .build())
+                .build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        mActivity.onUsername(View::requestFocus);
+        sReplier.getNextFillRequest();
+
+        // Make sure all datasets are available...
+        sUiBot.assertDatasets("The Dude", "THE DUDE");
+
+        // ... on all fields.
+        mActivity.onPassword(View::requestFocus);
+        sUiBot.assertDatasets("The Dude", "THE DUDE");
+
+        // Auto-fill it.
+        sUiBot.selectDataset("The Dude");
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testAutoFillTwoDatasetsUnevenNumberOfFieldsFillsAll() throws Exception {
+        autoFillTwoDatasetsUnevenNumberOfFieldsTest(true);
+    }
+
+    @Test
+    public void testAutoFillTwoDatasetsUnevenNumberOfFieldsFillsOne() throws Exception {
+        autoFillTwoDatasetsUnevenNumberOfFieldsTest(false);
+    }
+
+    private void autoFillTwoDatasetsUnevenNumberOfFieldsTest(boolean fillsAll) throws Exception {
+        // Set service.
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("The Dude"))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "DUDE")
+                        .setPresentation(createPresentation("THE DUDE"))
+                        .build())
+                .build());
+        if (fillsAll) {
+            mActivity.expectAutoFill("dude", "sweet");
+        } else {
+            mActivity.expectAutoFill("DUDE");
+        }
+
+        // Trigger auto-fill.
+        mActivity.onUsername(View::requestFocus);
+        sReplier.getNextFillRequest();
+
+        // Make sure all datasets are available on username...
+        sUiBot.assertDatasets("The Dude", "THE DUDE");
+
+        // ... but just one for password
+        mActivity.onPassword(View::requestFocus);
+        sUiBot.assertDatasets("The Dude");
+
+        // Auto-fill it.
+        mActivity.onUsername(View::requestFocus);
+        sUiBot.assertDatasets("The Dude", "THE DUDE");
+        if (fillsAll) {
+            sUiBot.selectDataset("The Dude");
+        } else {
+            sUiBot.selectDataset("THE DUDE");
+        }
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
     public void testAutoFillWhenViewHasChildAccessibilityNodes() throws Exception {
         mActivity.onUsername((v) -> v.setAccessibilityDelegate(new AccessibilityDelegate() {
             @Override
@@ -358,6 +451,10 @@
 
         // Trigger auto-fill.
         mActivity.onUsername(View::requestFocus);
+
+        // Since this is a Presubmit test, wait for connection to avoid flakiness.
+        waitUntilConnected();
+
         sReplier.getNextFillRequest();
 
         // Auto-fill it.
@@ -955,7 +1052,7 @@
 
         // Configure the service behavior
         sReplier.addResponse(new CannedFillResponse.Builder()
-                .setAuthentication(authentication)
+                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
                 .setPresentation(createPresentation("Tap to auth response"))
                 .setExtras(extras)
                 .build());
@@ -1019,7 +1116,6 @@
                                 .setField(ID_PASSWORD, "sweet")
                                 .setPresentation(createPresentation("Dataset"))
                                 .build())
-                        .setAuthenticationIds(ID_USERNAME)
                         .build());
 
         // Create the authentication intent
@@ -1028,7 +1124,8 @@
 
         // Configure the service behavior
         sReplier.addResponse(new CannedFillResponse.Builder()
-                .setAuthentication(authentication)
+                .setAuthentication(authentication, ID_USERNAME)
+                .setIgnoreFields(ID_PASSWORD)
                 .setPresentation(createPresentation("Tap to auth response"))
                 .setExtras(extras)
                 .build());
@@ -1045,29 +1142,13 @@
         callback.assertUiShownEvent(username);
         sUiBot.assertShownByText("Tap to auth response");
 
-        if (SUPPORTS_PARTITIONED_AUTH) {
-            // Make sure UI is not show on 2nd field
-            final View password = mActivity.getPassword();
-            mActivity.onPassword(View::requestFocus);
-            callback.assertUiHiddenEvent(username);
-            sUiBot.assertNotShownByText("Tap to auth response");
-            // Now tap on 1st field to show it again...
-            mActivity.onUsername(View::requestFocus);
-            callback.assertUiShownEvent(username);
-        } else {
-            // Make sure UI is show on 2nd field as well
-            final View password = mActivity.getPassword();
-            mActivity.onPassword(View::requestFocus);
-
-            callback.assertUiHiddenEvent(username);
-            callback.assertUiShownEvent(password);
-            sUiBot.assertShownByText("Tap to auth response");
-
-            // Now tap on 1st field to show it again...
-            mActivity.onUsername(View::requestFocus);
-            callback.assertUiHiddenEvent(password);
-            callback.assertUiShownEvent(username);
-        }
+        // Make sure UI is not show on 2nd field
+        mActivity.onPassword(View::requestFocus);
+        callback.assertUiHiddenEvent(username);
+        sUiBot.assertNotShownByText("Tap to auth response");
+        // Now tap on 1st field to show it again...
+        mActivity.onUsername(View::requestFocus);
+        callback.assertUiShownEvent(username);
 
         // ...and select it this time
         sUiBot.selectByText("Tap to auth response");
@@ -1082,7 +1163,6 @@
 
         // Check the results.
         mActivity.assertAutoFilled();
-
         final Bundle data = AuthenticationActivity.getData();
         assertThat(data).isNotNull();
         final String extraValue = data.getString("numbers");
@@ -1090,7 +1170,44 @@
     }
 
     @Test
-    public void testDatasetAuth() throws Exception {
+    public void testFillResponseAuthServiceHasNoData() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        AuthenticationActivity.setResponse(
+                new CannedFillResponse.Builder()
+                        .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
+                        .build());
+
+        // Create the authentication intent
+        final IntentSender authentication = PendingIntent.getActivity(getContext(), 0,
+                new Intent(getContext(), AuthenticationActivity.class), 0).getIntentSender();
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
+                .setPresentation(createPresentation("Tap to auth response"))
+                .build());
+
+        // Trigger auto-fill.
+        mActivity.onUsername(View::requestFocus);
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+        callback.assertUiShownEvent(username);
+
+        // Select the authentication dialog.
+        sUiBot.selectByText("Tap to auth response");
+        callback.assertUiHiddenEvent(username);
+        sUiBot.assertNotShownByText("Tap to auth response");
+        sUiBot.assertNoDatasets();
+    }
+
+    @Test
+    public void testDatasetAuthTwoFields() throws Exception {
         // Set service.
         enableService();
         final MyAutofillCallback callback = mActivity.registerCallback();
@@ -1103,7 +1220,7 @@
                 .build());
 
         // Create the authentication intent
-        IntentSender authentication = PendingIntent.getActivity(getContext(), 0,
+        final IntentSender authentication = PendingIntent.getActivity(getContext(), 0,
                 new Intent(getContext(), AuthenticationActivity.class), 0).getIntentSender();
 
         // Configure the service behavior
@@ -1137,6 +1254,131 @@
     }
 
     @Test
+    public void testDatasetAuthTwoDatasets() throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        AuthenticationActivity.setDataset(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .setPresentation(createPresentation("Dataset"))
+                .build());
+
+        // Create the authentication intents
+        final IntentSender authentication1 = PendingIntent.getActivity(getContext(), 1,
+                new Intent(getContext(), AuthenticationActivity.class), 0).getIntentSender();
+        final IntentSender authentication2 = PendingIntent.getActivity(getContext(), 2,
+                new Intent(getContext(), AuthenticationActivity.class), 0).getIntentSender();
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("Tap to auth dataset 1"))
+                        .setAuthentication(authentication1)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "DUDE")
+                        .setField(ID_PASSWORD, "SWEET")
+                        .setPresentation(createPresentation("Tap to auth dataset 2"))
+                        .setAuthentication(authentication2)
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        mActivity.onUsername(View::requestFocus);
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Authenticate
+        callback.assertUiShownEvent(username);
+        sUiBot.assertDatasets("Tap to auth dataset 1", "Tap to auth dataset 2");
+
+        sUiBot.selectDataset("Tap to auth dataset 1");
+        callback.assertUiHiddenEvent(username);
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testDatasetAuthMixedSelectAuth() throws Exception {
+        datasetAuthMixedTest(true);
+    }
+
+    @Test
+    public void testDatasetAuthMixedSelectNonAuth() throws Exception {
+        datasetAuthMixedTest(false);
+    }
+
+    private void datasetAuthMixedTest(boolean selectAuth) throws Exception {
+        // Set service.
+        enableService();
+        final MyAutofillCallback callback = mActivity.registerCallback();
+
+        // Prepare the authenticated response
+        AuthenticationActivity.setDataset(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .setPresentation(createPresentation("Dataset"))
+                .build());
+
+        // Create the authentication intents
+        final IntentSender authentication = PendingIntent.getActivity(getContext(), 0,
+                new Intent(getContext(), AuthenticationActivity.class), 0).getIntentSender();
+
+        // Configure the service behavior
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("Tap to auth dataset"))
+                        .setAuthentication(authentication)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "DUDE")
+                        .setField(ID_PASSWORD, "SWEET")
+                        .setPresentation(createPresentation("What, me auth?"))
+                        .build())
+                .build());
+
+        // Set expectation for the activity
+        if (selectAuth) {
+            mActivity.expectAutoFill("dude", "sweet");
+        } else {
+            mActivity.expectAutoFill("DUDE", "SWEET");
+        }
+
+        // Trigger auto-fill.
+        mActivity.onUsername(View::requestFocus);
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+        final View username = mActivity.getUsername();
+
+        // Authenticate
+        callback.assertUiShownEvent(username);
+        sUiBot.assertDatasets("Tap to auth dataset", "What, me auth?");
+
+        final String chosenOne = selectAuth ? "Tap to auth dataset" : "What, me auth?";
+        sUiBot.selectDataset(chosenOne);
+        callback.assertUiHiddenEvent(username);
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
     public void testDisableSelf() throws Exception {
         enableService();
 
@@ -1283,7 +1525,7 @@
 
         final FillRequest fillRequest = sReplier.getNextFillRequest();
 
-        // Assert it only has 1 root view with 9 "leaf" nodes:
+        // Assert it only has 1 root view with 10 "leaf" nodes:
         // 1.text view for app title
         // 2.username text label
         // 3.username text field
@@ -1293,11 +1535,12 @@
         // 7.clear button
         // 8.save button
         // 9.login button
+        // 10.cancel button
         //
         // But it also has an intermediate container (for username) that should be included because
         // it has a resource id.
 
-        assertNumberOfChildren(fillRequest.structure, 11);
+        assertNumberOfChildren(fillRequest.structure, 12);
 
         // Make sure container with a resource id was included:
         final ViewNode usernameContainer = findNodeByResourceId(fillRequest.structure,
@@ -1306,21 +1549,13 @@
         assertThat(usernameContainer.getChildCount()).isEqualTo(2);
     }
 
-    private static final boolean BUG_36171235_FIXED = false;
-
     @Test
     public void testAutofillManuallyOneDataset() throws Exception {
         // Set service.
         enableService();
 
-        if (BUG_36171235_FIXED)
         // And activity.
-        mActivity.onUsername((v) -> {
-            v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
-            // TODO: setting an empty text, otherwise longPress() does not
-            // display the AUTOFILL context menu. Need to fix it, but it's a test case issue...
-            v.setText("");
-        });
+        mActivity.onUsername((v) -> v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO));
 
         // Set expectations.
         sReplier.addResponse(new CannedDataset.Builder()
@@ -1330,12 +1565,7 @@
                 .build());
         mActivity.expectAutoFill("dude", "sweet");
 
-        // Long-press field to trigger AUTOFILL menu.
-        if (BUG_36171235_FIXED) {
-            sUiBot.getAutofillMenuOption(ID_USERNAME).click();
-        } else {
-            mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
-        }
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
 
         final FillRequest fillRequest = sReplier.getNextFillRequest();
         assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
@@ -1361,14 +1591,8 @@
         // Set service.
         enableService();
 
-        if (BUG_36171235_FIXED)
         // And activity.
-        mActivity.onUsername((v) -> {
-            v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
-            // TODO: setting an empty text, otherwise longPress() does not display the AUTOFILL
-            // context menu. Need to fix it, but it's a test case issue...
-            v.setText("");
-        });
+        mActivity.onUsername((v) -> v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO));
 
         // Set expectations.
         sReplier.addResponse(new CannedFillResponse.Builder()
@@ -1391,11 +1615,7 @@
         }
 
         // Long-press field to trigger AUTOFILL menu.
-        if (BUG_36171235_FIXED) {
-            sUiBot.getAutofillMenuOption(ID_USERNAME).click();
-        } else {
-            mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
-        }
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
 
         final FillRequest fillRequest = sReplier.getNextFillRequest();
         assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
@@ -1409,6 +1629,164 @@
     }
 
     @Test
+    public void testAutofillManuallyPartialField() throws Exception {
+        // Set service.
+        enableService();
+
+        // And activity.
+        mActivity.onUsername((v) -> {
+            v.setText("dud");
+            v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
+        });
+        mActivity.onPassword((v) -> v.setText("IamSecretMan"));
+
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .setPresentation(createPresentation("The Dude"))
+                .build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+
+        final FillRequest fillRequest = sReplier.getNextFillRequest();
+        assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
+        // Username value should be available because it triggered the manual request...
+        assertValue(fillRequest.structure, ID_USERNAME, "dud");
+        // ... but password didn't
+        assertTextIsSanitized(fillRequest.structure, ID_PASSWORD);
+
+        // Should have been automatically filled.
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testAutofillManuallyAgainAfterAutomaticallyAutofilledBefore() throws Exception {
+        // Set service.
+        enableService();
+
+        /*
+         * 1st fill (automatic).
+         */
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .setPresentation(createPresentation("The Dude"))
+                .build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        mActivity.onUsername(View::requestFocus);
+
+        // Assert request.
+        final FillRequest fillRequest1 = sReplier.getNextFillRequest();
+        assertThat(fillRequest1.flags).isEqualTo(0);
+        assertTextIsSanitized(fillRequest1.structure, ID_USERNAME);
+        assertTextIsSanitized(fillRequest1.structure, ID_PASSWORD);
+
+        // Select it.
+        sUiBot.selectDataset("The Dude");
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        /*
+         * 2nd fill (manual).
+         */
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "DUDE")
+                .setField(ID_PASSWORD, "SWEET")
+                .setPresentation(createPresentation("THE DUDE"))
+                .build());
+        mActivity.expectAutoFill("DUDE", "SWEET");
+        // Change password to make sure it's not sent to the service.
+        mActivity.onPassword((v) -> v.setText("IamSecretMan"));
+
+        // Trigger auto-fill.
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+
+        // Assert request.
+        final FillRequest fillRequest2 = sReplier.getNextFillRequest();
+        assertThat(fillRequest2.flags).isEqualTo(FLAG_MANUAL_REQUEST);
+        assertValue(fillRequest2.structure, ID_USERNAME, "dude");
+        assertTextIsSanitized(fillRequest2.structure, ID_PASSWORD);
+
+        // Should have been automatically filled.
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testAutofillManuallyAgainAfterManuallyAutofilledBefore() throws Exception {
+        // Set service.
+        enableService();
+        // And activity
+        mActivity.onUsername((v) -> v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO));
+
+        /*
+         * 1st fill (manual).
+         */
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "dude")
+                .setField(ID_PASSWORD, "sweet")
+                .setPresentation(createPresentation("The Dude"))
+                .build());
+        mActivity.expectAutoFill("dude", "sweet");
+
+        // Trigger auto-fill.
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+
+        // Assert request.
+        final FillRequest fillRequest1 = sReplier.getNextFillRequest();
+        assertThat(fillRequest1.flags).isEqualTo(FLAG_MANUAL_REQUEST);
+        assertValue(fillRequest1.structure, ID_USERNAME, "");
+        assertTextIsSanitized(fillRequest1.structure, ID_PASSWORD);
+
+        // Should have been automatically filled.
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        /*
+         * 2nd fill (manual).
+         */
+        // Set expectations.
+        sReplier.addResponse(new CannedDataset.Builder()
+                .setField(ID_USERNAME, "DUDE")
+                .setField(ID_PASSWORD, "SWEET")
+                .setPresentation(createPresentation("THE DUDE"))
+                .build());
+        mActivity.expectAutoFill("DUDE", "SWEET");
+        // Change password to make sure it's not sent to the service.
+        mActivity.onPassword((v) -> v.setText("IamSecretMan"));
+
+        // Trigger auto-fill.
+        sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+
+        // Assert request.
+        final FillRequest fillRequest2 = sReplier.getNextFillRequest();
+        assertThat(fillRequest2.flags).isEqualTo(FLAG_MANUAL_REQUEST);
+        assertValue(fillRequest2.structure, ID_USERNAME, "dude");
+        assertTextIsSanitized(fillRequest2.structure, ID_PASSWORD);
+
+        // Should have been automatically filled.
+        sUiBot.assertNoDatasets();
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
     public void testCommitMultipleTimes() throws Throwable {
         // Set service.
         enableService();
@@ -1585,7 +1963,7 @@
 
         // Set expectations.
         sReplier.addResponse(new CannedFillResponse.Builder()
-                .setAuthentication(sender)
+                .setAuthentication(sender, ID_USERNAME)
                 .setPresentation(presentation)
                 .build());
 
@@ -1678,7 +2056,7 @@
 
         sReplier.addResponse(new CannedFillResponse.Builder().setExtras(clientState)
                 .setPresentation(createPresentation("authentication"))
-                .setAuthentication(authentication)
+                .setAuthentication(authentication, ID_USERNAME)
                 .build());
 
         // Trigger autofill.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/OneTimeSettingsListener.java b/tests/autofillservice/src/android/autofillservice/cts/OneTimeSettingsListener.java
new file mode 100644
index 0000000..e723357
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/OneTimeSettingsListener.java
@@ -0,0 +1,51 @@
+package android.autofillservice.cts;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Helper used to block tests until a secure settings value has been updated.
+ */
+final class OneTimeSettingsListener extends ContentObserver {
+    private final CountDownLatch mLatch = new CountDownLatch(1);
+    private final ContentResolver mResolver;
+    private final String mKey;
+
+    public OneTimeSettingsListener(Context context, String key) {
+        super(new Handler(Looper.getMainLooper()));
+        mKey = key;
+        mResolver = context.getContentResolver();
+        mResolver.registerContentObserver(Settings.Secure.getUriFor(key), false, this);
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        mResolver.unregisterContentObserver(this);
+        mLatch.countDown();
+    }
+
+    /**
+     * Blocks for a few seconds until it's called.
+     *
+     * @throws IllegalStateException if it's not called.
+     */
+    void assertCalled() {
+        try {
+            final boolean updated = mLatch.await(5, TimeUnit.SECONDS);
+            if (!updated) {
+                throw new IllegalStateException("Settings " + mKey + " not called in 5s");
+            }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new IllegalStateException("Interrupted", e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
index 19f6b80..2a3bee1 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
@@ -35,13 +35,18 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import android.app.PendingIntent;
 import android.app.assist.AssistStructure.ViewNode;
 import android.autofillservice.cts.CannedFillResponse.CannedDataset;
 import android.autofillservice.cts.GridActivity.FillExpectation;
 import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
 import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
+import android.content.Intent;
+import android.content.IntentSender;
 import android.os.Bundle;
+import android.service.autofill.FillResponse;
 import android.support.test.rule.ActivityTestRule;
+import android.widget.RemoteViews;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -240,7 +245,11 @@
         final FillRequest fillRequest1 = sReplier.getNextFillRequest();
         assertThat(fillRequest1.flags).isEqualTo(expectedFlag);
 
-        assertTextIsSanitized(fillRequest1.structure, ID_L1C1);
+        if (manually) {
+            assertValue(fillRequest1.structure, ID_L1C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest1.structure, ID_L1C1);
+        }
         assertTextIsSanitized(fillRequest1.structure, ID_L1C2);
 
         // Auto-fill it.
@@ -272,7 +281,11 @@
 
         assertValue(fillRequest2.structure, ID_L1C1, "l1c1");
         assertValue(fillRequest2.structure, ID_L1C2, "l1c2");
-        assertTextIsSanitized(fillRequest2.structure, ID_L2C1);
+        if (manually) {
+            assertValue(fillRequest2.structure, ID_L2C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest2.structure, ID_L2C1);
+        }
         assertTextIsSanitized(fillRequest2.structure, ID_L2C2);
 
         // Auto-fill it.
@@ -306,7 +319,11 @@
         assertValue(fillRequest3.structure, ID_L1C2, "l1c2");
         assertValue(fillRequest3.structure, ID_L2C1, "l2c1");
         assertValue(fillRequest3.structure, ID_L2C2, "l2c2");
-        assertTextIsSanitized(fillRequest3.structure, ID_L3C1);
+        if (manually) {
+            assertValue(fillRequest3.structure, ID_L3C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest3.structure, ID_L3C1);
+        }
         assertTextIsSanitized(fillRequest3.structure, ID_L3C2);
 
         // Auto-fill it.
@@ -342,7 +359,11 @@
         assertValue(fillRequest4.structure, ID_L2C2, "l2c2");
         assertValue(fillRequest4.structure, ID_L3C1, "l3c1");
         assertValue(fillRequest4.structure, ID_L3C2, "l3c2");
-        assertTextIsSanitized(fillRequest4.structure, ID_L4C1);
+        if (manually) {
+            assertValue(fillRequest4.structure, ID_L4C1, "");
+        } else {
+            assertTextIsSanitized(fillRequest4.structure, ID_L4C1);
+        }
         assertTextIsSanitized(fillRequest4.structure, ID_L4C2);
 
         // Auto-fill it.
@@ -389,6 +410,7 @@
 
         // 2nd partition - manual
         // Prepare.
+        mActivity.setText(2, 1, "L2.."); // Must set before creating expectation.
         final CannedFillResponse response2 = new CannedFillResponse.Builder()
                 .addDataset(new CannedDataset.Builder()
                         .setPresentation(createPresentation("Partition 2"))
@@ -408,7 +430,7 @@
 
         assertValue(fillRequest2.structure, ID_L1C1, "l1c1");
         assertValue(fillRequest2.structure, ID_L1C2, "l1c2");
-        assertTextIsSanitized(fillRequest2.structure, ID_L2C1);
+        assertValue(fillRequest2.structure, ID_L2C1, "L2..");
         assertTextIsSanitized(fillRequest2.structure, ID_L2C2);
 
         // Check the results.
@@ -448,6 +470,7 @@
 
         // 4th partition - manual
         // Prepare.
+        mActivity.setText(4, 1, "L4.."); // Must set before creating expectation.
         final CannedFillResponse response4 = new CannedFillResponse.Builder()
                 .addDataset(new CannedDataset.Builder()
                         .setPresentation(createPresentation("Partition 4"))
@@ -471,7 +494,7 @@
         assertValue(fillRequest4.structure, ID_L2C2, "l2c2");
         assertValue(fillRequest4.structure, ID_L3C1, "l3c1");
         assertValue(fillRequest4.structure, ID_L3C2, "l3c2");
-        assertTextIsSanitized(fillRequest4.structure, ID_L4C1);
+        assertValue(fillRequest4.structure, ID_L4C1, "L4..");
         assertTextIsSanitized(fillRequest4.structure, ID_L4C2);
 
         // Check the results.
@@ -916,4 +939,557 @@
         mActivity.focusCell(2, 2);
         sUiBot.assertNoDatasets();
     }
+
+    /**
+     * Tests scenario where each partition has more than one dataset, but they don't overlap, i.e.,
+     * each {@link FillResponse} only contain fields within the partition.
+     */
+    @Test
+    public void testAutofillMultipleDatasetsNoOverlap() throws Exception {
+        // Set service.
+        enableService();
+
+        /**
+         * 1st partition.
+         */
+        // Set expectations.
+        final CannedFillResponse response1 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P1D1"))
+                        .setField(ID_L1C1, "l1c1")
+                        .setField(ID_L1C2, "l1c2")
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P1D2"))
+                        .setField(ID_L1C1, "L1C1")
+                        .build())
+                .build();
+        sReplier.addResponse(response1);
+        final FillExpectation expectation1 = mActivity.expectAutofill()
+                .onCell(1, 1, "l1c1")
+                .onCell(1, 2, "l1c2");
+
+        // Trigger partition.
+        mActivity.focusCell(1, 1);
+        sReplier.getNextFillRequest();
+
+
+        /**
+         * 2nd partition.
+         */
+        // Set expectations.
+        final CannedFillResponse response2 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P2D1"))
+                        .setField(ID_L2C1, "l2c1")
+                        .setField(ID_L2C2, "l2c2")
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P2D2"))
+                        .setField(ID_L2C2, "L2C2")
+                        .build())
+                .build();
+        sReplier.addResponse(response2);
+        final FillExpectation expectation2 = mActivity.expectAutofill()
+                .onCell(2, 2, "L2C2");
+
+        // Trigger partition.
+        mActivity.focusCell(2, 1);
+        sReplier.getNextFillRequest();
+
+        /**
+         * 3rd partition.
+         */
+        // Set expectations.
+        final CannedFillResponse response3 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P3D1"))
+                        .setField(ID_L3C1, "l3c1")
+                        .setField(ID_L3C2, "l3c2")
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P3D2"))
+                        .setField(ID_L3C1, "L3C1")
+                        .setField(ID_L3C2, "L3C2")
+                        .build())
+                .build();
+        sReplier.addResponse(response3);
+        final FillExpectation expectation3 = mActivity.expectAutofill()
+                .onCell(3, 1, "L3C1")
+                .onCell(3, 2, "L3C2");
+
+        // Trigger partition.
+        mActivity.focusCell(3, 1);
+        sReplier.getNextFillRequest();
+
+        /**
+         * 4th partition.
+         */
+        // Set expectations.
+        final CannedFillResponse response4 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P4D1"))
+                        .setField(ID_L4C1, "l4c1")
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P4D2"))
+                        .setField(ID_L4C1, "L4C1")
+                        .setField(ID_L4C2, "L4C2")
+                        .build())
+                .build();
+        sReplier.addResponse(response4);
+        final FillExpectation expectation4 = mActivity.expectAutofill()
+                .onCell(4, 1, "l4c1");
+
+        // Trigger partition.
+        mActivity.focusCell(4, 1);
+        sReplier.getNextFillRequest();
+
+        /*
+         *  Now move focus around to make sure the proper values are displayed each time.
+         */
+        mActivity.focusCell(1, 1);
+        sUiBot.assertDatasets("P1D1", "P1D2");
+        mActivity.focusCell(1, 2);
+        sUiBot.assertDatasets("P1D1");
+
+        mActivity.focusCell(2, 1);
+        sUiBot.assertDatasets("P2D1");
+        mActivity.focusCell(2, 2);
+        sUiBot.assertDatasets("P2D1", "P2D2");
+
+        mActivity.focusCell(4, 1);
+        sUiBot.assertDatasets("P4D1", "P4D2");
+        mActivity.focusCell(4, 2);
+        sUiBot.assertDatasets("P4D2");
+
+        mActivity.focusCell(3, 2);
+        sUiBot.assertDatasets("P3D1", "P3D2");
+        mActivity.focusCell(3, 1);
+        sUiBot.assertDatasets("P3D1", "P3D2");
+
+        /*
+         *  Finally, autofill and check results.
+         */
+        mActivity.focusCell(4, 1);
+        sUiBot.selectDataset("P4D1");
+        expectation4.assertAutoFilled();
+
+        mActivity.focusCell(1, 1);
+        sUiBot.selectDataset("P1D1");
+        expectation1.assertAutoFilled();
+
+        mActivity.focusCell(3, 1);
+        sUiBot.selectDataset("P3D2");
+        expectation3.assertAutoFilled();
+
+        mActivity.focusCell(2, 2);
+        sUiBot.selectDataset("P2D2");
+        expectation2.assertAutoFilled();
+    }
+
+    /**
+     * Tests scenario where each partition has more than one dataset, but they overlap, i.e.,
+     * some fields are present in more than one partition.
+     *
+     * <p>Whenever a new partition defines a field previously present in another partittion, that
+     * partition will "own" that field.
+     *
+     * <p>In the end, 4th partition will one all fields in 2 datasets; and this test cases picks
+     * the first.
+     */
+    @Test
+    public void testAutofillMultipleDatasetsOverlappingPicksFirst() throws Exception {
+        autofillMultipleDatasetsOverlapping(true);
+    }
+
+    /**
+     * Tests scenario where each partition has more than one dataset, but they overlap, i.e.,
+     * some fields are present in more than one partition.
+     *
+     * <p>Whenever a new partition defines a field previously present in another partittion, that
+     * partition will "own" that field.
+     *
+     * <p>In the end, 4th partition will one all fields in 2 datasets; and this test cases picks
+     * the second.
+     */
+    @Test
+    public void testAutofillMultipleDatasetsOverlappingPicksSecond() throws Exception {
+        autofillMultipleDatasetsOverlapping(false);
+    }
+
+    private void autofillMultipleDatasetsOverlapping(boolean pickFirst) throws Exception {
+        // Set service.
+        enableService();
+
+        /**
+         * 1st partition.
+         */
+        // Set expectations.
+        final CannedFillResponse response1 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P1D1"))
+                        .setField(ID_L1C1, "l1c1")
+                        .setField(ID_L1C2, "l1c2")
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P1D2"))
+                        .setField(ID_L1C1, "L1C1")
+                        .build())
+                .build();
+        sReplier.addResponse(response1);
+
+        // Trigger partition.
+        mActivity.focusCell(1, 1);
+        sReplier.getNextFillRequest();
+
+        // Asserts proper datasets are shown on each field defined so far.
+        mActivity.focusCell(1, 1);
+        sUiBot.assertDatasets("P1D1", "P1D2");
+        mActivity.focusCell(1, 2);
+        sUiBot.assertDatasets("P1D1");
+
+        /**
+         * 2nd partition.
+         */
+        // Set expectations.
+        final CannedFillResponse response2 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P2D1"))
+                        .setField(ID_L1C1, "l1c1") // from previous partition
+                        .setField(ID_L2C1, "l2c1")
+                        .setField(ID_L2C2, "l2c2")
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P2D2"))
+                        .setField(ID_L2C2, "L2C2")
+                        .build())
+                .build();
+        sReplier.addResponse(response2);
+
+        // Trigger partition.
+        mActivity.focusCell(2, 1);
+        sReplier.getNextFillRequest();
+
+        // Asserts proper datasets are shown on each field defined so far.
+        mActivity.focusCell(1, 1);
+        sUiBot.assertDatasets("P2D1"); // changed
+        mActivity.focusCell(1, 2);
+        sUiBot.assertDatasets("P1D1");
+        mActivity.focusCell(2, 1);
+        sUiBot.assertDatasets("P2D1");
+        mActivity.focusCell(2, 2);
+        sUiBot.assertDatasets("P2D1", "P2D2");
+
+        /**
+         * 3rd partition.
+         */
+        // Set expectations.
+        final CannedFillResponse response3 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P3D1"))
+                        .setField(ID_L1C2, "l1c2")
+                        .setField(ID_L3C1, "l3c1")
+                        .setField(ID_L3C2, "l3c2")
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P3D2"))
+                        .setField(ID_L2C2, "l2c2")
+                        .setField(ID_L3C1, "L3C1")
+                        .setField(ID_L3C2, "L3C2")
+                        .build())
+                .build();
+        sReplier.addResponse(response3);
+
+        // Trigger partition.
+        mActivity.focusCell(3, 1);
+        sReplier.getNextFillRequest();
+
+        // Asserts proper datasets are shown on each field defined so far.
+        mActivity.focusCell(1, 1);
+        sUiBot.assertDatasets("P2D1");
+        mActivity.focusCell(1, 2);
+        sUiBot.assertDatasets("P3D1"); // changed
+        mActivity.focusCell(2, 1);
+        sUiBot.assertDatasets("P2D1");
+        mActivity.focusCell(2, 2);
+        sUiBot.assertDatasets("P3D2"); // changed
+        mActivity.focusCell(3, 2);
+        sUiBot.assertDatasets("P3D1", "P3D2");
+        mActivity.focusCell(3, 1);
+        sUiBot.assertDatasets("P3D1", "P3D2");
+
+        /**
+         * 4th partition.
+         */
+        // Set expectations.
+        final CannedFillResponse response4 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P4D1"))
+                        .setField(ID_L1C1, "l1c1")
+                        .setField(ID_L1C2, "l1c2")
+                        .setField(ID_L2C1, "l2c1")
+                        .setField(ID_L2C2, "l2c2")
+                        .setField(ID_L3C1, "l3c1")
+                        .setField(ID_L3C2, "l3c2")
+                        .setField(ID_L4C1, "l4c1")
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setPresentation(createPresentation("P4D2"))
+                        .setField(ID_L1C1, "L1C1")
+                        .setField(ID_L1C2, "L1C2")
+                        .setField(ID_L2C1, "L2C1")
+                        .setField(ID_L2C2, "L2C2")
+                        .setField(ID_L3C1, "L3C1")
+                        .setField(ID_L3C2, "L3C2")
+                        .setField(ID_L1C1, "L1C1")
+                        .setField(ID_L4C1, "L4C1")
+                        .setField(ID_L4C2, "L4C2")
+                        .build())
+                .build();
+        sReplier.addResponse(response4);
+
+        // Trigger partition.
+        mActivity.focusCell(4, 1);
+        sReplier.getNextFillRequest();
+
+        // Asserts proper datasets are shown on each field defined so far.
+        mActivity.focusCell(1, 1);
+        sUiBot.assertDatasets("P4D1", "P4D2");
+        mActivity.focusCell(1, 2);
+        sUiBot.assertDatasets("P4D1", "P4D2");
+        mActivity.focusCell(2, 1);
+        sUiBot.assertDatasets("P4D1", "P4D2");
+        mActivity.focusCell(2, 2);
+        sUiBot.assertDatasets("P4D1", "P4D2");
+        mActivity.focusCell(3, 2);
+        sUiBot.assertDatasets("P4D1", "P4D2");
+        mActivity.focusCell(3, 1);
+        sUiBot.assertDatasets("P4D1", "P4D2");
+        mActivity.focusCell(4, 1);
+        sUiBot.assertDatasets("P4D1", "P4D2");
+        mActivity.focusCell(4, 2);
+        sUiBot.assertDatasets("P4D2");
+
+        /*
+         * Finally, autofill and check results.
+         */
+        final FillExpectation expectation = mActivity.expectAutofill();
+        final String chosenOne;
+        if (pickFirst) {
+            expectation
+                .onCell(1, 1, "l1c1")
+                .onCell(1, 2, "l1c2")
+                .onCell(2, 1, "l2c1")
+                .onCell(2, 2, "l2c2")
+                .onCell(3, 1, "l3c1")
+                .onCell(3, 2, "l3c2")
+                .onCell(4, 1, "l4c1");
+            chosenOne = "P4D1";
+        } else {
+            expectation
+                .onCell(1, 1, "L1C1")
+                .onCell(1, 2, "L1C2")
+                .onCell(2, 1, "L2C1")
+                .onCell(2, 2, "L2C2")
+                .onCell(3, 1, "L3C1")
+                .onCell(3, 2, "L3C2")
+                .onCell(4, 1, "L4C1")
+                .onCell(4, 2, "L4C2");
+            chosenOne = "P4D2";
+        }
+
+          mActivity.focusCell(4, 1);
+          sUiBot.selectDataset(chosenOne);
+          expectation.assertAutoFilled();
+    }
+
+    @Test
+    public void testAutofillMultipleAuthDatasetsInSequence() throws Exception {
+        // Set service.
+        enableService();
+
+        // TODO: current API requires these fields...
+        final RemoteViews bogusPresentation = createPresentation("Whatever man, I'm not used...");
+        final String bogusValue = "Y U REQUIRE IT?";
+
+        /**
+         * 1st partition.
+         */
+        // Set expectations.
+        final IntentSender auth11 = AuthenticationActivity.createSender(getContext(), 11,
+                new CannedDataset.Builder()
+                        .setField(ID_L1C1, "l1c1")
+                        .setField(ID_L1C2, "l1c2")
+                        .setPresentation(bogusPresentation)
+                        .build());
+        final IntentSender auth12 = AuthenticationActivity.createSender(getContext(), 12);
+        final CannedFillResponse response1 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setAuthentication(auth11)
+                        .setField(ID_L1C1, bogusValue)
+                        .setField(ID_L1C2, bogusValue)
+                        .setPresentation(createPresentation("P1D1"))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setAuthentication(auth12)
+                        .setField(ID_L1C1, bogusValue)
+                        .setPresentation(createPresentation("P1D2"))
+                        .build())
+                .build();
+        sReplier.addResponse(response1);
+        final FillExpectation expectation1 = mActivity.expectAutofill()
+                .onCell(1, 1, "l1c1")
+                .onCell(1, 2, "l1c2");
+
+        // Trigger partition.
+        mActivity.focusCell(1, 1);
+        sReplier.getNextFillRequest();
+
+        // Focus around different fields in the partition.
+        sUiBot.assertDatasets("P1D1", "P1D2");
+        mActivity.focusCell(1, 2);
+        sUiBot.assertDatasets("P1D1");
+
+        // Autofill it...
+        sUiBot.selectDataset("P1D1");
+        // ... and assert result
+        expectation1.assertAutoFilled();
+
+
+        /**
+         * 2nd partition.
+         */
+        // Set expectations.
+        final IntentSender auth21 = AuthenticationActivity.createSender(getContext(), 21, null);
+        final IntentSender auth22 = AuthenticationActivity.createSender(getContext(), 22,
+                new CannedDataset.Builder()
+                    .setField(ID_L2C2, "L2C2")
+                    .setPresentation(bogusPresentation)
+                    .build());
+        final CannedFillResponse response2 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setAuthentication(auth21)
+                        .setPresentation(createPresentation("P2D1"))
+                        .setField(ID_L2C1, bogusValue)
+                        .setField(ID_L2C2, bogusValue)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setAuthentication(auth22)
+                        .setPresentation(createPresentation("P2D2"))
+                        .setField(ID_L2C2, bogusValue)
+                        .build())
+                .build();
+        sReplier.addResponse(response2);
+        final FillExpectation expectation2 = mActivity.expectAutofill()
+                .onCell(2, 2, "L2C2");
+
+
+        // Trigger partition.
+        mActivity.focusCell(2, 1);
+        sReplier.getNextFillRequest();
+
+        // Focus around different fields in the partition.
+        sUiBot.assertDatasets("P2D1");
+        mActivity.focusCell(2, 2);
+        sUiBot.assertDatasets("P2D1", "P2D2");
+
+        // Autofill it...
+        sUiBot.selectDataset("P2D2");
+        // ... and assert result
+        expectation2.assertAutoFilled();
+
+        /**
+         * 3rd partition.
+         */
+        // Set expectations.
+        final IntentSender auth31 = AuthenticationActivity.createSender(getContext(), 31,
+                new CannedDataset.Builder()
+                        .setField(ID_L3C1, "l3c1")
+                        .setField(ID_L3C2, "l3c2")
+                        .setPresentation(bogusPresentation)
+                        .build());
+        final IntentSender auth32 = AuthenticationActivity.createSender(getContext(), 32);
+        final CannedFillResponse response3 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setAuthentication(auth31)
+                        .setPresentation(createPresentation("P3D1"))
+                        .setField(ID_L3C1, bogusValue)
+                        .setField(ID_L3C2, bogusValue)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setAuthentication(auth32)
+                        .setPresentation(createPresentation("P3D2"))
+                        .setField(ID_L3C1, bogusValue)
+                        .setField(ID_L3C2, bogusValue)
+                        .build())
+                .build();
+        sReplier.addResponse(response3);
+        final FillExpectation expectation3 = mActivity.expectAutofill()
+                .onCell(3, 1, "l3c1")
+                .onCell(3, 2, "l3c2");
+
+        // Trigger partition.
+        mActivity.focusCell(3, 2);
+        sReplier.getNextFillRequest();
+
+        // Focus around different fields in the partition.
+        sUiBot.assertDatasets("P3D1", "P3D2");
+        mActivity.focusCell(3, 1);
+        sUiBot.assertDatasets("P3D1", "P3D2");
+
+        // Autofill it...
+        sUiBot.selectDataset("P3D1");
+        // ... and assert result
+        expectation3.assertAutoFilled();
+
+        /**
+         * 4th partition.
+         */
+        // Set expectations.
+        final IntentSender auth41 = AuthenticationActivity.createSender(getContext(), 41, null);
+        final IntentSender auth42 = AuthenticationActivity.createSender(getContext(), 42,
+                new CannedDataset.Builder()
+                    .setField(ID_L4C1, "L4C1")
+                    .setField(ID_L4C2, "L4C2")
+                    .setPresentation(bogusPresentation)
+                    .build());
+        final CannedFillResponse response4 = new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setAuthentication(auth41)
+                        .setPresentation(createPresentation("P4D1"))
+                        .setField(ID_L4C1, bogusValue)
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setAuthentication(auth42)
+                        .setPresentation(createPresentation("P4D2"))
+                        .setField(ID_L4C1, bogusValue)
+                        .setField(ID_L4C2, bogusValue)
+                        .build())
+                .build();
+        sReplier.addResponse(response4);
+        final FillExpectation expectation4 = mActivity.expectAutofill()
+                .onCell(4, 1, "L4C1")
+                .onCell(4, 2, "L4C2");
+
+        // Trigger partition.
+        mActivity.focusCell(4, 1);
+        sReplier.getNextFillRequest();
+
+        // Focus around different fields in the partition.
+        sUiBot.assertDatasets("P4D1", "P4D2");
+        mActivity.focusCell(4, 2);
+        sUiBot.assertDatasets("P4D2");
+
+        // Autofill it...
+        sUiBot.selectDataset("P4D2");
+        // ... and assert result
+        expectation4.assertAutoFilled();
+
+    }
+
+    // TODO(b/37424539): more scenarios:
+    // - overlapping instead of sequence
+    // - mixed of auth / no auth
+    // - overlapping 1st/2nd cases
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
index 0454277..19b7e46 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
@@ -38,12 +38,11 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.os.Bundle;
-import android.support.test.rule.ActivityTestRule;
+import android.os.SystemClock;
 import android.view.autofill.AutofillValue;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 
 /**
@@ -54,14 +53,7 @@
     private static final String PASSWORD_FULL_ID = "android.autofillservice.cts:id/" + ID_PASSWORD;
     private static final String LOGIN_FULL_ID = "android.autofillservice.cts:id/" + ID_LOGIN;
     private static final String BUTTON_FULL_ID = "android.autofillservice.cts:id/button";
-
-    /**
-     * Use an activity as background so that orientation change always works (Home screen does not
-     * allow rotation
-     */
-    @Rule
-    public final ActivityTestRule<EmptyActivity> mActivityRule =
-            new ActivityTestRule<>(EmptyActivity.class);
+    private static final String CANCEL_FULL_ID = "android.autofillservice.cts:id/cancel";
 
     @Before
     public void removeAllSessions() {
@@ -84,8 +76,20 @@
         Helper.allowAutoRotation();
     }
 
+    private void killOfProcessLoginActivityProcess() throws Exception {
+        // Waiting for activity to stop (stop marker appears)
+        eventually(() -> assertThat(getStoppedMarker(getContext()).exists()).isTrue());
+
+        // onStop might not be finished, hence wait more
+        SystemClock.sleep(1000);
+
+        // Kill activity that is in the background
+        runShellCommand("kill -9 %d",
+                getOutOfProcessPid("android.autofillservice.cts.outside"));
+    }
+
     @Test
-    public void testSessionRetainedWhileAutofilledAppIsLifecycled() throws Exception {
+    public void testDatasetAuthResponseWhileAutofilledAppIsLifecycled() throws Exception {
         // Set service.
         enableService();
 
@@ -113,7 +117,7 @@
                     .setExtras(extras).build());
 
             CannedFillResponse response = new CannedFillResponse.Builder()
-                    .setAuthentication(authentication)
+                    .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
                     .setPresentation(createPresentation("authenticate"))
                     .build();
             sReplier.addResponse(response);
@@ -125,7 +129,7 @@
             sReplier.getNextFillRequest();
 
             // Wait until authentication is shown
-            sUiBot.assertShownByText("authenticate");
+            sUiBot.assertDatasets("authenticate");
 
             // Change orientation which triggers a destroy -> create in the app as the activity
             // cannot deal with such situations
@@ -135,17 +139,10 @@
             getStoppedMarker(getContext()).delete();
 
             // Authenticate
-            sUiBot.selectByText("authenticate");
-
-            // Waiting for activity to stop (stop marker appears)
-            eventually(() -> assertThat(getStoppedMarker(getContext()).exists()).isTrue());
-
-            // onStop might not be finished, hence wait more
-            Thread.sleep(1000);
+            sUiBot.selectDataset("authenticate");
 
             // Kill activity that is in the background
-            runShellCommand("kill -9 %d",
-                    getOutOfProcessPid("android.autofillservice.cts.outside"));
+            killOfProcessLoginActivityProcess();
 
             // Change orientation which triggers a destroy -> create in the app as the activity
             // cannot deal with such situations
@@ -155,7 +152,7 @@
             sUiBot.selectById(BUTTON_FULL_ID);
 
             // Wait for dataset to be shown
-            sUiBot.assertShownByText("dataset");
+            sUiBot.assertDatasets("dataset");
 
             // Change orientation which triggers a destroy -> create in the app as the activity
             // cannot deal with such situations
@@ -205,4 +202,169 @@
             disableService();
         }
     }
+
+    @Test
+    public void testAuthCanceledWhileAutofilledAppIsLifecycled() throws Exception {
+        // Set service.
+        enableService();
+
+        try {
+            // Start activity that is autofilled in a separate process so it can be killed
+            Intent outOfProcessAcvitityStartIntent = new Intent(getContext(),
+                    OutOfProcessLoginActivity.class);
+            getContext().startActivity(outOfProcessAcvitityStartIntent);
+
+            // Create the authentication intent (launching a full screen activity)
+            IntentSender authentication = PendingIntent.getActivity(getContext(), 0,
+                    new Intent(getContext(), ManualAuthenticationActivity.class),
+                    0).getIntentSender();
+
+            CannedFillResponse response = new CannedFillResponse.Builder()
+                    .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
+                    .setPresentation(createPresentation("authenticate"))
+                    .build();
+            sReplier.addResponse(response);
+
+            // Trigger autofill on username
+            sUiBot.selectById(USERNAME_FULL_ID);
+
+            // Wait for fill request to be processed
+            sReplier.getNextFillRequest();
+
+            // Wait until authentication is shown
+            sUiBot.assertDatasets("authenticate");
+
+            // Delete stopped marker
+            getStoppedMarker(getContext()).delete();
+
+            // Authenticate
+            sUiBot.selectDataset("authenticate");
+
+            // Kill activity that is in the background
+            killOfProcessLoginActivityProcess();
+
+            // Cancel authentication activity
+            sUiBot.pressBack();
+
+            // Authentication should still be shown
+            sUiBot.assertDatasets("authenticate");
+        } finally {
+            disableService();
+        }
+    }
+
+    @Test
+    public void testDatasetVisibleWhileAutofilledAppIsLifecycled() throws Exception {
+        // Set service.
+        enableService();
+
+        try {
+            // Start activity that is autofilled in a separate process so it can be killed
+            Intent outOfProcessAcvitityStartIntent = new Intent(getContext(),
+                    OutOfProcessLoginActivity.class);
+            getContext().startActivity(outOfProcessAcvitityStartIntent);
+
+            CannedFillResponse response = new CannedFillResponse.Builder()
+                    .addDataset(new CannedFillResponse.CannedDataset.Builder(
+                            createPresentation("dataset"))
+                            .setField(ID_USERNAME, "filled").build())
+                    .build();
+            sReplier.addResponse(response);
+
+            // Trigger autofill on username
+            sUiBot.selectById(USERNAME_FULL_ID);
+
+            // Wait for fill request to be processed
+            sReplier.getNextFillRequest();
+
+            // Wait until dataset is shown
+            sUiBot.assertDatasets("dataset");
+
+            // Delete stopped marker
+            getStoppedMarker(getContext()).delete();
+
+            // Start an activity on top of the autofilled activity
+            Intent intent = new Intent(getContext(), EmptyActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            getContext().startActivity(intent);
+
+            // Kill activity that is in the background
+            killOfProcessLoginActivityProcess();
+
+            // Cancel activity on top
+            sUiBot.pressBack();
+
+            // Dataset should still be shown
+            sUiBot.assertDatasets("dataset");
+        } finally {
+            disableService();
+        }
+    }
+
+    @Test
+    public void testAutofillNestedActivitiesWhileAutofilledAppIsLifecycled() throws Exception {
+        // Set service.
+        enableService();
+
+        try {
+            // Start activity that is autofilled in a separate process so it can be killed
+            Intent outOfProcessAcvitityStartIntent = new Intent(getContext(),
+                    OutOfProcessLoginActivity.class);
+            getContext().startActivity(outOfProcessAcvitityStartIntent);
+
+            // Prepare response for first activity
+            CannedFillResponse response = new CannedFillResponse.Builder()
+                    .addDataset(new CannedFillResponse.CannedDataset.Builder(
+                            createPresentation("dataset1"))
+                            .setField(ID_USERNAME, "filled").build())
+                    .build();
+            sReplier.addResponse(response);
+
+            // Trigger autofill on username
+            sUiBot.selectById(USERNAME_FULL_ID);
+
+            // Wait for fill request to be processed
+            sReplier.getNextFillRequest();
+
+            // Wait until dataset1 is shown
+            sUiBot.assertDatasets("dataset1");
+
+            // Delete stopped marker
+            getStoppedMarker(getContext()).delete();
+
+            // Prepare response for nested activity
+            response = new CannedFillResponse.Builder()
+                    .addDataset(new CannedFillResponse.CannedDataset.Builder(
+                            createPresentation("dataset2"))
+                            .setField(ID_USERNAME, "filled").build())
+                    .build();
+            sReplier.addResponse(response);
+
+            // Start nested login activity
+            Intent intent = new Intent(getContext(), LoginActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            getContext().startActivity(intent);
+
+            // Kill activity that is in the background
+            killOfProcessLoginActivityProcess();
+
+            // Trigger autofill on username in nested activity
+            sUiBot.selectById(USERNAME_FULL_ID);
+
+            // Wait for fill request to be processed
+            sReplier.getNextFillRequest();
+
+            // Wait until dataset in nested activity is shown
+            sUiBot.assertDatasets("dataset2");
+
+            // Tap "Cancel".
+            sUiBot.selectById(CANCEL_FULL_ID);
+
+            // Dataset should still be shown
+            sUiBot.assertDatasets("dataset1");
+        } finally {
+            disableService();
+        }
+    }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index fa7780a..eba7a3f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -16,7 +16,9 @@
 
 package android.autofillservice.cts;
 
+import static android.autofillservice.cts.Helper.NOT_SHOWING_TIMEOUT_MS;
 import static android.autofillservice.cts.Helper.SAVE_TIMEOUT_MS;
+import static android.autofillservice.cts.Helper.UI_TIMEOUT_MS;
 import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_ADDRESS;
 import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD;
 import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS;
@@ -73,13 +75,11 @@
     private static final String TAG = "AutoFillCtsUiBot";
 
     private final UiDevice mDevice;
-    private final long mTimeout;
     private final String mPackageName;
     private final UiAutomation mAutoman;
 
-    UiBot(Instrumentation instrumentation, long timeout) throws Exception {
+    UiBot(Instrumentation instrumentation) throws Exception {
         mDevice = UiDevice.getInstance(instrumentation);
-        mTimeout = timeout;
         mPackageName = instrumentation.getContext().getPackageName();
         mAutoman = instrumentation.getUiAutomation();
     }
@@ -88,14 +88,16 @@
      * Asserts the dataset chooser is not shown.
      */
     void assertNoDatasets() {
-        final UiObject2 ui;
+        final UiObject2 picker;
         try {
-            ui = findDatasetPicker();
+            picker = findDatasetPicker(NOT_SHOWING_TIMEOUT_MS);
         } catch (Throwable t) {
             // Use a more elegant check than catching the expection because it's not showing...
             return;
         }
-        throw new RetryableException("floating ui is shown: %s", ui);
+        final StringBuilder error = new StringBuilder("Should not be showing datasets, but got [ ");
+        getAllText(picker, error);
+        throw new RetryableException(error.append("]").toString());
     }
 
     /**
@@ -107,12 +109,31 @@
         final UiObject2 picker = findDatasetPicker();
         for (String name : names) {
             final UiObject2 dataset = picker.findObject(By.text(name));
-            assertWithMessage("no dataset named %s", name).that(dataset).isNotNull();
+            if (dataset == null) {
+                final StringBuilder error = new StringBuilder("no dataset named ").append(name)
+                        .append(" on [ ");
+                getAllText(picker, error);
+                throw new AssertionError(error.append("]").toString()); // not retryable
+
+            }
         }
         return picker;
     }
 
     /**
+     * Gets the text from an object and all its descendants.
+     */
+    private static void getAllText(UiObject2 object, StringBuilder builder) {
+        final String text = object.getText();
+        if (text != null) {
+            builder.append(text).append(' ');
+        }
+        for (UiObject2 child : object.getChildren()) {
+            getAllText(child, builder);
+        }
+    }
+
+    /**
      * Selects a dataset that should be visible in the floating UI.
      */
     void selectDataset(String name) {
@@ -152,7 +173,12 @@
      */
     public void assertNotShownByText(String text) {
         final UiObject2 uiObject = mDevice.findObject(By.text(text));
-        assertWithMessage(text).that(uiObject).isNull();
+        if (uiObject != null) {
+            final StringBuilder error = new StringBuilder("Should not find object with text '")
+                    .append(text).append("', but found: ");
+            getAllText(uiObject, error);
+            throw new AssertionError(error.toString()); // don't retry
+        }
     }
 
     /**
@@ -201,7 +227,14 @@
      * Asserts the save snackbar is showing and returns it.
      */
     UiObject2 assertSaveShowing(int type) {
-        return assertSaveShowing(null, type);
+        return assertSaveShowing(SAVE_TIMEOUT_MS, type);
+    }
+
+    /**
+     * Asserts the save snackbar is showing and returns it.
+     */
+    UiObject2 assertSaveShowing(long timeout, int type) {
+        return assertSaveShowing(null, timeout, type);
     }
 
     /**
@@ -216,7 +249,7 @@
      */
     void assertSaveNotShowing(int type) {
         try {
-            assertSaveShowing(type);
+            assertSaveShowing(NOT_SHOWING_TIMEOUT_MS, type);
         } catch (Throwable t) {
             // TODO: use a more elegant check than catching the expection because it's not showing
             // (in which case it wouldn't need a type as parameter).
@@ -250,12 +283,24 @@
     }
 
     UiObject2 assertSaveShowing(String description, int... types) {
-        return assertSaveShowing(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, description, types);
+        return assertSaveShowing(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, description,
+                SAVE_TIMEOUT_MS, types);
     }
 
-    UiObject2 assertSaveShowing(int negativeButtonStyle, String description, int... types) {
+    UiObject2 assertSaveShowing(String description, long timeout, int... types) {
+        return assertSaveShowing(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, description, timeout,
+                types);
+    }
+
+    UiObject2 assertSaveShowing(int negativeButtonStyle, String description,
+            int... types) {
+        return assertSaveShowing(negativeButtonStyle, description, SAVE_TIMEOUT_MS, types);
+    }
+
+    UiObject2 assertSaveShowing(int negativeButtonStyle, String description, long timeout,
+            int... types) {
         final UiObject2 snackbar = waitForObject(By.res("android", RESOURCE_ID_SAVE_SNACKBAR),
-                SAVE_TIMEOUT_MS);
+                timeout);
 
         final UiObject2 titleView = snackbar.findObject(By.res("android", RESOURCE_ID_SAVE_TITLE));
         assertWithMessage("save title (%s)", RESOURCE_ID_SAVE_TITLE).that(titleView).isNotNull();
@@ -314,7 +359,7 @@
      */
     void saveForAutofill(boolean yesDoIt, int... types) {
         final UiObject2 saveSnackBar = assertSaveShowing(
-                SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL,null, types);
+                SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, null, types);
         saveForAutofill(saveSnackBar, yesDoIt);
     }
 
@@ -392,7 +437,7 @@
      * @param selector {@link BySelector} that identifies the object.
      */
     private UiObject2 waitForObject(BySelector selector) {
-        return waitForObject(selector, mTimeout);
+        return waitForObject(selector, UI_TIMEOUT_MS);
     }
 
     /**
@@ -413,7 +458,7 @@
             SystemClock.sleep(napTime);
         }
         throw new RetryableException("Object with selector '%s' not found in %d ms",
-                selector, mTimeout);
+                selector, UI_TIMEOUT_MS);
     }
 
     /**
@@ -422,7 +467,7 @@
      * @param selector {@link BySelector} that identifies the object.
      */
     private List<UiObject2> waitForObjects(BySelector selector) {
-        return waitForObjects(selector, mTimeout);
+        return waitForObjects(selector, UI_TIMEOUT_MS);
     }
 
     /**
@@ -443,11 +488,16 @@
             SystemClock.sleep(napTime);
         }
         throw new RetryableException("Objects with selector '%s' not found in %d ms",
-                selector, mTimeout);
+                selector, UI_TIMEOUT_MS);
     }
 
     private UiObject2 findDatasetPicker() {
-        final UiObject2 picker = waitForObject(By.res("android", RESOURCE_ID_DATASET_PICKER));
+        return findDatasetPicker(UI_TIMEOUT_MS);
+    }
+
+    private UiObject2 findDatasetPicker(long timeout) {
+        final UiObject2 picker = waitForObject(By.res("android", RESOURCE_ID_DATASET_PICKER),
+                timeout);
 
         final String expectedTitle = getString(RESOURCE_STRING_DATASET_PICKER_ACCESSIBILITY_TITLE);
         assertAccessibilityTitle(picker, expectedTitle);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
index 763c57f..31e95f1 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
@@ -16,19 +16,33 @@
 
 package android.autofillservice.cts;
 
+import static android.autofillservice.cts.Helper.FILL_TIMEOUT_MS;
+import static android.autofillservice.cts.Helper.eventually;
+import static android.autofillservice.cts.Helper.findNodeByResourceId;
+
 import static com.google.common.truth.Truth.assertThat;
 
+import android.app.assist.AssistStructure;
+import android.support.annotation.IdRes;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
 import android.view.View;
+import android.view.autofill.AutofillValue;
+import android.widget.EditText;
 
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.function.Consumer;
+
 @RunWith(AndroidJUnit4.class)
 public class ViewAttributesTest extends AutoFillServiceTestCase {
+    private static final String LOG_TAG = ViewAttributesTest.class.getSimpleName();
     @Rule
     public final ActivityTestRule<ViewAttributesTestActivity> mActivityRule =
             new ActivityTestRule<>(ViewAttributesTestActivity.class);
@@ -40,38 +54,44 @@
         mActivity = mActivityRule.getActivity();
     }
 
-    @Test
-    public void checkTextViewNoHint() {
-        assertThat(mActivity.findViewById(R.id.textViewNoHint).getAutofillHints()).isNull();
+    @Nullable private String[] getHintsFromView(@IdRes int resId) {
+        return mActivity.findViewById(resId).getAutofillHints();
+    }
+
+    private void checkEditTextNoHint(@Nullable String[] hints) {
+        assertThat(hints).isNull();
+    }
+
+    private void checkEditTextHintCustom(@Nullable String[] hints) {
+        assertThat(hints).isEqualTo(
+                new String[] {mActivity.getString(R.string.new_password_label)});
+    }
+
+    private void checkEditTextPassword(@Nullable String[] hints) {
+        assertThat(hints).isEqualTo(new String[] {View.AUTOFILL_HINT_PASSWORD});
+    }
+
+    private void checkEditTextPhoneName(@Nullable String[] hints) {
+        assertThat(hints).isEqualTo(
+                new String[] {View.AUTOFILL_HINT_PHONE, View.AUTOFILL_HINT_USERNAME});
+    }
+
+    private void checkEditTextHintsFromArray(@Nullable String[] hints) {
+        assertThat(hints).isEqualTo(new String[] {"yesterday", "today", "tomorrow", "never"});
     }
 
     @Test
-    public void checkTextViewHintCustom() {
-        assertThat(mActivity.findViewById(R.id.textViewHintCustom).getAutofillHints()).isEqualTo(
-                new String[]{mActivity.getString(R.string.new_password_label)});
-    }
-
-    @Test
-    public void checkTextViewPassword() {
-        assertThat(mActivity.findViewById(R.id.textViewPassword).getAutofillHints()).isEqualTo(
-                new String[]{View.AUTOFILL_HINT_PASSWORD});
-    }
-
-    @Test
-    public void checkTextViewPhoneName() {
-        assertThat(mActivity.findViewById(R.id.textViewPhoneName).getAutofillHints()).isEqualTo(
-                new String[]{View.AUTOFILL_HINT_PHONE, View.AUTOFILL_HINT_USERNAME});
-    }
-
-    @Test
-    public void checkTextViewHintsFromArray() {
-        assertThat(mActivity.findViewById(R.id.textViewHintsFromArray).getAutofillHints()).isEqualTo(
-                new String[]{"yesterday", "today", "tomorrow", "never"});
+    public void checkViewHints() {
+        checkEditTextNoHint(getHintsFromView(R.id.editTextNoHint));
+        checkEditTextHintCustom(getHintsFromView(R.id.editTextHintCustom));
+        checkEditTextPassword(getHintsFromView(R.id.editTextPassword));
+        checkEditTextPhoneName(getHintsFromView(R.id.editTextPhoneName));
+        checkEditTextHintsFromArray(getHintsFromView(R.id.editTextHintsFromArray));
     }
 
     @Test
     public void checkSetAutoFill() {
-        View v = mActivity.findViewById(R.id.textViewNoHint);
+        View v = mActivity.findViewById(R.id.editTextNoHint);
 
         v.setAutofillHints(null);
         assertThat(v.getAutofillHints()).isNull();
@@ -93,4 +113,177 @@
         assertThat(v.getAutofillHints()).isEqualTo(new String[]{View.AUTOFILL_HINT_PASSWORD,
                 View.AUTOFILL_HINT_EMAIL_ADDRESS});
     }
+
+    /**
+     * Wait for autofill to be initialized and trigger autofill on a view.
+     *
+     * @param view The view to trigger the autofill on
+     *
+     * @return The {@link InstrumentedAutoFillService.FillRequest triggered}
+     */
+    private InstrumentedAutoFillService.FillRequest startAutoFill(boolean forceAutofill,
+            @NonNull View view) throws Exception {
+        if (forceAutofill) {
+            mActivity.getAutofillManager().requestAutofill(view);
+        } else {
+            mActivity.syncRunOnUiThread(() -> {
+                view.clearFocus();
+                view.requestFocus();
+            });
+        }
+
+        InstrumentedAutoFillService.waitUntilConnected();
+
+        return sReplier.getNextFillRequest();
+    }
+
+    @Nullable private String[] getHintsFromStructure(@NonNull AssistStructure structure,
+            @NonNull String resName) {
+        return findNodeByResourceId(structure, resName).getAutofillHints();
+    }
+
+    private void onAssistStructure(boolean forceAutofill, @NonNull Consumer<AssistStructure> test)
+            throws Exception {
+        EditText editTextNoHint = mActivity.findViewById(R.id.editTextNoHint);
+        mActivity.syncRunOnUiThread(() -> editTextNoHint.setVisibility(View.VISIBLE));
+
+        // Set service.
+        enableService();
+        try {
+            // Set expectations.
+            sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+                    .setField("editTextNoHint", AutofillValue.forText("filled"))
+                    .setPresentation(createPresentation("dataset"))
+                    .build());
+
+            // Trigger autofill.
+            InstrumentedAutoFillService.FillRequest request = startAutoFill(forceAutofill,
+                    editTextNoHint);
+
+            assertThat(request.contexts.size()).isEqualTo(1);
+            test.accept(request.contexts.get(0).getStructure());
+        } finally {
+            disableService();
+        }
+    }
+
+    @Test
+    public void checkAssistStructureHints() throws Exception {
+        onAssistStructure(false, (structure) -> {
+                    // Check autofill hints analogue to #checkViewHints
+                    checkEditTextNoHint(getHintsFromStructure(structure, "editTextNoHint"));
+                    checkEditTextHintCustom(getHintsFromStructure(structure, "editTextHintCustom"));
+                    checkEditTextPassword(getHintsFromStructure(structure, "editTextPassword"));
+                    checkEditTextPhoneName(getHintsFromStructure(structure, "editTextPhoneName"));
+                    checkEditTextHintsFromArray(getHintsFromStructure(structure,
+                            "editTextHintsFromArray"));
+                }
+        );
+    }
+
+    @Test
+    public void checkViewLocationInAssistStructure() throws Exception {
+        onAssistStructure(false, (structure) -> {
+                    // check size of outerView
+                    AssistStructure.ViewNode outerView = findNodeByResourceId(structure,
+                            "outerView");
+
+                    // The size of the view should include all paddings and size of all children
+                    assertThat(outerView.getHeight()).isEqualTo(
+                            2             // outerView.top
+                                    + 11  // nestedView.top
+                                    + 23  // doubleNestedView.top
+                                    + 41  // tripleNestedView.height
+                                    + 47  // secondDoubleNestedView.height
+                                    + 31  // doubleNestedView.bottom
+                                    + 17  // nestedView.bottom
+                                    + 5); // outerView.bottom
+                    assertThat(outerView.getWidth()).isEqualTo(
+                            7                     // outerView.left
+                                    + 19          // nestedView.left
+                                    + Math.max(37 // doubleNestedView.left
+                                            + 43  // tripleNestedView.width
+                                            + 29, // doubleNestedView.right
+                                    53)           // secondDoubleNestedView.width
+                                    + 13          // nestedView.right
+                                    + 3);         // outerView.right
+
+
+                    // The nestedView is suppressed, hence the structure should be
+                    //
+                    // outerView
+                    //  doubleNestedView left=26 top=13
+                    //   tripleNestedView left=37 top=23
+                    //  secondDoubleNestedView left=26 top=108
+
+                    assertThat(outerView.getChildCount()).isEqualTo(2);
+                    AssistStructure.ViewNode doubleNestedView;
+                    AssistStructure.ViewNode secondDoubleNestedView;
+                    if (outerView.getChildAt(0).getIdEntry().equals("doubleNestedView")) {
+                        doubleNestedView = outerView.getChildAt(0);
+                        secondDoubleNestedView = outerView.getChildAt(1);
+                    } else {
+                        secondDoubleNestedView = outerView.getChildAt(0);
+                        doubleNestedView = outerView.getChildAt(1);
+                    }
+                    assertThat(doubleNestedView.getIdEntry()).isEqualTo("doubleNestedView");
+                    assertThat(secondDoubleNestedView.getIdEntry()).isEqualTo
+                            ("secondDoubleNestedView");
+
+                    // The location of the doubleNestedView should include all suppressed parent's
+                    // offset
+                    assertThat(doubleNestedView.getLeft()).isEqualTo(
+                            7              // outerView.left
+                                    + 19); // nestedView.left
+                    assertThat(doubleNestedView.getTop()).isEqualTo(
+                            2              // outerView.top
+                                    + 11); // nestedView.top
+
+                    // The location of the tripleNestedView should be relative to it's parent
+                    assertThat(doubleNestedView.getChildCount()).isEqualTo(1);
+                    AssistStructure.ViewNode tripleNestedView = doubleNestedView.getChildAt(0);
+                    assertThat(doubleNestedView.getIdEntry()).isEqualTo("doubleNestedView");
+
+                    assertThat(tripleNestedView.getLeft()).isEqualTo(37); // doubleNestedView.left
+                    assertThat(tripleNestedView.getTop()).isEqualTo(23); // doubleNestedView.top
+                }
+        );
+    }
+
+    @Test
+    public void checkViewLocationInAssistStructureAfterForceAutofill() throws Exception {
+        onAssistStructure(true, (structure) -> {
+                    AssistStructure.ViewNode outerView = findNodeByResourceId(structure,
+                            "outerView");
+
+                    // The structure should be
+                    //
+                    // outerView
+                    //  nestedView left=7 top=2
+                    //   doubleNestedView left=19 top=11
+                    //    tripleNestedView left=37 top=23
+                    //   secondDoubleNestedView left=19 top=106
+
+                    // Test only what is different from #checkViewLocationInAssistStructure
+                    assertThat(outerView.getChildCount()).isEqualTo(1);
+
+                    AssistStructure.ViewNode nestedView = outerView.getChildAt(0);
+                    assertThat(nestedView.getIdEntry()).isEqualTo("nestedView");
+                    assertThat(nestedView.getLeft()).isEqualTo(7); // outerView.left
+                    assertThat(nestedView.getTop()).isEqualTo(2); // outerView.top
+
+                    assertThat(nestedView.getChildCount()).isEqualTo(2);
+                    AssistStructure.ViewNode doubleNestedView;
+                    if (nestedView.getChildAt(0).getIdEntry().equals("doubleNestedView")) {
+                        doubleNestedView = nestedView.getChildAt(0);
+                    } else {
+                        doubleNestedView = nestedView.getChildAt(1);
+                    }
+                    assertThat(doubleNestedView.getIdEntry()).isEqualTo("doubleNestedView");
+
+                    assertThat(doubleNestedView.getLeft()).isEqualTo(19); // nestedView.left
+                    assertThat(doubleNestedView.getTop()).isEqualTo(11); // nestedView.top
+                }
+        );
+    }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java
index cd1084d..82bf213 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivity.java
@@ -26,6 +26,7 @@
 import android.autofillservice.cts.VirtualContainerView.Line.OneTimeLineWatcher;
 import android.graphics.Canvas;
 import android.os.Bundle;
+import android.view.autofill.AutofillManager;
 
 /**
  * A custom activity that uses {@link Canvas} to draw the following fields:
@@ -59,6 +60,13 @@
     }
 
     /**
+     * Triggers manual autofill in a given line.
+     */
+    void requestAutofill(Line line) {
+        getAutofillManager().requestAutofill(mCustomView, line.text.id, line.bounds);
+    }
+
+    /**
      * Sets the expectation for an auto-fill request, so it can be asserted through
      * {@link #assertAutoFilled()} later.
      */
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
index 739e70e..5aac510 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
@@ -34,6 +34,8 @@
 import android.app.assist.AssistStructure.ViewNode;
 import android.autofillservice.cts.CannedFillResponse.CannedDataset;
 import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
+import android.autofillservice.cts.VirtualContainerView.Line;
+import android.graphics.Rect;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.uiautomator.UiObject2;
 import android.view.autofill.AutofillManager;
@@ -74,12 +76,6 @@
         autofillTest(false);
     }
 
-    @Test
-    public void testAutofillOverrideDispatchProvideAutofillStructure() throws Exception {
-        mActivity.mCustomView.setOverrideDispatchProvideAutofillStructure(true);
-        autofillTest(true);
-    }
-
     /**
      * Tests autofilling the virtual views, using the sync / async version of ViewStructure.addChild
      */
@@ -98,6 +94,13 @@
 
         // Trigger auto-fill.
         mActivity.mUsername.changeFocus(true);
+        assertDatasetShown(mActivity.mUsername, "The Dude");
+
+        // Play around with focus to make sure picker is properly drawn.
+        mActivity.mPassword.changeFocus(true);
+        assertDatasetShown(mActivity.mPassword, "The Dude");
+        mActivity.mUsername.changeFocus(true);
+        assertDatasetShown(mActivity.mUsername, "The Dude");
 
         // Make sure input was sanitized.
         final FillRequest request = sReplier.getNextFillRequest();
@@ -148,6 +151,50 @@
     }
 
     @Test
+    public void testAutofillTwoDatasets() throws Exception {
+        // Set service.
+        enableService();
+
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "dude")
+                        .setField(ID_PASSWORD, "sweet")
+                        .setPresentation(createPresentation("The Dude"))
+                        .build())
+                .addDataset(new CannedDataset.Builder()
+                        .setField(ID_USERNAME, "DUDE")
+                        .setField(ID_PASSWORD, "SWEET")
+                        .setPresentation(createPresentation("THE DUDE"))
+                        .build())
+                .build());
+        mActivity.expectAutoFill("DUDE", "SWEET");
+
+        // Trigger auto-fill.
+        mActivity.mUsername.changeFocus(true);
+        sReplier.getNextFillRequest();
+        assertDatasetShown(mActivity.mUsername, "The Dude", "THE DUDE");
+
+        // Play around with focus to make sure picker is properly drawn.
+        mActivity.mPassword.changeFocus(true);
+        assertDatasetShown(mActivity.mPassword, "The Dude", "THE DUDE");
+        mActivity.mUsername.changeFocus(true);
+        assertDatasetShown(mActivity.mUsername, "The Dude", "THE DUDE");
+
+        // Auto-fill it.
+        sUiBot.selectDataset("THE DUDE");
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+    }
+
+    @Test
+    public void testAutofillOverrideDispatchProvideAutofillStructure() throws Exception {
+        mActivity.mCustomView.setOverrideDispatchProvideAutofillStructure(true);
+        autofillTest(true);
+    }
+
+    @Test
     public void testAutofillManuallyOneDataset() throws Exception {
         // Set service.
         enableService();
@@ -161,8 +208,7 @@
         mActivity.expectAutoFill("dude", "sweet");
 
         // Trigger auto-fill.
-        mActivity.getSystemService(AutofillManager.class).requestAutofill(
-                mActivity.mCustomView, mActivity.mUsername.text.id, mActivity.mUsername.bounds);
+        mActivity.requestAutofill(mActivity.mUsername);
         sReplier.getNextFillRequest();
 
         // Should have been automatically filled.
@@ -296,4 +342,16 @@
         // Assert callback was called
         callback.assertUiUnavailableEvent(mActivity.mCustomView, mActivity.mUsername.text.id);
     }
+
+    /**
+     * Asserts the dataset picker is properly displayed in a give line.
+     */
+    private void assertDatasetShown(Line line, String... expectedDatasets) {
+        final Rect pickerBounds = sUiBot.assertDatasets(expectedDatasets).getVisibleBounds();
+        final Rect fieldBounds = line.getAbsCoordinates();
+        assertWithMessage("vertical coordinates don't match; picker=%s, field=%s", pickerBounds,
+                fieldBounds).that(pickerBounds.top).isEqualTo(fieldBounds.bottom);
+        assertWithMessage("horizontal coordinates don't match; picker=%s, field=%s", pickerBounds,
+                fieldBounds).that(pickerBounds.left).isEqualTo(fieldBounds.left);
+    }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
index 2102773..7c0148e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
@@ -41,6 +41,7 @@
 import android.view.autofill.AutofillValue;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -118,15 +119,24 @@
         super.onDraw(canvas);
 
         Log.d(TAG, "onDraw: " + mLines.size() + " lines; canvas:" + canvas);
-        final float x = mLeftMargin;
+        float x;
         float y = mTopMargin + mLineLength;
         for (int i = 0; i < mLines.size(); i++) {
+            x = mLeftMargin;
             final Line line = mLines.get(i);
             Log.v(TAG, "Drawing '" + line + "' at " + x + "x" + y);
             mTextPaint.setColor(line.focused ? mFocusedColor : mUnfocusedColor);
-            final String text = line.label.text + ":  [" + line.text.text + "]";
-            canvas.drawText(text, x, y, mTextPaint);
-            line.setBounds(x, y);
+            final String readOnlyText = line.label.text + ":  [";
+            final String writeText = line.text.text + "]";
+            // Paints the label first...
+            canvas.drawText(readOnlyText, x, y, mTextPaint);
+            // ...then paints the edit text and sets the proper boundary
+            final float deltaX = mTextPaint.measureText(readOnlyText);
+            x += deltaX;
+            line.bounds.set((int) x, (int) (y - mLineLength),
+                    (int) (x + mTextPaint.measureText(writeText)), (int) y);
+            Log.d(TAG, "setBounds(" + x + ", " + y + "): " + line.bounds);
+            canvas.drawText(writeText, x, y, mTextPaint);
             y += mLineLength;
         }
     }
@@ -243,8 +253,8 @@
 
         final Item label;
         final Item text;
-
-        Rect bounds;
+        // Boundaries of the text field, relative to the CustomView
+        final Rect bounds = new Rect();
 
         private boolean focused;
 
@@ -253,30 +263,30 @@
             this.text = new Item(this, ++nextId, textId, text, true, true);
         }
 
-        void setBounds(float x, float y) {
-            int left = (int) x;
-            int right = (int) (x + mTextPaint.getTextSize());
-            int top = (int) y;
-            int bottom = (int) (y + mTextHeight);
-            if (bounds == null) {
-                bounds = new Rect(left, top, right, bottom);
-            } else {
-                bounds.set(left, top, right, bottom);
-            }
-            Log.d(TAG, "setBounds(" + x + ", " + y + "): " + bounds);
-        }
-
         void changeFocus(boolean focused) {
-            // TODO: fix bounds values
-            Log.d(TAG, "changeFocus() on " + text.id + ": " + focused + " bounds: " + bounds);
             this.focused = focused;
             if (focused) {
-                mAfm.notifyViewEntered(VirtualContainerView.this, text.id, bounds);
+                final Rect absBounds = getAbsCoordinates();
+                Log.d(TAG, "focus gained on " + text.id + "; absBounds=" + absBounds);
+                mAfm.notifyViewEntered(VirtualContainerView.this, text.id, absBounds);
             } else {
+                Log.d(TAG, "focus lost on " + text.id);
                 mAfm.notifyViewExited(VirtualContainerView.this, text.id);
             }
         }
 
+        Rect getAbsCoordinates() {
+            // Must offset the boundaries so they're relative to the CustomView.
+            final int offset[] = new int[2];
+            getLocationOnScreen(offset);
+            final Rect absBounds = new Rect(bounds.left + offset[0],
+                    bounds.top + offset[1],
+                    bounds.right + offset[0], bounds.bottom + offset[1]);
+            Log.v(TAG, "getAbsCoordinates() for " + text.id + ": bounds=" + bounds
+                    + " offset: " + Arrays.toString(offset) + " absBounds: " + absBounds);
+            return absBounds;
+        }
+
         void setTextChangedListener(TextWatcher listener) {
             text.listener = listener;
         }
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index ba902bf..e4ca5af 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -296,12 +296,5 @@
     "android.telecom.cts.WiredHeadsetTest"
   ],
   bug: 26149528
-},
-{
-  desciption: "Seems to be failing on X86, flaky on arm. Root cause to be investigated",
-  names: [
-    "android.webkit.cts.WebViewClientTest#testOnRenderProcessGone"
-  ],
-  bug: 37704262
 }
 ]
diff --git a/tests/fragment/src/android/fragment/cts/FragmentTransactionTest.java b/tests/fragment/src/android/fragment/cts/FragmentTransactionTest.java
index ea713fc..2a532d7 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentTransactionTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentTransactionTest.java
@@ -40,6 +40,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -60,10 +61,27 @@
             new ActivityTestRule<>(FragmentTestActivity.class);
 
     private FragmentTestActivity mActivity;
+    private int mOnBackStackChangedTimes;
+    private FragmentManager.OnBackStackChangedListener mOnBackStackChangedListener;
 
     @Before
     public void setUp() {
         mActivity = mActivityRule.getActivity();
+        mOnBackStackChangedTimes = 0;
+        mOnBackStackChangedListener = new FragmentManager.OnBackStackChangedListener() {
+            @Override
+            public void onBackStackChanged() {
+                mOnBackStackChangedTimes++;
+            }
+        };
+        mActivity.getFragmentManager().addOnBackStackChangedListener(mOnBackStackChangedListener);
+    }
+
+    @After
+    public void tearDown() {
+        mActivity.getFragmentManager()
+                .removeOnBackStackChangedListener(mOnBackStackChangedListener);
+        mOnBackStackChangedListener = null;
     }
 
     @Test
@@ -77,6 +95,7 @@
                         .addToBackStack(null)
                         .commit();
                 mActivity.getFragmentManager().executePendingTransactions();
+                assertEquals(1, mOnBackStackChangedTimes);
             }
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -96,6 +115,7 @@
                             .addToBackStack(null)
                             .commit();
                     mActivity.getFragmentManager().executePendingTransactions();
+                    assertEquals(1, mOnBackStackChangedTimes);
                 } catch (IllegalStateException e) {
                     exceptionThrown = true;
                 } finally {
@@ -120,6 +140,7 @@
                             .addToBackStack(null)
                             .commit();
                     mActivity.getFragmentManager().executePendingTransactions();
+                    assertEquals(1, mOnBackStackChangedTimes);
                 } catch (IllegalStateException e) {
                     exceptionThrown = true;
                 } finally {
@@ -144,6 +165,7 @@
                             .addToBackStack(null)
                             .commit();
                     mActivity.getFragmentManager().executePendingTransactions();
+                    assertEquals(1, mOnBackStackChangedTimes);
                 } catch (IllegalStateException e) {
                     exceptionThrown = true;
                 } finally {
@@ -168,6 +190,7 @@
                             .addToBackStack(null)
                             .commit();
                     mActivity.getFragmentManager().executePendingTransactions();
+                    assertEquals(1, mOnBackStackChangedTimes);
                 } catch (IllegalStateException e) {
                     exceptionThrown = true;
                 } finally {
@@ -193,6 +216,7 @@
                     }
                 }).commit();
                 fm.executePendingTransactions();
+                assertEquals(0, mOnBackStackChangedTimes);
 
                 assertTrue("runOnCommit runnable never ran", ran[0]);
 
@@ -211,6 +235,7 @@
                 }
 
                 fm.executePendingTransactions();
+                assertEquals(0, mOnBackStackChangedTimes);
 
                 assertTrue("runOnCommit was allowed to be called for back stack transaction",
                         threw);
@@ -235,6 +260,7 @@
         Collection<Fragment> fragments = fm.getFragments();
         assertEquals(1, fragments.size());
         assertTrue(fragments.contains(fragment));
+        assertEquals(1, mOnBackStackChangedTimes);
 
         // Removed fragments shouldn't show
         fm.beginTransaction()
@@ -243,18 +269,22 @@
                 .commit();
         FragmentTestUtil.executePendingTransactions(mActivityRule);
         assertTrue(fm.getFragments().isEmpty());
+        assertEquals(2, mOnBackStackChangedTimes);
 
         // Now try detached fragments
         FragmentTestUtil.popBackStackImmediate(mActivityRule);
+        assertEquals(3, mOnBackStackChangedTimes);
         fm.beginTransaction()
                 .detach(fragment)
                 .addToBackStack(null)
                 .commit();
         FragmentTestUtil.executePendingTransactions(mActivityRule);
         assertTrue(fm.getFragments().isEmpty());
+        assertEquals(4, mOnBackStackChangedTimes);
 
         // Now try hidden fragments
         FragmentTestUtil.popBackStackImmediate(mActivityRule);
+        assertEquals(5, mOnBackStackChangedTimes);
         fm.beginTransaction()
                 .hide(fragment)
                 .addToBackStack(null)
@@ -263,15 +293,18 @@
         fragments = fm.getFragments();
         assertEquals(1, fragments.size());
         assertTrue(fragments.contains(fragment));
+        assertEquals(6, mOnBackStackChangedTimes);
 
         // And showing it again shouldn't change anything:
         FragmentTestUtil.popBackStackImmediate(mActivityRule);
         fragments = fm.getFragments();
         assertEquals(1, fragments.size());
         assertTrue(fragments.contains(fragment));
+        assertEquals(7, mOnBackStackChangedTimes);
 
         // Now pop back to the start state
         FragmentTestUtil.popBackStackImmediate(mActivityRule);
+        assertEquals(8, mOnBackStackChangedTimes);
 
         // We can't force concurrency, but we can do it lots of times and hope that
         // we hit it.
@@ -300,6 +333,7 @@
                 .add(fragment1, "1")
                 .commit();
         FragmentTestUtil.executePendingTransactions(mActivityRule);
+        assertEquals(0, mOnBackStackChangedTimes);
         final FragmentManager fm = fragment1.getChildFragmentManager();
         mActivity.getFragmentManager()
                 .beginTransaction()
@@ -308,6 +342,7 @@
         FragmentTestUtil.executePendingTransactions(mActivityRule);
         assertEquals(0, mActivity.getFragmentManager().getFragments().size());
         assertEquals(0, fm.getFragments().size());
+        assertEquals(0, mOnBackStackChangedTimes);
 
         // Now the fragment1's fragment manager should allow commitAllowingStateLoss
         // by doing nothing since it has been detached.
@@ -317,6 +352,7 @@
                 .commitAllowingStateLoss();
         FragmentTestUtil.executePendingTransactions(mActivityRule);
         assertEquals(0, fm.getFragments().size());
+        assertEquals(0, mOnBackStackChangedTimes);
 
         // It should also allow commitNowAllowingStateLoss by doing nothing
         mActivityRule.runOnUiThread(() -> {
@@ -326,6 +362,7 @@
                     .commitNowAllowingStateLoss();
             assertEquals(0, fm.getFragments().size());
         });
+        assertEquals(0, mOnBackStackChangedTimes);
     }
 
     /**
diff --git a/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java b/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java
index 7a73046..6f63e98 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java
@@ -38,6 +38,7 @@
 import com.android.compatibility.common.util.transition.TargetTracking;
 import com.android.compatibility.common.util.transition.TrackingTransition;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -55,6 +56,8 @@
 @RunWith(Parameterized.class)
 public class FragmentTransitionTest {
     private final boolean mReordered;
+    private int mOnBackStackChangedTimes;
+    private FragmentManager.OnBackStackChangedListener mOnBackStackChangedListener;
 
     @Parameterized.Parameters
     public static Object[] data() {
@@ -77,6 +80,20 @@
     public void setup() throws Throwable {
         mFragmentManager = mActivityRule.getActivity().getFragmentManager();
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
+        mOnBackStackChangedTimes = 0;
+        mOnBackStackChangedListener = new FragmentManager.OnBackStackChangedListener() {
+            @Override
+            public void onBackStackChanged() {
+                mOnBackStackChangedTimes++;
+            }
+        };
+        mFragmentManager.addOnBackStackChangedListener(mOnBackStackChangedListener);
+    }
+
+    @After
+    public void teardown() throws Throwable {
+        mFragmentManager.removeOnBackStackChangedListener(mOnBackStackChangedListener);
+        mOnBackStackChangedListener = null;
     }
 
     // Test that normal view transitions (enter, exit, reenter, return) run with
@@ -98,6 +115,7 @@
         fragment.waitForTransition();
         verifyAndClearTransition(fragment.exitTransition, null, green, blue);
         verifyNoOtherTransitions(fragment);
+        assertEquals(2, mOnBackStackChangedTimes);
 
         // reenter transition
         FragmentTestUtil.popBackStackImmediate(mActivityRule);
@@ -106,12 +124,14 @@
         final View blue2 = findBlue();
         verifyAndClearTransition(fragment.reenterTransition, null, green2, blue2);
         verifyNoOtherTransitions(fragment);
+        assertEquals(3, mOnBackStackChangedTimes);
 
         // return transition
         FragmentTestUtil.popBackStackImmediate(mActivityRule);
         fragment.waitForTransition();
         verifyAndClearTransition(fragment.returnTransition, null, green2, blue2);
         verifyNoOtherTransitions(fragment);
+        assertEquals(4, mOnBackStackChangedTimes);
     }
 
     // Test that shared elements transition from one fragment to the next
@@ -125,9 +145,11 @@
         fragment2.setLayoutId(R.layout.scene2);
 
         verifyTransition(fragment1, fragment2, "blueSquare");
+        assertEquals(2, mOnBackStackChangedTimes);
 
         // Now pop the back stack
         verifyPopTransition(1, fragment2, fragment1);
+        assertEquals(3, mOnBackStackChangedTimes);
     }
 
     // Test that shared element transitions through multiple fragments work together
@@ -173,6 +195,7 @@
             }
         });
         FragmentTestUtil.waitForExecution(mActivityRule);
+        assertEquals(2, mOnBackStackChangedTimes);
 
         // should be a normal transition from fragment1 to fragment2
         fragment1.waitForTransition();
@@ -188,6 +211,7 @@
 
         // Pop should also do the same thing
         FragmentTestUtil.popBackStackImmediate(mActivityRule);
+        assertEquals(3, mOnBackStackChangedTimes);
 
         fragment1.waitForTransition();
         fragment2.waitForTransition();
@@ -216,6 +240,7 @@
                 .addToBackStack(null)
                 .commit();
         FragmentTestUtil.waitForExecution(mActivityRule);
+        assertEquals(1, mOnBackStackChangedTimes);
 
         fragment1.waitForTransition();
         final View greenSquare1 = findViewById(fragment1, R.id.greenSquare);
@@ -450,6 +475,7 @@
                 .addToBackStack(null)
                 .commit();
         FragmentTestUtil.waitForExecution(mActivityRule);
+        assertEquals(2, mOnBackStackChangedTimes);
 
         fragment1.waitForTransition();
         fragment2.waitForTransition();
@@ -465,6 +491,7 @@
 
         // Now see if it works when popped
         FragmentTestUtil.popBackStackImmediate(mActivityRule);
+        assertEquals(3, mOnBackStackChangedTimes);
 
         fragment1.waitForTransition();
         fragment2.waitForTransition();
@@ -778,6 +805,7 @@
                 .addToBackStack(null)
                 .commit();
         FragmentTestUtil.waitForExecution(mActivityRule);
+        assertEquals(1, mOnBackStackChangedTimes);
         fragment1.waitForTransition();
         final View blueSquare1 = findBlue();
         final View greenSquare1 = findGreen();
@@ -833,6 +861,7 @@
 
     private void verifyTransition(TransitionFragment from, TransitionFragment to,
             String sharedElementName) throws Throwable {
+        final int startOnBackStackChanged = mOnBackStackChangedTimes;
         final View startBlue = findBlue();
         final View startGreen = findGreen();
         final View startRed = findRed();
@@ -847,6 +876,7 @@
                 .commit();
 
         FragmentTestUtil.waitForExecution(mActivityRule);
+        assertEquals(startOnBackStackChanged + 1, mOnBackStackChangedTimes);
 
         to.waitForTransition();
         final View endGreen = findGreen();
@@ -872,7 +902,8 @@
 
     private void verifyCrossTransition(boolean swapSource,
             TransitionFragment from1, TransitionFragment from2) throws Throwable {
-
+        final int startNumOnBackStackChanged = mOnBackStackChangedTimes;
+        final int changesPerOperation = mReordered ? 1 : 2;
         final TransitionFragment to1 = new TransitionFragment();
         to1.setLayoutId(R.layout.scene2);
         final TransitionFragment to2 = new TransitionFragment();
@@ -906,6 +937,8 @@
         });
         FragmentTestUtil.waitForExecution(mActivityRule);
 
+        assertEquals(startNumOnBackStackChanged + changesPerOperation, mOnBackStackChangedTimes);
+
         from1.waitForTransition();
         from2.waitForTransition();
         to1.waitForTransition();
@@ -937,6 +970,8 @@
             mFragmentManager.popBackStack();
         });
         FragmentTestUtil.waitForExecution(mActivityRule);
+        assertEquals(startNumOnBackStackChanged + changesPerOperation + 1,
+                mOnBackStackChangedTimes);
 
         from1.waitForTransition();
         from2.waitForTransition();
@@ -964,6 +999,7 @@
 
     private void verifyPopTransition(final int numPops, TransitionFragment from,
             TransitionFragment to, TransitionFragment... others) throws Throwable {
+        final int startOnBackStackChanged = mOnBackStackChangedTimes;
         final View startBlue = findBlue();
         final View startGreen = findGreen();
         final View startRed = findRed();
@@ -975,6 +1011,7 @@
             }
         });
         FragmentTestUtil.waitForExecution(mActivityRule);
+        assertEquals(startOnBackStackChanged + 1, mOnBackStackChangedTimes);
 
         to.waitForTransition();
         final View endGreen = findGreen();
diff --git a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
index f0d5947..927552d 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
@@ -298,19 +298,14 @@
         FragmentTestUtil.assertChildren(container);
     }
 
-    // Removing a fragment that isn't in should throw
+    // Removing a fragment that isn't in should not throw
     @Test
-    public void removeNothThere() throws Throwable {
+    public void removeNotThere() throws Throwable {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
         final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
         final StrictViewFragment fragment = new StrictViewFragment();
         fm.beginTransaction().remove(fragment).commit();
-        try {
-            FragmentTestUtil.executePendingTransactions(mActivityRule);
-            fail("Removing a fragment that isn't in should throw an exception");
-        } catch (Throwable t) {
-            // expected
-        }
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
     }
 
     // Hide a fragment and its View should be GONE. Then pop it and the View should be VISIBLE
@@ -342,7 +337,7 @@
         assertEquals(View.VISIBLE, fragment.getView().getVisibility());
     }
 
-    // Hiding a hidden fragment should throw
+    // Hiding a hidden fragment should not throw
     @Test
     public void doubleHide() throws Throwable {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
@@ -353,15 +348,11 @@
                 .hide(fragment)
                 .hide(fragment)
                 .commit();
-        try {
-            FragmentTestUtil.executePendingTransactions(mActivityRule);
-            fail("Hiding a hidden fragment should throw an exception");
-        } catch (Throwable t) {
-            // expected
-        }
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        // should not throw
     }
 
-    // Hiding a non-existing fragment should throw
+    // Hiding a non-existing fragment should not throw
     @Test
     public void hideUnAdded() throws Throwable {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
@@ -370,12 +361,8 @@
         fm.beginTransaction()
                 .hide(fragment)
                 .commit();
-        try {
-            FragmentTestUtil.executePendingTransactions(mActivityRule);
-            fail("Hiding a non-existing fragment should throw an exception");
-        } catch (Throwable t) {
-            // expected
-        }
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        // should not throw
     }
 
     // Show a hidden fragment and its View should be VISIBLE. Then pop it and the View should be
@@ -409,7 +396,7 @@
         assertEquals(View.GONE, fragment.getView().getVisibility());
     }
 
-    // Showing a shown fragment should throw
+    // Showing a shown fragment should not throw
     @Test
     public void showShown() throws Throwable {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
@@ -419,15 +406,11 @@
                 .add(R.id.fragmentContainer, fragment)
                 .show(fragment)
                 .commit();
-        try {
-            FragmentTestUtil.executePendingTransactions(mActivityRule);
-            fail("Showing a visible fragment should throw an exception");
-        } catch (Throwable t) {
-            // expected
-        }
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        // should not throw
     }
 
-    // Showing a non-existing fragment should throw
+    // Showing a non-existing fragment should not throw
     @Test
     public void showUnAdded() throws Throwable {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
@@ -436,12 +419,8 @@
         fm.beginTransaction()
                 .show(fragment)
                 .commit();
-        try {
-            FragmentTestUtil.executePendingTransactions(mActivityRule);
-            fail("Showing a non-existing fragment should throw an exception");
-        } catch (Throwable t) {
-            // expected
-        }
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        // should not throw
     }
 
     // Detaching a fragment should remove the View from the hierarchy. Then popping it should
@@ -507,7 +486,7 @@
         assertEquals(View.GONE, fragment.getView().getVisibility());
     }
 
-    // Detaching a detached fragment should throw
+    // Detaching a detached fragment should not throw
     @Test
     public void detachDetatched() throws Throwable {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
@@ -518,15 +497,11 @@
                 .detach(fragment)
                 .detach(fragment)
                 .commit();
-        try {
-            FragmentTestUtil.executePendingTransactions(mActivityRule);
-            fail("Detaching a detached fragment should throw an exception");
-        } catch (Throwable t) {
-            // expected
-        }
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        // should not throw
     }
 
-    // Detaching a non-existing fragment should throw
+    // Detaching a non-existing fragment should not throw
     @Test
     public void detachUnAdded() throws Throwable {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
@@ -535,12 +510,8 @@
         fm.beginTransaction()
                 .detach(fragment)
                 .commit();
-        try {
-            FragmentTestUtil.executePendingTransactions(mActivityRule);
-            fail("Detaching a non-existing fragment should throw an exception");
-        } catch (Throwable t) {
-            // expected
-        }
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        // should not throw
     }
 
     // Attaching a fragment should add the View back into the hierarchy. Then popping it should
@@ -608,7 +579,7 @@
         assertTrue(fragment.isHidden());
     }
 
-    // Attaching an attached fragment should throw
+    // Attaching an attached fragment should not throw
     @Test
     public void attachAttached() throws Throwable {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
@@ -618,15 +589,11 @@
                 .add(R.id.fragmentContainer, fragment)
                 .attach(fragment)
                 .commit();
-        try {
-            FragmentTestUtil.executePendingTransactions(mActivityRule);
-            fail("Attaching an attached fragment should throw an exception");
-        } catch (Throwable t) {
-            // expected
-        }
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        // should not throw an exception
     }
 
-    // Attaching a non-existing fragment should throw
+    // Attaching a non-existing fragment should not throw
     @Test
     public void attachUnAdded() throws Throwable {
         FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
@@ -635,12 +602,8 @@
         fm.beginTransaction()
                 .attach(fragment)
                 .commit();
-        try {
-            FragmentTestUtil.executePendingTransactions(mActivityRule);
-            fail("Attaching a non-existing fragment should throw an exception");
-        } catch (Throwable t) {
-            // expected
-        }
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        // should not throw
     }
 
     // Simple replace of one fragment in a container. Popping should replace it back again
diff --git a/tests/fragment/src/android/fragment/cts/TransitionFragment.java b/tests/fragment/src/android/fragment/cts/TransitionFragment.java
index fbe2250..17363ac 100644
--- a/tests/fragment/src/android/fragment/cts/TransitionFragment.java
+++ b/tests/fragment/src/android/fragment/cts/TransitionFragment.java
@@ -71,7 +71,7 @@
     }
 
     void waitForTransition() throws InterruptedException {
-        verify(mListener, within(300)).onTransitionEnd(any());
+        verify(mListener, within(500)).onTransitionEnd(any());
         reset(mListener);
     }
 
diff --git a/tests/sensor/jni/SensorTestCases.cpp b/tests/sensor/jni/SensorTestCases.cpp
index f86f262..43e07a4 100644
--- a/tests/sensor/jni/SensorTestCases.cpp
+++ b/tests/sensor/jni/SensorTestCases.cpp
@@ -135,7 +135,7 @@
 // Test sensor direct report functionality
 void SensorTest::testDirectReport(JNIEnv* env, int32_t sensorType, int32_t channelType, int32_t rateLevel) {
     constexpr size_t kEventSize = sizeof(ASensorEvent);
-    constexpr size_t kNEvent = 500;
+    constexpr size_t kNEvent = 4096; // enough to contain 1.5 * 800 * 2.2 events
     constexpr size_t kMemSize = kEventSize * kNEvent;
 
     // value check criterion
diff --git a/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java b/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
index 6c2462f..78ac59d 100644
--- a/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
@@ -65,7 +65,8 @@
     private static final int TEST_RUN_TIME_PERIOD_MILLISEC = 5000;
     private static final int ALLOWED_SENSOR_INIT_TIME_MILLISEC = 500;
     private static final int SENSORS_EVENT_SIZE = 104;
-    private static final int SHARED_MEMORY_SIZE = 2000 * SENSORS_EVENT_SIZE;
+    private static final int SENSORS_EVENT_COUNT = 10240; // 800Hz * 2.2 * 5 sec + extra
+    private static final int SHARED_MEMORY_SIZE = SENSORS_EVENT_COUNT * SENSORS_EVENT_SIZE;
     private static final float MERCY_FACTOR = 0.1f;
 
     private static native boolean nativeReadHardwareBuffer(HardwareBuffer hardwareBuffer,
diff --git a/tests/tests/content/res/font/broken_xmlfont.xml b/tests/tests/content/res/font/broken_xmlfont.xml
new file mode 100644
index 0000000..be30f2f
--- /dev/null
+++ b/tests/tests/content/res/font/broken_xmlfont.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+  <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/brokenfont" />
+</font-family>
diff --git a/tests/tests/content/res/font/brokenfont.ttf b/tests/tests/content/res/font/brokenfont.ttf
new file mode 100644
index 0000000..12b2713
--- /dev/null
+++ b/tests/tests/content/res/font/brokenfont.ttf
Binary files differ
diff --git a/tests/tests/content/res/font/brokenfont_source.ttx b/tests/tests/content/res/font/brokenfont_source.ttx
new file mode 100644
index 0000000..34217b4
--- /dev/null
+++ b/tests/tests/content/res/font/brokenfont_source.ttx
@@ -0,0 +1,177 @@
+<?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.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Mon May 1 00:00:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="a" width="500" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="a" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Broken Font
+    </namerecord>
+    <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Broken Font
+    </namerecord>
+    <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      BrokenFont-Regular
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Broken Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Broken Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      BrokenFont-Regular
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/tests/tests/content/res/font/invalid_xmlfont_nosource.xml b/tests/tests/content/res/font/invalid_xmlfont_nosource.xml
new file mode 100644
index 0000000..6b70222
--- /dev/null
+++ b/tests/tests/content/res/font/invalid_xmlfont_nosource.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+  <!-- missing the android:font entry -->
+  <font android:fontStyle="normal" android:fontWeight="400" />
+</font-family>
diff --git a/tests/tests/content/res/font/sample_bold_family.xml b/tests/tests/content/res/font/sample_bold_family.xml
new file mode 100644
index 0000000..7c09f27
--- /dev/null
+++ b/tests/tests/content/res/font/sample_bold_family.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+    <font android:font="@font/sample_bold_font" />
+</font-family>
diff --git a/tests/tests/content/res/font/sample_bold_font.ttf b/tests/tests/content/res/font/sample_bold_font.ttf
new file mode 100644
index 0000000..de4cb7e
--- /dev/null
+++ b/tests/tests/content/res/font/sample_bold_font.ttf
Binary files differ
diff --git a/tests/tests/content/res/font/sample_bold_font_source.ttx b/tests/tests/content/res/font/sample_bold_font_source.ttx
new file mode 100644
index 0000000..5fcb8ce
--- /dev/null
+++ b/tests/tests/content/res/font/sample_bold_font_source.ttx
@@ -0,0 +1,186 @@
+<?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.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="500"/>
+    <usWeightClass value="700"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/> <!-- the last bit is for italic -->
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="a" width="500" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="a" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0">
+      <!-- FreeType treats empty table as missing table. Then if glyf table is missing, FreeType
+           treats the font as old Mac font and ignores OS/2 table. Thus needs outline here. -->
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="100" y="0" on="1"/>
+        <pt x="50" y="100" on="1"/>
+      </contour>
+      <instructions><assembly></assembly></instructions>
+    </TTGlyph>
+  </glyf>
+
+  <name>
+    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/tests/tests/content/res/font/sample_bolditalic_family.xml b/tests/tests/content/res/font/sample_bolditalic_family.xml
new file mode 100644
index 0000000..e467b38
--- /dev/null
+++ b/tests/tests/content/res/font/sample_bolditalic_family.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+    <font android:font="@font/sample_bolditalic_font" />
+</font-family>
diff --git a/tests/tests/content/res/font/sample_bolditalic_font.ttf b/tests/tests/content/res/font/sample_bolditalic_font.ttf
new file mode 100644
index 0000000..4a35061
--- /dev/null
+++ b/tests/tests/content/res/font/sample_bolditalic_font.ttf
Binary files differ
diff --git a/tests/tests/content/res/font/sample_bolditalic_font_source.ttx b/tests/tests/content/res/font/sample_bolditalic_font_source.ttx
new file mode 100644
index 0000000..37e97d8
--- /dev/null
+++ b/tests/tests/content/res/font/sample_bolditalic_font_source.ttx
@@ -0,0 +1,186 @@
+<?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.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="500"/>
+    <usWeightClass value="700"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000001"/> <!-- the last bit is for italic -->
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="a" width="500" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="a" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0">
+      <!-- FreeType treats empty table as missing table. Then if glyf table is missing, FreeType
+           treats the font as old Mac font and ignores OS/2 table. Thus needs outline here. -->
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="100" y="0" on="1"/>
+        <pt x="50" y="100" on="1"/>
+      </contour>
+      <instructions><assembly></assembly></instructions>
+    </TTGlyph>
+  </glyf>
+
+  <name>
+    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/tests/tests/content/res/font/sample_italic_family.xml b/tests/tests/content/res/font/sample_italic_family.xml
new file mode 100644
index 0000000..18a0a04
--- /dev/null
+++ b/tests/tests/content/res/font/sample_italic_family.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+    <font android:font="@font/sample_italic_font" />
+</font-family>
diff --git a/tests/tests/content/res/font/sample_italic_font.ttf b/tests/tests/content/res/font/sample_italic_font.ttf
new file mode 100644
index 0000000..1278e14
--- /dev/null
+++ b/tests/tests/content/res/font/sample_italic_font.ttf
Binary files differ
diff --git a/tests/tests/content/res/font/sample_italic_font_source.ttx b/tests/tests/content/res/font/sample_italic_font_source.ttx
new file mode 100644
index 0000000..870b35c
--- /dev/null
+++ b/tests/tests/content/res/font/sample_italic_font_source.ttx
@@ -0,0 +1,186 @@
+<?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.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="500"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000001"/>  <!-- the last bit is for italic -->
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="a" width="500" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="a" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0">
+      <!-- FreeType treats empty table as missing table. Then if glyf table is missing, FreeType
+           treats the font as old Mac font and ignores OS/2 table. Thus needs outline here. -->
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="100" y="0" on="1"/>
+        <pt x="50" y="100" on="1"/>
+      </contour>
+      <instructions><assembly></assembly></instructions>
+    </TTGlyph>
+  </glyf>
+
+  <name>
+    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/tests/tests/content/res/font/sample_regular_family.xml b/tests/tests/content/res/font/sample_regular_family.xml
new file mode 100644
index 0000000..7b4da4c
--- /dev/null
+++ b/tests/tests/content/res/font/sample_regular_family.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+    <font android:font="@font/sample_regular_font" />
+</font-family>
diff --git a/tests/tests/content/res/font/sample_regular_font.ttf b/tests/tests/content/res/font/sample_regular_font.ttf
new file mode 100644
index 0000000..8e3d602
--- /dev/null
+++ b/tests/tests/content/res/font/sample_regular_font.ttf
Binary files differ
diff --git a/tests/tests/content/res/font/sample_regular_font_source.ttx b/tests/tests/content/res/font/sample_regular_font_source.ttx
new file mode 100644
index 0000000..cffee51
--- /dev/null
+++ b/tests/tests/content/res/font/sample_regular_font_source.ttx
@@ -0,0 +1,186 @@
+<?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.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="500"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>  <!-- the last bit is for italic -->
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="a" width="500" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="a" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0">
+      <!-- FreeType treats empty table as missing table. Then if glyf table is missing, FreeType
+           treats the font as old Mac font and ignores OS/2 table. Thus needs outline here. -->
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="100" y="0" on="1"/>
+        <pt x="50" y="100" on="1"/>
+      </contour>
+      <instructions><assembly></assembly></instructions>
+    </TTGlyph>
+  </glyf>
+
+  <name>
+    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/tests/tests/content/src/android/content/pm/cts/InstantAppTest.java b/tests/tests/content/src/android/content/pm/cts/InstantAppTest.java
new file mode 100644
index 0000000..81263d1
--- /dev/null
+++ b/tests/tests/content/src/android/content/pm/cts/InstantAppTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.content.pm.cts;
+
+
+import android.content.cts.MockActivity;
+
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Test instant apps.
+ */
+public class InstantAppTest extends AndroidTestCase {
+    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+
+    private PackageManager mPackageManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mPackageManager = getContext().getPackageManager();
+    }
+
+    /** Ensure only one resolver is defined */
+    public void testInstantAppResolverQuery() {
+        final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE);
+        final int resolveFlags =
+                MATCH_DIRECT_BOOT_AWARE
+                | MATCH_DIRECT_BOOT_UNAWARE
+                | MATCH_SYSTEM_ONLY;
+        final List<ResolveInfo> matches =
+                mPackageManager.queryIntentServices(resolverIntent, resolveFlags);
+        assertTrue(matches == null || matches.size() <= 1);
+    }
+
+    /** Ensure only one resolver is defined */
+    public void testInstantAppInstallerQuery() {
+        final Intent intent = new Intent(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
+        final int resolveFlags =
+                MATCH_DIRECT_BOOT_AWARE
+                | MATCH_DIRECT_BOOT_UNAWARE
+                | MATCH_SYSTEM_ONLY;
+        final List<ResolveInfo> matches =
+                mPackageManager.queryIntentActivities(intent, resolveFlags);
+        assertTrue(matches == null || matches.size() <= 1);
+    }
+}
diff --git a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
index 89ea29b..e8fe4bf 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -814,6 +814,30 @@
         } catch (RuntimeException e) {
             // pass
         }
+
+        try {
+            mResources.getFont(R.font.invalid_xmlfont_nosource);
+            fail();
+        } catch (RuntimeException e) {
+            // pass
+        }
+
+    }
+
+    public void testGetFont_brokenFontFiles() {
+        try {
+            mResources.getFont(R.font.brokenfont);
+            fail();
+        } catch (RuntimeException e) {
+            // pass
+        }
+
+        try {
+            mResources.getFont(R.font.broken_xmlfont);
+            fail();
+        } catch (RuntimeException e) {
+            // pass
+        }
     }
 
     public void testGetFont_fontFileIsCached() {
@@ -829,4 +853,18 @@
 
         assertEquals(font, font2);
     }
+
+    public void testGetFont_resolveByFontTable() {
+        assertEquals(Typeface.NORMAL, mResources.getFont(R.font.sample_regular_font).getStyle());
+        assertEquals(Typeface.BOLD, mResources.getFont(R.font.sample_bold_font).getStyle());
+        assertEquals(Typeface.ITALIC, mResources.getFont(R.font.sample_italic_font).getStyle());
+        assertEquals(Typeface.BOLD_ITALIC,
+                mResources.getFont(R.font.sample_bolditalic_font).getStyle());
+
+        assertEquals(Typeface.NORMAL, mResources.getFont(R.font.sample_regular_family).getStyle());
+        assertEquals(Typeface.BOLD, mResources.getFont(R.font.sample_bold_family).getStyle());
+        assertEquals(Typeface.ITALIC, mResources.getFont(R.font.sample_italic_family).getStyle());
+        assertEquals(Typeface.BOLD_ITALIC,
+                mResources.getFont(R.font.sample_bolditalic_family).getStyle());
+    }
 }
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index 3059d71..af59cbf 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -40,6 +40,9 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
+# Enforce public / test api only
+LOCAL_SDK_VERSION := test_current
+
 include $(BUILD_CTS_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/graphics/res/drawable/vector_icon_size_1.xml b/tests/tests/graphics/res/drawable/vector_icon_size_1.xml
new file mode 100644
index 0000000..1c57e30
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_size_1.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="7dp"
+        android:height="7dp"
+        android:viewportWidth="20.0"
+        android:viewportHeight="50.0">
+    <path
+        android:pathData="M14.285706,47.362198A50.71429,62.14286 0,0 0,1.0630035 5.5146027"
+        android:fillColor="#ff55ff"/>
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_size_2.xml b/tests/tests/graphics/res/drawable/vector_icon_size_2.xml
new file mode 100644
index 0000000..1069e5c
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_size_2.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="9dp"
+        android:height="9dp"
+        android:viewportWidth="20.0"
+        android:viewportHeight="50.0">
+    <path
+        android:pathData="M14.285706,47.362198A50.71429,62.14286 0,0 0,1.0630035 5.5146027"
+        android:fillColor="#ff55ff"/>
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
index 0d43322..fc23fb2 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
@@ -29,9 +29,11 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.ColorSpace;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.os.Parcel;
+import android.os.StrictMode;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -389,6 +391,51 @@
     }
 
     @Test
+    public void testCreateBitmap_displayMetrics_mutable() {
+        DisplayMetrics metrics =
+                InstrumentationRegistry.getTargetContext().getResources().getDisplayMetrics();
+
+        Bitmap bitmap;
+        bitmap = Bitmap.createBitmap(metrics, 10, 10, Config.ARGB_8888);
+        assertTrue(bitmap.isMutable());
+        assertEquals(metrics.densityDpi, bitmap.getDensity());
+
+        bitmap = Bitmap.createBitmap(metrics, 10, 10, Config.ARGB_8888);
+        assertTrue(bitmap.isMutable());
+        assertEquals(metrics.densityDpi, bitmap.getDensity());
+
+        bitmap = Bitmap.createBitmap(metrics, 10, 10, Config.ARGB_8888, true);
+        assertTrue(bitmap.isMutable());
+        assertEquals(metrics.densityDpi, bitmap.getDensity());
+
+        bitmap = Bitmap.createBitmap(metrics, 10, 10, Config.ARGB_8888, true, ColorSpace.get(
+                ColorSpace.Named.SRGB));
+
+        assertTrue(bitmap.isMutable());
+        assertEquals(metrics.densityDpi, bitmap.getDensity());
+
+        int[] colors = createColors(100);
+        assertNotNull(Bitmap.createBitmap(metrics, colors, 0, 10, 10, 10, Config.ARGB_8888));
+        assertNotNull(Bitmap.createBitmap(metrics, colors, 10, 10, Config.ARGB_8888));
+    }
+
+    @Test
+    public void testCreateBitmap_displayMetrics_immutable() {
+        DisplayMetrics metrics =
+                InstrumentationRegistry.getTargetContext().getResources().getDisplayMetrics();
+        int[] colors = createColors(100);
+
+        Bitmap bitmap;
+        bitmap = Bitmap.createBitmap(metrics, colors, 0, 10, 10, 10, Config.ARGB_8888);
+        assertFalse(bitmap.isMutable());
+        assertEquals(metrics.densityDpi, bitmap.getDensity());
+
+        bitmap = Bitmap.createBitmap(metrics, colors, 10, 10, Config.ARGB_8888);
+        assertFalse(bitmap.isMutable());
+        assertEquals(metrics.densityDpi, bitmap.getDensity());
+    }
+
+    @Test
     public void testCreateScaledBitmap() {
         mBitmap = Bitmap.createBitmap(100, 200, Config.RGB_565);
         Bitmap ret = Bitmap.createScaledBitmap(mBitmap, 50, 100, false);
@@ -398,6 +445,27 @@
     }
 
     @Test
+    public void testGenerationId() {
+        Bitmap bitmap = Bitmap.createBitmap(10, 10, Config.ARGB_8888);
+        int genId = bitmap.getGenerationId();
+        assertEquals("not expected to change", genId, bitmap.getGenerationId());
+        bitmap.setDensity(bitmap.getDensity() + 4);
+        assertEquals("not expected to change", genId, bitmap.getGenerationId());
+        bitmap.getPixel(0, 0);
+        assertEquals("not expected to change", genId, bitmap.getGenerationId());
+
+        int beforeGenId = bitmap.getGenerationId();
+        bitmap.eraseColor(Color.WHITE);
+        int afterGenId = bitmap.getGenerationId();
+        assertTrue("expected to increase", afterGenId > beforeGenId);
+
+        beforeGenId = bitmap.getGenerationId();
+        bitmap.setPixel(4, 4, Color.BLUE);
+        afterGenId = bitmap.getGenerationId();
+        assertTrue("expected to increase again", afterGenId > beforeGenId);
+    }
+
+    @Test
     public void testDescribeContents() {
         assertEquals(0, mBitmap.describeContents());
     }
@@ -1333,6 +1401,68 @@
     }
 
     @Test
+    public void testCopyHWBitmapInStrictMode() {
+        strictModeTest(()->{
+            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
+            hwBitmap.copy(Config.ARGB_8888, false);
+        });
+    }
+
+    @Test
+    public void testCreateScaledFromHWInStrictMode() {
+        strictModeTest(()->{
+            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
+            Bitmap.createScaledBitmap(hwBitmap, 200, 200, false);
+        });
+    }
+
+    @Test
+    public void testExtractAlphaFromHWInStrictMode() {
+        strictModeTest(()->{
+            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
+            hwBitmap.extractAlpha();
+        });
+    }
+
+    @Test
+    public void testCompressInStrictMode() {
+        strictModeTest(()->{
+            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+            bitmap.compress(CompressFormat.JPEG, 90, new ByteArrayOutputStream());
+        });
+    }
+
+    @Test
+    public void testParcelHWInStrictMode() {
+        strictModeTest(()->{
+            mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+            Bitmap hwBitmap = mBitmap.copy(Config.HARDWARE, false);
+            hwBitmap.writeToParcel(Parcel.obtain(), 0);
+        });
+    }
+
+    @Test
+    public void testSameAsFirstHWInStrictMode() {
+        strictModeTest(()->{
+            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
+            hwBitmap.sameAs(bitmap);
+        });
+    }
+
+    @Test
+    public void testSameAsSecondHWInStrictMode() {
+        strictModeTest(()->{
+            Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+            Bitmap hwBitmap = bitmap.copy(Config.HARDWARE, false);
+            bitmap.sameAs(hwBitmap);
+        });
+    }
+
+    @Test
     public void testNdkAccessAfterRecycle() {
         Bitmap bitmap = Bitmap.createBitmap(10, 20, Config.RGB_565);
         nValidateBitmapInfo(bitmap, 10, 20, true);
@@ -1341,6 +1471,20 @@
         nValidateNdkAccessAfterRecycle(bitmap);
     }
 
+    private void strictModeTest(Runnable runnable) {
+        StrictMode.ThreadPolicy originalPolicy = StrictMode.getThreadPolicy();
+        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+                .detectCustomSlowCalls().penaltyDeath().build());
+        try {
+            runnable.run();
+            fail("Shouldn't reach it");
+        } catch (RuntimeException expected){
+            // expect to receive StrictModeViolation
+        } finally {
+            StrictMode.setThreadPolicy(originalPolicy);
+        }
+    }
+
     private static native void nValidateBitmapInfo(Bitmap bitmap, int width, int height,
             boolean is565);
     private static native void nValidateNdkAccessAfterRecycle(Bitmap bitmap);
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index 52db21f..b36c23a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -1153,6 +1153,13 @@
     }
 
     @Test
+    public void testClipOutPath() {
+        final Path p = new Path();
+        p.addRect(new RectF(5, 5, 10, 10), Direction.CW);
+        assertTrue(mCanvas.clipOutPath(p));
+    }
+
+    @Test
     public void testClipInversePath() {
         final Path p = new Path();
         p.addRoundRect(new RectF(0, 0, 10, 10), 0.5f, 0.5f, Direction.CW);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java
index 5ade66e..54021b9 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java
@@ -1,17 +1,18 @@
-package android.graphics.drawable;
+package android.graphics.drawable.cts;
 
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.Path.Direction;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.test.AndroidTestCase;
 import android.util.Log;
 import java.io.File;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconMaskTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconMaskTest.java
index 5102ef9..99d1327 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconMaskTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconMaskTest.java
@@ -30,10 +30,10 @@
 import android.graphics.Region.Op;
 import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.ColorDrawable;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
-import android.util.PathParser;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -53,6 +53,8 @@
     private ColorDrawable mBlueDrawable;
     private ColorDrawable mRedDrawable;
     private AdaptiveIconDrawable mDrawable;
+    private static final float sMaskSize = AdaptiveIconDrawable.MASK_SIZE;
+    private boolean mUseRoundIcon;
 
     @Before
     public void setup() {
@@ -60,12 +62,15 @@
         mRedDrawable = new ColorDrawable(Color.RED);
         mDrawable = new AdaptiveIconDrawable( mBlueDrawable, mRedDrawable);
 
-        String path = Resources.getSystem().getString(com.android.internal.R.string.config_icon_mask);
-        L("config_icon_mask: " + path);
-        mMask = PathParser.createPathFromPathData(path);
+        mMask = mDrawable.getIconMask();
+
         int sInset = (int) (SAFEZONE_INSET * AdaptiveIconDrawable.MASK_SIZE);
         mSafeZone.addCircle(AdaptiveIconDrawable.MASK_SIZE/2, AdaptiveIconDrawable.MASK_SIZE/2,
             AdaptiveIconDrawable.MASK_SIZE/2/2 - sInset, Direction.CW);
+        mUseRoundIcon =  Resources.getSystem().getBoolean(
+            InstrumentationRegistry.getTargetContext().getResources().getIdentifier(
+                "config_useRoundIcon", "bool", "android"));
+        L("config_useRoundIcon:" + mUseRoundIcon);
     }
 
     @Test
@@ -75,7 +80,6 @@
         // Bounds should be [100 x 100]
         RectF bounds = new RectF();
         mMask.computeBounds(bounds, true);
-        System.out.println("MERONG:" + bounds.toShortString());
         assertTrue("Mask top should be larger than or equal to 0", -DELTA <= bounds.top);
         assertTrue("Mask left should be larger than or equal to 0", -DELTA <= bounds.left);
         assertTrue("Mask bottom should be smaller than or equal to" +
@@ -112,7 +116,6 @@
     @Test
     public void testDeviceConfigMask_isConvex() {
         assertNotNull(mMask);
-
         assertTrue("Mask is not convex", mMask.isConvex());
     }
 
@@ -123,4 +126,28 @@
         assertEquals("Foreground layer is not the same.",
             mRedDrawable, mDrawable.getForeground());
     }
+
+    @Test
+    public void testDeviceConfig_iconMask_useRoundIcon() {
+        assertNotNull(mMask);
+
+        boolean circleMask = isCircle(mMask);
+        // If mask shape is circle, then mUseRoundIcon should be defined and should be true.
+        // If mask shape is not a circle
+        //           mUseRoundIcon doesn't have to be defined.
+        //           if mUseRoundIcon is defined, then should be false
+        assertEquals(mUseRoundIcon, circleMask);
+    }
+
+    private boolean isCircle(Path maskPath) {
+        Path circle101 = new Path();
+        circle101.addCircle(50, 50, 50.5f, Direction.CCW);
+        Path circle99 = new Path();
+        circle99.addCircle(50, 50, 49.5f, Direction.CCW);
+        circle99.op(maskPath, Path.Op.DIFFERENCE);
+        boolean fullyEnclosesSmallerCircle = circle99.isEmpty();
+        maskPath.op(circle101, Path.Op.DIFFERENCE);
+        boolean fullyEnclosedByLargerCircle = maskPath.isEmpty();
+        return fullyEnclosedByLargerCircle && fullyEnclosesSmallerCircle;
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableSizeTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableSizeTest.java
new file mode 100644
index 0000000..0b50f35
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableSizeTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.graphics.drawable.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.cts.R;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.VectorDrawable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+
+@MediumTest
+@RunWith(Parameterized.class)
+public class VectorDrawableSizeTest {
+    private Context mContext = null;
+    private Resources mResources = null;
+    private int mResId;
+    private int mDpSize;
+
+    @Parameters ( name = "{0}" )
+    public static Iterable<Object[]> data() {
+        return Arrays.asList(new Object[][]{
+                {"size_1", R.drawable.vector_icon_size_1, 7},
+                {"size_2", R.drawable.vector_icon_size_2, 9}
+        });
+    }
+
+    public VectorDrawableSizeTest(String name, int resId, int dp) throws Throwable {
+        mResId = resId;
+        mDpSize = dp;
+    }
+
+    @Before
+    public void setup() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mResources = mContext.getResources();
+
+    }
+
+    @Test
+    public void testVectorDrawableSize() throws Throwable {
+        // This test makes sure the size computation for VectorDrawable is using round, instead of
+        // rounding down.
+        final int densityDpi = mResources.getConfiguration().densityDpi;
+
+        VectorDrawable drawable = (VectorDrawable) mResources.getDrawable(mResId, null);
+        assertEquals(Math.round(mDpSize * densityDpi / 160f),  drawable.getIntrinsicWidth());
+        assertEquals(Math.round(mDpSize * densityDpi / 160f),  drawable.getIntrinsicHeight());
+
+        final Drawable.ConstantState constantState = drawable.getConstantState();
+
+        DrawableTestUtils.setResourcesDensity(mResources, densityDpi / 2);
+        final VectorDrawable halfDrawable =
+                (VectorDrawable) constantState.newDrawable(mResources);
+
+        assertEquals(Math.round(mDpSize * densityDpi / 320f),  halfDrawable.getIntrinsicWidth());
+        assertEquals(Math.round(mDpSize * densityDpi / 320f),  halfDrawable.getIntrinsicHeight());
+
+        // Reset the density
+        DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
+    }
+}
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
index 4721afb..ec81980 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
@@ -47,18 +47,23 @@
 
 // This is not the complete list - just a small subset
 // of the libraries that should reside in /system/lib
+// for app-compatibility reasons.
 // (in addition to kSystemPublicLibraries)
 static std::vector<std::string> kSystemLibraries = {
     "libart.so",
     "libandroid_runtime.so",
     "libbinder.so",
+    "libcrypto.so",
     "libcutils.so",
+    "libexpat.so",
     "libgui.so",
     "libmedia.so",
     "libnativehelper.so",
     "libstagefright.so",
+    "libsqlite.so",
     "libui.so",
     "libutils.so",
+    "libvorbisidec.so",
   };
 
 static bool is_directory(const std::string& path) {
@@ -70,22 +75,20 @@
   return false;
 }
 
-static bool already_loaded(const std::string& library, const std::string& err) {
-  // SELinux denials for /vendor libraries may return with library not found
-  if (err.find("dlopen failed: library \"" + library + "\"") == 0 &&
-      (err.find("not found") != std::string::npos ||
-      err.find("is not accessible for the namespace \"classloader-namespace\"") != std::string::npos)) {
-    return true;
-  }
-
-  return false;
+static bool not_accessible(const std::string& library, const std::string& err) {
+  return err.find("dlopen failed: library \"" + library + "\"") == 0 &&
+         err.find("is not accessible for the namespace \"classloader-namespace\"") != std::string::npos;
 }
 
-static bool wrong_arch(const std::string& err) {
+static bool not_found(const std::string& library, const std::string& err) {
+  return err == "dlopen failed: library \"" + library + "\" not found";
+}
+
+static bool wrong_arch(const std::string& library, const std::string& err) {
   // https://issuetracker.google.com/37428428
   // It's okay to not be able to load a library because it's for another
   // architecture (typically on an x86 device, when we come across an arm library).
-  return err.find("unexpected e_machine: ") != std::string::npos;
+  return err.find("dlopen failed: library \"" + library + "\" has unexpected e_machine: ") == 0;
 }
 
 static bool check_lib(const std::string& path,
@@ -114,7 +117,7 @@
   } else { // (handle == nullptr && !shouldBeAccessible(path))
     // Check the error message
     std::string err = dlerror();
-    if (!already_loaded(path, err) && !wrong_arch(err)) {
+    if (!not_accessible(path, err) && !not_found(path, err) && !wrong_arch(path, err)) {
       errors->push_back("unexpected dlerror: " + err);
       return false;
     }
@@ -240,9 +243,9 @@
     void* handle = dlopen(library.c_str(), RTLD_NOW);
     if (handle == nullptr) {
       std::string err = dlerror();
-      // If the library is already loaded, then dlopen failing is okay.
-      if (!already_loaded(library, err)) {
-          errors.push_back("Mandatory system library \"" + library + "\" failed to load: " + err);
+      // The libraries should be present and produce specific dlerror when inaccessible.
+      if (!not_accessible(library, err)) {
+          errors.push_back("Mandatory system library \"" + library + "\" failed to load with unexpected error: " + err);
           success = false;
       }
     } else {
diff --git a/tests/tests/location/AndroidManifest.xml b/tests/tests/location/AndroidManifest.xml
index f9985ba..1357a38 100644
--- a/tests/tests/location/AndroidManifest.xml
+++ b/tests/tests/location/AndroidManifest.xml
@@ -27,6 +27,10 @@
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
 
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />>
+    <uses-permission android:name="android.permission.INTERNET" />
+
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.location.cts"
                      android:label="CTS tests of android.location">
diff --git a/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java b/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java
new file mode 100644
index 0000000..5fa09c2
--- /dev/null
+++ b/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2017 Google Inc.
+ *
+ * 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.location.cts;
+
+import android.location.Criteria;
+import android.location.Location;
+import android.location.LocationManager;
+import android.util.Log;
+
+/**
+ * Test the {@link Location} values.
+ *
+ * Test steps:
+ * 1. Register for location updates.
+ * 2. Wait for {@link #LOCATION_TO_COLLECT_COUNT} locations.
+ *          3.1 Confirm locations have been found.
+ * 3. Get LastKnownLocation, verified all fields are in the correct range.
+ */
+public class GnssLocationValuesTest extends GnssTestCase {
+
+  private static final String TAG = "GnssLocationValuesTest";
+  private static final int LOCATION_TO_COLLECT_COUNT = 5;
+  private TestLocationListener mLocationListener;
+  private static final int LOCATION_UNCERTIANTY_MIN_YEAR = 2017;
+  private boolean extendedLocationAccuracyExpected = false;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    mTestLocationManager = new TestLocationManager(getContext());
+    int gnssYearOfHardware = mTestLocationManager.getLocationManager().getGnssYearOfHardware();
+    if(gnssYearOfHardware >= LOCATION_UNCERTIANTY_MIN_YEAR) {
+      extendedLocationAccuracyExpected = true;
+    }
+    mLocationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    // Unregister listeners
+    if (mLocationListener != null) {
+      mTestLocationManager.removeLocationUpdates(mLocationListener);
+    }
+    super.tearDown();
+  }
+
+  /**
+   * Those accuracy fields are new O-features,
+   * only test them if the hardware is later than 2017
+   */
+  public void testAccuracyFields() throws Exception {
+    SoftAssert softAssert = new SoftAssert(TAG);
+    mTestLocationManager.requestLocationUpdates(mLocationListener);
+    boolean success = mLocationListener.await();
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+        "Time elapsed without getting the GPS locations."
+            + " Possibly, the test has been run deep indoors."
+            + " Consider retrying test outdoors.",
+        success);
+
+    for (Location location : mLocationListener.getReceivedLocationList()) {
+      checkLocationAccuracyFields(softAssert, location,
+          extendedLocationAccuracyExpected);
+    }
+
+    softAssert.assertAll();
+  }
+
+  public static void checkLocationAccuracyFields(SoftAssert softAssert,
+      Location location, boolean extendedLocationAccuracyExpected) {
+    softAssert.assertTrue("All locations generated by the LocationManager "
+        + "should have a horizontal accuracy.", location.hasAccuracy());
+    if (location.hasAccuracy()) {
+      softAssert.assertTrue("Location Accuracy should be greater than 0.",
+          location.getAccuracy() > 0);
+    }
+
+    if(!extendedLocationAccuracyExpected) {
+      return;
+    }
+    Log.i(TAG, "This is a device from 2017 or later.");
+
+    softAssert.assertTrue("All GPS locations generated by the LocationManager "
+        + "must have a bearing accuracy.", location.hasBearingAccuracy());
+    if (location.hasBearingAccuracy()) {
+      softAssert.assertTrue("Bearing Accuracy should be greater than 0.",
+          location.getBearingAccuracyDegrees() > 0);
+    }
+    softAssert.assertTrue("All GPS locations generated by the LocationManager "
+        + "must have a speed accuracy.", location.hasSpeedAccuracy());
+    if (location.hasSpeedAccuracy()) {
+      softAssert.assertTrue("Speed Accuracy should be greater than 0.",
+          location.getSpeedAccuracyMetersPerSecond() > 0);
+    }
+    softAssert.assertTrue("All GPS locations generated by the LocationManager "
+        + "must have a vertical accuracy.", location.hasVerticalAccuracy());
+    if (location.hasVerticalAccuracy()) {
+      softAssert.assertTrue("Vertical Accuracy should be greater than 0.",
+          location.getVerticalAccuracyMeters() > 0);
+    }
+  }
+
+  /**
+   * Get the location info from the device
+   * check whether all fields' value make sense
+   */
+  public void testLocationRegularFields() throws Exception {
+    mTestLocationManager.requestLocationUpdates(mLocationListener);
+    boolean success = mLocationListener.await();
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+        "Time elapsed without getting the GPS locations."
+            + " Possibly, the test has been run deep indoors."
+            + " Consider retrying test outdoors.",
+        success);
+
+    SoftAssert softAssert = new SoftAssert(TAG);
+    for (Location location : mLocationListener.getReceivedLocationList()) {
+      checkLocationRegularFields(softAssert, location);
+    }
+
+    softAssert.assertAll();
+  }
+
+  public static void checkLocationRegularFields(SoftAssert softAssert, Location location) {
+    // For the altitude: the unit is meter
+    // The lowest exposed land on Earth is at the Dead Sea shore, at -413 meters.
+    // Whilst University of Tokyo Atacama Obsevatory is on 5,640m above sea level.
+    if(location.hasAltitude()) {
+      softAssert.assertTrue("Altitude should be greater than -500 (meters).",
+          location.getAltitude() >= -500);
+      softAssert.assertTrue("Altitude should be less than 6000 (meters).",
+          location.getAltitude() < 6000);
+    }
+
+    // It is guaranteed to be in the range [0.0, 360.0] if the device has a bearing.
+    // The API will return 0.0 if there is no bearing
+    if(location.hasBearing()) {
+      softAssert.assertTrue("Bearing should be in the range of [0.0, 360.0]",
+          location.getBearing() >= 0 && location.getBearing() <= 360);
+    }
+
+    softAssert.assertTrue("ElapsedRaltimeNanos should be great than 0.",
+        location.getElapsedRealtimeNanos() > 0);
+
+    assertEquals("gps", location.getProvider());
+    assertTrue(location.getTime() > 0);
+
+    softAssert.assertTrue("Longitude should be in the range of [-180.0, 180.0] degrees",
+        location.getLongitude() >= -180 && location.getLongitude() <= 180);
+
+    softAssert.assertTrue("Latitude should be in the range of [-90.0, 90.0] degrees",
+        location.getLatitude() >= -90 && location.getLatitude() <= 90);
+
+    // For the speed, during the cts test device shouldn't move faster than 1m/s
+    if(location.hasSpeed()) {
+      softAssert.assertTrue("In the test enviorment, speed should be in the range of [0, 1] m/s",
+          location.getSpeed() >= 0 && location.getSpeed() <= 1);
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java b/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
new file mode 100644
index 0000000..709fb3a
--- /dev/null
+++ b/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 Google Inc.
+ *
+ * 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.location.cts;
+
+
+import android.location.GnssMeasurement;
+import android.location.GnssMeasurementsEvent;
+import android.util.Log;
+import com.android.compatibility.common.util.CddTest;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Test computing and verifying the pseudoranges based on the raw measurements
+ * reported by the GNSS chipset
+ */
+public class GnssPseudorangeVerificationTest extends GnssTestCase {
+  private static final String TAG = "GnssPseudorangeValTest";
+  private static final int LOCATION_TO_COLLECT_COUNT = 5;
+  private static final int MIN_SATELLITES_REQUIREMENT = 4;
+  private static final double SECONDS_PER_NANO = 1.0e-9;
+
+  private TestGnssMeasurementListener mMeasurementListener;
+  private TestLocationListener mLocationListener;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+
+    mTestLocationManager = new TestLocationManager(getContext());
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    // Unregister listeners
+    if (mLocationListener != null) {
+      mTestLocationManager.removeLocationUpdates(mLocationListener);
+    }
+    if (mMeasurementListener != null) {
+      mTestLocationManager.unregisterGnssMeasurementCallback(mMeasurementListener);
+    }
+    super.tearDown();
+  }
+
+  /**
+   * Tests that one can listen for {@link GnssMeasurementsEvent} for collection purposes.
+   * It only performs sanity checks for the measurements received.
+   * This tests uses actual data retrieved from Gnss HAL.
+   */
+  @CddTest(requirement="7.3.3")
+  public void testPseudorangeValue() throws Exception {
+    // Checks if Gnss hardware feature is present, skips test (pass) if not,
+    // and hard asserts that Location/Gnss (Provider) is turned on if is Cts Verifier.
+    if (!TestMeasurementUtil.canTestRunOnCurrentDevice(mTestLocationManager,
+        TAG, MIN_HARDWARE_YEAR_MEASUREMENTS_REQUIRED, isCtsVerifierTest())) {
+      return;
+    }
+
+    mLocationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
+    mTestLocationManager.requestLocationUpdates(mLocationListener);
+
+    mMeasurementListener = new TestGnssMeasurementListener(TAG);
+    mTestLocationManager.registerGnssMeasurementCallback(mMeasurementListener);
+
+    boolean success = mLocationListener.await();
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+        "Time elapsed without getting enough location fixes."
+            + " Possibly, the test has been run deep indoors."
+            + " Consider retrying test outdoors.",
+        success);
+
+    Log.i(TAG, "Location status received = " + mLocationListener.isLocationReceived());
+
+    if (!mMeasurementListener.verifyStatus(isMeasurementTestStrict())) {
+      // If test is strict and verifyStatus reutrns false, an assert exception happens and
+      // test fails.   If test is not strict, we arrive here, and:
+      return; // exit (with pass)
+    }
+
+    List<GnssMeasurementsEvent> events = mMeasurementListener.getEvents();
+    int eventCount = events.size();
+    Log.i(TAG, "Number of GNSS measurement events received = " + eventCount);
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+        "GnssMeasurementEvent count: expected > 0, received = " + eventCount,
+        eventCount > 0);
+
+    SoftAssert softAssert = new SoftAssert(TAG);
+
+    boolean hasEventWithEnoughMeasurements = false;
+    // we received events, so perform a quick sanity check on mandatory fields
+    for (GnssMeasurementsEvent event : events) {
+      // Verify Gnss Event mandatory fields are in required ranges
+      assertNotNull("GnssMeasurementEvent cannot be null.", event);
+
+
+      long timeInNs = event.getClock().getTimeNanos();
+      TestMeasurementUtil.assertGnssClockFields(event.getClock(), softAssert, timeInNs);
+
+      // we need at least 4 satellites to calculate the pseudorange
+      if(event.getMeasurements().size() >= MIN_SATELLITES_REQUIREMENT) {
+        validatePseudorange(event.getMeasurements(), softAssert, timeInNs);
+        hasEventWithEnoughMeasurements = true;
+      }
+    }
+
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+        "Should have at least one GnssMeasurementEvent with at least 4"
+            + "GnssMeasurement.  If failed, retry near window or outdoors?",
+        hasEventWithEnoughMeasurements);
+
+    softAssert.assertAll();
+  }
+
+  /**
+   * Uses the common reception time approach to calculate pseudorange time
+   * measurements reported by the receiver according to http://cdn.intechopen.com/pdfs-wm/27712.pdf.
+   */
+  private void validatePseudorange(Collection<GnssMeasurement> measurements,
+      SoftAssert softAssert, long timeInNs) {
+    long largestReceivedSvTimeNanos = 0;
+    for(GnssMeasurement measurement : measurements) {
+      if (largestReceivedSvTimeNanos < measurement.getReceivedSvTimeNanos()) {
+        largestReceivedSvTimeNanos =  measurement.getReceivedSvTimeNanos();
+      }
+    }
+    for (GnssMeasurement measurement : measurements) {
+      double deltaiNanos = largestReceivedSvTimeNanos
+                          - measurement.getReceivedSvTimeNanos();
+      double deltaiSeconds = deltaiNanos * SECONDS_PER_NANO;
+      // according to http://cdn.intechopen.com/pdfs-wm/27712.pdf
+      // the pseudorange in time is 65-83 ms, which is 18 ms range,
+      // deltaiSeconds should be in the range of [0.0, 0.018] seconds
+      softAssert.assertTrue("deltaiSeconds in Seconds." ,
+          timeInNs,
+          "0.0 <= deltaiSeconds <= 0.018",
+          String.valueOf(deltaiSeconds),
+          (deltaiSeconds >= 0.0 && deltaiSeconds <= 0.018));
+    }
+
+  }
+}
diff --git a/tests/tests/location/src/android/location/cts/GnssStatusTest.java b/tests/tests/location/src/android/location/cts/GnssStatusTest.java
index e8f3cb13..fa35438 100644
--- a/tests/tests/location/src/android/location/cts/GnssStatusTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssStatusTest.java
@@ -1,6 +1,7 @@
 package android.location.cts;
 
 import android.location.GnssStatus;
+import android.util.Log;
 
 public class GnssStatusTest extends GnssTestCase  {
 
@@ -28,6 +29,11 @@
     // Register Gps Status Listener.
     TestGnssStatusCallback testGnssStatusCallback =
         new TestGnssStatusCallback(TAG, STATUS_TO_COLLECT_COUNT);
+    checkGnssChange(testGnssStatusCallback);
+  }
+
+  private void checkGnssChange(TestGnssStatusCallback testGnssStatusCallback)
+      throws InterruptedException {
     mTestLocationManager.registerGnssStatusCallback(testGnssStatusCallback);
 
     TestLocationListener locationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
@@ -46,4 +52,70 @@
             + " Consider retrying test outdoors.",
         success);
   }
+
+  /**
+   * Tests values of {@link GnssStatus}.
+   */
+  public void testGnssStatusValues() throws InterruptedException {
+    // Checks if GPS hardware feature is present, skips test (pass) if not,
+    // and hard asserts that Location/GPS (Provider) is turned on if is Cts Verifier.
+    if (!TestMeasurementUtil.canTestRunOnCurrentDevice(mTestLocationManager,
+        TAG, MIN_HARDWARE_YEAR_MEASUREMENTS_REQUIRED, isCtsVerifierTest())) {
+      return;
+    }
+    SoftAssert softAssert = new SoftAssert(TAG);
+    // Register Gps Status Listener.
+    TestGnssStatusCallback testGnssStatusCallback =
+        new TestGnssStatusCallback(TAG, STATUS_TO_COLLECT_COUNT);
+    checkGnssChange(testGnssStatusCallback);
+    validateGnssStatus(testGnssStatusCallback.getGnssStatus(), softAssert);
+    softAssert.assertAll();
+  }
+
+  /**
+   * To validate the fields in GnssStatus class, the value is got from device
+   * @param status, GnssStatus
+   * @param softAssert, customized assert class.
+   */
+  public static void validateGnssStatus(GnssStatus status, SoftAssert softAssert) {
+    int sCount = status.getSatelliteCount();
+    Log.i(TAG, "Total satellite:" + sCount);
+    // total number of satellites for all constellation is less than 200
+    softAssert.assertTrue("Satellite count test sCount : " + sCount , sCount < 200);
+    for (int i = 0; i < sCount; ++i) {
+      softAssert.assertTrue("azimuth_degrees: Azimuth in degrees: ",
+          "0.0 <= X <= 360.0",
+          String.valueOf(status.getAzimuthDegrees(i)),
+          status.getAzimuthDegrees(i) >= 0.0 && status.getAzimuthDegrees(i) <= 360.0);
+
+      if (status.hasCarrierFrequencyHz(i)) {
+        softAssert.assertTrue("carrier_frequency_hz: Carrier frequency in hz",
+            "X > 0.0",
+            String.valueOf(status.getCarrierFrequencyHz(i)),
+            status.getCarrierFrequencyHz(i) > 0.0);
+      }
+
+      softAssert.assertTrue("c_n0_dbhz: Carrier-to-noise density",
+          "0.0 >= X <= 63",
+          String.valueOf(status.getCn0DbHz(i)),
+          status.getCn0DbHz(i) >= 0.0 &&
+              status.getCn0DbHz(i) <= 63.0);
+
+      softAssert.assertTrue("elevation_degrees: Elevation in Degrees :",
+          "0.0 <= X <= 90.0",
+          String.valueOf(status.getElevationDegrees(i)),
+          status.getElevationDegrees(i) >= 0.0 && status.getElevationDegrees(i) <= 90.0);
+
+      // in validateSvidSub, it will validate ConstellationType, svid
+      // however, we don't have the event time in the current scope, pass in "-1" instead
+      TestMeasurementUtil.validateSvidSub(softAssert, null,
+          status.getConstellationType(i),status.getSvid(i));
+
+      // For those function with boolean type return, just simplly call the function
+      // to make sure those function won't crash, also increase the test coverage.
+      Log.i(TAG, "hasAlmanacData: " + status.hasAlmanacData(i));
+      Log.i(TAG, "hasEphemerisData: " + status.hasEphemerisData(i));
+      Log.i(TAG, "usedInFix: " + status.usedInFix(i));
+    }
+  }
 }
diff --git a/tests/tests/location/src/android/location/cts/GnssTtffTests.java b/tests/tests/location/src/android/location/cts/GnssTtffTests.java
new file mode 100644
index 0000000..8c407d5
--- /dev/null
+++ b/tests/tests/location/src/android/location/cts/GnssTtffTests.java
@@ -0,0 +1,169 @@
+package android.location.cts;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import com.android.compatibility.common.util.CddTest;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for the ttff (time to the first fix) validating whether TTFF is
+ * below the expected thresholds in differnt scenario
+ */
+public class GnssTtffTests extends GnssTestCase {
+
+  private static final String TAG = "GnssTtffTests";
+  private static final int LOCATION_TO_COLLECT_COUNT = 1;
+  private static final int STATUS_TO_COLLECT_COUNT = 3;
+  private static final int AIDING_DATA_RESET_DELAY_SECS = 10;
+  // Threshold values
+  private static final int TTFF_WITH_WIFI_CELLUAR_WARM_TH_SECS = 7;
+  private static final int TTFF_WITH_WIFI_CELLUAR_HOT_TH_SECS = 5;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    mTestLocationManager = new TestLocationManager(getContext());
+  }
+
+  /**
+   * Test the TTFF in the case where there is a network connection for both
+   * warm and hot start TTFF cases.
+   * @throws Exception
+   */
+  @CddTest(requirement="7.3.3")
+  public void testTtffWithNetwork() throws Exception {
+    checkTtffWarmWithCellularAndWifiOn();
+    checkTtffHotWithCellularAndWifiOn();
+  }
+
+  /**
+   * Test Scenario 1
+   * check whether TTFF is below the threshold on the warm start, without any network
+   * 1) Turn on wifi, turn on mobile data
+   * 2) Get GPS, check the TTFF value
+   */
+  public void checkTtffWarmWithCellularAndWifiOn() throws Exception {
+    ensureNetworkStatus();
+    SoftAssert softAssert = new SoftAssert(TAG);
+    mTestLocationManager.sendExtraCommand("delete_aiding_data");
+    Thread.sleep(TimeUnit.SECONDS.toMillis(AIDING_DATA_RESET_DELAY_SECS));
+    checkTtffByThreshold("checkTtffWarmWithCellularAndWifiOn",
+        TimeUnit.SECONDS.toMillis(TTFF_WITH_WIFI_CELLUAR_WARM_TH_SECS), softAssert);
+    softAssert.assertAll();
+  }
+
+  /**
+   * Test Scenario 2
+   * check whether TTFF is below the threhold on the hot start, without any network
+   * 1) Turn on wifi, turn on mobile data
+   * 2) Get GPS, check the TTFF value
+   */
+  public void checkTtffHotWithCellularAndWifiOn() throws Exception {
+    ensureNetworkStatus();
+    SoftAssert softAssert = new SoftAssert(TAG);
+    checkTtffByThreshold("checkTtffHotWithCellularAndWifiOn",
+        TimeUnit.SECONDS.toMillis(TTFF_WITH_WIFI_CELLUAR_HOT_TH_SECS), softAssert);
+    softAssert.assertAll();
+
+  }
+
+  /**
+   * Make sure the device has mobile data and wifi connection
+   */
+  private void ensureNetworkStatus(){
+    assertTrue("Device has to connect to Wifi to complete this test.",
+        isConnectedToWifi(getContext()));
+    ConnectivityManager connManager = getConnectivityManager(getContext());
+    NetworkInfo mobileNetworkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+    // check whether the mobile data is ON if the device has cellular capability
+    if (mobileNetworkInfo != null) {
+      TelephonyManager telephonyManager = (TelephonyManager) getContext().getApplicationContext()
+          .getSystemService(getContext().TELEPHONY_SERVICE);
+      assertTrue("Device has to have mobile data ON to complete this test.",
+          telephonyManager.isDataEnabled());
+    }
+    else {
+      Log.i(TAG, "This is a wifi only device.");
+    }
+
+  }
+
+  /*
+   * Check whether TTFF is below the threshold
+   * @param testName
+   * @param threshold, the threshold for the TTFF value
+   */
+  private void checkTtffByThreshold(String testName,
+      long threshold, SoftAssert softAssert) throws Exception {
+    TestLocationListener networkLocationListener
+        = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
+    // fetch the networklocation first to make sure the ttff is not flaky
+    mTestLocationManager.requestNetworkLocationUpdates(networkLocationListener);
+    networkLocationListener.await();
+
+    TestGnssStatusCallback testGnssStatusCallback =
+        new TestGnssStatusCallback(TAG, STATUS_TO_COLLECT_COUNT);
+    mTestLocationManager.registerGnssStatusCallback(testGnssStatusCallback);
+
+    TestLocationListener locationListener = new TestLocationListener(LOCATION_TO_COLLECT_COUNT);
+    mTestLocationManager.requestLocationUpdates(locationListener);
+
+
+    long startTimeMillis = System.currentTimeMillis();
+    boolean success = testGnssStatusCallback.awaitTtff();
+    long ttffTimeMillis = System.currentTimeMillis() - startTimeMillis;
+
+    SoftAssert.failOrWarning(isMeasurementTestStrict(),
+            "Test case:" + testName
+            + ". Threshold exceeded without getting a location."
+            + " Possibly, the test has been run deep indoors."
+            + " Consider retrying test outdoors.",
+        success);
+    mTestLocationManager.removeLocationUpdates(locationListener);
+    mTestLocationManager.unregisterGnssStatusCallback(testGnssStatusCallback);
+    softAssert.assertTrue("Test case: " + testName +", TTFF should be less than " + threshold
+        + " . In current test, TTFF value is: " + ttffTimeMillis, ttffTimeMillis < threshold);
+  }
+
+  /**
+   * Returns whether the device is currently connected to a wifi.
+   *
+   * @param context {@link Context} object
+   * @return {@code true} if connected to Wifi; {@code false} otherwise
+   */
+  public static boolean isConnectedToWifi(Context context) {
+    NetworkInfo info = getActiveNetworkInfo(context);
+    return info != null
+        && info.isConnected()
+        && info.getType() == ConnectivityManager.TYPE_WIFI;
+  }
+
+  /**
+   * Gets the active network info.
+   *
+   * @param context {@link Context} object
+   * @return {@link NetworkInfo}
+   */
+  private static NetworkInfo getActiveNetworkInfo(Context context) {
+    ConnectivityManager cm = getConnectivityManager(context);
+    if (cm != null) {
+      return cm.getActiveNetworkInfo();
+    }
+    return null;
+  }
+
+  /**
+   * Gets the connectivity manager.
+   *
+   * @param context {@link Context} object
+   * @return {@link ConnectivityManager}
+   */
+  private static ConnectivityManager getConnectivityManager(Context context) {
+    return (ConnectivityManager) context.getApplicationContext()
+        .getSystemService(Context.CONNECTIVITY_SERVICE);
+  }
+
+}
\ No newline at end of file
diff --git a/tests/tests/location/src/android/location/cts/SoftAssert.java b/tests/tests/location/src/android/location/cts/SoftAssert.java
index 4349f07..d118021 100644
--- a/tests/tests/location/src/android/location/cts/SoftAssert.java
+++ b/tests/tests/location/src/android/location/cts/SoftAssert.java
@@ -48,13 +48,17 @@
      * @param actualResult   actual value
      * @param condition      condition for test
      */
-    public void assertTrue(String message, long eventTimeInNs, String expectedResult,
+    public void assertTrue(String message, Long eventTimeInNs, String expectedResult,
                            String actualResult, boolean condition) {
         if (condition) {
             Log.i(mTag, message + ", (Test: PASS, actual : " +
                     actualResult + ", expected: " + expectedResult + ")");
         } else {
-            String errorMessage = "At time = " + eventTimeInNs + " ns, " + message +
+            String errorMessage = "";
+            if (eventTimeInNs != null) {
+                errorMessage = "At time = " + eventTimeInNs + " ns, ";
+            }
+            errorMessage += message +
                     " (Test: FAIL, actual :" + actualResult + ", " +
                     "expected: " + expectedResult + ")";
             Log.e(mTag, errorMessage);
@@ -63,6 +67,19 @@
     }
 
     /**
+     * assertTrue without eventTime
+     *
+     * @param message        test message
+     * @param expectedResult expected value
+     * @param actualResult   actual value
+     * @param condition      condition for test
+     */
+    public void assertTrue(String message, String expectedResult,
+        String actualResult, boolean condition) {
+        assertTrue(message, null, expectedResult, actualResult, condition);
+    }
+
+    /**
      * Check if a condition is true.
      * NOTE: A failure is downgraded to a warning.
      *
diff --git a/tests/tests/location/src/android/location/cts/TestGnssStatusCallback.java b/tests/tests/location/src/android/location/cts/TestGnssStatusCallback.java
index c63fb01..38b749f 100644
--- a/tests/tests/location/src/android/location/cts/TestGnssStatusCallback.java
+++ b/tests/tests/location/src/android/location/cts/TestGnssStatusCallback.java
@@ -72,6 +72,7 @@
     @Override
     public void onSatelliteStatusChanged(GnssStatus status) {
         Log.i(mTag, "Gnss Status Listener Received Status Update");
+        mGnssStatus = status;
         mLatchStatus.countDown();
     }
 
diff --git a/tests/tests/location/src/android/location/cts/TestLocationListener.java b/tests/tests/location/src/android/location/cts/TestLocationListener.java
index f266d5a..2e4b826 100644
--- a/tests/tests/location/src/android/location/cts/TestLocationListener.java
+++ b/tests/tests/location/src/android/location/cts/TestLocationListener.java
@@ -20,6 +20,8 @@
 import android.location.LocationManager;
 import android.os.Bundle;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -32,14 +34,17 @@
     // Timeout in sec for count down latch wait
     private static final int TIMEOUT_IN_SEC = 120;
     private final CountDownLatch mCountDownLatch;
+    private List<Location>  mLocationList = null;
 
     TestLocationListener(int locationToCollect) {
         mCountDownLatch = new CountDownLatch(locationToCollect);
+        mLocationList = new ArrayList<>();
     }
 
     @Override
     public void onLocationChanged(Location location) {
         mLocationReceived = true;
+        mLocationList.add(location);
         mCountDownLatch.countDown();
     }
 
@@ -66,6 +71,15 @@
     }
 
     /**
+     * Get the list of locations received
+     *
+     * @return mLocationList, List of {@link Location}.
+     */
+    public List<Location> getReceivedLocationList(){
+        return mLocationList;
+    }
+
+    /**
      * Check if location provider is enabled.
      *
      * @return {@code true} if the location provider is enabled and {@code false}
diff --git a/tests/tests/location/src/android/location/cts/TestLocationManager.java b/tests/tests/location/src/android/location/cts/TestLocationManager.java
index cca2b78..390d450 100644
--- a/tests/tests/location/src/android/location/cts/TestLocationManager.java
+++ b/tests/tests/location/src/android/location/cts/TestLocationManager.java
@@ -117,6 +117,21 @@
     }
 
     /**
+     * See {@code LocationManager#requestNetworkLocationUpdates}.
+     *
+     * @param locationListener location listener for request
+     */
+    public void requestNetworkLocationUpdates(LocationListener locationListener) {
+        if (mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
+            Log.i(TAG, "Request Network Location updates.");
+            mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
+                0 /* minTime*/,
+                0 /* minDistance */,
+                locationListener,
+                Looper.getMainLooper());
+        }
+    }
+    /**
      * See {@link android.location.LocationManager#addGpsStatusListener (GpsStatus.Listener)}.
      * @param listener the GpsStatus.Listener to add
      */
diff --git a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
index bdfd676..eb78a5b 100644
--- a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
+++ b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
@@ -263,6 +263,17 @@
                     String.valueOf(measurement.getSnrInDb()),
                     measurement.getSnrInDb() >= 0.0 && measurement.getSnrInDb() <= 63);
         }
+
+        // Check Automatic Gain Control level in dB.
+        if (measurement.hasAutomaticGainControlLevelDb()) {
+            softAssert.assertTrue("Automatic Gain Control level in dB",
+                timeInNs,
+                "-100 >= X <= 100",
+                String.valueOf(measurement.getAutomaticGainControlLevelDb()),
+                measurement.getAutomaticGainControlLevelDb() >= -100
+                    && measurement.getAutomaticGainControlLevelDb() <= 100);
+        }
+
     }
 
     /**
@@ -315,6 +326,12 @@
         String svidLogMessageFormat = "svid: Space Vehicle ID. Constellation type = %s";
         int constellationType = measurement.getConstellationType();
         int svid = measurement.getSvid();
+        validateSvidSub(softAssert, timeInNs, constellationType, svid);
+    }
+
+    public static void validateSvidSub(SoftAssert softAssert, Long timeInNs,
+        int constellationType, int svid) {
+
         String svidValue = String.valueOf(svid);
 
         switch (constellationType) {
@@ -472,6 +489,15 @@
                             "0 day >= X <= 1 day",
                             String.valueOf(sv_time_days),
                             sv_time_days >= 0 && sv_time_days <= 1);
+                } else if ((state | GnssMeasurement.STATE_GLO_TOD_KNOWN)
+                         == GnssMeasurement.STATE_GLO_TOD_KNOWN) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_GLO_TOD_KNOWN",
+                                    "GnssStatus.CONSTELLATION_GLONASS"),
+                            timeInNs,
+                            "0 day >= X <= 1 day",
+                            String.valueOf(sv_time_days),
+                            sv_time_days >= 0 && sv_time_days <= 1);
                 } else if ((state | GnssMeasurement.STATE_GLO_STRING_SYNC)
                         == GnssMeasurement.STATE_GLO_STRING_SYNC) {
                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
@@ -520,6 +546,15 @@
                             "0 >= X <= 7 days",
                             String.valueOf(sv_time_days),
                             sv_time_days >= 0 && sv_time_days <= 7);
+                } else if ((state | GnssMeasurement.STATE_TOW_KNOWN)
+                              == GnssMeasurement.STATE_TOW_KNOWN) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_TOW_DECODED",
+                                    "GnssStatus.CONSTELLATION_GALILEO"),
+                        timeInNs,
+                        "0 >= X <= 7 days",
+                        String.valueOf(sv_time_days),
+                        sv_time_days >= 0 && sv_time_days <= 7);
                 } else if ((state | GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC)
                         == GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC) {
                     softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
diff --git a/tests/tests/location/src/android/location/cts/TestUtils.java b/tests/tests/location/src/android/location/cts/TestUtils.java
index a038457..113af49 100644
--- a/tests/tests/location/src/android/location/cts/TestUtils.java
+++ b/tests/tests/location/src/android/location/cts/TestUtils.java
@@ -16,6 +16,7 @@
 
 package android.location.cts;
 
+import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -46,4 +47,14 @@
         }
         return false;
     }
+    public static boolean waitForWithCondition(int timeInSec, Callable<Boolean> callback)
+        throws Exception {
+        long waitTimeRounds = (TimeUnit.SECONDS.toMillis(timeInSec)) / STANDARD_SLEEP_TIME_MS;
+        for (int i = 0; i < waitTimeRounds; ++i) {
+            Thread.sleep(STANDARD_SLEEP_TIME_MS);
+            if(callback.call()) return true;
+        }
+        return false;
+    }
+
 }
diff --git a/tests/tests/media/libimagereaderjni/AImageReaderCts.cpp b/tests/tests/media/libimagereaderjni/AImageReaderCts.cpp
index a8ce1c7..c098f5f 100644
--- a/tests/tests/media/libimagereaderjni/AImageReaderCts.cpp
+++ b/tests/tests/media/libimagereaderjni/AImageReaderCts.cpp
@@ -48,14 +48,22 @@
 static constexpr int kCaptureWaitRetry = 10;
 static constexpr int kTestImageWidth = 640;
 static constexpr int kTestImageHeight = 480;
-static constexpr int kTestImageFormat = AIMAGE_FORMAT_JPEG;
+static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
 
-static constexpr int supportedUsage[] = {
-    AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
-    AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
-    AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
-    AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER,
-    AHARDWAREBUFFER_USAGE_VIDEO_ENCODE,
+struct FormatUsageCombination {
+    uint64_t format;
+    uint64_t usage;
+};
+
+static constexpr FormatUsageCombination supportedFormatUsage[] = {
+    {AIMAGE_FORMAT_YUV_420_888, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY},
+    {AIMAGE_FORMAT_YUV_420_888, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN},
+    {AIMAGE_FORMAT_JPEG, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY},
+    {AIMAGE_FORMAT_JPEG, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN},
+    {AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY},
+    {AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN},
+    {AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE},
+    {AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_VIDEO_ENCODE},
 };
 
 class CameraHelper {
@@ -283,7 +291,7 @@
         }
 
         media_status_t ret = AImageReader_newWithUsage(
-                mWidth, mHeight, mFormat, mUsage, 0, mMaxImages, &mImgReader);
+                mWidth, mHeight, mFormat, mUsage, mMaxImages, &mImgReader);
         if (ret != AMEDIA_OK || mImgReader == nullptr) {
             ALOGE("Failed to create new AImageReader, ret=%d, mImgReader=%p", ret, mImgReader);
             return -1;
@@ -497,16 +505,17 @@
 
 // Test that newWithUsage can create AImageReader correctly.
 extern "C" jboolean Java_android_media_cts_NativeImageReaderTest_\
-testSucceedsWithSupportedUsageNative(JNIEnv* /*env*/, jclass /*clazz*/) {
+testSucceedsWithSupportedUsageFormatNative(JNIEnv* /*env*/, jclass /*clazz*/) {
     static constexpr int kTestImageCount = 8;
 
-    for (auto& usage : supportedUsage) {
+    for (auto& combination : supportedFormatUsage) {
         AImageReader* outReader;
         media_status_t ret = AImageReader_newWithUsage(
-                kTestImageWidth, kTestImageHeight, kTestImageFormat, usage, 0, kTestImageCount,
-                &outReader);
+                kTestImageWidth, kTestImageHeight, combination.format, combination.usage,
+                kTestImageCount, &outReader);
         if (ret != AMEDIA_OK || outReader == nullptr) {
-            ALOGE("AImageReader_newWithUsage failed with usage: %d", usage);
+            ALOGE("AImageReader_newWithUsage failed with format: %" PRId64 ", usage: %" PRId64 ".",
+                  combination.format, combination.usage);
             return false;
         }
         AImageReader_delete(outReader);
@@ -518,7 +527,7 @@
 extern "C" jboolean Java_android_media_cts_NativeImageReaderTest_\
 testTakePicturesNative(JNIEnv* /*env*/, jclass /*clazz*/) {
     for (auto& readerUsage :
-         {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER}) {
+         {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
         for (auto& readerMaxImages : {1, 4, 8}) {
             for (auto& readerAsync : {true, false}) {
                 for (auto& pictureCount : {1, 8, 16}) {
diff --git a/tests/tests/media/src/android/media/cts/AudioFocusTest.java b/tests/tests/media/src/android/media/cts/AudioFocusTest.java
index 2ef0c68..afc272e 100644
--- a/tests/tests/media/src/android/media/cts/AudioFocusTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioFocusTest.java
@@ -88,7 +88,7 @@
         final AudioFocusRequest reqToCopy =
                 new AudioFocusRequest.Builder(focusGain)
                 .setAudioAttributes(ATTR_DRIVE_DIR)
-                .setOnAudioFocusChangeListener(focusListener, null)
+                .setOnAudioFocusChangeListener(focusListener)
                 .setAcceptsDelayedFocusGain(true)
                 .setWillPauseWhenDucked(true)
                 .build();
@@ -111,6 +111,34 @@
         assertEquals("Delayed focus differs", true, newReq.acceptsDelayedFocusGain());
     }
 
+    public void testNullListenerHandlerNpe() throws Exception {
+        final AudioFocusRequest.Builder afBuilder =
+                new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN);
+        try {
+            afBuilder.setOnAudioFocusChangeListener(null);
+            fail("no NPE when setting a null listener");
+        } catch (NullPointerException e) {
+        }
+
+        final HandlerThread handlerThread = new HandlerThread(TAG);
+        handlerThread.start();
+        final Handler h = new Handler(handlerThread.getLooper());
+        final AudioFocusRequest.Builder afBuilderH =
+                new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN);
+        try {
+            afBuilderH.setOnAudioFocusChangeListener(null, h);
+            fail("no NPE when setting a null listener with non-null Handler");
+        } catch (NullPointerException e) {
+        }
+
+        final AudioFocusRequest.Builder afBuilderL =
+                new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN);
+        try {
+            afBuilderL.setOnAudioFocusChangeListener(new FocusChangeListener(), null);
+            fail("no NPE when setting a non-null listener with null Handler");
+        } catch (NullPointerException e) {
+        }
+    }
 
     public void testAudioFocusRequestGainLoss() throws Exception {
         final AudioAttributes[] attributes = { ATTR_DRIVE_DIR, ATTR_MEDIA };
@@ -188,10 +216,17 @@
         try {
             for (int i = 0 ; i < NB_FOCUS_OWNERS ; i++) {
                 focusListeners[i] = new FocusChangeListener();
-                focusRequests[i] = new AudioFocusRequest.Builder(focusGains[i])
-                        .setAudioAttributes(attributes[i])
-                        .setOnAudioFocusChangeListener(focusListeners[i], h /*handler*/)
-                        .build();
+                if (h != null) {
+                    focusRequests[i] = new AudioFocusRequest.Builder(focusGains[i])
+                            .setAudioAttributes(attributes[i])
+                            .setOnAudioFocusChangeListener(focusListeners[i], h /*handler*/)
+                            .build();
+                } else {
+                    focusRequests[i] = new AudioFocusRequest.Builder(focusGains[i])
+                            .setAudioAttributes(attributes[i])
+                            .setOnAudioFocusChangeListener(focusListeners[i])
+                            .build();
+                }
             }
 
             // focus owner 0 requests focus with GAIN,
diff --git a/tests/tests/media/src/android/media/cts/NativeImageReaderTest.java b/tests/tests/media/src/android/media/cts/NativeImageReaderTest.java
index 8fac952..1d57609 100644
--- a/tests/tests/media/src/android/media/cts/NativeImageReaderTest.java
+++ b/tests/tests/media/src/android/media/cts/NativeImageReaderTest.java
@@ -34,9 +34,10 @@
         Log.i("NativeImageReaderTest", "after loadlibrary");
     }
 
-    public void testSucceedsWithSupportedUsage() {
+    public void testSucceedsWithSupportedUsageFormat() {
         assertTrue(
-                "Native test failed, see log for details", testSucceedsWithSupportedUsageNative());
+                "Native test failed, see log for details",
+                testSucceedsWithSupportedUsageFormatNative());
     }
 
     public void testTakePictures() {
@@ -49,7 +50,7 @@
         assertTrue("Surface created is invalid.", surface.isValid());
     }
 
-    private static native boolean testSucceedsWithSupportedUsageNative();
+    private static native boolean testSucceedsWithSupportedUsageFormatNative();
     private static native boolean testTakePicturesNative();
     private static native Surface testCreateSurfaceNative();
 }
diff --git a/tests/tests/nativehardware/Android.mk b/tests/tests/nativehardware/Android.mk
index 7f05395..a001387 100644
--- a/tests/tests/nativehardware/Android.mk
+++ b/tests/tests/nativehardware/Android.mk
@@ -12,32 +12,83 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Build the unit tests.
-
 LOCAL_PATH:= $(call my-dir)
 
+#
+# Reusable test classes and helpers.
+#
 include $(CLEAR_VARS)
-LOCAL_MODULE:= CtsNativeHardwareTestCases
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_MODULE := cts-nativehardware-tests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
+
+LOCAL_JAVA_LIBRARIES := platform-test-annotations
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+#
+# JNI components for testing NDK.
+#
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libcts-nativehardware-ndk-jni
+
+LOCAL_CFLAGS += -Werror -Wall -Wextra
+
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := \
-    src/AHardwareBufferTest.cpp \
+    jni/AHardwareBufferTest.cpp \
+    jni/android_hardware_cts_AHardwareBufferNativeTest.cpp \
+    jni/NativeTestHelper.cpp
 
-LOCAL_SHARED_LIBRARIES := \
-  libnativewindow \
-  liblog \
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
 
-LOCAL_STATIC_LIBRARIES := \
-  libgtest_ndk_c++ \
-  libgtest_main_ndk_c++ \
+LOCAL_SHARED_LIBRARIES := libandroid liblog
 
-LOCAL_CTS_TEST_PACKAGE := android.nativehardware
+LOCAL_SDK_VERSION := current
+
+LOCAL_NDK_STL_VARIANT := c++_shared
+
+include $(BUILD_SHARED_LIBRARY)
+
+#
+# CtsNativeHardwareTestCases package
+#
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_SDK_VERSION := current
-LOCAL_NDK_STL_VARIANT := c++_static
+# include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
-include $(BUILD_NATIVE_TEST)
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    compatibility-device-util \
+    ctstestrunner \
+    cts-nativehardware-tests \
+
+LOCAL_JNI_SHARED_LIBRARIES := libcts-nativehardware-ndk-jni
+
+LOCAL_PACKAGE_NAME := CtsNativeHardwareTestCases
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_NDK_STL_VARIANT := c++_shared
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/nativehardware/AndroidManifest.xml b/tests/tests/nativehardware/AndroidManifest.xml
new file mode 100644
index 0000000..f453fa8
--- /dev/null
+++ b/tests/tests/nativehardware/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?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.hardware.nativehardware.cts">
+
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.hardware.nativehardware.cts"
+                     android:label="CTS native hardware tests">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/nativehardware/AndroidTest.xml b/tests/tests/nativehardware/AndroidTest.xml
index 8fec974..787a89d 100644
--- a/tests/tests/nativehardware/AndroidTest.xml
+++ b/tests/tests/nativehardware/AndroidTest.xml
@@ -14,14 +14,12 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Native Hardware test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
-        <option name="cleanup" value="true" />
-        <option name="push" value="CtsNativeHardwareTestCases->/data/local/tmp/CtsNativeHardwareTestCases" />
-        <option name="append-bitness" value="true" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsNativeHardwareTestCases.apk" />
     </target_preparer>
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="CtsNativeHardwareTestCases" />
-        <option name="runtime-hint" value="1s" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.hardware.nativehardware.cts" />
+        <option name="runtime-hint" value="10s" />
     </test>
 </configuration>
diff --git a/tests/tests/nativehardware/src/AHardwareBufferTest.cpp b/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp
similarity index 71%
rename from tests/tests/nativehardware/src/AHardwareBufferTest.cpp
rename to tests/tests/nativehardware/jni/AHardwareBufferTest.cpp
index d467929..adb9a91 100644
--- a/tests/tests/nativehardware/src/AHardwareBufferTest.cpp
+++ b/tests/tests/nativehardware/jni/AHardwareBufferTest.cpp
@@ -14,36 +14,45 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AHardwareBuffer_test"
-//#define LOG_NDEBUG 0
+#include "AHardwareBufferTest.h"
 
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <unistd.h>
+
+#include <sstream>
+#include <string>
 
 #include <android/hardware_buffer.h>
-#include <gtest/gtest.h>
+#define LOG_TAG "AHardwareBufferTest"
+#include "NativeTestHelper.h"
+
+namespace android {
+
+//#define LOG_NDEBUG 0
 
 #define BAD_VALUE -EINVAL
 #define NO_ERROR 0
 
-static ::testing::AssertionResult BuildHexFailureMessage(uint64_t expected,
+static std::string BuildHexFailureMessage(uint64_t expected,
         uint64_t actual, const char* type) {
     std::ostringstream ss;
     ss << type << " 0x" << std::hex << actual
             << " does not match expected " << type << " 0x" << std::hex
             << expected;
-    return ::testing::AssertionFailure() << ss.str();
+    return ss.str();
 }
 
-static ::testing::AssertionResult BuildFailureMessage(uint32_t expected,
+static std::string BuildFailureMessage(uint32_t expected,
         uint32_t actual, const char* type) {
-    return ::testing::AssertionFailure() << "Buffer " << type << " do not match"
-            << ": " << actual << " != " << expected;
+    std::ostringstream ss;
+    ss << "Buffer " << type << " do not match" << ": " << actual << " != " << expected;
+    return ss.str();
 }
 
-static ::testing::AssertionResult CheckAHardwareBufferMatchesDesc(
+static std::string CheckAHardwareBufferMatchesDesc(
         AHardwareBuffer* abuffer, const AHardwareBuffer_Desc& desc) {
     AHardwareBuffer_Desc bufferDesc;
     AHardwareBuffer_describe(abuffer, &bufferDesc);
@@ -57,26 +66,30 @@
         return BuildHexFailureMessage(desc.usage, bufferDesc.usage, "usage");
     if (bufferDesc.format != desc.format)
         return BuildFailureMessage(desc.format, bufferDesc.format, "formats");
-    return ::testing::AssertionSuccess();
+    return std::string();
 }
 
+bool AHardwareBufferTest::SetUp() { return true; }
+
+void AHardwareBufferTest::TearDown() {}
+
 // Test that passing in NULL values to allocate works as expected.
-TEST(AHardwareBufferTest, AHardwareBuffer_allocate_FailsWithNullInput) {
+void AHardwareBufferTest::testAHardwareBuffer_allocate_FailsWithNullInput(JNIEnv* env) {
     AHardwareBuffer* buffer;
     AHardwareBuffer_Desc desc;
 
     memset(&desc, 0, sizeof(AHardwareBuffer_Desc));
 
     int res = AHardwareBuffer_allocate(&desc, NULL);
-    EXPECT_EQ(BAD_VALUE, res);
+    ASSERT_EQ(BAD_VALUE, res);
     res = AHardwareBuffer_allocate(NULL, &buffer);
-    EXPECT_EQ(BAD_VALUE, res);
+    ASSERT_EQ(BAD_VALUE, res);
     res = AHardwareBuffer_allocate(NULL, NULL);
-    EXPECT_EQ(BAD_VALUE, res);
+    ASSERT_EQ(BAD_VALUE, res);
 }
 
 // Test that passing in NULL values to allocate works as expected.
-TEST(AHardwareBufferTest, AHardwareBuffer_allocate_BlobFormatRequiresHeight1) {
+void AHardwareBufferTest::testAHardwareBuffer_allocate_BlobFormatRequiresHeight1(JNIEnv* env) {
     AHardwareBuffer* buffer;
     AHardwareBuffer_Desc desc = {};
 
@@ -86,18 +99,18 @@
     desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
     desc.format = AHARDWAREBUFFER_FORMAT_BLOB;
     int res = AHardwareBuffer_allocate(&desc, &buffer);
-    EXPECT_EQ(BAD_VALUE, res);
+    ASSERT_EQ(BAD_VALUE, res);
 
     desc.height = 1;
     res = AHardwareBuffer_allocate(&desc, &buffer);
-    EXPECT_EQ(NO_ERROR, res);
-    EXPECT_TRUE(CheckAHardwareBufferMatchesDesc(buffer, desc));
+    ASSERT_EQ(NO_ERROR, res);
+    ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
     AHardwareBuffer_release(buffer);
     buffer = NULL;
 }
 
 // Test that allocate can create an AHardwareBuffer correctly.
-TEST(AHardwareBufferTest, AHardwareBuffer_allocate_Succeeds) {
+void AHardwareBufferTest::testAHardwareBuffer_allocate_Succeeds(JNIEnv* env) {
     AHardwareBuffer* buffer = NULL;
     AHardwareBuffer_Desc desc = {};
 
@@ -107,8 +120,8 @@
     desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
     desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
     int res = AHardwareBuffer_allocate(&desc, &buffer);
-    EXPECT_EQ(NO_ERROR, res);
-    EXPECT_TRUE(CheckAHardwareBufferMatchesDesc(buffer, desc));
+    ASSERT_EQ(NO_ERROR, res);
+    ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
     AHardwareBuffer_release(buffer);
     buffer = NULL;
 
@@ -118,12 +131,12 @@
     desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
     desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
     res = AHardwareBuffer_allocate(&desc, &buffer);
-    EXPECT_EQ(NO_ERROR, res);
-    EXPECT_TRUE(CheckAHardwareBufferMatchesDesc(buffer, desc));
+    ASSERT_EQ(NO_ERROR, res);
+    ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
     AHardwareBuffer_release(buffer);
 }
 
-TEST(AHardwareBufferTest, AHardwareBuffer_describe_Succeeds) {
+void AHardwareBufferTest::testAHardwareBuffer_describe_Succeeds(JNIEnv* env) {
     AHardwareBuffer* buffer = NULL;
     AHardwareBuffer_Desc desc = {};
 
@@ -133,36 +146,39 @@
     desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
     desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
     int res = AHardwareBuffer_allocate(&desc, &buffer);
-    EXPECT_EQ(NO_ERROR, res);
+    ASSERT_EQ(NO_ERROR, res);
 
     AHardwareBuffer_Desc expected_desc;
     memset(&expected_desc, 0, sizeof(AHardwareBuffer_Desc));
     AHardwareBuffer_describe(NULL, &desc);
-    EXPECT_EQ(0U, expected_desc.width);
+    ASSERT_EQ(0U, expected_desc.width);
     AHardwareBuffer_describe(buffer, NULL);
-    EXPECT_EQ(0U, expected_desc.width);
+    ASSERT_EQ(0U, expected_desc.width);
     AHardwareBuffer_describe(buffer, &desc);
-    EXPECT_TRUE(CheckAHardwareBufferMatchesDesc(buffer, desc));
+    ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
 
     AHardwareBuffer_release(buffer);
 }
 
 struct ClientData {
     int fd;
+    JNIEnv* env;
     AHardwareBuffer* buffer;
-    ClientData(int fd_in, AHardwareBuffer* buffer_in)
-            : fd(fd_in), buffer(buffer_in) {}
+    ClientData(int fd_in, JNIEnv* env_in, AHardwareBuffer* buffer_in)
+            : fd(fd_in), env(env_in), buffer(buffer_in) {}
 };
 
 static void* clientFunction(void* data) {
     ClientData* pdata = reinterpret_cast<ClientData*>(data);
     int err = AHardwareBuffer_sendHandleToUnixSocket(pdata->buffer, pdata->fd);
-    EXPECT_EQ(NO_ERROR, err);
+    if (err != NO_ERROR) {
+        fail(pdata->env, "Error sending handle to socket: %d", err);
+    }
     close(pdata->fd);
     return 0;
 }
 
-TEST(AHardwareBufferTest, AHardwareBuffer_SendAndRecv_Succeeds) {
+void AHardwareBufferTest::testAHardwareBuffer_SendAndRecv_Succeeds(JNIEnv* env) {
     AHardwareBuffer* buffer = NULL;
     AHardwareBuffer_Desc desc = {};
 
@@ -174,32 +190,32 @@
 
     // Test that an invalid buffer fails.
     int err = AHardwareBuffer_sendHandleToUnixSocket(NULL, 0);
-    EXPECT_EQ(BAD_VALUE, err);
+    ASSERT_EQ(BAD_VALUE, err);
     err = 0;
     err = AHardwareBuffer_sendHandleToUnixSocket(buffer, 0);
-    EXPECT_EQ(BAD_VALUE, err);
+    ASSERT_EQ(BAD_VALUE, err);
 
     // Allocate the buffer.
     err = AHardwareBuffer_allocate(&desc, &buffer);
-    EXPECT_EQ(NO_ERROR, err);
+    ASSERT_EQ(NO_ERROR, err);
 
     int fds[2];
     err = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds);
 
     // Launch a client that will send the buffer back.
-    ClientData data(fds[1], buffer);
+    ClientData data(fds[1], env, buffer);
     pthread_t thread;
     ASSERT_EQ(0, pthread_create(&thread, NULL, clientFunction, &data));
 
     // Receive the buffer.
     err = AHardwareBuffer_recvHandleFromUnixSocket(fds[0], NULL);
-    EXPECT_EQ(BAD_VALUE, err);
+    ASSERT_EQ(BAD_VALUE, err);
 
     AHardwareBuffer* received = NULL;
     err = AHardwareBuffer_recvHandleFromUnixSocket(fds[0], &received);
-    EXPECT_EQ(NO_ERROR, err);
+    ASSERT_EQ(NO_ERROR, err);
     ASSERT_TRUE(received != NULL);
-    EXPECT_TRUE(CheckAHardwareBufferMatchesDesc(received, desc));
+    ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(received, desc));
 
     void* ret_val;
     ASSERT_EQ(0, pthread_join(thread, &ret_val));
@@ -210,7 +226,7 @@
     AHardwareBuffer_release(received);
 }
 
-TEST(AHardwareBufferTest, AHardwareBuffer_Lock_and_Unlock_Succeed) {
+void AHardwareBufferTest::testAHardwareBuffer_Lock_and_Unlock_Succeed(JNIEnv* env) {
     AHardwareBuffer* buffer = NULL;
     AHardwareBuffer_Desc desc = {};
 
@@ -222,19 +238,21 @@
 
     // Test that an invalid buffer fails.
     int err = AHardwareBuffer_lock(NULL, 0, -1, NULL, NULL);
-    EXPECT_EQ(BAD_VALUE, err);
+    ASSERT_EQ(BAD_VALUE, err);
     err = 0;
 
     // Allocate the buffer.
     err = AHardwareBuffer_allocate(&desc, &buffer);
-    EXPECT_EQ(NO_ERROR, err);
+    ASSERT_EQ(NO_ERROR, err);
     void* bufferData = NULL;
     err = AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1,
           NULL, &bufferData);
-    EXPECT_EQ(NO_ERROR, err);
-    EXPECT_TRUE(bufferData != NULL);
+    ASSERT_EQ(NO_ERROR, err);
+    ASSERT_TRUE(bufferData != NULL);
     int32_t fence = -1;
     err = AHardwareBuffer_unlock(buffer, &fence);
 
     AHardwareBuffer_release(buffer);
 }
+
+} // namespace android
diff --git a/tests/tests/nativehardware/jni/AHardwareBufferTest.h b/tests/tests/nativehardware/jni/AHardwareBufferTest.h
new file mode 100644
index 0000000..7f39f57
--- /dev/null
+++ b/tests/tests/nativehardware/jni/AHardwareBufferTest.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#ifndef AHARDWAREBUFFER_TEST_H
+#define AHARDWAREBUFFER_TEST_H
+
+#include "NativeHardwareTest.h"
+
+#include <jni.h>
+
+namespace android {
+
+class AHardwareBufferTest : public NativeHardwareTest {
+public:
+    bool SetUp() override;
+    void TearDown() override;
+    virtual ~AHardwareBufferTest() = default;
+
+    // tests
+    void testAHardwareBuffer_allocate_FailsWithNullInput(JNIEnv *env);
+    void testAHardwareBuffer_allocate_BlobFormatRequiresHeight1(JNIEnv *env);
+    void testAHardwareBuffer_allocate_Succeeds(JNIEnv *env);
+    void testAHardwareBuffer_describe_Succeeds(JNIEnv *env);
+    void testAHardwareBuffer_SendAndRecv_Succeeds(JNIEnv *env);
+    void testAHardwareBuffer_Lock_and_Unlock_Succeed(JNIEnv *env);
+};
+
+} // namespace android
+
+#endif // AHARDWAREBUFFER_TEST_H
diff --git a/tests/tests/nativehardware/jni/NativeHardwareTest.h b/tests/tests/nativehardware/jni/NativeHardwareTest.h
new file mode 100644
index 0000000..2b3fda9
--- /dev/null
+++ b/tests/tests/nativehardware/jni/NativeHardwareTest.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#ifndef NATIVEHARDWARE_TEST_H
+#define NATIVEHARDWARE_TEST_H
+
+namespace android {
+
+class NativeHardwareTest {
+public:
+    virtual bool SetUp() = 0;
+    virtual void TearDown() = 0;
+    virtual ~NativeHardwareTest() = default;
+};
+
+} // namespace android
+
+#endif // NATIVEHARDWARE_TEST_H
diff --git a/tests/tests/nativehardware/jni/NativeTestHelper.cpp b/tests/tests/nativehardware/jni/NativeTestHelper.cpp
new file mode 100644
index 0000000..5737d0c
--- /dev/null
+++ b/tests/tests/nativehardware/jni/NativeTestHelper.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 "NativeTestHelper.h"
+
+#include <cstdlib>
+#include <cstring>
+
+extern int register_android_hardware_cts_AHardwareBufferNativeTest(JNIEnv* env);
+
+void fail(JNIEnv* env, const char* format, ...) {
+    va_list args;
+
+    va_start(args, format);
+    char *msg;
+    vasprintf(&msg, format, args);
+    va_end(args);
+
+    jclass exClass;
+    const char *className = "java/lang/AssertionError";
+    exClass = env->FindClass(className);
+    env->ThrowNew(exClass, msg);
+    free(msg);
+}
+
+jint JNI_OnLoad(JavaVM *vm, void *) {
+    JNIEnv *env = NULL;
+    if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
+        return JNI_ERR;
+    }
+    if (register_android_hardware_cts_AHardwareBufferNativeTest(env)) {
+        return JNI_ERR;
+    }
+    return JNI_VERSION_1_4;
+}
diff --git a/tests/tests/nativehardware/jni/NativeTestHelper.h b/tests/tests/nativehardware/jni/NativeTestHelper.h
new file mode 100644
index 0000000..fcc8d7f
--- /dev/null
+++ b/tests/tests/nativehardware/jni/NativeTestHelper.h
@@ -0,0 +1,63 @@
+/*
+ * 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 <android/log.h>
+#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
+
+#define ASSERT(condition, format, args...) \
+        if (!(condition)) { \
+            fail(env, format, ## args); \
+            return; \
+        }
+
+// gtest style assert
+#define ASSERT_TRUE(a) ASSERT((a), "assert failed on (" #a ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_FALSE(a) ASSERT(!(a), "assert failed on (!" #a ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_EQ(a, b) \
+        ASSERT((a) == (b), "assert failed on (" #a " == " #b ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_NE(a, b) \
+        ASSERT((a) != (b), "assert failed on (" #a " != " #b ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_GT(a, b) \
+        ASSERT((a) > (b), "assert failed on (" #a " > " #b ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_GE(a, b) \
+        ASSERT((a) >= (b), "assert failed on (" #a " >= " #b ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_LT(a, b) \
+        ASSERT((a) < (b), "assert failed on (" #a " < " #b ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_LE(a, b) \
+        ASSERT((a) <= (b), "assert failed on (" #a " <= " #b ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_NULL(a) \
+        ASSERT((a) == nullptr, "assert failed on isNull(" #a ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_NOT_NULL(a) \
+        ASSERT((a) != nullptr, "assert failed on isNotNull(" #a ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_NAN(a) \
+        ASSERT(isnan(a), "assert failed on isNan(" #a ") at " __FILE__ ":%d", __LINE__)
+#define ASSERT_EMPTY_CSTR(a) do { \
+        const char *tmp = a; \
+        ASSERT(tmp != nullptr, \
+               "assert failed on (empty_cstr(" #a "): " #a " != nullptr) " \
+               "at " __FILE__ ":%d", __LINE__); \
+        ASSERT(tmp[0] == '\0', \
+               "assert failed on (empty_cstr(" #a "): strlen() == 0) " \
+               "at " __FILE__ ":%d", __LINE__); \
+    } while (false)
+
+
+void fail(JNIEnv* env, const char* format, ...);
diff --git a/tests/tests/nativehardware/jni/android_hardware_cts_AHardwareBufferNativeTest.cpp b/tests/tests/nativehardware/jni/android_hardware_cts_AHardwareBufferNativeTest.cpp
new file mode 100644
index 0000000..afe17d6
--- /dev/null
+++ b/tests/tests/nativehardware/jni/android_hardware_cts_AHardwareBufferNativeTest.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 "AHardwareBufferTest.h"
+#define TAG "AHardwareBufferTest"
+#include "NativeTestHelper.h"
+
+namespace {
+
+using android::AHardwareBufferTest;
+
+#define RETURN_ON_EXCEPTION() do { if (env->ExceptionCheck()) { return; } } while(false)
+
+jlong setUp(JNIEnv*, jclass) {
+    AHardwareBufferTest* test = new AHardwareBufferTest();
+    if (test != nullptr) {
+        test->SetUp();
+    }
+    return reinterpret_cast<jlong>(test);
+}
+
+void tearDown(JNIEnv*, jclass, jlong instance) {
+    delete reinterpret_cast<AHardwareBufferTest*>(instance);
+}
+
+void test(JNIEnv* env, jclass, jlong instance) {
+    AHardwareBufferTest *test = reinterpret_cast<AHardwareBufferTest*>(instance);
+    ASSERT_NOT_NULL(test);
+
+    ALOGI("testAHardwareBuffer_allocate_FailsWithNullInput");
+    test->testAHardwareBuffer_allocate_FailsWithNullInput(env);
+    RETURN_ON_EXCEPTION();
+
+    ALOGI("testAHardwareBuffer_allocate_BlobFormatRequiresHeight1");
+    test->testAHardwareBuffer_allocate_BlobFormatRequiresHeight1(env);
+    RETURN_ON_EXCEPTION();
+
+    ALOGI("testAHardwareBuffer_allocate_Succeeds");
+    test->testAHardwareBuffer_allocate_Succeeds(env);
+    RETURN_ON_EXCEPTION();
+
+    ALOGI("testAHardwareBuffer_describe_Succeeds");
+    test->testAHardwareBuffer_describe_Succeeds(env);
+    RETURN_ON_EXCEPTION();
+
+    ALOGI("testAHardwareBuffer_SendAndRecv_Succeeds");
+    test->testAHardwareBuffer_SendAndRecv_Succeeds(env);
+    RETURN_ON_EXCEPTION();
+
+    ALOGI("testAHardwareBuffer_Lock_and_Unlock_Succeed");
+    test->testAHardwareBuffer_Lock_and_Unlock_Succeed(env);
+    RETURN_ON_EXCEPTION();
+}
+
+JNINativeMethod gMethods[] = {
+    {"nativeSetUp", "()J", (void *)setUp},
+    {"nativeTearDown", "(J)V", (void *)tearDown},
+    {"nativeTest", "(J)V", (void *)test},
+};
+
+} // namespace
+
+int register_android_hardware_cts_AHardwareBufferNativeTest(JNIEnv* env) {
+    jclass clazz = env->FindClass("android/hardware/cts/AHardwareBufferNativeTest");
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/nativehardware/src/android/hardware/cts/AHardwareBufferNativeTest.java b/tests/tests/nativehardware/src/android/hardware/cts/AHardwareBufferNativeTest.java
new file mode 100644
index 0000000..883ca3f
--- /dev/null
+++ b/tests/tests/nativehardware/src/android/hardware/cts/AHardwareBufferNativeTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.hardware.cts;
+
+import android.test.AndroidTestCase;
+
+/**
+ * Check AHardwareBuffer functionality.
+ *
+ * This is the place to implement AHardwareBuffer NDK CTS tests.
+ */
+public class AHardwareBufferNativeTest extends AndroidTestCase {
+    protected native long nativeSetUp();
+    protected native void nativeTearDown(long instance);
+    private native void nativeTest(long instance);
+    private long mNativeInstance;
+
+    static {
+        System.loadLibrary("cts-nativehardware-ndk-jni");
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mNativeInstance = nativeSetUp();
+        assertTrue("create native instance failed", mNativeInstance != 0);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        nativeTearDown(mNativeInstance);
+    }
+
+    public void testNative() throws AssertionError {
+        nativeTest(mNativeInstance);
+    }
+}
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
index 37b434e..c57682f 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
@@ -57,6 +57,58 @@
 
 }
 
+
+// Test creating a default stream with specific devices
+void runtest_aaudio_devices(int32_t deviceId, bool expectFail) {
+    AAudioStreamBuilder *aaudioBuilder = nullptr;
+    AAudioStream *aaudioStream = nullptr;
+
+    // Use an AAudioStreamBuilder to define the stream.
+    aaudio_result_t result = AAudio_createStreamBuilder(&aaudioBuilder);
+    ASSERT_EQ(AAUDIO_OK, result);
+    ASSERT_NE(nullptr, aaudioBuilder);
+
+    AAudioStreamBuilder_setDeviceId(aaudioBuilder,deviceId);
+
+    // Create an AAudioStream using the Builder.
+    result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+    if (expectFail) {
+        ASSERT_NE(AAUDIO_OK, result);
+        ASSERT_EQ(nullptr, aaudioStream);
+    } else {
+        // Pass or fail is OK. Just don't crash.
+        ASSERT_TRUE(((result < 0) && (aaudioStream == nullptr))
+                    || ((result == AAUDIO_OK) && (aaudioStream != nullptr)));
+    }
+
+    // Cleanup
+    EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
+    if (aaudioStream != nullptr) {
+        AAudioStream_close(aaudioStream);
+    }
+}
+
+TEST(test_aaudio, aaudio_stream_device_unspecified) {
+    runtest_aaudio_devices(AAUDIO_DEVICE_UNSPECIFIED, false);
+}
+
+/* FIXME - why can we open this device? What is an illegal deviceId?
+TEST(test_aaudio, aaudio_stream_device_absurd) {
+    runtest_aaudio_devices(19736459, true);
+}
+*/
+/* FIXME review
+TEST(test_aaudio, aaudio_stream_device_reasonable) {
+    runtest_aaudio_devices(1, false);
+}
+*/
+
+/* FIXME - why can we open this device? What is an illegal deviceId?
+TEST(test_aaudio, aaudio_stream_device_negative) {
+    runtest_aaudio_devices(-765, true);
+}
+*/
+
 // Test creating a default stream with everything unspecified.
 TEST(test_aaudio, aaudio_stream_unspecified) {
     AAudioStreamBuilder *aaudioBuilder = nullptr;
@@ -120,7 +172,12 @@
     AAudioStreamBuilder_setBufferCapacityInFrames(aaudioBuilder, 2000);
 
     // Create an AAudioStream using the Builder.
-    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+    result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+    if (requestedSharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE
+        && result != AAUDIO_OK) {
+        return; // EXCLUSIVE just may not be available. Should not crash.
+    }
+    ASSERT_EQ(AAUDIO_OK, result);
     EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
 
     EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, AAudioStream_getState(aaudioStream));
@@ -184,15 +241,14 @@
         // Write some data while we are running. Read counter should be advancing.
         writeLoops = 1 * actualSampleRate / framesPerBurst; // 1 second
         ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst
-        timeoutNanos = 10 * NANOS_PER_SECOND * framesPerBurst / actualSampleRate; // bursts
+        timeoutNanos = 100 * (NANOS_PER_SECOND * framesPerBurst / actualSampleRate); // N bursts
         framesWritten = 1;
         aaudioFramesRead = AAudioStream_getFramesRead(aaudioStream);
         aaudioFramesRead1 = aaudioFramesRead;
         int64_t beginTime = getNanoseconds(CLOCK_MONOTONIC);
         do {
             framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
-            ASSERT_GE(framesWritten, 0);
-            ASSERT_LE(framesWritten, framesPerBurst);
+            ASSERT_EQ(framesWritten, framesPerBurst);
 
             framesTotal += framesWritten;
             aaudioFramesWritten = AAudioStream_getFramesWritten(aaudioStream);
@@ -211,8 +267,8 @@
         aaudioFramesRead2 = AAudioStream_getFramesRead(aaudioStream);
         int64_t endTime = getNanoseconds(CLOCK_MONOTONIC);
         ASSERT_GT(aaudioFramesRead2, 0);
-        ASSERT_GT(aaudioFramesRead2, aaudioFramesRead1);
-        ASSERT_LE(aaudioFramesRead2, aaudioFramesWritten);
+        EXPECT_GT(aaudioFramesRead2, aaudioFramesRead1);
+
 
         // TODO why is AudioTrack path so inaccurate?
         const double rateTolerance = 200.0; // arbitrary tolerance for sample rate
@@ -236,15 +292,16 @@
     aaudioFramesRead = AAudioStream_getFramesRead(aaudioStream);
     ASSERT_GE(aaudioFramesRead, aaudioFramesRead2); // monotonic increase
 
-    // Use this to sleep by waiting for something that won't happen.
-    AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_PAUSED, &state, timeoutNanos);
+    // Use this to sleep by waiting for a state that won't happen.
+    timeoutNanos = 100 * NANOS_PER_MILLISECOND;
+    AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_OPEN, &state, timeoutNanos);
     aaudioFramesRead2 = AAudioStream_getFramesRead(aaudioStream);
     EXPECT_EQ(aaudioFramesRead, aaudioFramesRead2);
 
     // ------------------- TEST FLUSH -----------------
     // Prime the buffer.
     timeoutNanos = 0;
-    writeLoops = 100;
+    writeLoops = 1000;
     do {
         framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
         framesTotal += framesWritten;
@@ -282,12 +339,10 @@
     runtest_aaudio_stream(AAUDIO_SHARING_MODE_SHARED);
 }
 
-/* TODO Enable exclusive mode test.
-// Test Writing to an AAudioStream using EXCLUSIVE sharing mode.
+// Test Writing to an AAudioStream using EXCLUSIVE sharing mode. It may fail gracefully.
 TEST(test_aaudio, aaudio_stream_exclusive) {
     runtest_aaudio_stream(AAUDIO_SHARING_MODE_EXCLUSIVE);
 }
-*/
 
 int main(int argc, char **argv) {
     testing::InitGoogleTest(&argc, argv);
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
index 2ec1e1c..3786967 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
@@ -18,17 +18,55 @@
 #define LOG_TAG "AAudioTest"
 
 #include <gtest/gtest.h>
+#include <atomic>
 #include <utils/Log.h>
 
 #include <aaudio/AAudio.h>
 #include "test_aaudio.h"
 
 typedef struct AAudioCallbackTestData {
-    int32_t callbackCount;
     int32_t expectedFramesPerCallback;
     int32_t actualFramesPerCallback;
+    int32_t minLatency;
+    int32_t maxLatency;
+    std::atomic<aaudio_result_t> callbackError;
+    std::atomic<int32_t> callbackCount;
 } AAudioCallbackTestData;
 
+static int32_t measureLatency(AAudioStream *stream) {
+    int64_t presentationTime = 0;
+    int64_t presentationPosition = 0;
+    int64_t now = getNanoseconds();
+    int32_t sampleRate = AAudioStream_getSampleRate(stream);
+    int64_t framesWritten = AAudioStream_getFramesWritten(stream);
+    aaudio_result_t result = AAudioStream_getTimestamp(stream,
+                                                       CLOCK_MONOTONIC,
+                                                       &presentationPosition,
+                                                       &presentationTime);
+    if (result < 0) {
+        return result;
+    }
+    // Calculate when the last frame written would be played.
+    int64_t deltaFrames = framesWritten - presentationPosition;
+    EXPECT_GE(framesWritten, presentationPosition);
+    int64_t calculatedDeltaNanos = deltaFrames * NANOS_PER_SECOND / sampleRate;
+    int64_t calculatedTimeNanos = presentationTime +  calculatedDeltaNanos;
+    int64_t latencyNanos = calculatedTimeNanos - now;
+    int32_t latencyMillis = (int32_t) ((latencyNanos + NANOS_PER_MILLISECOND - 1)
+                            / NANOS_PER_MILLISECOND);
+    return latencyMillis;
+}
+
+static void MyErrorCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        aaudio_result_t error) {
+    (void) stream;
+    AAudioCallbackTestData *myData = (AAudioCallbackTestData *) userData;
+    myData->callbackError = error;
+
+}
+
 // Callback function that fills the audio output buffer.
 static aaudio_data_callback_result_t MyDataCallbackProc(
         AAudioStream *stream,
@@ -54,6 +92,17 @@
         float *floatData = (float *) audioData;
         for (int i = 0; i < numSamples; i++) *floatData++ = 0.0f;
     }
+
+    int32_t latency = measureLatency(stream);
+    if (latency > 0) {
+        if (latency < myData->minLatency) {
+            myData->minLatency = latency;
+        }
+        if (latency > myData->maxLatency) {
+            myData->maxLatency = latency;
+        }
+    }
+
     myData->callbackCount++;
     return AAUDIO_CALLBACK_RESULT_CONTINUE;
 }
@@ -61,7 +110,7 @@
 // Test Writing to an AAudioStream using a Callback
 void runtest_aaudio_callback(aaudio_sharing_mode_t requestedSharingMode,
                              int32_t framesPerDataCallback) {
-    AAudioCallbackTestData myTestData = { 0, 0, 0 };
+    AAudioCallbackTestData myTestData;
     const int32_t requestedSampleRate = 48000;
     const int32_t requestedSamplesPerFrame = 2;
     const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16;
@@ -79,6 +128,10 @@
     AAudioStream *stream = nullptr;
 
     aaudio_result_t result = AAUDIO_OK;
+    myTestData.callbackCount.store(0);
+    myTestData.callbackError = AAUDIO_OK;
+    myTestData.actualFramesPerCallback = 0;
+    myTestData.expectedFramesPerCallback = 0;
 
     // Use an AAudioStreamBuilder to define the stream.
     result = AAudio_createStreamBuilder(&builder);
@@ -93,6 +146,7 @@
     AAudioStreamBuilder_setSharingMode(builder, requestedSharingMode);
     AAudioStreamBuilder_setBufferCapacityInFrames(builder, 2000);
 
+    AAudioStreamBuilder_setErrorCallback(builder, MyErrorCallbackProc, &myTestData);
     AAudioStreamBuilder_setDataCallback(builder, MyDataCallbackProc, &myTestData);
     if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
         AAudioStreamBuilder_setFramesPerDataCallback(builder, framesPerDataCallback);
@@ -118,8 +172,8 @@
 
     actualDataFormat = AAudioStream_getFormat(stream);
 
-    // TODO test this on full build
-    // ASSERT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
+    // TODO Why does getDeviceId() always return 0?
+    // EXPECT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
 
     framesPerBurst = AAudioStream_getFramesPerBurst(stream);
     ASSERT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?
@@ -136,18 +190,27 @@
     // Start/stop more than once to see if it fails after the first time.
     // Write some data and measure the rate to see if the timing is OK.
     for (int loopIndex = 0; loopIndex < 2; loopIndex++) {
+
         myTestData.callbackCount = 0;
+        myTestData.minLatency = INT32_MAX;
+        myTestData.maxLatency = 0;
+        myTestData.callbackCount.store(0);
+
         myTestData.expectedFramesPerCallback = actualFramesPerDataCallback;
 
         // Start and wait for server to respond.
         ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(stream));
+
         ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream,
                                                              AAUDIO_STREAM_STATE_STARTING,
                                                              &state,
                                                              DEFAULT_STATE_TIMEOUT));
         EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
 
-        sleep(2);
+        sleep(2); // let the stream run
+
+        ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
+        ASSERT_GT(myTestData.callbackCount.load(), 10);
 
         // For more coverage, alternate pausing and stopping.
         if ((loopIndex & 1) == 0) {
@@ -168,29 +231,34 @@
             EXPECT_EQ(AAUDIO_STREAM_STATE_STOPPED, state);
         }
 
-        int32_t oldCallbackCount = myTestData.callbackCount;
+        int32_t oldCallbackCount = myTestData.callbackCount.load();
         EXPECT_GT(oldCallbackCount, 10);
         sleep(1);
-        EXPECT_EQ(oldCallbackCount, myTestData.callbackCount); // expect not advancing
+        EXPECT_EQ(oldCallbackCount, myTestData.callbackCount.load()); // expect not advancing
 
         if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
             ASSERT_EQ(framesPerDataCallback, myTestData.actualFramesPerCallback);
         }
+
+        EXPECT_GE(myTestData.minLatency, 1);   // Absurdly low
+        EXPECT_LE(myTestData.maxLatency, 200); // Absurdly high, should be < 30
+        //printf("latency: %d, %d\n", myTestData.minLatency, myTestData.maxLatency);
     }
 
+    ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
+
     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(stream));
 }
 
 // Test Using an AAudioStream callback in SHARED mode.
-
 TEST(test_aaudio, aaudio_callback_shared_unspecified) {
-runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED);
+    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED);
 }
 
 TEST(test_aaudio, aaudio_callback_shared_109) {
-runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 109); // arbitrary prime number < 192
+    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 109); // arbitrary prime number < 192
 }
 
 TEST(test_aaudio, aaudio_callback_shared_223) {
-runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
+    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
 }
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
index 8599d48..6662b72 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
@@ -1,7 +1,7 @@
 /*
  * Copyright 2017 The Android Open Source Project
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the "License", ENUM_CANNOT_CHANGE);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
@@ -25,53 +25,55 @@
 // Make sure enums do not change value.
 TEST(test_aaudio_misc, aaudio_freeze_enums) {
 
-    ASSERT_EQ(0, AAUDIO_DIRECTION_OUTPUT);
-    ASSERT_EQ(1, AAUDIO_DIRECTION_INPUT);
+#define ENUM_CANNOT_CHANGE "enum in API cannot change"
 
-    ASSERT_EQ(-1, AAUDIO_FORMAT_INVALID);
-    ASSERT_EQ(0, AAUDIO_FORMAT_UNSPECIFIED);
-    ASSERT_EQ(1, AAUDIO_FORMAT_PCM_I16);
-    ASSERT_EQ(2, AAUDIO_FORMAT_PCM_FLOAT);
+    static_assert(0 == AAUDIO_DIRECTION_OUTPUT, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_DIRECTION_INPUT, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_OK);
-    ASSERT_EQ(-900, AAUDIO_ERROR_BASE);
-    ASSERT_EQ(-899, AAUDIO_ERROR_DISCONNECTED);
-    ASSERT_EQ(-898, AAUDIO_ERROR_ILLEGAL_ARGUMENT);
-    ASSERT_EQ(-897, AAUDIO_ERROR_INCOMPATIBLE);
-    ASSERT_EQ(-896, AAUDIO_ERROR_INTERNAL);
-    ASSERT_EQ(-895, AAUDIO_ERROR_INVALID_STATE);
-    ASSERT_EQ(-894, AAUDIO_ERROR_UNEXPECTED_STATE);
-    ASSERT_EQ(-893, AAUDIO_ERROR_UNEXPECTED_VALUE);
-    ASSERT_EQ(-892, AAUDIO_ERROR_INVALID_HANDLE);
-    ASSERT_EQ(-891, AAUDIO_ERROR_INVALID_QUERY);
-    ASSERT_EQ(-890, AAUDIO_ERROR_UNIMPLEMENTED);
-    ASSERT_EQ(-889, AAUDIO_ERROR_UNAVAILABLE);
-    ASSERT_EQ(-888, AAUDIO_ERROR_NO_FREE_HANDLES);
-    ASSERT_EQ(-887, AAUDIO_ERROR_NO_MEMORY);
-    ASSERT_EQ(-886, AAUDIO_ERROR_NULL);
-    ASSERT_EQ(-885, AAUDIO_ERROR_TIMEOUT);
-    ASSERT_EQ(-884, AAUDIO_ERROR_WOULD_BLOCK);
-    ASSERT_EQ(-883, AAUDIO_ERROR_INVALID_FORMAT);
-    ASSERT_EQ(-882, AAUDIO_ERROR_OUT_OF_RANGE);
-    ASSERT_EQ(-881, AAUDIO_ERROR_NO_SERVICE);
+    static_assert(-1 == AAUDIO_FORMAT_INVALID, ENUM_CANNOT_CHANGE);
+    static_assert(0 == AAUDIO_FORMAT_UNSPECIFIED, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_FORMAT_PCM_I16, ENUM_CANNOT_CHANGE);
+    static_assert(2 == AAUDIO_FORMAT_PCM_FLOAT, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_STREAM_STATE_UNINITIALIZED);
-    ASSERT_EQ(1, AAUDIO_STREAM_STATE_UNKNOWN);
-    ASSERT_EQ(2, AAUDIO_STREAM_STATE_OPEN);
-    ASSERT_EQ(3, AAUDIO_STREAM_STATE_STARTING);
-    ASSERT_EQ(4, AAUDIO_STREAM_STATE_STARTED);
-    ASSERT_EQ(5, AAUDIO_STREAM_STATE_PAUSING);
-    ASSERT_EQ(6, AAUDIO_STREAM_STATE_PAUSED);
-    ASSERT_EQ(7, AAUDIO_STREAM_STATE_FLUSHING);
-    ASSERT_EQ(8, AAUDIO_STREAM_STATE_FLUSHED);
-    ASSERT_EQ(9, AAUDIO_STREAM_STATE_STOPPING);
-    ASSERT_EQ(10, AAUDIO_STREAM_STATE_STOPPED);
-    ASSERT_EQ(11, AAUDIO_STREAM_STATE_CLOSING);
-    ASSERT_EQ(12, AAUDIO_STREAM_STATE_CLOSED);
+    static_assert(0 == AAUDIO_OK, ENUM_CANNOT_CHANGE);
+    static_assert(-900 == AAUDIO_ERROR_BASE, ENUM_CANNOT_CHANGE);
+    static_assert(-899 == AAUDIO_ERROR_DISCONNECTED, ENUM_CANNOT_CHANGE);
+    static_assert(-898 == AAUDIO_ERROR_ILLEGAL_ARGUMENT, ENUM_CANNOT_CHANGE);
+    static_assert(-897 == AAUDIO_ERROR_INCOMPATIBLE, ENUM_CANNOT_CHANGE);
+    static_assert(-896 == AAUDIO_ERROR_INTERNAL, ENUM_CANNOT_CHANGE);
+    static_assert(-895 == AAUDIO_ERROR_INVALID_STATE, ENUM_CANNOT_CHANGE);
+    static_assert(-894 == AAUDIO_ERROR_UNEXPECTED_STATE, ENUM_CANNOT_CHANGE);
+    static_assert(-893 == AAUDIO_ERROR_UNEXPECTED_VALUE, ENUM_CANNOT_CHANGE);
+    static_assert(-892 == AAUDIO_ERROR_INVALID_HANDLE, ENUM_CANNOT_CHANGE);
+    static_assert(-891 == AAUDIO_ERROR_INVALID_QUERY, ENUM_CANNOT_CHANGE);
+    static_assert(-890 == AAUDIO_ERROR_UNIMPLEMENTED, ENUM_CANNOT_CHANGE);
+    static_assert(-889 == AAUDIO_ERROR_UNAVAILABLE, ENUM_CANNOT_CHANGE);
+    static_assert(-888 == AAUDIO_ERROR_NO_FREE_HANDLES, ENUM_CANNOT_CHANGE);
+    static_assert(-887 == AAUDIO_ERROR_NO_MEMORY, ENUM_CANNOT_CHANGE);
+    static_assert(-886 == AAUDIO_ERROR_NULL, ENUM_CANNOT_CHANGE);
+    static_assert(-885 == AAUDIO_ERROR_TIMEOUT, ENUM_CANNOT_CHANGE);
+    static_assert(-884 == AAUDIO_ERROR_WOULD_BLOCK, ENUM_CANNOT_CHANGE);
+    static_assert(-883 == AAUDIO_ERROR_INVALID_FORMAT, ENUM_CANNOT_CHANGE);
+    static_assert(-882 == AAUDIO_ERROR_OUT_OF_RANGE, ENUM_CANNOT_CHANGE);
+    static_assert(-881 == AAUDIO_ERROR_NO_SERVICE, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_SHARING_MODE_EXCLUSIVE);
-    ASSERT_EQ(1, AAUDIO_SHARING_MODE_SHARED);
+    static_assert(0 == AAUDIO_STREAM_STATE_UNINITIALIZED, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_STREAM_STATE_UNKNOWN, ENUM_CANNOT_CHANGE);
+    static_assert(2 == AAUDIO_STREAM_STATE_OPEN, ENUM_CANNOT_CHANGE);
+    static_assert(3 == AAUDIO_STREAM_STATE_STARTING, ENUM_CANNOT_CHANGE);
+    static_assert(4 == AAUDIO_STREAM_STATE_STARTED, ENUM_CANNOT_CHANGE);
+    static_assert(5 == AAUDIO_STREAM_STATE_PAUSING, ENUM_CANNOT_CHANGE);
+    static_assert(6 == AAUDIO_STREAM_STATE_PAUSED, ENUM_CANNOT_CHANGE);
+    static_assert(7 == AAUDIO_STREAM_STATE_FLUSHING, ENUM_CANNOT_CHANGE);
+    static_assert(8 == AAUDIO_STREAM_STATE_FLUSHED, ENUM_CANNOT_CHANGE);
+    static_assert(9 == AAUDIO_STREAM_STATE_STOPPING, ENUM_CANNOT_CHANGE);
+    static_assert(10 == AAUDIO_STREAM_STATE_STOPPED, ENUM_CANNOT_CHANGE);
+    static_assert(11 == AAUDIO_STREAM_STATE_CLOSING, ENUM_CANNOT_CHANGE);
+    static_assert(12 == AAUDIO_STREAM_STATE_CLOSED, ENUM_CANNOT_CHANGE);
 
-    ASSERT_EQ(0, AAUDIO_CALLBACK_RESULT_CONTINUE);
-    ASSERT_EQ(1, AAUDIO_CALLBACK_RESULT_STOP);
+    static_assert(0 == AAUDIO_SHARING_MODE_EXCLUSIVE, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_SHARING_MODE_SHARED, ENUM_CANNOT_CHANGE);
+
+    static_assert(0 == AAUDIO_CALLBACK_RESULT_CONTINUE, ENUM_CANNOT_CHANGE);
+    static_assert(1 == AAUDIO_CALLBACK_RESULT_STOP, ENUM_CANNOT_CHANGE);
 }
diff --git a/tests/tests/net/src/android/net/wifi/cts/PpsMoParserTest.java b/tests/tests/net/src/android/net/wifi/cts/PpsMoParserTest.java
index b5e2f77..0304fda 100644
--- a/tests/tests/net/src/android/net/wifi/cts/PpsMoParserTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/PpsMoParserTest.java
@@ -107,19 +107,19 @@
         assertEquals(subscriptionUpdate, config.getSubscriptionUpdate());
 
         // Subscription parameters.
-        config.setSubscriptionCreationTimeInMs(format.parse("2016-02-01T10:00:00Z").getTime());
+        config.setSubscriptionCreationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime());
         assertEquals(format.parse("2016-02-01T10:00:00Z").getTime(),
-                config.getSubscriptionCreationTimeInMs());
-        config.setSubscriptionExpirationTimeInMs(format.parse("2016-03-01T10:00:00Z").getTime());
+                config.getSubscriptionCreationTimeInMillis());
+        config.setSubscriptionExpirationTimeInMillis(format.parse("2016-03-01T10:00:00Z").getTime());
         assertEquals(format.parse("2016-03-01T10:00:00Z").getTime(),
-                config.getSubscriptionExpirationTimeInMs());
+                config.getSubscriptionExpirationTimeInMillis());
         config.setSubscriptionType("Gold");
         assertEquals("Gold", config.getSubscriptionType());
         config.setUsageLimitDataLimit(921890);
         assertEquals(921890, config.getUsageLimitDataLimit());
-        config.setUsageLimitStartTimeInMs(format.parse("2016-12-01T10:00:00Z").getTime());
+        config.setUsageLimitStartTimeInMillis(format.parse("2016-12-01T10:00:00Z").getTime());
         assertEquals(format.parse("2016-12-01T10:00:00Z").getTime(),
-                config.getUsageLimitStartTimeInMs());
+                config.getUsageLimitStartTimeInMillis());
         config.setUsageLimitTimeLimitInMinutes(120);
         assertEquals(120, config.getUsageLimitTimeLimitInMinutes());
         config.setUsageLimitUsageTimePeriodInMinutes(99910);
@@ -153,12 +153,12 @@
 
         // Credential configuration.
         Credential credential = new Credential();
-        credential.setCreationTimeInMs(format.parse("2016-01-01T10:00:00Z").getTime());
+        credential.setCreationTimeInMillis(format.parse("2016-01-01T10:00:00Z").getTime());
         assertEquals(format.parse("2016-01-01T10:00:00Z").getTime(),
-                credential.getCreationTimeInMs());
-        credential.setExpirationTimeInMs(format.parse("2016-02-01T10:00:00Z").getTime());
+                credential.getCreationTimeInMillis());
+        credential.setExpirationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime());
         assertEquals(format.parse("2016-02-01T10:00:00Z").getTime(),
-                credential.getExpirationTimeInMs());
+                credential.getExpirationTimeInMillis());
         credential.setRealm("shaken.stirred.com");
         assertEquals("shaken.stirred.com", credential.getRealm());
         credential.setCheckAaaServerCertStatus(true);
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index 14ae1b4..e888c14 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -239,11 +239,10 @@
         assertTrue(mWifiManager.reconnect());
         assertTrue(mWifiManager.reassociate());
         assertTrue(mWifiManager.disconnect());
-        assertTrue(mWifiManager.pingSupplicant());
         startScan();
         setWifiEnabled(false);
         Thread.sleep(DURATION);
-        assertTrue(mWifiManager.pingSupplicant() == mWifiManager.isScanAlwaysAvailable());
+        assertTrue(mWifiManager.isScanAlwaysAvailable());
         final String TAG = "Test";
         assertNotNull(mWifiManager.createWifiLock(TAG));
         assertNotNull(mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG));
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 704cc93..3b281a6 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -18,8 +18,8 @@
 */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android" coreApp="true" android:sharedUserId="android.uid.system"
-    android:sharedUserLabel="@string/android_system_label">
+          package="android" coreApp="true" android:sharedUserId="android.uid.system"
+          android:sharedUserLabel="@string/android_system_label">
 
     <!-- ================================================ -->
     <!-- Special broadcasts that only the system can send -->
@@ -149,59 +149,59 @@
     <protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" />
     <protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />
     <protected-broadcast
-        android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
+            android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
+            android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
+            android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
     <protected-broadcast
-        android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
+            android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
+            android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
+            android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
+            android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
     <protected-broadcast
-        android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
+            android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
+            android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
     <protected-broadcast
-        android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
+            android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
     <protected-broadcast
-        android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
+            android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
+            android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
+            android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
+            android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
+            android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
+            android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
+            android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
+            android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
+            android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
+            android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
     <protected-broadcast
-        android:name="android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED" />
+            android:name="android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast
-        android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" />
+            android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED" />
     <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY" />
     <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY" />
     <protected-broadcast
-        android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT" />
+            android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT" />
     <protected-broadcast
-        android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
+            android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
     <protected-broadcast
-        android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
+            android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED" />
@@ -363,11 +363,11 @@
     <protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
 
     <protected-broadcast
-        android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
+            android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
 
     <!-- Defined in RestrictionsManager -->
     <protected-broadcast
-        android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
+            android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
     <!-- Defined in RestrictionsManager -->
 
     <protected-broadcast android:name="android.intent.action.REQUEST_PERMISSION" />
@@ -553,28 +553,28 @@
     <!-- Used for runtime permissions related to contacts and profiles on this
         device. -->
     <permission-group android:name="android.permission-group.CONTACTS"
-        android:icon="@drawable/perm_group_contacts"
-        android:label="@string/permgrouplab_contacts"
-        android:description="@string/permgroupdesc_contacts"
-        android:priority="100" />
+                      android:icon="@drawable/perm_group_contacts"
+                      android:label="@string/permgrouplab_contacts"
+                      android:description="@string/permgroupdesc_contacts"
+                      android:priority="100" />
 
     <!-- Allows an application to read the user's contacts data.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CONTACTS"
-        android:permissionGroup="android.permission-group.CONTACTS"
-        android:label="@string/permlab_readContacts"
-        android:description="@string/permdesc_readContacts"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.CONTACTS"
+                android:label="@string/permlab_readContacts"
+                android:description="@string/permdesc_readContacts"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write the user's contacts data.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CONTACTS"
-        android:permissionGroup="android.permission-group.CONTACTS"
-        android:label="@string/permlab_writeContacts"
-        android:description="@string/permdesc_writeContacts"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.CONTACTS"
+                android:label="@string/permlab_writeContacts"
+                android:description="@string/permdesc_writeContacts"
+                android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing user's calendar                              -->
@@ -583,28 +583,28 @@
 
     <!-- Used for runtime permissions related to user's calendar. -->
     <permission-group android:name="android.permission-group.CALENDAR"
-        android:icon="@drawable/perm_group_calendar"
-        android:label="@string/permgrouplab_calendar"
-        android:description="@string/permgroupdesc_calendar"
-        android:priority="200" />
+                      android:icon="@drawable/perm_group_calendar"
+                      android:label="@string/permgrouplab_calendar"
+                      android:description="@string/permgroupdesc_calendar"
+                      android:priority="200" />
 
     <!-- Allows an application to read the user's calendar data.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CALENDAR"
-        android:permissionGroup="android.permission-group.CALENDAR"
-        android:label="@string/permlab_readCalendar"
-        android:description="@string/permdesc_readCalendar"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.CALENDAR"
+                android:label="@string/permlab_readCalendar"
+                android:description="@string/permdesc_readCalendar"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write the user's calendar data.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CALENDAR"
-        android:permissionGroup="android.permission-group.CALENDAR"
-        android:label="@string/permlab_writeCalendar"
-        android:description="@string/permdesc_writeCalendar"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.CALENDAR"
+                android:label="@string/permlab_writeCalendar"
+                android:description="@string/permdesc_writeCalendar"
+                android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing and modifying user's SMS messages            -->
@@ -613,56 +613,56 @@
 
     <!-- Used for runtime permissions related to user's SMS messages. -->
     <permission-group android:name="android.permission-group.SMS"
-        android:icon="@drawable/perm_group_sms"
-        android:label="@string/permgrouplab_sms"
-        android:description="@string/permgroupdesc_sms"
-        android:priority="300" />
+                      android:icon="@drawable/perm_group_sms"
+                      android:label="@string/permgrouplab_sms"
+                      android:description="@string/permgroupdesc_sms"
+                      android:priority="300" />
 
     <!-- Allows an application to send SMS messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.SEND_SMS"
-        android:permissionGroup="android.permission-group.SMS"
-        android:label="@string/permlab_sendSms"
-        android:description="@string/permdesc_sendSms"
-        android:permissionFlags="costsMoney"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.SMS"
+                android:label="@string/permlab_sendSms"
+                android:description="@string/permdesc_sendSms"
+                android:permissionFlags="costsMoney"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to receive SMS messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_SMS"
-        android:permissionGroup="android.permission-group.SMS"
-        android:label="@string/permlab_receiveSms"
-        android:description="@string/permdesc_receiveSms"
-        android:protectionLevel="dangerous"/>
+                android:permissionGroup="android.permission-group.SMS"
+                android:label="@string/permlab_receiveSms"
+                android:description="@string/permdesc_receiveSms"
+                android:protectionLevel="dangerous"/>
 
     <!-- Allows an application to read SMS messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_SMS"
-        android:permissionGroup="android.permission-group.SMS"
-        android:label="@string/permlab_readSms"
-        android:description="@string/permdesc_readSms"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.SMS"
+                android:label="@string/permlab_readSms"
+                android:description="@string/permdesc_readSms"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to receive WAP push messages.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_WAP_PUSH"
-        android:permissionGroup="android.permission-group.SMS"
-        android:label="@string/permlab_receiveWapPush"
-        android:description="@string/permdesc_receiveWapPush"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.SMS"
+                android:label="@string/permlab_receiveWapPush"
+                android:description="@string/permdesc_receiveWapPush"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to monitor incoming MMS messages.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_MMS"
-        android:permissionGroup="android.permission-group.SMS"
-        android:label="@string/permlab_receiveMms"
-        android:description="@string/permdesc_receiveMms"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.SMS"
+                android:label="@string/permlab_receiveMms"
+                android:description="@string/permdesc_receiveMms"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to read previously received cell broadcast
          messages and to register a content observer to get notifications when
@@ -677,10 +677,10 @@
          <p>Protection level: dangerous
          @hide Pending API council approval -->
     <permission android:name="android.permission.READ_CELL_BROADCASTS"
-        android:permissionGroup="android.permission-group.SMS"
-        android:label="@string/permlab_readCellBroadcasts"
-        android:description="@string/permdesc_readCellBroadcasts"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.SMS"
+                android:label="@string/permlab_readCellBroadcasts"
+                android:description="@string/permdesc_readCellBroadcasts"
+                android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing external storage                             -->
@@ -689,10 +689,10 @@
 
     <!-- Used for runtime permissions related to the shared external storage. -->
     <permission-group android:name="android.permission-group.STORAGE"
-        android:icon="@drawable/perm_group_storage"
-        android:label="@string/permgrouplab_storage"
-        android:description="@string/permgroupdesc_storage"
-        android:priority="900" />
+                      android:icon="@drawable/perm_group_storage"
+                      android:label="@string/permgrouplab_storage"
+                      android:description="@string/permgroupdesc_storage"
+                      android:priority="900" />
 
     <!-- Allows an application to read from external storage.
      <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
@@ -717,10 +717,10 @@
      <p>Protection level: dangerous
      -->
     <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
-        android:permissionGroup="android.permission-group.STORAGE"
-        android:label="@string/permlab_sdcardRead"
-        android:description="@string/permdesc_sdcardRead"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.STORAGE"
+                android:label="@string/permlab_sdcardRead"
+                android:description="@string/permdesc_sdcardRead"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write to external storage.
          <p class="note"><strong>Note:</strong> If <em>both</em> your <a
@@ -738,10 +738,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
-        android:permissionGroup="android.permission-group.STORAGE"
-        android:label="@string/permlab_sdcardWrite"
-        android:description="@string/permdesc_sdcardWrite"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.STORAGE"
+                android:label="@string/permlab_sdcardWrite"
+                android:description="@string/permdesc_sdcardWrite"
+                android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device location                          -->
@@ -750,30 +750,30 @@
 
     <!-- Used for permissions that allow accessing the device location. -->
     <permission-group android:name="android.permission-group.LOCATION"
-        android:icon="@drawable/perm_group_location"
-        android:label="@string/permgrouplab_location"
-        android:description="@string/permgroupdesc_location"
-        android:priority="400" />
+                      android:icon="@drawable/perm_group_location"
+                      android:label="@string/permgrouplab_location"
+                      android:description="@string/permgroupdesc_location"
+                      android:priority="400" />
 
     <!-- Allows an app to access precise location.
          Alternatively, you might want {@link #ACCESS_COARSE_LOCATION}.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_FINE_LOCATION"
-        android:permissionGroup="android.permission-group.LOCATION"
-        android:label="@string/permlab_accessFineLocation"
-        android:description="@string/permdesc_accessFineLocation"
-        android:protectionLevel="dangerous|ephemeral" />
+                android:permissionGroup="android.permission-group.LOCATION"
+                android:label="@string/permlab_accessFineLocation"
+                android:description="@string/permdesc_accessFineLocation"
+                android:protectionLevel="dangerous|ephemeral" />
 
     <!-- Allows an app to access approximate location.
          Alternatively, you might want {@link #ACCESS_FINE_LOCATION}.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_COARSE_LOCATION"
-        android:permissionGroup="android.permission-group.LOCATION"
-        android:label="@string/permlab_accessCoarseLocation"
-        android:description="@string/permdesc_accessCoarseLocation"
-        android:protectionLevel="dangerous|ephemeral" />
+                android:permissionGroup="android.permission-group.LOCATION"
+                android:label="@string/permlab_accessCoarseLocation"
+                android:description="@string/permdesc_accessCoarseLocation"
+                android:protectionLevel="dangerous|ephemeral" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device telephony                         -->
@@ -782,10 +782,10 @@
 
     <!-- Used for permissions that are associated telephony features. -->
     <permission-group android:name="android.permission-group.PHONE"
-        android:icon="@drawable/perm_group_phone_calls"
-        android:label="@string/permgrouplab_phone"
-        android:description="@string/permgroupdesc_phone"
-        android:priority="500" />
+                      android:icon="@drawable/perm_group_phone_calls"
+                      android:label="@string/permgrouplab_phone"
+                      android:description="@string/permgroupdesc_phone"
+                      android:priority="500" />
 
     <!-- Allows read only access to phone state, including the phone number of the device,
          current cellular network information, the status of any ongoing calls, and a list of any
@@ -801,40 +801,30 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_PHONE_STATE"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:label="@string/permlab_readPhoneState"
-        android:description="@string/permdesc_readPhoneState"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.PHONE"
+                android:label="@string/permlab_readPhoneState"
+                android:description="@string/permdesc_readPhoneState"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
          granted by {@link #READ_PHONE_STATE} but is exposed to ephemeral applications.
          <p>Protection level: dangerous-->
     <permission android:name="android.permission.READ_PHONE_NUMBERS"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:label="@string/permlab_readPhoneNumbers"
-        android:description="@string/permdesc_readPhoneNumbers"
-        android:protectionLevel="dangerous|ephemeral" />
+                android:permissionGroup="android.permission-group.PHONE"
+                android:label="@string/permlab_readPhoneNumbers"
+                android:description="@string/permdesc_readPhoneNumbers"
+                android:protectionLevel="dangerous|ephemeral" />
 
     <!-- Allows an application to initiate a phone call without going through
         the Dialer user interface for the user to confirm the call.
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.CALL_PHONE"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:permissionFlags="costsMoney"
-        android:label="@string/permlab_callPhone"
-        android:description="@string/permdesc_callPhone"
-        android:protectionLevel="dangerous" />
-
-    <!-- Allows an application to manage its own calls, but rely on the system to route focus to the
-         currently active call.
-        <p>Protection level: dangerous
-    -->
-    <permission android:name="android.permission.MANAGE_OWN_CALLS"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:label="@string/permlab_manageOwnCalls"
-        android:description="@string/permdesc_manageOwnCalls"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.PHONE"
+                android:permissionFlags="costsMoney"
+                android:label="@string/permlab_callPhone"
+                android:description="@string/permdesc_callPhone"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to access the IMS call service: making and
          modifying a call
@@ -842,10 +832,10 @@
         @hide
     -->
     <permission android:name="android.permission.ACCESS_IMS_CALL_SERVICE"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:label="@string/permlab_accessImsCallService"
-        android:description="@string/permdesc_accessImsCallService"
-        android:protectionLevel="signature|privileged" />
+                android:permissionGroup="android.permission-group.PHONE"
+                android:label="@string/permlab_accessImsCallService"
+                android:description="@string/permdesc_accessImsCallService"
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to read the user's call log.
          <p class="note"><strong>Note:</strong> If your app uses the
@@ -860,10 +850,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CALL_LOG"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:label="@string/permlab_readCallLog"
-        android:description="@string/permdesc_readCallLog"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.PHONE"
+                android:label="@string/permlab_readCallLog"
+                android:description="@string/permdesc_readCallLog"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to write (but not read) the user's
          call log data.
@@ -879,28 +869,28 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CALL_LOG"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:label="@string/permlab_writeCallLog"
-        android:description="@string/permdesc_writeCallLog"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.PHONE"
+                android:label="@string/permlab_writeCallLog"
+                android:description="@string/permdesc_writeCallLog"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to add voicemails into the system.
          <p>Protection level: dangerous
     -->
     <permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:label="@string/permlab_addVoicemail"
-        android:description="@string/permdesc_addVoicemail"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.PHONE"
+                android:label="@string/permlab_addVoicemail"
+                android:description="@string/permdesc_addVoicemail"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an application to use SIP service.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.USE_SIP"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:description="@string/permdesc_use_sip"
-        android:label="@string/permlab_use_sip"
-        android:protectionLevel="dangerous"/>
+                android:permissionGroup="android.permission-group.PHONE"
+                android:description="@string/permdesc_use_sip"
+                android:label="@string/permlab_use_sip"
+                android:protectionLevel="dangerous"/>
 
     <!-- Allows an application to see the number being dialed during an outgoing
          call with the option to redirect the call to a different number or
@@ -908,21 +898,31 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:label="@string/permlab_processOutgoingCalls"
-        android:description="@string/permdesc_processOutgoingCalls"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.PHONE"
+                android:label="@string/permlab_processOutgoingCalls"
+                android:description="@string/permdesc_processOutgoingCalls"
+                android:protectionLevel="dangerous" />
 
 
     <!-- Allows the app to answer an incoming phone call.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ANSWER_PHONE_CALLS"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:label="@string/permlab_answerPhoneCalls"
-        android:description="@string/permdesc_answerPhoneCalls"
-        android:protectionLevel="dangerous|runtime" />
+                android:permissionGroup="android.permission-group.PHONE"
+                android:label="@string/permlab_answerPhoneCalls"
+                android:description="@string/permdesc_answerPhoneCalls"
+                android:protectionLevel="dangerous|runtime" />
 
+    <!-- Allows a calling application which manages it own calls through the self-managed
+         {@link android.telecom.ConnectionService} APIs.  See
+         {@link android.telecom.PhoneAccount#CAPABILITY_SELF_MANAGED for more information on the
+         self-managed ConnectionService APIs.
+         <p>Protection level: normal
+    -->
+    <permission android:name="android.permission.MANAGE_OWN_CALLS"
+                android:label="@string/permlab_manageOwnCalls"
+                android:description="@string/permdesc_manageOwnCalls"
+                android:protectionLevel="normal" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device microphone                        -->
@@ -933,19 +933,19 @@
          microphone audio from the device. Note that phone calls also capture audio
          but are in a separate (more visible) permission group. -->
     <permission-group android:name="android.permission-group.MICROPHONE"
-        android:icon="@drawable/perm_group_microphone"
-        android:label="@string/permgrouplab_microphone"
-        android:description="@string/permgroupdesc_microphone"
-        android:priority="600" />
+                      android:icon="@drawable/perm_group_microphone"
+                      android:label="@string/permgrouplab_microphone"
+                      android:description="@string/permgroupdesc_microphone"
+                      android:priority="600" />
 
     <!-- Allows an application to record audio.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECORD_AUDIO"
-        android:permissionGroup="android.permission-group.MICROPHONE"
-        android:label="@string/permlab_recordAudio"
-        android:description="@string/permdesc_recordAudio"
-        android:protectionLevel="dangerous"/>
+                android:permissionGroup="android.permission-group.MICROPHONE"
+                android:label="@string/permlab_recordAudio"
+                android:description="@string/permdesc_recordAudio"
+                android:protectionLevel="dangerous"/>
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the UCE Service                              -->
@@ -955,15 +955,15 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_UCE_PRESENCE_SERVICE"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:protectionLevel="signatureOrSystem"/>
+                android:permissionGroup="android.permission-group.PHONE"
+                android:protectionLevel="signatureOrSystem"/>
 
     <!-- @hide Allows an application to Access UCE-OPTIONS.
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_UCE_OPTIONS_SERVICE"
-        android:permissionGroup="android.permission-group.PHONE"
-        android:protectionLevel="signatureOrSystem"/>
+                android:permissionGroup="android.permission-group.PHONE"
+                android:protectionLevel="signatureOrSystem"/>
 
 
 
@@ -975,10 +975,10 @@
     <!-- Used for permissions that are associated with accessing
      camera or capturing images/video from the device. -->
     <permission-group android:name="android.permission-group.CAMERA"
-        android:icon="@drawable/perm_group_camera"
-        android:label="@string/permgrouplab_camera"
-        android:description="@string/permgroupdesc_camera"
-        android:priority="700" />
+                      android:icon="@drawable/perm_group_camera"
+                      android:label="@string/permgrouplab_camera"
+                      android:description="@string/permgroupdesc_camera"
+                      android:priority="700" />
 
     <!-- Required to be able to access the camera device.
          <p>This will automatically enforce the <a
@@ -990,10 +990,10 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.CAMERA"
-        android:permissionGroup="android.permission-group.CAMERA"
-        android:label="@string/permlab_camera"
-        android:description="@string/permdesc_camera"
-        android:protectionLevel="dangerous|ephemeral" />
+                android:permissionGroup="android.permission-group.CAMERA"
+                android:label="@string/permlab_camera"
+                android:description="@string/permdesc_camera"
+                android:protectionLevel="dangerous|ephemeral" />
 
 
     <!-- ====================================================================== -->
@@ -1004,28 +1004,28 @@
     <!-- Used for permissions that are associated with accessing
          camera or capturing images/video from the device. -->
     <permission-group android:name="android.permission-group.SENSORS"
-        android:icon="@drawable/perm_group_sensors"
-        android:label="@string/permgrouplab_sensors"
-        android:description="@string/permgroupdesc_sensors"
-        android:priority="800" />
+                      android:icon="@drawable/perm_group_sensors"
+                      android:label="@string/permgrouplab_sensors"
+                      android:description="@string/permgroupdesc_sensors"
+                      android:priority="800" />
 
     <!-- Allows an application to access data from sensors that the user uses to
          measure what is happening inside his/her body, such as heart rate.
          <p>Protection level: dangerous -->
     <permission android:name="android.permission.BODY_SENSORS"
-        android:permissionGroup="android.permission-group.SENSORS"
-        android:label="@string/permlab_bodySensors"
-        android:description="@string/permdesc_bodySensors"
-        android:protectionLevel="dangerous" />
+                android:permissionGroup="android.permission-group.SENSORS"
+                android:label="@string/permlab_bodySensors"
+                android:description="@string/permdesc_bodySensors"
+                android:protectionLevel="dangerous" />
 
     <!-- Allows an app to use fingerprint hardware.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.USE_FINGERPRINT"
-        android:permissionGroup="android.permission-group.SENSORS"
-        android:label="@string/permlab_useFingerprint"
-        android:description="@string/permdesc_useFingerprint"
-        android:protectionLevel="normal" />
+                android:permissionGroup="android.permission-group.SENSORS"
+                android:label="@string/permlab_useFingerprint"
+                android:description="@string/permdesc_useFingerprint"
+                android:protectionLevel="normal" />
 
     <!-- ====================================================================== -->
     <!-- REMOVED PERMISSIONS                                                    -->
@@ -1033,78 +1033,78 @@
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.READ_PROFILE"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_PROFILE"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.READ_SOCIAL_STREAM"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_SOCIAL_STREAM"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.READ_USER_DICTIONARY"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_USER_DICTIONARY"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.WRITE_SMS"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.MANAGE_ACCOUNTS"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.USE_CREDENTIALS"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- @hide We need to keep this around for backwards compatibility -->
     <permission android:name="android.permission.FLASHLIGHT"
-        android:protectionLevel="normal"
-        android:permissionFlags="removed"/>
+                android:protectionLevel="normal"
+                android:permissionFlags="removed"/>
 
     <!-- ====================================================================== -->
     <!-- INSTALL PERMISSIONS                                                    -->
@@ -1119,37 +1119,37 @@
          to handle the respond-via-message action during incoming calls.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to send SMS to premium shortcodes without user permission.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to filter carrier specific sms.
          @hide -->
     <permission android:name="android.permission.CARRIER_FILTER_SMS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to receive emergency cell broadcast messages,
          to record or display them to the user.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to monitor incoming Bluetooth MAP messages, to record
          or perform processing on them. -->
     <!-- @hide -->
     <permission android:name="android.permission.RECEIVE_BLUETOOTH_MAP"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to execute contacts directory search.
          This should only be used by ContactsProvider.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to modify cell broadcasts through the content provider.
          <p>Not for use by third-party applications. -->
@@ -1165,9 +1165,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="com.android.alarm.permission.SET_ALARM"
-        android:label="@string/permlab_setAlarm"
-        android:description="@string/permdesc_setAlarm"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_setAlarm"
+                android:description="@string/permdesc_setAlarm"
+                android:protectionLevel="normal" />
 
     <!-- =============================================================== -->
     <!-- Permissions for accessing the user voicemail                    -->
@@ -1178,13 +1178,13 @@
         <p>Protection level: signature|privileged
     -->
     <permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to read voicemails in the system.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="com.android.voicemail.permission.READ_VOICEMAIL"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- ======================================= -->
     <!-- Permissions for accessing location info -->
@@ -1195,26 +1195,26 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"
-        android:label="@string/permlab_accessLocationExtraCommands"
-        android:description="@string/permdesc_accessLocationExtraCommands"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_accessLocationExtraCommands"
+                android:description="@string/permdesc_accessLocationExtraCommands"
+                android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an application to install a location provider into the Location Manager.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.INSTALL_LOCATION_PROVIDER"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows HDMI-CEC service to access device and configuration files.
          This should only be used by HDMI-CEC service.
     -->
     <permission android:name="android.permission.HDMI_CEC"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to use location features in hardware,
          such as the geofencing api.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.LOCATION_HARDWARE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
     <uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
 
     <!-- @SystemApi Allows an application to create mock location providers for testing.
@@ -1222,7 +1222,7 @@
          @hide
     -->
     <permission android:name="android.permission.ACCESS_MOCK_LOCATION"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- ======================================= -->
     <!-- Permissions for accessing networks -->
@@ -1233,79 +1233,79 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.INTERNET"
-        android:description="@string/permdesc_createNetworkSockets"
-        android:label="@string/permlab_createNetworkSockets"
-        android:protectionLevel="normal|ephemeral" />
+                android:description="@string/permdesc_createNetworkSockets"
+                android:label="@string/permlab_createNetworkSockets"
+                android:protectionLevel="normal|ephemeral" />
 
     <!-- Allows applications to access information about networks.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_NETWORK_STATE"
-        android:description="@string/permdesc_accessNetworkState"
-        android:label="@string/permlab_accessNetworkState"
-        android:protectionLevel="normal|ephemeral" />
+                android:description="@string/permdesc_accessNetworkState"
+                android:label="@string/permlab_accessNetworkState"
+                android:protectionLevel="normal|ephemeral" />
 
     <!-- Allows applications to access information about Wi-Fi networks.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_WIFI_STATE"
-        android:description="@string/permdesc_accessWifiState"
-        android:label="@string/permlab_accessWifiState"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_accessWifiState"
+                android:label="@string/permlab_accessWifiState"
+                android:protectionLevel="normal" />
 
     <!-- Allows applications to change Wi-Fi connectivity state.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_WIFI_STATE"
-        android:description="@string/permdesc_changeWifiState"
-        android:label="@string/permlab_changeWifiState"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_changeWifiState"
+                android:label="@string/permlab_changeWifiState"
+                android:protectionLevel="normal" />
 
     <!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_WIFI_CREDENTIAL"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows applications to change tether state and run
          tether carrier provisioning.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.TETHER_PRIVILEGED"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allow system apps to receive broadcast
          when a wifi network credential is changed.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to modify any wifi configuration, even if created
      by another application. Once reconfigured the original creator cannot make any further
      modifications.
      <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @hide -->
     <permission android:name="android.permission.ACCESS_WIMAX_STATE"
-        android:description="@string/permdesc_accessWimaxState"
-        android:label="@string/permlab_accessWimaxState"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_accessWimaxState"
+                android:label="@string/permlab_accessWimaxState"
+                android:protectionLevel="normal" />
 
     <!-- @hide -->
     <permission android:name="android.permission.CHANGE_WIMAX_STATE"
-        android:description="@string/permdesc_changeWimaxState"
-        android:label="@string/permlab_changeWimaxState"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_changeWimaxState"
+                android:label="@string/permlab_changeWimaxState"
+                android:protectionLevel="normal" />
 
     <!-- Allows applications to act as network scorers. @hide @SystemApi-->
     <permission android:name="android.permission.SCORE_NETWORKS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to request network
          recommendations and scores from the NetworkScoreService.
          <p>Not for use by third-party applications. @hide -->
     <permission android:name="android.permission.REQUEST_NETWORK_SCORES"
-        android:protectionLevel="signature|setup" />
+                android:protectionLevel="signature|setup" />
 
     <!-- Allows network stack services (Connectivity and Wifi) to coordinate
          <p>Not for use by third-party or privileged applications.
@@ -1323,73 +1323,73 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.BLUETOOTH"
-        android:description="@string/permdesc_bluetooth"
-        android:label="@string/permlab_bluetooth"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_bluetooth"
+                android:label="@string/permlab_bluetooth"
+                android:protectionLevel="normal" />
 
     <!-- Allows applications to discover and pair bluetooth devices.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.BLUETOOTH_ADMIN"
-        android:description="@string/permdesc_bluetoothAdmin"
-        android:label="@string/permlab_bluetoothAdmin"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_bluetoothAdmin"
+                android:label="@string/permlab_bluetoothAdmin"
+                android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows applications to pair bluetooth devices without user interaction, and to
          allow or disallow phonebook access or message access.
          This is not available to third party applications. -->
     <permission android:name="android.permission.BLUETOOTH_PRIVILEGED"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Control access to email providers exclusively for Bluetooth
          @hide
     -->
     <permission android:name="android.permission.BLUETOOTH_MAP"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows bluetooth stack to access files
          @hide This should only be used by Bluetooth apk.
     -->
     <permission android:name="android.permission.BLUETOOTH_STACK"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows applications to perform I/O operations over NFC.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.NFC"
-        android:description="@string/permdesc_nfc"
-        android:label="@string/permlab_nfc"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_nfc"
+                android:label="@string/permlab_nfc"
+                android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an internal user to use privileged ConnectivityManager APIs.
          @hide -->
     <permission android:name="android.permission.CONNECTIVITY_INTERNAL"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an internal user to use restricted Networks.
          @hide -->
     <permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows a system application to access hardware packet offload capabilities.
          @hide -->
     <permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi
          @hide -->
     <permission android:name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows access to the loop radio (Android@Home mesh network) device.
          @hide -->
     <permission android:name="android.permission.LOOP_RADIO"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows sending and receiving handover transfer status from Wifi and Bluetooth
          @hide -->
     <permission android:name="android.permission.NFC_HANDOVER_STATUS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
@@ -1408,16 +1408,16 @@
     <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.GET_ACCOUNTS"
-        android:permissionGroup="android.permission-group.CONTACTS"
-        android:protectionLevel="dangerous"
-        android:description="@string/permdesc_getAccounts"
-        android:label="@string/permlab_getAccounts" />
+                android:permissionGroup="android.permission-group.CONTACTS"
+                android:protectionLevel="dangerous"
+                android:description="@string/permdesc_getAccounts"
+                android:label="@string/permlab_getAccounts" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
 
     <!-- @SystemApi Allows applications to call into AccountAuthenticators.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCOUNT_MANAGER"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing hardware that may effect battery life-->
@@ -1428,34 +1428,34 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
-        android:description="@string/permdesc_changeWifiMulticastState"
-        android:label="@string/permlab_changeWifiMulticastState"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_changeWifiMulticastState"
+                android:label="@string/permlab_changeWifiMulticastState"
+                android:protectionLevel="normal" />
 
     <!-- Allows access to the vibrator.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.VIBRATE"
-        android:label="@string/permlab_vibrate"
-        android:description="@string/permdesc_vibrate"
-        android:protectionLevel="normal|ephemeral" />
+                android:label="@string/permlab_vibrate"
+                android:description="@string/permdesc_vibrate"
+                android:protectionLevel="normal|ephemeral" />
 
     <!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
          from dimming.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.WAKE_LOCK"
-        android:label="@string/permlab_wakeLock"
-        android:description="@string/permdesc_wakeLock"
-        android:protectionLevel="normal|ephemeral" />
+                android:label="@string/permlab_wakeLock"
+                android:description="@string/permdesc_wakeLock"
+                android:protectionLevel="normal|ephemeral" />
 
     <!-- Allows using the device's IR transmitter, if available.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.TRANSMIT_IR"
-        android:label="@string/permlab_transmitIr"
-        android:description="@string/permdesc_transmitIr"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_transmitIr"
+                android:description="@string/permdesc_transmitIr"
+                android:protectionLevel="normal" />
 
     <!-- ==================================================== -->
     <!-- Permissions related to changing audio settings   -->
@@ -1466,9 +1466,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
-        android:label="@string/permlab_modifyAudioSettings"
-        android:description="@string/permdesc_modifyAudioSettings"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_modifyAudioSettings"
+                android:description="@string/permdesc_modifyAudioSettings"
+                android:protectionLevel="normal" />
 
     <!-- ================================== -->
     <!-- Permissions for accessing hardware -->
@@ -1478,83 +1478,83 @@
     <!-- @SystemApi Allows an application to manage preferences and permissions for USB devices
          @hide -->
     <permission android:name="android.permission.MANAGE_USB"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to access the MTP USB kernel driver.
          For use only by the device side MTP implementation.
          @hide -->
     <permission android:name="android.permission.ACCESS_MTP"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows access to hardware peripherals.  Intended only for hardware testing.
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.HARDWARE_TEST"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows access to FM
          @hide This is not a third-party API (intended for system apps).-->
     <permission android:name="android.permission.ACCESS_FM_RADIO"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows access to configure network interfaces, configure/use IPSec, etc.
          @hide -->
     <permission android:name="android.permission.NET_ADMIN"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows registration for remote audio playback. @hide -->
     <permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows TvInputService to access underlying TV input hardware such as
          built-in tuners and HDMI-in's.
          @hide This should only be used by OEM's TvInputService's.
     -->
     <permission android:name="android.permission.TV_INPUT_HARDWARE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows to capture a frame of TV input hardware such as
          built-in tuners and HDMI-in's.
          @hide <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.CAPTURE_TV_INPUT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @hide Allows TvInputService to access DVB device.
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DVB_DEVICE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by carrier state
          @hide <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by user state
          @hide <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows reading the OEM unlock state
          @hide <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_OEM_UNLOCK_STATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @hide Allows enabling/disabling OEM unlock
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.OEM_UNLOCK_STATE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows querying state of PersistentDataBlock
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCESS_PDB_STATE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows system update service to notify device owner about pending updates.
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- =========================================== -->
     <!-- Permissions associated with camera and image capture -->
@@ -1565,12 +1565,12 @@
          a camera is in use by an application.
          @hide -->
     <permission android:name="android.permission.CAMERA_DISABLE_TRANSMIT_LED"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows sending the camera service notifications about system-wide events.
         @hide -->
     <permission android:name="android.permission.CAMERA_SEND_SYSTEM_EVENTS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- =========================================== -->
     <!-- Permissions associated with telephony state -->
@@ -1581,58 +1581,58 @@
          Does not include placing calls.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MODIFY_PHONE_STATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows read only access to precise phone state.
          @hide Pending API council approval -->
     <permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows read access to privileged phone state.
          @hide Used internally. -->
     <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
          corresponds to a device SIM.
          @hide -->
     <permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_CALL_PROVIDER.
          @hide -->
     <permission android:name="android.permission.REGISTER_CALL_PROVIDER"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_CONNECTION_MANAGER
          @hide -->
     <permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.InCallService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_INCALL_SERVICE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a link {@link android.telephony.VisualVoicemailService} to ensure that
          only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission
-      android:name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"
-      android:protectionLevel="signature|privileged"/>
+            android:name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"
+            android:protectionLevel="signature|privileged"/>
 
     <!-- Must be required by a {@link android.telecom.CallScreeningService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_SCREENING_SERVICE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
@@ -1641,24 +1641,24 @@
          @SystemApi
          @hide -->
     <permission android:name="android.permission.BIND_CONNECTION_SERVICE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to control the in-call experience.
          @hide -->
     <permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to receive STK related commands.
          @hide -->
     <permission android:name="android.permission.RECEIVE_STK_COMMANDS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by an ImsService to ensure that only the
          system can bind to it.
@@ -1667,7 +1667,7 @@
          @hide
     -->
     <permission android:name="android.permission.BIND_IMS_SERVICE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
 
     <!-- ================================== -->
@@ -1678,7 +1678,7 @@
     <!-- @SystemApi Allows an application to write to internal media storage
          @hide  -->
     <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to manage access to documents, usually as part
          of a document picker.
@@ -1688,20 +1688,21 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.MANAGE_DOCUMENTS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to cache content.
          <p>Not for use by third-party applications.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.CACHE_CONTENT"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
-    <!-- Allows an application to aggressively allocate disk space.
+    <!-- @SystemApi @hide
+         Allows an application to aggressively allocate disk space.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.ALLOCATE_AGGRESSIVE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- ================================== -->
     <!-- Permissions for screenlock         -->
@@ -1712,9 +1713,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.DISABLE_KEYGUARD"
-        android:description="@string/permdesc_disableKeyguard"
-        android:label="@string/permlab_disableKeyguard"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_disableKeyguard"
+                android:label="@string/permlab_disableKeyguard"
+                android:protectionLevel="normal" />
 
     <!-- ================================== -->
     <!-- Permissions to access other installed applications  -->
@@ -1723,9 +1724,9 @@
 
     <!-- @deprecated No longer enforced. -->
     <permission android:name="android.permission.GET_TASKS"
-        android:label="@string/permlab_getTasks"
-        android:description="@string/permdesc_getTasks"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_getTasks"
+                android:description="@string/permdesc_getTasks"
+                android:protectionLevel="normal" />
 
     <!-- New version of GET_TASKS that apps can request, since GET_TASKS doesn't really
          give access to task information.  We need this new one because there are
@@ -1738,32 +1739,32 @@
          @hide
          @SystemApi -->
     <permission android:name="android.permission.REAL_GET_TASKS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to start a task from a ActivityManager#RecentTaskInfo.
          @hide -->
     <permission android:name="android.permission.START_TASKS_FROM_RECENTS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to do interactions
          across the users on the device, using singleton services and
          user-targeted broadcasts.  This permission is not available to
          third party applications. -->
     <permission android:name="android.permission.INTERACT_ACROSS_USERS"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
          that removes restrictions on where broadcasts can be sent and allows other
          types of interactions
          @hide -->
     <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
-        android:protectionLevel="signature|installer" />
+                android:protectionLevel="signature|installer" />
 
     <!-- @SystemApi @hide Allows an application to call APIs that allow it to query and manage
          users on the device. This permission is not available to
          third party applications. -->
     <permission android:name="android.permission.MANAGE_USERS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @hide Allows an application to create, remove users and get the list of
          users on the device. Applications holding this permission can only create restricted,
@@ -1771,69 +1772,69 @@
          {@link android.Manifest.permission#MANAGE_USERS} is needed.
          This permission is not available to third party applications. -->
     <permission android:name="android.permission.CREATE_USERS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to set the profile owners and the device owner.
          This permission is not available to third party applications.-->
     <permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
-        android:protectionLevel="signature"
-        android:label="@string/permlab_manageProfileAndDeviceOwners"
-        android:description="@string/permdesc_manageProfileAndDeviceOwners" />
+                android:protectionLevel="signature"
+                android:label="@string/permlab_manageProfileAndDeviceOwners"
+                android:description="@string/permdesc_manageProfileAndDeviceOwners" />
 
     <!-- Allows an application to get full detailed information about
          recently running tasks, with full fidelity to the real state.
          @hide -->
     <permission android:name="android.permission.GET_DETAILED_TASKS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to change the Z-order of tasks.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.REORDER_TASKS"
-        android:label="@string/permlab_reorderTasks"
-        android:description="@string/permdesc_reorderTasks"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_reorderTasks"
+                android:description="@string/permdesc_reorderTasks"
+                android:protectionLevel="normal" />
 
     <!-- @hide Allows an application to change to remove/kill tasks -->
     <permission android:name="android.permission.REMOVE_TASKS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi @hide Allows an application to create/manage/remove stacks -->
     <permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to start any activity, regardless of permission
          protection or exported state.
          @hide -->
     <permission android:name="android.permission.START_ANY_ACTIVITY"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
         API is no longer supported. -->
     <permission android:name="android.permission.RESTART_PACKAGES"
-        android:label="@string/permlab_killBackgroundProcesses"
-        android:description="@string/permdesc_killBackgroundProcesses"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_killBackgroundProcesses"
+                android:description="@string/permdesc_killBackgroundProcesses"
+                android:protectionLevel="normal" />
 
     <!-- Allows an application to call
         {@link android.app.ActivityManager#killBackgroundProcesses}.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
-        android:label="@string/permlab_killBackgroundProcesses"
-        android:description="@string/permdesc_killBackgroundProcesses"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_killBackgroundProcesses"
+                android:description="@string/permdesc_killBackgroundProcesses"
+                android:protectionLevel="normal" />
 
     <!-- @SystemApi @hide Allows an application to query process states and current
          OOM adjustment scores.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- Allows use of PendingIntent.getIntent().
          @hide -->
     <permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- ================================== -->
     <!-- Permissions affecting the display of other applications  -->
@@ -1856,25 +1857,43 @@
          Settings.canDrawOverlays()}.
          <p>Protection level: signature -->
     <permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
-        android:label="@string/permlab_systemAlertWindow"
-        android:description="@string/permdesc_systemAlertWindow"
-        android:protectionLevel="signature|preinstalled|appop|pre23|development" />
+                android:label="@string/permlab_systemAlertWindow"
+                android:description="@string/permdesc_systemAlertWindow"
+                android:protectionLevel="signature|preinstalled|appop|pre23|development" />
 
-    <!-- Allows an app to run in the background.
-         <p>Protection level: signature
+    <!-- @deprecated Use {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND}
+         @hide
     -->
     <permission android:name="android.permission.RUN_IN_BACKGROUND"
-        android:label="@string/permlab_runInBackground"
-        android:description="@string/permdesc_runInBackground"
-        android:protectionLevel="signature" />
+                android:label="@string/permlab_runInBackground"
+                android:description="@string/permdesc_runInBackground"
+                android:protectionLevel="signature" />
 
-    <!-- Allows an app to use data in the background.
-         <p>Protection level: signature
+    <!-- @deprecated Use
+        {@link android.Manifest.permission#REQUEST_COMPANION_USE_DATA_IN_BACKGROUND}
+         @hide
     -->
     <permission android:name="android.permission.USE_DATA_IN_BACKGROUND"
-        android:label="@string/permlab_useDataInBackground"
-        android:description="@string/permdesc_useDataInBackground"
-        android:protectionLevel="signature" />
+                android:label="@string/permlab_useDataInBackground"
+                android:description="@string/permdesc_useDataInBackground"
+                android:protectionLevel="signature" />
+
+    <!-- Allows a companion app to run in the background.
+         <p>Protection level: normal
+    -->
+    <permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND"
+                android:label="@string/permlab_runInBackground"
+                android:description="@string/permdesc_runInBackground"
+                android:protectionLevel="normal" />
+
+    <!-- Allows a companion app to use data in the background.
+         <p>Protection level: normal
+    -->
+    <permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND"
+                android:label="@string/permlab_useDataInBackground"
+                android:description="@string/permdesc_useDataInBackground"
+                android:protectionLevel="normal" />
+
 
     <!-- ================================== -->
     <!-- Permissions affecting the system wallpaper -->
@@ -1885,17 +1904,17 @@
          <p>Protection level: normal
      -->
     <permission android:name="android.permission.SET_WALLPAPER"
-        android:label="@string/permlab_setWallpaper"
-        android:description="@string/permdesc_setWallpaper"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_setWallpaper"
+                android:description="@string/permdesc_setWallpaper"
+                android:protectionLevel="normal" />
 
     <!-- Allows applications to set the wallpaper hints.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.SET_WALLPAPER_HINTS"
-        android:label="@string/permlab_setWallpaperHints"
-        android:description="@string/permdesc_setWallpaperHints"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_setWallpaperHints"
+                android:description="@string/permdesc_setWallpaperHints"
+                android:protectionLevel="normal" />
 
     <!-- ============================================ -->
     <!-- Permissions for changing the system clock -->
@@ -1905,15 +1924,15 @@
     <!-- @SystemApi Allows applications to set the system time.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_TIME"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to set the system time zone.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.SET_TIME_ZONE"
-        android:label="@string/permlab_setTimeZone"
-        android:description="@string/permdesc_setTimeZone"
-        android:protectionLevel="signature|privileged" />
+                android:label="@string/permlab_setTimeZone"
+                android:description="@string/permdesc_setTimeZone"
+                android:protectionLevel="signature|privileged" />
 
     <!-- ==================================================== -->
     <!-- Permissions related to changing status bar   -->
@@ -1924,9 +1943,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.EXPAND_STATUS_BAR"
-        android:label="@string/permlab_expandStatusBar"
-        android:description="@string/permdesc_expandStatusBar"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_expandStatusBar"
+                android:description="@string/permdesc_expandStatusBar"
+                android:protectionLevel="normal" />
 
     <!-- ============================================================== -->
     <!-- Permissions related to adding/removing shortcuts from Launcher -->
@@ -1937,16 +1956,16 @@
          <p>Protection level: normal
     -->
     <permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
-        android:label="@string/permlab_install_shortcut"
-        android:description="@string/permdesc_install_shortcut"
-        android:protectionLevel="normal"/>
+                android:label="@string/permlab_install_shortcut"
+                android:description="@string/permdesc_install_shortcut"
+                android:protectionLevel="normal"/>
 
     <!--This permission is no longer supported.
     -->
     <permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
-        android:label="@string/permlab_uninstall_shortcut"
-        android:description="@string/permdesc_uninstall_shortcut"
-        android:protectionLevel="normal"/>
+                android:label="@string/permlab_uninstall_shortcut"
+                android:description="@string/permdesc_uninstall_shortcut"
+                android:protectionLevel="normal"/>
 
     <!-- ==================================================== -->
     <!-- Permissions related to accessing sync settings   -->
@@ -1957,25 +1976,25 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.READ_SYNC_SETTINGS"
-        android:description="@string/permdesc_readSyncSettings"
-        android:label="@string/permlab_readSyncSettings"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_readSyncSettings"
+                android:label="@string/permlab_readSyncSettings"
+                android:protectionLevel="normal" />
 
     <!-- Allows applications to write the sync settings.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.WRITE_SYNC_SETTINGS"
-        android:description="@string/permdesc_writeSyncSettings"
-        android:label="@string/permlab_writeSyncSettings"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_writeSyncSettings"
+                android:label="@string/permlab_writeSyncSettings"
+                android:protectionLevel="normal" />
 
     <!-- Allows applications to read the sync stats.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.READ_SYNC_STATS"
-        android:description="@string/permdesc_readSyncStats"
-        android:label="@string/permlab_readSyncStats"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_readSyncStats"
+                android:label="@string/permlab_readSyncStats"
+                android:protectionLevel="normal" />
 
     <!-- ============================================ -->
     <!-- Permissions for low-level system interaction -->
@@ -1984,12 +2003,12 @@
 
     <!-- @SystemApi @hide Change the screen compatibility mode of applications -->
     <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to modify the current configuration, such
          as locale. -->
     <permission android:name="android.permission.CHANGE_CONFIGURATION"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- Allows an application to read or write the system settings.
 
@@ -2004,51 +2023,51 @@
         <p>Protection level: signature
     -->
     <permission android:name="android.permission.WRITE_SETTINGS"
-        android:label="@string/permlab_writeSettings"
-        android:description="@string/permdesc_writeSettings"
-        android:protectionLevel="signature|preinstalled|appop|pre23" />
+                android:label="@string/permlab_writeSettings"
+                android:description="@string/permdesc_writeSettings"
+                android:protectionLevel="signature|preinstalled|appop|pre23" />
 
     <!-- @SystemApi Allows an application to modify the Google service map.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_GSERVICES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to call
         {@link android.app.ActivityManager#forceStopPackage}.
         @hide -->
     <permission android:name="android.permission.FORCE_STOP_PACKAGES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to retrieve the content of the active window
          An active window is the window that has fired an accessibility event. -->
     <permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Modify the global animation scaling factor.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_ANIMATION_SCALE"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @deprecated This functionality will be removed in the future; please do
          not use. Allow an application to make its activities persistent. -->
     <permission android:name="android.permission.PERSISTENT_ACTIVITY"
-        android:label="@string/permlab_persistentActivity"
-        android:description="@string/permdesc_persistentActivity"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_persistentActivity"
+                android:description="@string/permdesc_persistentActivity"
+                android:protectionLevel="normal" />
 
     <!-- Allows an application to find out the space used by any package.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.GET_PACKAGE_SIZE"
-        android:label="@string/permlab_getPackageSize"
-        android:description="@string/permdesc_getPackageSize"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_getPackageSize"
+                android:description="@string/permdesc_getPackageSize"
+                android:protectionLevel="normal" />
 
     <!-- @deprecated No longer useful, see
          {@link android.content.pm.PackageManager#addPackageToPreferred}
          for details. -->
     <permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"
-        android:protectionLevel="signature|verifier" />
+                android:protectionLevel="signature|verifier" />
 
     <!-- Allows an application to receive the
          {@link android.content.Intent#ACTION_BOOT_COMPLETED} that is
@@ -2064,9 +2083,9 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"
-        android:label="@string/permlab_receiveBootCompleted"
-        android:description="@string/permdesc_receiveBootCompleted"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_receiveBootCompleted"
+                android:description="@string/permdesc_receiveBootCompleted"
+                android:protectionLevel="normal" />
 
     <!-- Allows an application to broadcast sticky intents.  These are
          broadcasts whose data is held by the system after being finished,
@@ -2075,90 +2094,90 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.BROADCAST_STICKY"
-        android:label="@string/permlab_broadcastSticky"
-        android:description="@string/permdesc_broadcastSticky"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_broadcastSticky"
+                android:description="@string/permdesc_broadcastSticky"
+                android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows mounting and unmounting file systems for removable storage.
     <p>Not for use by third-party applications.-->
     <permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows formatting file systems for removable storage.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @hide -->
     <permission android:name="android.permission.STORAGE_INTERNAL"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows access to ASEC non-destructive API calls
          @hide  -->
     <permission android:name="android.permission.ASEC_ACCESS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows creation of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_CREATE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows destruction of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_DESTROY"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows mount / unmount of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows rename of ASEC volumes
          @hide  -->
     <permission android:name="android.permission.ASEC_RENAME"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows applications to write the apn settings.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_APN_SETTINGS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to change network connectivity state.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_NETWORK_STATE"
-        android:description="@string/permdesc_changeNetworkState"
-        android:label="@string/permlab_changeNetworkState"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_changeNetworkState"
+                android:label="@string/permlab_changeNetworkState"
+                android:protectionLevel="normal" />
 
     <!-- Allows an application to clear the caches of all installed
          applications on the device.
          <p>Protection level: system|signature
     -->
     <permission android:name="android.permission.CLEAR_APP_CACHE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to use any media decoder when decoding for playback
          @hide -->
     <permission android:name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to install and/or uninstall CA certificates on
          behalf of the user.
          @hide -->
     <permission android:name="android.permission.MANAGE_CA_CERTIFICATES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to do certain operations needed for
          interacting with the recovery (system update) system.
          @hide -->
     <permission android:name="android.permission.RECOVERY"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows the system to bind to an application's task services
          @hide -->
     <permission android:name="android.permission.BIND_JOB_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
     <uses-permission android:name="android.permission.BIND_JOB_SERVICE"/>
 
     <!-- Allows an application to initiate configuration updates
@@ -2167,24 +2186,24 @@
          it off to the various individual installer components
          @hide -->
     <permission android:name="android.permission.UPDATE_CONFIG"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows the system to reset throttling in shortcut manager.
          @hide -->
     <permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows the system to bind to the discovered Network Recommendation Service.
          @SystemApi @hide -->
     <permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
     <uses-permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"/>
 
     <!-- Allows an application to enable, disable and change priority of
          runtime resource overlays.
          @hide -->
     <permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
@@ -2194,40 +2213,40 @@
     <!-- @SystemApi Allows an application to read or write the secure system settings.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.WRITE_SECURE_SETTINGS"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to retrieve state dump information from system services.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DUMP"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to read the low-level system log files.
     <p>Not for use by third-party applications, because
     Log entries can contain the user's private information. -->
     <permission android:name="android.permission.READ_LOGS"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Configure an application for debugging.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_DEBUG_APP"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to set the maximum number of (not needed)
          application processes that can be running.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_PROCESS_LIMIT"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to control whether activities are immediately
          finished when put in the background.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SET_ALWAYS_FINISH"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allow an application to request that a signal be sent to all persistent processes.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- ==================================== -->
     <!-- Private permissions                  -->
@@ -2236,34 +2255,34 @@
 
     <!-- @SystemApi Allows access to the list of accounts in the Accounts Service. -->
     <permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows but does not guarantee access to user passwords at the conclusion of add account
     @hide -->
     <permission android:name="android.permission.GET_PASSWORD"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows applications to RW to diagnostic resources.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DIAGNOSTIC"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to open, close, or disable the status bar
          and its icons.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.STATUS_BAR"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to be the status bar.  Currently used only by SystemUI.apk
     @hide -->
     <permission android:name="android.permission.STATUS_BAR_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to bind to third party quick settings tiles.
          <p>Should only be requested by the System, should be required by
          TileService declarations.-->
     <permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to force a BACK operation on whatever is the
          top activity.
@@ -2271,28 +2290,28 @@
          @hide
     -->
     <permission android:name="android.permission.FORCE_BACK"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to update device statistics.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.UPDATE_DEVICE_STATS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to collect battery statistics -->
     <permission android:name="android.permission.GET_APP_OPS_STATS"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to update application operation statistics. Not for
          use by third party apps.
          @hide -->
     <permission android:name="android.permission.UPDATE_APP_OPS_STATS"
-        android:protectionLevel="signature|privileged|installer" />
+                android:protectionLevel="signature|privileged|installer" />
 
     <!-- @SystemApi Allows an application to update the user app op restrictions.
          Not for use by third party apps.
          @hide -->
     <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
-        android:protectionLevel="signature|installer" />
+                android:protectionLevel="signature|installer" />
 
     <!-- @SystemApi Allows an application to open windows that are for use by parts
          of the system user interface.
@@ -2300,7 +2319,7 @@
          @hide
     -->
     <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to manage (create, destroy,
          Z-order) application tokens in the window manager.
@@ -2308,17 +2327,17 @@
          @hide
     -->
     <permission android:name="android.permission.MANAGE_APP_TOKENS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows System UI to register listeners for events from Window Manager.
          @hide -->
     <permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows the application to temporarily freeze the screen for a
          full-screen transition. -->
     <permission android:name="android.permission.FREEZE_SCREEN"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to inject user events (keys, touch, trackball)
          into the event stream and deliver them to ANY window.  Without this
@@ -2327,16 +2346,16 @@
          @hide
     -->
     <permission android:name="android.permission.INJECT_EVENTS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to register an input filter which filters the stream
          of user events (keys, touch, trackball) before they are dispatched to any window. -->
     <permission android:name="android.permission.FILTER_EVENTS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
     <permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to modify accessibility information from another app. -->
     <permission android:name="android.permission.MODIFY_ACCESSIBILITY_DATA"
@@ -2348,11 +2367,11 @@
 
     <!-- @hide Allows an application to collect frame statistics -->
     <permission android:name="android.permission.FRAME_STATS"
-         android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to temporary enable accessibility on the device. -->
     <permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to watch and control how activities are
          started globally in the system.  Only for is in debugging
@@ -2361,13 +2380,13 @@
          @hide
     -->
     <permission android:name="android.permission.SET_ACTIVITY_WATCHER"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to call the activity manager shutdown() API
          to put the higher-level system there into a shutdown state.
          @hide -->
     <permission android:name="android.permission.SHUTDOWN"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to tell the activity manager to temporarily
          stop application switches, putting it into a special mode that
@@ -2375,7 +2394,7 @@
          critical UI such as the home screen.
          @hide -->
     <permission android:name="android.permission.STOP_APP_SWITCHES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to retrieve private information about
          the current top activity, such as any assist context it can provide.
@@ -2383,42 +2402,42 @@
          @hide
     -->
     <permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to retrieve the current state of keys and
          switches.
          <p>Not for use by third-party applications.
          @deprecated The API that used this permission has been removed. -->
     <permission android:name="android.permission.READ_INPUT_STATE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.inputmethodservice.InputMethodService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_INPUT_METHOD"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.media.midi.MidiDeviceService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_MIDI_DEVICE_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.accessibilityservice.AccessibilityService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.printservice.PrintService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_PRINT_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.printservice.recommendation.RecommendationService},
      to ensure that only the system can bind to it.
@@ -2427,7 +2446,7 @@
      <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"
-            android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.nfc.cardemulation.HostApduService}
          or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only
@@ -2435,81 +2454,81 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_NFC_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by the CompanionDeviceManager to ensure that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
          that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by a TextService (e.g. SpellCheckerService)
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_TEXT_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.net.VpnService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_VPN_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.service.wallpaper.WallpaperService},
          to ensure that only the system can bind to it.
          <p>Protection level: system|signature
     -->
     <permission android:name="android.permission.BIND_WALLPAPER"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.service.voice.VoiceInteractionService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_VOICE_INTERACTION"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.service.autofill.AutofillService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_AUTOFILL_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide TODO(b/37563972): remove once clients use BIND_AUTOFILL_SERVICE -->
     <permission android:name="android.permission.BIND_AUTOFILL"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by hotword enrollment application,
          to ensure that only the system can interact with it.
          @hide <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider},
          to ensure that only the system can bind to it.
          @hide -->
     <permission android:name="android.permission.BIND_REMOTE_DISPLAY"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.media.tv.TvInputService}
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_TV_INPUT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi
          Must be required by a {@link com.android.media.tv.remoteprovider.TvRemoteProvider}
@@ -2518,7 +2537,7 @@
          <p>Not for use by third-party applications. </p>
          @hide  -->
     <permission android:name="android.permission.BIND_TV_REMOTE_SERVICE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi
          Must be required for a virtual remote controller for TV.
@@ -2526,13 +2545,13 @@
          <p>Not for use by third-party applications. </p>
          @hide  -->
     <permission android:name="android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to modify parental controls
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to notify TV inputs by sending broadcasts.
          <p>Protection level: signature|privileged
@@ -2545,20 +2564,20 @@
          to ensure that only the system can interact with it.
          @hide -->
     <permission android:name="android.permission.BIND_ROUTE_PROVIDER"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by device administration receiver, to ensure that only the
          system can interact with it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_DEVICE_ADMIN"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Required to add or remove another application as a device admin.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.MANAGE_DEVICE_ADMINS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows low-level access to setting the orientation (actually
          rotation) of the screen.
@@ -2566,33 +2585,33 @@
          @hide
     -->
     <permission android:name="android.permission.SET_ORIENTATION"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows low-level access to setting the pointer speed.
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.SET_POINTER_SPEED"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows low-level access to setting input device calibration.
          <p>Not for use by normal applications.
          @hide -->
     <permission android:name="android.permission.SET_INPUT_CALIBRATION"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows low-level access to setting the keyboard layout.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to query tablet mode state and monitor changes
          in it.
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.TABLET_MODE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to request installing packages. Apps
          targeting APIs greater than 25 must hold this permission in
@@ -2600,9 +2619,9 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
-        android:label="@string/permlab_requestInstallPackages"
-        android:description="@string/permdesc_requestInstallPackages"
-        android:protectionLevel="signature|appop" />
+                android:label="@string/permlab_requestInstallPackages"
+                android:description="@string/permdesc_requestInstallPackages"
+                android:protectionLevel="signature|appop" />
 
     <!-- Allows an application to request deleting packages. Apps
          targeting APIs greater than 25 must hold this permission in
@@ -2610,41 +2629,41 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.REQUEST_DELETE_PACKAGES"
-        android:label="@string/permlab_requestDeletePackages"
-        android:description="@string/permdesc_requestDeletePackages"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_requestDeletePackages"
+                android:description="@string/permdesc_requestDeletePackages"
+                android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an application to install packages.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.INSTALL_PACKAGES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to clear user data.
          <p>Not for use by third-party applications
          @hide
     -->
     <permission android:name="android.permission.CLEAR_APP_USER_DATA"
-        android:protectionLevel="signature|installer" />
+                android:protectionLevel="signature|installer" />
 
     <!-- @hide Allows an application to get the URI permissions
          granted to another application.
          <p>Not for use by third-party applications
     -->
     <permission android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide Allows an application to clear the URI permissions
          granted to another application.
          <p>Not for use by third-party applications
     -->
     <permission
-        android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
-        android:protectionLevel="signature" />
+            android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
+            android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to delete cache files.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.DELETE_CACHE_FILES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to delete packages.
          <p>Not for use by third-party applications.
@@ -2652,120 +2671,120 @@
          when the application deleting the package is not the same application that installed the
          package. -->
     <permission android:name="android.permission.DELETE_PACKAGES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to move location of installed package.
          @hide -->
     <permission android:name="android.permission.MOVE_PACKAGE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to change whether an application component (other than its own) is
          enabled or not.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to grant specific permissions.
          @hide -->
     <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
-        android:protectionLevel="signature|installer|verifier" />
+                android:protectionLevel="signature|installer|verifier" />
 
     <!-- @SystemApi Allows an app that has this permission and the permissions to install packages
          to request certain runtime permissions to be granted at installation.
          @hide -->
     <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
-        android:protectionLevel="signature|installer|verifier" />
+                android:protectionLevel="signature|installer|verifier" />
 
     <!-- @SystemApi Allows an application to revoke specific permissions.
         @hide -->
     <permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
-         android:protectionLevel="signature|installer|verifier" />
+                android:protectionLevel="signature|installer|verifier" />
 
     <!-- @hide Allows an application to observe permission changes. -->
     <permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to take screen shots and more generally
          get access to the frame buffer data.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_FRAME_BUFFER"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to use InputFlinger's low level features.
          @hide -->
     <permission android:name="android.permission.ACCESS_INPUT_FLINGER"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to configure and connect to Wifi displays
          @hide -->
     <permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to control low-level features of Wifi displays
          such as opening an RTSP socket.  This permission should only be used
          by the display manager.
          @hide -->
     <permission android:name="android.permission.CONTROL_WIFI_DISPLAY"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to control the color modes set for displays system-wide.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to control VPN.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CONTROL_VPN"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
     <uses-permission android:name="android.permission.CONTROL_VPN" />
 
     <!-- @SystemApi Allows an application to capture audio output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to capture audio for hotword detection.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to modify audio routing and override policy decisions.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.MODIFY_AUDIO_ROUTING"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to capture video output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to capture secure video output.
          <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to know what content is playing and control its playback.
          <p>Not for use by third-party applications due to privacy of media consumption</p>  -->
     <permission android:name="android.permission.MEDIA_CONTENT_CONTROL"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi @hide Allows an application to set the volume key long-press listener.
          <p>When it's set, the application will receive the volume key long-press event
          instead of changing volume.</p>
          <p>Not for use by third-party applications</p> -->
     <permission android:name="android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi @hide Allows an application to set media key event listener.
          <p>When it's set, the application will receive the media key event before
@@ -2773,61 +2792,61 @@
          cannot get the event.</p>
          <p>Not for use by third-party applications</p> -->
     <permission android:name="android.permission.SET_MEDIA_KEY_LISTENER"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Required to be able to disable the device (very dangerous!).
          <p>Not for use by third-party applications.
          @hide
     -->
     <permission android:name="android.permission.BRICK"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Required to be able to reboot the device.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.REBOOT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
-   <!-- @SystemApi Allows low-level access to power management.
-        <p>Not for use by third-party applications.
-        @hide
-    -->
-   <permission android:name="android.permission.DEVICE_POWER"
-        android:protectionLevel="signature" />
+    <!-- @SystemApi Allows low-level access to power management.
+         <p>Not for use by third-party applications.
+         @hide
+     -->
+    <permission android:name="android.permission.DEVICE_POWER"
+                android:protectionLevel="signature" />
 
-   <!-- Allows access to the PowerManager.userActivity function.
-   <p>Not for use by third-party applications. @hide @SystemApi -->
+    <!-- Allows access to the PowerManager.userActivity function.
+    <p>Not for use by third-party applications. @hide @SystemApi -->
     <permission android:name="android.permission.USER_ACTIVITY"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
-   <!-- @hide Allows low-level access to tun tap driver -->
+    <!-- @hide Allows low-level access to tun tap driver -->
     <permission android:name="android.permission.NET_TUNNELING"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Run as a manufacturer test application, running as the root user.
          Only available when the device is running in manufacturer test mode.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.FACTORY_TEST"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to broadcast a notification that an application
          package has been removed.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to broadcast an SMS receipt notification.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_SMS"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to broadcast a WAP PUSH receipt notification.
          <p>Not for use by third-party applications.
     -->
     <permission android:name="android.permission.BROADCAST_WAP_PUSH"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to broadcast privileged networking requests.
          <p>Not for use by third-party applications.
@@ -2835,87 +2854,87 @@
          @deprecated Use {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} instead
     -->
     <permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Not for use by third-party applications. -->
     <permission android:name="android.permission.MASTER_CLEAR"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to call any phone number, including emergency
          numbers, without going through the Dialer user interface for the user
          to confirm the call being placed.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CALL_PRIVILEGED"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to perform CDMA OTA provisioning @hide -->
     <permission android:name="android.permission.PERFORM_CDMA_PROVISIONING"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to perform SIM Activation @hide -->
     <permission android:name="android.permission.PERFORM_SIM_ACTIVATION"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows enabling/disabling location update notifications from
          the radio.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CONTROL_LOCATION_UPDATES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows read/write access to the "properties" table in the checkin
          database, to change values that get uploaded.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to collect component usage
          statistics
          <p>Declaring the permission implies intention to use the API and the user of the
          device can grant permission through the Settings application. -->
     <permission android:name="android.permission.PACKAGE_USAGE_STATS"
-        android:protectionLevel="signature|privileged|development|appop" />
+                android:protectionLevel="signature|privileged|development|appop" />
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
     <!-- @hide Allows an application to change the app idle state of an app.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_APP_IDLE_STATE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @hide @SystemApi Allows an application to temporarily whitelist an inactive app to
          access the network and acquire wakelocks.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Permission an application must hold in order to use
          {@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}.
          This is a normal permission: an app requesting it will always be granted the
          permission, without the user needing to approve or see it. -->
     <permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
-        android:label="@string/permlab_requestIgnoreBatteryOptimizations"
-        android:description="@string/permdesc_requestIgnoreBatteryOptimizations"
-        android:protectionLevel="normal" />
+                android:label="@string/permlab_requestIgnoreBatteryOptimizations"
+                android:description="@string/permdesc_requestIgnoreBatteryOptimizations"
+                android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows an application to collect battery statistics -->
     <permission android:name="android.permission.BATTERY_STATS"
-        android:protectionLevel="signature|privileged|development" />
+                android:protectionLevel="signature|privileged|development" />
 
     <!-- @SystemApi Allows an application to control the backup and restore process.
     <p>Not for use by third-party applications.
          @hide pending API council -->
     <permission android:name="android.permission.BACKUP"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows a package to launch the secure full-backup confirmation UI.
          ONLY the system process may hold this permission.
          @hide -->
     <permission android:name="android.permission.CONFIRM_FULL_BACKUP"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Must be required by a {@link android.widget.RemoteViewsService},
          to ensure that only the system can bind to it. -->
     <permission android:name="android.permission.BIND_REMOTEVIEWS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to tell the AppWidget service which application
          can access AppWidget's data.  The normal user flow is that a user
@@ -2924,25 +2943,25 @@
          An application that has this permission should honor that contract.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.BIND_APPWIDGET"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Private permission, to restrict who can bring up a dialog to add a new
          keyguard widget
          @hide -->
     <permission android:name="android.permission.BIND_KEYGUARD_APPWIDGET"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Internal permission allowing an application to query/set which
          applications can bind AppWidgets.
          @hide -->
     <permission android:name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows applications to change the background data setting.
     <p>Not for use by third-party applications.
          @hide pending API council -->
     <permission android:name="android.permission.CHANGE_BACKGROUND_DATA_SETTING"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi This permission can be used on content providers to allow the global
          search system to access their data.  Typically it used when the
@@ -2953,7 +2972,7 @@
          it is used by applications to protect themselves from everyone else
          besides global search. -->
     <permission android:name="android.permission.GLOBAL_SEARCH"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Internal permission protecting access to the global search
          system: ensures that only the system can access the provider
@@ -2963,33 +2982,33 @@
          ranking).
          @hide -->
     <permission android:name="android.permission.GLOBAL_SEARCH_CONTROL"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Internal permission to allows an application to read indexable data.
         @hide -->
     <permission android:name="android.permission.READ_SEARCH_INDEXABLES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows applications to set a live wallpaper.
          @hide XXX Change to signature once the picker is moved to its
          own apk as Ghod Intended. -->
     <permission android:name="android.permission.SET_WALLPAPER_COMPONENT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows applications to read dream settings and dream state.
          @hide -->
     <permission android:name="android.permission.READ_DREAM_STATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows applications to write dream settings, and start or stop dreaming.
          @hide -->
     <permission android:name="android.permission.WRITE_DREAM_STATE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allow an application to read and write the cache partition.
          @hide -->
     <permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by default container service so that only
          the system can bind to it and use it to copy
@@ -2997,67 +3016,67 @@
          accessible to the system.
          @hide -->
     <permission android:name="android.permission.COPY_PROTECTED_DATA"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Internal permission protecting access to the encryption methods
         @hide
     -->
     <permission android:name="android.permission.CRYPT_KEEPER"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to read historical network usage for
          specific networks and applications. @hide -->
     <permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to manage network policies (such as warning and disable
          limits) and to define application-specific rules. @hide -->
     <permission android:name="android.permission.MANAGE_NETWORK_POLICY"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to account its network traffic against other UIDs. Used
          by system services like download manager and media server. Not for use by
          third party apps. @hide -->
     <permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- C2DM permission.
          @hide Used internally.
      -->
     <permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"
-          android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
     <uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
 
     <!-- @SystemApi @hide Package verifier needs to have this permission before the PackageManager will
          trust it to verify packages.
     -->
     <permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by package verifier receiver, to ensure that only the
          system can interact with it.
          @hide
     -->
     <permission android:name="android.permission.BIND_PACKAGE_VERIFIER"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi @hide Intent filter verifier needs to have this permission before the
          PackageManager will trust it to verify intent filters.
     -->
     <permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by intent filter verifier receiver, to ensure that only the
          system can interact with it.
          @hide
     -->
     <permission android:name="android.permission.BIND_INTENT_FILTER_VERIFIER"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows applications to access serial ports via the SerialManager.
          @hide -->
     <permission android:name="android.permission.SERIAL_PORT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows the holder to access content providers from outside an ApplicationThread.
          This permission is enforced by the ActivityManagerService on the corresponding APIs,
@@ -3066,27 +3085,27 @@
          @hide
     -->
     <permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to hold an UpdateLock, recommending that a headless
          OTA reboot *not* occur while the lock is held.
          @hide -->
     <permission android:name="android.permission.UPDATE_LOCK"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to read the current set of notifications, including
          any metadata and intents attached.
          @hide -->
     <permission android:name="android.permission.ACCESS_NOTIFICATIONS"
-        android:protectionLevel="signature|privileged|appop" />
+                android:protectionLevel="signature|privileged|appop" />
 
     <!-- Marker permission for applications that wish to access notification policy.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"
-        android:description="@string/permdesc_access_notification_policy"
-        android:label="@string/permlab_access_notification_policy"
-        android:protectionLevel="normal" />
+                android:description="@string/permdesc_access_notification_policy"
+                android:label="@string/permlab_access_notification_policy"
+                android:protectionLevel="normal" />
 
     <!-- Allows modification of do not disturb rules and policies. Only allowed for system
         processes.
@@ -3097,42 +3116,42 @@
     <!-- Allows access to keyguard secure storage.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows managing (adding, removing) fingerprint templates. Reserved for the system. @hide -->
     <permission android:name="android.permission.MANAGE_FINGERPRINT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an app to reset fingerprint attempt counter. Reserved for the system. @hide -->
     <permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to control keyguard.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.CONTROL_KEYGUARD"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to listen to trust changes.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.TRUST_LISTENER"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to provide a trust agent.
          @hide For security reasons, this is a platform-only permission. -->
     <permission android:name="android.permission.PROVIDE_TRUST_AGENT"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to launch the trust agent settings activity.
         @hide -->
     <permission android:name="android.permission.LAUNCH_TRUST_AGENT_SETTINGS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Must be required by an {@link
         android.service.trust.TrustAgentService},
         to ensure that only the system can bind to it.
         @hide -->
     <permission android:name="android.permission.BIND_TRUST_AGENT"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link
          android.service.notification.NotificationListenerService},
@@ -3140,7 +3159,7 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Must be required by an {@link
          android.service.notification.NotificationAssistantService} to ensure that only the system
@@ -3149,7 +3168,7 @@
          @hide
     -->
     <permission android:name="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
          android.service.chooser.ChooserTargetService}, to ensure that
@@ -3157,7 +3176,7 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Must be held by services that extend
          {@link android.service.resolver.ResolverRankerService}.
@@ -3182,14 +3201,14 @@
          <p>Protection level: signature
          -->
     <permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.service.dreams.DreamService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_DREAM_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link android.app.usage.CacheQuotaService} to ensure that only the
          system can bind to it.
@@ -3202,44 +3221,44 @@
          carrier setup application to enforce that this permission is required
          @hide This is not a third-party API (intended for OEMs and system apps). -->
     <permission android:name="android.permission.INVOKE_CARRIER_SETUP"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to listen for network condition observations.
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.ACCESS_NETWORK_CONDITIONS"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to provision and access DRM certificates
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.ACCESS_DRM_CERTIFICATES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Api Allows an application to manage media projection sessions.
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to read install sessions
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.READ_INSTALL_SESSIONS"
-        android:label="@string/permlab_readInstallSessions"
-        android:description="@string/permdesc_readInstallSessions"
-        android:protectionLevel="normal"/>
+                android:label="@string/permlab_readInstallSessions"
+                android:description="@string/permdesc_readInstallSessions"
+                android:protectionLevel="normal"/>
 
     <!-- @SystemApi Allows an application to remove DRM certificates
          @hide This is not a third-party API (intended for system apps). -->
     <permission android:name="android.permission.REMOVE_DRM_CERTIFICATES"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @deprecated Use {@link android.Manifest.permission#BIND_CARRIER_SERVICES} instead -->
     <permission android:name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to interact with the currently active
          {@link android.service.voice.VoiceInteractionService}.
          @hide -->
     <permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- The system process that is allowed to bind to services in carrier apps will
          have this permission. Carrier apps should use this permission to protect
@@ -3247,9 +3266,9 @@
          <p>Protection level: system|signature
     -->
     <permission android:name="android.permission.BIND_CARRIER_SERVICES"
-        android:label="@string/permlab_bindCarrierServices"
-        android:description="@string/permdesc_bindCarrierServices"
-        android:protectionLevel="signature|privileged" />
+                android:label="@string/permlab_bindCarrierServices"
+                android:description="@string/permdesc_bindCarrierServices"
+                android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to query whether DO_NOT_ASK_CREDENTIALS_ON_BOOT
          flag is set.
@@ -3295,7 +3314,7 @@
     <!-- Allows the holder to access the instant applications on the device.
     @hide -->
     <permission android:name="android.permission.ACCESS_INSTANT_APPS"
-            android:protectionLevel="signature|installer|verifier" />
+                android:protectionLevel="signature|installer|verifier" />
 
     <!-- Allows receiving the usage of media resource e.g. video/audio codec and
          graphic memory.
@@ -3307,7 +3326,7 @@
          APIs given by {@link SoundTriggerManager}.
          @hide <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
-        android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows trusted applications to dispatch managed provisioning message to Managed
          Provisioning app. If requesting app does not have permission, it will be ignored.
@@ -3331,24 +3350,24 @@
          the system can bind to it.
          <p>Protection level: signature -->
     <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Must be required by system apps when accessing restricted VR APIs.
          @hide
          @SystemApi
          <p>Protection level: signature -->
     <permission android:name="android.permission.RESTRICTED_VR_ACCESS"
-        android:protectionLevel="signature|preinstalled" />
+                android:protectionLevel="signature|preinstalled" />
 
     <!-- Required to make calls to {@link android.service.vr.IVrManager}.
          @hide -->
     <permission android:name="android.permission.ACCESS_VR_MANAGER"
-            android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an application to whitelist tasks during lock task mode
          @hide <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"
-        android:protectionLevel="signature|setup" />
+                android:protectionLevel="signature|setup" />
 
     <!-- @SystemApi Allows an application to replace the app name displayed alongside notifications
          in the N-release and later.
@@ -3364,7 +3383,7 @@
     <!-- @SystemApi Allows an application to manage auto-fill sessions.
          @hide  <p>Not for use by third-party applications.</p> -->
     <permission android:name="android.permission.MANAGE_AUTO_FILL"
-        android:protectionLevel="signature" />
+                android:protectionLevel="signature" />
 
     <!-- Allows an app to set the theme overlay in /vendor/overlay
          being used.
@@ -3374,7 +3393,7 @@
 
     <!-- Allows an instant app to create foreground services. -->
     <permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"
-        android:protectionLevel="signature|development|ephemeral|appop" />
+                android:protectionLevel="signature|development|ephemeral|appop" />
 
     <application android:process="system"
                  android:persistent="true"
@@ -3389,14 +3408,14 @@
                  android:defaultToDeviceProtectedStorage="true"
                  android:directBootAware="true">
         <activity android:name="com.android.internal.app.ChooserActivity"
-                android:theme="@style/Theme.DeviceDefault.Resolver"
-                android:finishOnCloseSystemDialogs="true"
-                android:excludeFromRecents="true"
-                android:documentLaunchMode="never"
-                android:relinquishTaskIdentity="true"
-                android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
-                android:process=":ui"
-                android:visibleToInstantApps="true">
+                  android:theme="@style/Theme.DeviceDefault.Resolver"
+                  android:finishOnCloseSystemDialogs="true"
+                  android:excludeFromRecents="true"
+                  android:documentLaunchMode="never"
+                  android:relinquishTaskIdentity="true"
+                  android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
+                  android:process=":ui"
+                  android:visibleToInstantApps="true">
             <intent-filter>
                 <action android:name="android.intent.action.CHOOSER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3419,106 +3438,106 @@
             </intent-filter>
         </activity>
         <activity android:name="com.android.internal.app.IntentForwarderActivity"
-                android:finishOnCloseSystemDialogs="true"
-                android:theme="@style/Theme.NoDisplay"
-                android:excludeFromRecents="true"
-                android:label="@string/user_owner_label"
-                android:exported="true"
-                >
+                  android:finishOnCloseSystemDialogs="true"
+                  android:theme="@style/Theme.NoDisplay"
+                  android:excludeFromRecents="true"
+                  android:label="@string/user_owner_label"
+                  android:exported="true"
+        >
         </activity>
         <activity-alias android:name="com.android.internal.app.ForwardIntentToParent"
-                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
-                android:exported="true"
-                android:label="@string/user_owner_label">
+                        android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                        android:exported="true"
+                        android:label="@string/user_owner_label">
         </activity-alias>
         <activity-alias android:name="com.android.internal.app.ForwardIntentToManagedProfile"
-                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
-                android:icon="@drawable/ic_corp_icon"
-                android:exported="true"
-                android:label="@string/managed_profile_label">
+                        android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                        android:icon="@drawable/ic_corp_icon"
+                        android:exported="true"
+                        android:label="@string/managed_profile_label">
         </activity-alias>
         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
-                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-                android:label="@string/heavy_weight_switcher_title"
-                android:finishOnCloseSystemDialogs="true"
-                android:excludeFromRecents="true"
-                android:process=":ui">
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+                  android:label="@string/heavy_weight_switcher_title"
+                  android:finishOnCloseSystemDialogs="true"
+                  android:excludeFromRecents="true"
+                  android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.PlatLogoActivity"
-                android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
-                android:configChanges="orientation|keyboardHidden"
-                android:process=":ui">
+                  android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+                  android:configChanges="orientation|keyboardHidden"
+                  android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.DisableCarModeActivity"
-                android:theme="@style/Theme.NoDisplay"
-                android:excludeFromRecents="true"
-                android:process=":ui">
+                  android:theme="@style/Theme.NoDisplay"
+                  android:excludeFromRecents="true"
+                  android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.DumpHeapActivity"
-                android:theme="@style/Theme.Translucent.NoTitleBar"
-                android:label="@string/dump_heap_title"
-                android:finishOnCloseSystemDialogs="true"
-                android:noHistory="true"
-                android:excludeFromRecents="true"
-                android:process=":ui">
+                  android:theme="@style/Theme.Translucent.NoTitleBar"
+                  android:label="@string/dump_heap_title"
+                  android:finishOnCloseSystemDialogs="true"
+                  android:noHistory="true"
+                  android:excludeFromRecents="true"
+                  android:process=":ui">
         </activity>
         <provider android:name="com.android.server.am.DumpHeapProvider"
-                android:authorities="com.android.server.heapdump"
-                android:grantUriPermissions="true"
-                android:multiprocess="false"
-                android:singleUser="true" />
+                  android:authorities="com.android.server.heapdump"
+                  android:grantUriPermissions="true"
+                  android:multiprocess="false"
+                  android:singleUser="true" />
 
         <activity android:name="android.accounts.ChooseAccountActivity"
-                android:excludeFromRecents="true"
-                android:exported="true"
-                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-                android:label="@string/choose_account_label"
-                android:process=":ui"
-                android:visibleToInstantApps="true">
+                  android:excludeFromRecents="true"
+                  android:exported="true"
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+                  android:label="@string/choose_account_label"
+                  android:process=":ui"
+                  android:visibleToInstantApps="true">
         </activity>
 
         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
-                android:excludeFromRecents="true"
-                android:exported="true"
-                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-                android:label="@string/choose_account_label"
-                android:process=":ui"
-                android:visibleToInstantApps="true">
+                  android:excludeFromRecents="true"
+                  android:exported="true"
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+                  android:label="@string/choose_account_label"
+                  android:process=":ui"
+                  android:visibleToInstantApps="true">
         </activity>
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
-                android:excludeFromRecents="true"
-                android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-                android:label="@string/choose_account_label"
-                android:process=":ui"
-                android:visibleToInstantApps="true">
+                  android:excludeFromRecents="true"
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+                  android:label="@string/choose_account_label"
+                  android:process=":ui"
+                  android:visibleToInstantApps="true">
         </activity>
 
         <activity android:name="android.accounts.CantAddAccountActivity"
-                android:excludeFromRecents="true"
-                android:exported="true"
-                android:theme="@style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
-                android:process=":ui">
+                  android:excludeFromRecents="true"
+                  android:exported="true"
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
+                  android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
-                android:excludeFromRecents="true"
-                android:exported="true"
-                android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
-                android:process=":ui"
-                android:visibleToInstantApps="true">
+                  android:excludeFromRecents="true"
+                  android:exported="true"
+                  android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
+                  android:process=":ui"
+                  android:visibleToInstantApps="true">
         </activity>
 
         <activity android:name="android.content.SyncActivityTooManyDeletes"
-               android:theme="@style/Theme.DeviceDefault.Light.Dialog"
-               android:label="@string/sync_too_many_deletes"
-               android:process=":ui">
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+                  android:label="@string/sync_too_many_deletes"
+                  android:process=":ui">
         </activity>
 
         <activity android:name="com.android.internal.app.ShutdownActivity"
-            android:permission="android.permission.SHUTDOWN"
-            android:theme="@style/Theme.NoDisplay"
-            android:excludeFromRecents="true">
+                  android:permission="android.permission.SHUTDOWN"
+                  android:theme="@style/Theme.NoDisplay"
+                  android:excludeFromRecents="true">
             <intent-filter>
                 <action android:name="com.android.internal.intent.action.REQUEST_SHUTDOWN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3530,9 +3549,9 @@
         </activity>
 
         <activity android:name="com.android.internal.app.NetInitiatedActivity"
-                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
-                android:excludeFromRecents="true"
-                android:process=":ui">
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
+                  android:excludeFromRecents="true"
+                  android:process=":ui">
         </activity>
 
         <activity android:name="com.android.internal.app.SystemUserHomeActivity"
@@ -3549,9 +3568,9 @@
         <!-- Activity to prompt user if it's ok to create a new user sandbox for a
              specified account. -->
         <activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
-                android:excludeFromRecents="true"
-                android:process=":ui"
-                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert">
+                  android:excludeFromRecents="true"
+                  android:process=":ui"
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert">
             <intent-filter android:priority="1000">
                 <action android:name="android.os.action.CREATE_USER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3559,9 +3578,9 @@
         </activity>
 
         <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
-                android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
-                android:excludeFromRecents="true"
-                android:process=":ui">
+                  android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
+                  android:excludeFromRecents="true"
+                  android:process=":ui">
         </activity>
 
         <activity android:name="com.android.settings.notification.NotificationAccessConfirmationActivity"
@@ -3570,14 +3589,14 @@
         </activity>
 
         <receiver android:name="com.android.server.BootReceiver"
-                android:systemUserOnly="true">
+                  android:systemUserOnly="true">
             <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
 
         <receiver android:name="com.android.server.updates.CertPinInstallReceiver"
-                android:permission="android.permission.UPDATE_CONFIG">
+                  android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_PINS" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3585,7 +3604,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver"
-                android:permission="android.permission.UPDATE_CONFIG">
+                  android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_INTENT_FIREWALL" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3593,7 +3612,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver"
-                android:permission="android.permission.UPDATE_CONFIG">
+                  android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3601,7 +3620,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.ApnDbInstallReceiver"
-                android:permission="android.permission.UPDATE_CONFIG">
+                  android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="com.android.internal.intent.action.UPDATE_APN_DB" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3609,7 +3628,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.CarrierProvisioningUrlsInstallReceiver"
-                android:permission="android.permission.UPDATE_CONFIG">
+                  android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3617,7 +3636,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.TzDataInstallReceiver"
-                android:permission="android.permission.UPDATE_CONFIG">
+                  android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_TZDATA" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3625,7 +3644,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.CertificateTransparencyLogInstallReceiver"
-                android:permission="android.permission.UPDATE_CONFIG">
+                  android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_CT_LOGS" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3649,7 +3668,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.MasterClearReceiver"
-            android:permission="android.permission.MASTER_CLEAR">
+                  android:permission="android.permission.MASTER_CLEAR">
             <intent-filter
                     android:priority="100" >
                 <!-- For Checkin, Settings, etc.: action=FACTORY_RESET -->
@@ -3665,12 +3684,12 @@
         </receiver>
 
         <service android:name="android.hardware.location.GeofenceHardwareService"
-            android:permission="android.permission.LOCATION_HARDWARE"
-            android:exported="false" />
+                 android:permission="android.permission.LOCATION_HARDWARE"
+                 android:exported="false" />
 
         <service android:name="com.android.internal.backup.LocalTransportService"
-                android:permission="android.permission.CONFIRM_FULL_BACKUP"
-                android:exported="false">
+                 android:permission="android.permission.CONFIRM_FULL_BACKUP"
+                 android:exported="false">
             <intent-filter>
                 <action android:name="android.backup.TRANSPORT_HOST" />
             </intent-filter>
diff --git a/tests/tests/provider/src/android/provider/cts/FontsContractTest.java b/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
index 745a490..fd25f99e 100644
--- a/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
@@ -17,44 +17,45 @@
 package android.provider.cts;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
 
 import android.app.Instrumentation;
-import android.content.pm.Signature;
+import android.content.Context;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageInfo;
-import android.content.Context;
+import android.content.pm.Signature;
 import android.graphics.Typeface;
-import android.graphics.fonts.FontVariationAxis;
+import android.os.Handler;
+import android.os.Looper;
 import android.provider.FontRequest;
 import android.provider.FontsContract;
+import android.provider.FontsContract.Columns;
 import android.provider.FontsContract.FontFamilyResult;
 import android.provider.FontsContract.FontInfo;
-import android.provider.FontsContract.Columns;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
+
+import com.android.internal.annotations.GuardedBy;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class FontsContractTest {
     private static final String AUTHORITY = "android.provider.fonts.cts.font";
     private static final String PACKAGE = "android.provider.cts";
 
-    private static long TIMEOUT_MILLIS = 1000;
-
     // Signature to be used for authentication to access content provider.
     // In this test case, the content provider and consumer live in the same package, self package's
     // signature works.
@@ -76,12 +77,115 @@
         }
     }
 
+    private Instrumentation mInstrumentation;
+    private Context mContext;
+    private Handler mMainThreadHandler;
+
+    @Before
+    public void setUp() throws Exception {
+        mMainThreadHandler = new Handler(Looper.getMainLooper());
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mContext = mInstrumentation.getTargetContext();
+        MockFontProvider.prepareFontFiles(
+                InstrumentationRegistry.getInstrumentation().getTargetContext());
+    }
+
+    @After
+    public void tearDown() {
+        mMainThreadHandler = null;
+        MockFontProvider.cleanUpFontFiles(
+                InstrumentationRegistry.getInstrumentation().getTargetContext());
+    }
+
+    private static class TestCallback extends FontsContract.FontRequestCallback {
+        private final Object mLock = new Object();
+        @GuardedBy("mLock")
+        private Typeface mTypeface;
+        @GuardedBy("mLock")
+        private int mFailedReason;
+        @GuardedBy("mLock")
+        private int mSuccessCallCount;
+        @GuardedBy("mLock")
+        private int mFailedCallCount;
+
+        public void onTypefaceRetrieved(Typeface typeface) {
+            synchronized(mLock) {
+                mTypeface = typeface;
+                mSuccessCallCount++;
+            }
+        }
+
+        public void onTypefaceRequestFailed(int reason) {
+            synchronized(mLock) {
+                mFailedCallCount++;
+                mFailedReason = reason;
+            }
+        }
+
+        public Typeface getTypeface() {
+            synchronized(mLock) {
+                return mTypeface;
+            }
+        }
+
+        public int getFailedReason() {
+            synchronized(mLock) {
+                return mFailedReason;
+            }
+        }
+
+        public int getSuccessCallCount() {
+            synchronized(mLock) {
+                return mSuccessCallCount;
+            }
+        }
+
+        public int getFailedCallCount() {
+            synchronized(mLock) {
+                return mFailedCallCount;
+            }
+        }
+    }
+
+
+    @Test
+    public void requestFont() throws NameNotFoundException {
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.SINGLE_FONT_FAMILY_QUERY, SIGNATURE);
+        TestCallback callback = new TestCallback();
+
+        mInstrumentation.runOnMainSync(() -> FontsContract.requestFonts(
+                mContext, request, mMainThreadHandler, null, callback));
+
+        mInstrumentation.waitForIdleSync();
+        assertEquals(1, callback.getSuccessCallCount());
+        assertEquals(0, callback.getFailedCallCount());
+        assertNotNull(callback.mTypeface);
+    }
+
+    @Test
+    public void requestFontNegativeErrorCode() throws NameNotFoundException {
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.NEGATIVE_ERROR_CODE_QUERY, SIGNATURE);
+        TestCallback callback = new TestCallback();
+
+        mInstrumentation.runOnMainSync(() -> FontsContract.requestFonts(
+                mContext, request, mMainThreadHandler, null, callback));
+
+        mInstrumentation.waitForIdleSync();
+        assertNull(callback.mTypeface);
+        assertEquals(1, callback.getFailedCallCount());
+        assertEquals(0, callback.getSuccessCallCount());
+        assertEquals(FontsContract.FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR,
+                callback.getFailedReason());
+    }
+
     @Test
     public void querySingleFont() throws NameNotFoundException {
-        Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        FontRequest request = new FontRequest(AUTHORITY, PACKAGE, "singleFontFamily", SIGNATURE);
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.SINGLE_FONT_FAMILY_QUERY, SIGNATURE);
         FontFamilyResult result = FontsContract.fetchFonts(
-                ctx, null /* cancellation signal */, request);
+                mContext, null /* cancellation signal */, request);
         assertNotNull(result);
         assertEquals(FontFamilyResult.STATUS_OK, result.getStatusCode());
 
@@ -90,17 +194,15 @@
         FontInfo font = fonts[0];
         assertNotNull(font.getUri());
         assertEquals(Columns.RESULT_CODE_OK, font.getResultCode());
-        // TODO: add more test cases for FontInfo members once the MockFontProvider becomes
-        // configurable.
-        assertNotNull(FontsContract.buildTypeface(ctx, null /* cancellation signal */, fonts));
+        assertNotNull(FontsContract.buildTypeface(mContext, null /* cancellation signal */, fonts));
     }
 
     @Test
     public void queryMultipleFont() throws NameNotFoundException {
-        Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        FontRequest request = new FontRequest(AUTHORITY, PACKAGE, "multipleFontFamily", SIGNATURE);
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.MULTIPLE_FAMILY_QUERY, SIGNATURE);
         FontFamilyResult result = FontsContract.fetchFonts(
-                ctx, null /* cancellation signal */, request);
+                mContext, null /* cancellation signal */, request);
         assertNotNull(result);
         assertEquals(FontFamilyResult.STATUS_OK, result.getStatusCode());
 
@@ -110,17 +212,122 @@
             assertNotNull(font.getUri());
             assertEquals(Columns.RESULT_CODE_OK, font.getResultCode());
         }
-        // TODO: add more test cases for FontInfo members once the MockFontProvider becomes
-        // configuarable.
-        assertNotNull(FontsContract.buildTypeface(ctx, null /* cancellation signal */, fonts));
+        assertNotNull(FontsContract.buildTypeface(mContext, null /* cancellation signal */, fonts));
+    }
+
+    @Test
+    public void queryAttributes() throws NameNotFoundException {
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.SINGLE_FONT_FAMILY2_QUERY, SIGNATURE);
+        FontFamilyResult result = FontsContract.fetchFonts(
+                mContext, null /* cancellation signal */, request);
+        assertNotNull(result);
+        assertEquals(FontFamilyResult.STATUS_OK, result.getStatusCode());
+
+        FontInfo[] fonts = result.getFonts();
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertNotNull(font.getUri());
+        assertEquals(700, font.getWeight());
+        assertEquals(1, font.getAxes().length);
+        assertTrue(font.isItalic());
+        assertEquals(Columns.RESULT_CODE_OK, font.getResultCode());
+        assertNotNull(FontsContract.buildTypeface(mContext, null /* cancellation signal */, fonts));
+    }
+
+    @Test
+    public void queryNotFound() throws NameNotFoundException {
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.NOT_FOUND_QUERY, SIGNATURE);
+        FontFamilyResult result = FontsContract.fetchFonts(
+                mContext, null /* cancellation signal */, request);
+        assertNotNull(result);
+        assertEquals(FontFamilyResult.STATUS_OK, result.getStatusCode());
+
+        FontInfo[] fonts = result.getFonts();
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertEquals(Columns.RESULT_CODE_FONT_NOT_FOUND, font.getResultCode());
+        assertNull(FontsContract.buildTypeface(mContext, null /* cancellation signal */, fonts));
+    }
+
+    @Test
+    public void queryUnavailable() throws NameNotFoundException {
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.UNAVAILABLE_QUERY, SIGNATURE);
+        FontFamilyResult result = FontsContract.fetchFonts(
+                mContext, null /* cancellation signal */, request);
+        assertNotNull(result);
+        assertEquals(FontFamilyResult.STATUS_OK, result.getStatusCode());
+
+        FontInfo[] fonts = result.getFonts();
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertEquals(Columns.RESULT_CODE_FONT_UNAVAILABLE, font.getResultCode());
+        assertNull(FontsContract.buildTypeface(mContext, null /* cancellation signal */, fonts));
+    }
+
+    @Test
+    public void queryMalformed() throws NameNotFoundException {
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.MALFORMED_QUERY, SIGNATURE);
+        FontFamilyResult result = FontsContract.fetchFonts(
+                mContext, null /* cancellation signal */, request);
+        assertNotNull(result);
+        assertEquals(FontFamilyResult.STATUS_OK, result.getStatusCode());
+
+        FontInfo[] fonts = result.getFonts();
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertEquals(Columns.RESULT_CODE_MALFORMED_QUERY, font.getResultCode());
+        assertNull(FontsContract.buildTypeface(mContext, null /* cancellation signal */, fonts));
+    }
+
+    @Test
+    public void queryMultipleOneNotFound() throws NameNotFoundException {
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.NOT_FOUND_SECOND_QUERY, SIGNATURE);
+        FontFamilyResult result = FontsContract.fetchFonts(
+                mContext, null /* cancellation signal */, request);
+        assertNotNull(result);
+        assertEquals(FontFamilyResult.STATUS_OK, result.getStatusCode());
+
+        FontInfo[] fonts = result.getFonts();
+        assertEquals(2, fonts.length);
+        FontInfo font = fonts[0];
+        assertEquals(Columns.RESULT_CODE_OK, font.getResultCode());
+        FontInfo font2 = fonts[1];
+        assertEquals(Columns.RESULT_CODE_FONT_NOT_FOUND, font2.getResultCode());
+        assertNotNull(FontsContract.buildTypeface(mContext, null /* cancellation signal */, fonts));
+    }
+
+    @Test
+    public void queryMandatoryFieldsOnly() throws NameNotFoundException {
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.MANDATORY_FIELDS_ONLY_QUERY, SIGNATURE);
+        FontFamilyResult result = FontsContract.fetchFonts(
+                mContext, null /* cancellation signal */, request);
+        assertNotNull(result);
+        assertEquals(FontFamilyResult.STATUS_OK, result.getStatusCode());
+
+        FontInfo[] fonts = result.getFonts();
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertNotNull(font.getUri());
+        assertEquals(400, font.getWeight());
+        assertNull(font.getAxes());
+        assertFalse(font.isItalic());
+        assertEquals(Columns.RESULT_CODE_OK, font.getResultCode());
+        assertNotNull(FontsContract.buildTypeface(mContext, null /* cancellation signal */, fonts));
     }
 
     @Test
     public void restrictContextRejection() throws NameNotFoundException {
-        Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
-        Context restrictedContext = ctx.createPackageContext(PACKAGE, Context.CONTEXT_RESTRICTED);
+        Context restrictedContext = mContext.createPackageContext(
+                PACKAGE, Context.CONTEXT_RESTRICTED);
 
-        FontRequest request = new FontRequest(AUTHORITY, PACKAGE, "singleFontFamily", SIGNATURE);
+        FontRequest request = new FontRequest(AUTHORITY, PACKAGE,
+                MockFontProvider.SINGLE_FONT_FAMILY_QUERY, SIGNATURE);
 
         // Rejected if restricted context is used.
         FontFamilyResult result = FontsContract.fetchFonts(
@@ -128,11 +335,9 @@
         assertEquals(FontFamilyResult.STATUS_REJECTED, result.getStatusCode());
 
         // Even if you have a result, buildTypeface should fail with restricted context.
-        result = FontsContract.fetchFonts(ctx, null /* cancellation signal */, request);
+        result = FontsContract.fetchFonts(mContext, null /* cancellation signal */, request);
         assertEquals(FontFamilyResult.STATUS_OK, result.getStatusCode());
         assertNull(FontsContract.buildTypeface(
                 restrictedContext, null /* cancellation signal */, result.getFonts()));
     }
-
-    // TODO: Add more test case.
 }
diff --git a/tests/tests/provider/src/android/provider/cts/MockFontProvider.java b/tests/tests/provider/src/android/provider/cts/MockFontProvider.java
index a348de2..9d925c7 100644
--- a/tests/tests/provider/src/android/provider/cts/MockFontProvider.java
+++ b/tests/tests/provider/src/android/provider/cts/MockFontProvider.java
@@ -21,25 +21,22 @@
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.res.AssetFileDescriptor;
 import android.content.res.AssetManager;
 import android.database.Cursor;
 import android.database.MatrixCursor;
-import android.graphics.fonts.FontVariationAxis;
 import android.net.Uri;
-import android.os.CancellationSignal;
 import android.os.ParcelFileDescriptor;
-import android.util.SparseArray;
 
-import java.util.Collections;
-import java.util.Map;
-import java.util.HashMap;
 import java.io.File;
-import java.nio.file.Files;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.FileNotFoundException;
+import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 public class MockFontProvider extends ContentProvider {
     final static String AUTHORITY = "android.provider.fonts.cts.font";
@@ -50,9 +47,20 @@
     private static final int SAMPLE_FONT_FILE_0_ID = 0;
     private static final int SAMPLE_FONT_FILE_1_ID = 1;
 
+    static final String SINGLE_FONT_FAMILY_QUERY = "singleFontFamily";
+    static final String SINGLE_FONT_FAMILY2_QUERY = "singleFontFamily2";
+    static final String MULTIPLE_FAMILY_QUERY = "multipleFontFamily";
+    static final String NOT_FOUND_QUERY = "notFound";
+    static final String UNAVAILABLE_QUERY = "unavailable";
+    static final String MALFORMED_QUERY = "malformed";
+    static final String NOT_FOUND_SECOND_QUERY = "notFoundSecond";
+    static final String NOT_FOUND_THIRD_QUERY = "notFoundThird";
+    static final String NEGATIVE_ERROR_CODE_QUERY = "negativeCode";
+    static final String MANDATORY_FIELDS_ONLY_QUERY = "mandatoryFields";
+
     static class Font {
         public Font(int id, int fileId, int ttcIndex, String varSettings, int weight, int italic,
-                int resultCode) {
+                int resultCode, boolean returnAllFields) {
             mId = id;
             mFileId = fileId;
             mTtcIndex = ttcIndex;
@@ -60,6 +68,7 @@
             mWeight = weight;
             mItalic = italic;
             mResultCode = resultCode;
+            mReturnAllFields = returnAllFields;
         }
 
         public int getId() {
@@ -90,6 +99,10 @@
             return mFileId;
         }
 
+        public boolean isReturnAllFields() {
+            return mReturnAllFields;
+        }
+
         private int mId;
         private int mFileId;
         private int mTtcIndex;
@@ -97,6 +110,7 @@
         private int mWeight;
         private int mItalic;
         private int mResultCode;
+        private final boolean mReturnAllFields;
     };
 
     private static Map<String, Font[]> QUERY_MAP;
@@ -104,21 +118,71 @@
         HashMap<String, Font[]> map = new HashMap<>();
         int id = 0;
 
-        map.put("singleFontFamily", new Font[] {
-            new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 400, 0, Columns.RESULT_CODE_OK),
+        map.put(SINGLE_FONT_FAMILY_QUERY, new Font[] {
+            new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 400, 0, Columns.RESULT_CODE_OK, true),
         });
 
-        map.put("multipleFontFamily", new Font[] {
-            new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 400, 0, Columns.RESULT_CODE_OK),
-            new Font(id++, SAMPLE_FONT_FILE_1_ID, 0, null, 400, 0, Columns.RESULT_CODE_OK),
-            new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 700, 1, Columns.RESULT_CODE_OK),
-            new Font(id++, SAMPLE_FONT_FILE_1_ID, 0, null, 700, 1, Columns.RESULT_CODE_OK),
+        map.put(MULTIPLE_FAMILY_QUERY, new Font[] {
+            new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 400, 0, Columns.RESULT_CODE_OK, true),
+            new Font(id++, SAMPLE_FONT_FILE_1_ID, 0, null, 400, 0, Columns.RESULT_CODE_OK, true),
+            new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 700, 1, Columns.RESULT_CODE_OK, true),
+            new Font(id++, SAMPLE_FONT_FILE_1_ID, 0, null, 700, 1, Columns.RESULT_CODE_OK, true),
         });
 
+        map.put(SINGLE_FONT_FAMILY2_QUERY, new Font[] {
+                new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, "'wght' 100", 700, 1,
+                        Columns.RESULT_CODE_OK, true),
+        });
+
+        map.put(NOT_FOUND_QUERY, new Font[] {
+                new Font(0, 0, 0, null, 400, 0, Columns.RESULT_CODE_FONT_NOT_FOUND, true),
+        });
+
+        map.put(UNAVAILABLE_QUERY, new Font[] {
+                new Font(0, 0, 0, null, 400, 0, Columns.RESULT_CODE_FONT_UNAVAILABLE, true),
+        });
+
+        map.put(MALFORMED_QUERY, new Font[] {
+                new Font(0, 0, 0, null, 400, 0, Columns.RESULT_CODE_MALFORMED_QUERY, true),
+        });
+
+        map.put(NOT_FOUND_SECOND_QUERY, new Font[] {
+                new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 700, 0, Columns.RESULT_CODE_OK,
+                        true),
+                new Font(0, 0, 0, null, 400, 0, Columns.RESULT_CODE_FONT_NOT_FOUND, true),
+        });
+
+        map.put(NOT_FOUND_THIRD_QUERY, new Font[] {
+                new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 700, 0, Columns.RESULT_CODE_OK,
+                        true),
+                new Font(0, 0, 0, null, 400, 0, Columns.RESULT_CODE_FONT_NOT_FOUND, true),
+                new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 700, 0, Columns.RESULT_CODE_OK,
+                        true),
+        });
+
+        map.put(NEGATIVE_ERROR_CODE_QUERY, new Font[] {
+                new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 700, 0, -5, true),
+        });
+
+        map.put(MANDATORY_FIELDS_ONLY_QUERY, new Font[] {
+                new Font(id++, SAMPLE_FONT_FILE_0_ID, 0, null, 400, 0,
+                        Columns.RESULT_CODE_OK, false),
+        });
+
+
         QUERY_MAP = Collections.unmodifiableMap(map);
     }
 
     private static Cursor buildCursor(Font[] in) {
+        if (!in[0].mReturnAllFields) {
+            MatrixCursor cursor = new MatrixCursor(new String[] { Columns._ID, Columns.FILE_ID });
+            for (Font font : in) {
+                MatrixCursor.RowBuilder builder = cursor.newRow();
+                builder.add(Columns._ID, font.getId());
+                builder.add(Columns.FILE_ID, font.getFileId());
+            }
+            return cursor;
+        }
         MatrixCursor cursor = new MatrixCursor(new String[] {
                 Columns._ID, Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, Columns.WEIGHT,
                 Columns.ITALIC, Columns.RESULT_CODE, Columns.FILE_ID});
@@ -135,35 +199,42 @@
         return cursor;
     }
 
-    public MockFontProvider() {
-    }
-
-    @Override
-    public ParcelFileDescriptor openFile(Uri uri, String mode) {
-        final int id = (int)ContentUris.parseId(uri);
-        final File targetFile = getCopiedFile(FONT_FILES[id]);
-        try {
-            return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_READ_ONLY);
-        } catch (FileNotFoundException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public File getCopiedFile(String path) {
-        return new File(getContext().getFilesDir(), path);
-    }
-
-    @Override
-    public boolean onCreate() {
-        final AssetManager mgr = getContext().getAssets();
+    public static void prepareFontFiles(Context context) {
+        final AssetManager mgr = context.getAssets();
         for (String path : FONT_FILES) {
             try (InputStream is = mgr.open(path)) {
-                Files.copy(is, getCopiedFile(path).toPath(), StandardCopyOption.REPLACE_EXISTING);
+                Files.copy(is, getCopiedFile(context, path).toPath(),
+                        StandardCopyOption.REPLACE_EXISTING);
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
         }
-        // TODO: do we have good time to remove above files from files directory?
+    }
+
+    public static void cleanUpFontFiles(Context context) {
+        for (String file : FONT_FILES) {
+            getCopiedFile(context, file).delete();
+        }
+    }
+
+    public static File getCopiedFile(Context context, String path) {
+        return new File(context.getFilesDir(), path);
+    }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) {
+        final int id = (int) ContentUris.parseId(uri);
+        final File targetFile = getCopiedFile(getContext(), FONT_FILES[id]);
+        try {
+            return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_READ_ONLY);
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException(
+                    "Failed to find font file. Did you forget to call prepareFontFiles in setUp?");
+        }
+    }
+
+    @Override
+    public boolean onCreate() {
         return true;
     }
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
index a739f23..ca12b34 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
@@ -103,11 +103,14 @@
         assertCallState(call, Call.STATE_DIALING);
 
         final int currentInvokeCount = mOnCallAudioStateChangedCounter.getInvokeCount();
-
+        mOnCallAudioStateChangedCounter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
+        CallAudioState callAudioState =
+                (CallAudioState) mOnCallAudioStateChangedCounter.getArgs(0)[0];
 
         // We need to check what audio routes are available. If speaker and either headset or
         // earpiece aren't available, then we should skip this test.
-        int availableRoutes = connection.getCallAudioState().getSupportedRouteMask();
+
+        int availableRoutes = callAudioState.getSupportedRouteMask();
         if ((availableRoutes & CallAudioState.ROUTE_SPEAKER) == 0) {
             return;
         }
diff --git a/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java b/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
index 57ec1ae..7fd12d9 100644
--- a/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
@@ -40,7 +40,6 @@
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
 import android.telephony.TelephonyManager;
-import android.telephony.VisualVoicemailService;
 import android.telephony.VisualVoicemailSms;
 import android.telephony.VisualVoicemailSmsFilterSettings;
 import android.test.InstrumentationTestCase;
@@ -527,7 +526,7 @@
         MockVisualVoicemailService.setSmsFuture(future);
 
         setupSmsReceiver(text);
-        try (SentSmsObserver observer = new SentSmsObserver(mContext)) {
+        try (SentSmsObserver observer = new SentSmsObserver(mContext, text)) {
             mTelephonyManager
                     .sendVisualVoicemailSms(mPhoneNumber,0, text, null);
 
@@ -654,12 +653,14 @@
     private static class SentSmsObserver extends ContentObserver implements AutoCloseable {
 
         private final Context mContext;
+        private final String mText;
 
         public CompletableFuture<Boolean> mFuture = new CompletableFuture<>();
 
-        public SentSmsObserver(Context context) {
+        public SentSmsObserver(Context context, String text) {
             super(new Handler(Looper.getMainLooper()));
             mContext = context;
+            mText = text;
             mContext.getContentResolver().registerContentObserver(Sms.CONTENT_URI, true, this);
         }
 
@@ -678,14 +679,15 @@
         @Override
         public void onChange(boolean selfChange, Uri uri) {
             try (Cursor cursor = mContext.getContentResolver()
-                    .query(uri, new String[] {Sms.TYPE}, null, null, null)) {
+                    .query(uri, new String[] {Sms.TYPE, Sms.BODY}, null, null, null)) {
                 if (cursor == null){
                     return;
                 }
                 if (!cursor.moveToFirst()){
                     return;
                 }
-                if (cursor.getInt(0) == Sms.MESSAGE_TYPE_SENT) {
+                if (cursor.getInt(0) == Sms.MESSAGE_TYPE_SENT && TextUtils
+                        .equals(cursor.getString(1), mText)) {
                     mFuture.complete(true);
                 }
             } catch (SQLiteException e) {
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index 308e750..df60064 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -227,6 +227,16 @@
         }
     }
 
+    @Test
+    public void testBuilder_setJustificationMode() {
+        StaticLayout.Builder builder = StaticLayout.Builder.obtain(LAYOUT_TEXT, 0,
+                LAYOUT_TEXT.length(), mDefaultPaint, DEFAULT_OUTER_WIDTH);
+        builder.setJustificationMode(Layout.JUSTIFICATION_MODE_INTER_WORD);
+        StaticLayout layout = builder.build();
+        // Hard to expect the justification result. Just make sure the final layout is created
+        // without causing any exceptions.
+        assertNotNull(layout);
+    }
     /*
      * Get the line number corresponding to the specified vertical position.
      *  If you ask for a position above 0, you get 0. above 0 means pixel above the fire line
diff --git a/tests/tests/text/src/android/text/cts/TextUtilsTest.java b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
index 979dc15..d549cfa 100644
--- a/tests/tests/text/src/android/text/cts/TextUtilsTest.java
+++ b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
@@ -259,8 +259,6 @@
 
     @Test
     public void testConcat() {
-        // issue 1695243
-        // the javadoc for concat() doesn't describe the expected result when parameter is empty.
         assertEquals("", TextUtils.concat().toString());
 
         assertEquals("first", TextUtils.concat("first").toString());
@@ -291,17 +289,76 @@
 
         assertEquals(string1, TextUtils.concat(string1));
 
-        // issue 1695243, the javadoc for concat() doesn't describe
-        // the expected result when parameters are null.
         assertEquals(null, TextUtils.concat((CharSequence) null));
     }
 
-    @Test(expected=NullPointerException.class)
-    public void testConcatNullArray() {
+    @Test(expected = NullPointerException.class)
+    public void testConcat_NullArray() {
         TextUtils.concat((CharSequence[]) null);
     }
 
     @Test
+    public void testConcat_NullParameters() {
+        assertEquals("nullA", TextUtils.concat(null, "A"));
+        assertEquals("Anull", TextUtils.concat("A", null));
+        assertEquals("AnullB", TextUtils.concat("A", null, "B"));
+
+        final SpannableString piece = new SpannableString("A");
+        final Object span = new Object();
+        piece.setSpan(span, 0, piece.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+        final Spanned result = (Spanned) TextUtils.concat(piece, null);
+        assertEquals("Anull", result.toString());
+        final Object[] spans = result.getSpans(0, result.length(), Object.class);
+        assertEquals(1, spans.length);
+        assertSame(span, spans[0]);
+        assertEquals(0, result.getSpanStart(spans[0]));
+        assertEquals(piece.length(), result.getSpanEnd(spans[0]));
+    }
+
+    @Test
+    public void testConcat_twoParagraphSpans() {
+        // Two paragraph spans. The first will get extended to cover the whole string and the second
+        // will be dropped.
+        final SpannableString string1 = new SpannableString("a");
+        final SpannableString string2 = new SpannableString("b");
+        final Object span1 = new Object();
+        final Object span2 = new Object();
+        string1.setSpan(span1, 0, string1.length(), Spanned.SPAN_PARAGRAPH);
+        string2.setSpan(span2, 0, string2.length(), Spanned.SPAN_PARAGRAPH);
+
+        final Spanned result = (Spanned) TextUtils.concat(string1, string2);
+        assertEquals("ab", result.toString());
+        final Object[] spans = result.getSpans(0, result.length(), Object.class);
+        assertEquals(1, spans.length);
+        assertSame(span1, spans[0]);
+        assertEquals(0, result.getSpanStart(spans[0]));
+        assertEquals(result.length(), result.getSpanEnd(spans[0]));
+    }
+
+    @Test
+    public void testConcat_oneParagraphSpanAndOneInclusiveSpan() {
+        // One paragraph span and one double-inclusive span. The first will get extended to cover
+        // the whole string and the second will be kept.
+        final SpannableString string1 = new SpannableString("a");
+        final SpannableString string2 = new SpannableString("b");
+        final Object span1 = new Object();
+        final Object span2 = new Object();
+        string1.setSpan(span1, 0, string1.length(), Spanned.SPAN_PARAGRAPH);
+        string2.setSpan(span2, 0, string2.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+
+        final Spanned result = (Spanned) TextUtils.concat(string1, string2);
+        assertEquals("ab", result.toString());
+        final Object[] spans = result.getSpans(0, result.length(), Object.class);
+        assertEquals(2, spans.length);
+        assertSame(span1, spans[0]);
+        assertEquals(0, result.getSpanStart(spans[0]));
+        assertEquals(result.length(), result.getSpanEnd(spans[0]));
+        assertSame(span2, spans[1]);
+        assertEquals(string1.length(), result.getSpanStart(spans[1]));
+        assertEquals(result.length(), result.getSpanEnd(spans[1]));
+    }
+
+    @Test
     public void testCopySpansFrom() {
         Object[] spans;
         String text = "content";
diff --git a/tests/tests/text/src/android/text/format/cts/FormatterTest.java b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
index fa11023..8c7fdc9 100644
--- a/tests/tests/text/src/android/text/format/cts/FormatterTest.java
+++ b/tests/tests/text/src/android/text/format/cts/FormatterTest.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
+import android.content.res.Configuration;
+import android.os.LocaleList;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -29,6 +31,7 @@
 
 import java.math.BigDecimal;
 import java.math.MathContext;
+import java.util.Locale;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -38,9 +41,12 @@
         // test null Context
         assertEquals("", Formatter.formatFileSize(null, 0));
 
-        MathContext mc = MathContext.DECIMAL64;
-        BigDecimal bd = new BigDecimal((long) 1000, mc);
-        Context context = InstrumentationRegistry.getTargetContext();
+        final MathContext mc = MathContext.DECIMAL64;
+        final BigDecimal bd = new BigDecimal((long) 1000, mc);
+        final Configuration config = new Configuration();
+        config.setLocales(new LocaleList(Locale.US));
+        final Context context =
+                InstrumentationRegistry.getTargetContext().createConfigurationContext(config);
 
         // test different long values with various length
         assertEquals("0 B", Formatter.formatFileSize(context, 0));
@@ -53,6 +59,8 @@
         assertEquals("0.90 kB", Formatter.formatFileSize(context, 901));
 
         assertEquals("1.00 kB", Formatter.formatFileSize(context, bd.pow(1).longValue()));
+        assertEquals("1.50 kB", Formatter.formatFileSize(context, bd.pow(1).longValue() * 3 / 2));
+        assertEquals("12.50 kB", Formatter.formatFileSize(context, bd.pow(1).longValue() * 25 / 2));
 
         assertEquals("1.00 MB", Formatter.formatFileSize(context, bd.pow(2).longValue()));
 
@@ -69,6 +77,48 @@
     }
 
     @Test
+    public void testFormatShortFileSize() {
+        // test null Context
+        assertEquals("", Formatter.formatFileSize(null, 0));
+
+        final MathContext mc = MathContext.DECIMAL64;
+        final BigDecimal bd = new BigDecimal((long) 1000, mc);
+        final Configuration config = new Configuration();
+        config.setLocales(new LocaleList(Locale.US));
+        final Context context =
+                InstrumentationRegistry.getTargetContext().createConfigurationContext(config);
+
+        // test different long values with various length
+        assertEquals("0 B", Formatter.formatShortFileSize(context, 0));
+        assertEquals("1 B", Formatter.formatShortFileSize(context, 1));
+        assertEquals("9 B", Formatter.formatShortFileSize(context, 9));
+        assertEquals("10 B", Formatter.formatShortFileSize(context, 10));
+        assertEquals("99 B", Formatter.formatShortFileSize(context, 99));
+        assertEquals("100 B", Formatter.formatShortFileSize(context, 100));
+        assertEquals("900 B", Formatter.formatShortFileSize(context, 900));
+        assertEquals("0.90 kB", Formatter.formatShortFileSize(context, 901));
+
+        assertEquals("1.0 kB", Formatter.formatShortFileSize(context, bd.pow(1).longValue()));
+        assertEquals("1.5 kB", Formatter.formatShortFileSize(context,
+                bd.pow(1).longValue() * 3 / 2));
+        assertEquals("13 kB", Formatter.formatShortFileSize(context,
+                bd.pow(1).longValue() * 25 / 2));
+
+        assertEquals("1.0 MB", Formatter.formatShortFileSize(context, bd.pow(2).longValue()));
+
+        assertEquals("1.0 GB", Formatter.formatShortFileSize(context, bd.pow(3).longValue()));
+
+        assertEquals("1.0 TB", Formatter.formatShortFileSize(context, bd.pow(4).longValue()));
+
+        assertEquals("1.0 PB", Formatter.formatShortFileSize(context, bd.pow(5).longValue()));
+
+        assertEquals("1000 PB", Formatter.formatShortFileSize(context, bd.pow(6).longValue()));
+
+        // test Negative value
+        assertEquals("-1 B", Formatter.formatShortFileSize(context, -1));
+    }
+
+    @Test
     public void testFormatIpAddress() {
         assertEquals("1.0.168.192", Formatter.formatIpAddress(0xC0A80001));
         assertEquals("1.0.0.127", Formatter.formatIpAddress(0x7F000001));
diff --git a/tests/tests/text/src/android/text/format/cts/TimeTest.java b/tests/tests/text/src/android/text/format/cts/TimeTest.java
index 7c44c77..e085a29 100644
--- a/tests/tests/text/src/android/text/format/cts/TimeTest.java
+++ b/tests/tests/text/src/android/text/format/cts/TimeTest.java
@@ -1995,6 +1995,54 @@
     }
 
     @Test
+    public void testGetJulianMondayFromWeeksSinceEpoch() {
+        final int mondayBeforeEpoch = Time.MONDAY_BEFORE_JULIAN_EPOCH;
+        assertEquals(mondayBeforeEpoch, Time.getJulianMondayFromWeeksSinceEpoch(0));
+        assertEquals(mondayBeforeEpoch + 7, Time.getJulianMondayFromWeeksSinceEpoch(1));
+        assertEquals(mondayBeforeEpoch + 14, Time.getJulianMondayFromWeeksSinceEpoch(2));
+        assertEquals(mondayBeforeEpoch - 7, Time.getJulianMondayFromWeeksSinceEpoch(-1));
+    }
+
+    @Test
+    public void testGetWeeksSinceEpochFromJulianDay() {
+        final int epoch = Time.EPOCH_JULIAN_DAY;  // a Thursday
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.SUNDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.MONDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.TUESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.WEDNESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.THURSDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.FRIDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epoch, Time.SATURDAY));
+
+        final int epochFriday = epoch + 1;
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.SUNDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.MONDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.TUESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.WEDNESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.THURSDAY));
+        assertEquals(1, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.FRIDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochFriday, Time.SATURDAY));
+
+        final int epochSaturday = epoch + 2;
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.SUNDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.MONDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.TUESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.WEDNESDAY));
+        assertEquals(0, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.THURSDAY));
+        assertEquals(1, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.FRIDAY));
+        assertEquals(1, Time.getWeeksSinceEpochFromJulianDay(epochSaturday, Time.SATURDAY));
+
+        final int tenWeeksLater = epochSaturday + 10 * 7;
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.SUNDAY));
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.MONDAY));
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.TUESDAY));
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.WEDNESDAY));
+        assertEquals(10, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.THURSDAY));
+        assertEquals(11, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.FRIDAY));
+        assertEquals(11, Time.getWeeksSinceEpochFromJulianDay(tenWeeksLater, Time.SATURDAY));
+    }
+
+    @Test
     public void testNormalize_utc() {
         Time t = new Time(Time.TIMEZONE_UTC);
         Time expected = new Time(Time.TIMEZONE_UTC);
diff --git a/tests/tests/uirendering/Android.mk b/tests/tests/uirendering/Android.mk
index 956a673..52d8580 100644
--- a/tests/tests/uirendering/Android.mk
+++ b/tests/tests/uirendering/Android.mk
@@ -33,7 +33,7 @@
     android-support-test \
     legacy-android-test
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsUiRenderingTestCases
 
diff --git a/tests/tests/uirendering/res/drawable-nodpi/pathclippingtest_torus.png b/tests/tests/uirendering/res/drawable-nodpi/pathclippingtest_torus.png
new file mode 100644
index 0000000..76dcbc5
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/pathclippingtest_torus.png
Binary files differ
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java
deleted file mode 100644
index 2b6ba0c..0000000
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2014 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.uirendering.cts.bitmapcomparers;
-
-import android.graphics.Color;
-import android.util.Log;
-
-/**
- * Finds the MSE using two images.
- */
-public class MeanSquaredComparer extends BitmapComparer {
-    private static final String TAG = "MeanSquared";
-    private float mErrorPerPixel;
-
-    /**
-     * @param errorPerPixel threshold for which the test will pass/fail. This is the mean-squared
-     *                      error averaged across all of those before comparing.
-     */
-    public MeanSquaredComparer(float errorPerPixel) {
-        mErrorPerPixel = errorPerPixel;
-    }
-
-    @Override
-    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
-            int height) {
-        float totalError = getMSE(ideal, given, offset, stride, width, height);
-        Log.d(TAG, "Error : " + totalError);
-        return (totalError < (mErrorPerPixel));
-    }
-
-    /**
-     * Gets the Mean Squared Error between two data sets.
-     */
-    public static float getMSE(int[] ideal, int[] given, int offset, int stride, int width,
-            int height) {
-        float totalError = 0;
-
-        for (int y = 0 ; y < height ; y++) {
-            for (int x = 0 ; x < width ; x++) {
-                int index = indexFromXAndY(x, y, stride, offset);
-                float idealSum = getColorSum(ideal[index]);
-                float givenSum = getColorSum(given[index]);
-                float difference = idealSum - givenSum;
-                totalError += (difference * difference);
-            }
-        }
-
-        totalError /= (width * height);
-        return totalError;
-    }
-
-    private static float getColorSum(int color) {
-        float red = Color.red(color) / 255.0f;
-        float green = Color.green(color) / 255.0f;
-        float blue = Color.blue(color) / 255.0f;
-        return (red + green + blue);
-    }
-}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/NearPixelComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/NearPixelComparer.java
deleted file mode 100644
index bfb2c77..0000000
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/NearPixelComparer.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2014 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.uirendering.cts.bitmapcomparers;
-
-import android.graphics.Color;
-import android.util.Log;
-
-/**
- * Checks to see that a pixel at a given location is the same as the corresponding pixel. If the
- * pixel is different, it checks the pixels around it to see if it is the same.
- */
-public class NearPixelComparer extends BitmapComparer {
-    private static final String TAG = "NearPixelComparer";
-    private static final int THRESHOLD = 10;
-    private static final int NEAR_PIXEL_RADIUS = 1;
-
-    @Override
-    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
-            int height) {
-        for (int y = 0 ; y < height ; y++) {
-            for (int x = 0 ; x < width ; x++) {
-                boolean success = false;
-
-                // we need to check the surrounding pixels
-                for (int dx = -NEAR_PIXEL_RADIUS ; dx <= NEAR_PIXEL_RADIUS ; dx++) {
-                    for (int dy = -NEAR_PIXEL_RADIUS ; dy <= NEAR_PIXEL_RADIUS ; dy++) {
-                        // need to be sure we don't hit pixels that aren't there
-                        if (x + dx >= width || x + dx < 0 || y + dy >= height || y + dy < 0) {
-                            continue;
-                        }
-                        int index = indexFromXAndY(x + dx, y + dy, stride, offset);
-                        if (!pixelsAreSame(ideal[index], given[index])) {
-                            success = true;
-                            break;
-                        }
-                    }
-                }
-                if (!success) {
-                    Log.d(TAG, "Failure at pixel (" + x + "," + y + ")");
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private boolean pixelsAreSame(int ideal, int given) {
-        int error = Math.abs(Color.red(ideal) - Color.red(given));
-        error += Math.abs(Color.green(ideal) - Color.green(given));
-        error += Math.abs(Color.blue(ideal) - Color.blue(given));
-        return (error < THRESHOLD);
-    }
-}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PSNRComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PSNRComparer.java
deleted file mode 100644
index a38a381..0000000
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PSNRComparer.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2014 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.uirendering.cts.bitmapcomparers;
-
-import android.graphics.Color;
-import android.util.Log;
-
-/**
- * Uses the Peak Signal-to-Noise Ratio approach to determine if two images are considered the same.
- */
-public class PSNRComparer extends BitmapComparer {
-    private static final String TAG = "PSNR";
-    private final float MAX = 255;
-    private final int REGION_SIZE = 10;
-
-    private float mThreshold;
-
-    /**
-     * @param threshold the PSNR necessary to pass the test, if the calculated PSNR is below this
-     *                  value, then the test will fail.
-     */
-    public PSNRComparer(float threshold) {
-        mThreshold = threshold;
-    }
-
-    @Override
-    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
-            int height) {
-        float MSE = 0f;
-        int interestingRegions = 0;
-        for (int y = 0 ; y < height ; y += REGION_SIZE) {
-            for (int x = 0 ; x < width ; x += REGION_SIZE) {
-                int index = indexFromXAndY(x, y, stride, offset);
-                if (inspectRegion(ideal, index)) {
-                    interestingRegions++;
-                }
-            }
-        }
-
-        if (interestingRegions == 0) {
-            return true;
-        }
-
-        for (int y = 0 ; y < height ; y += REGION_SIZE) {
-            for (int x = 0 ; x < width ; x += REGION_SIZE) {
-                int index = indexFromXAndY(x, y, stride, offset);
-                if (ideal[index] == given[index]) {
-                    continue;
-                }
-                MSE += (Color.red(ideal[index]) - Color.red(given[index])) *
-                        (Color.red(ideal[index]) - Color.red(given[index]));
-                MSE += (Color.blue(ideal[index]) - Color.blue(given[index])) *
-                        (Color.blue(ideal[index]) - Color.blue(given[index]));
-                MSE += (Color.green(ideal[index]) - Color.green(given[index])) *
-                        (Color.green(ideal[index]) - Color.green(given[index]));
-            }
-        }
-        MSE /= (interestingRegions * REGION_SIZE * 3);
-
-        float fraction = (MAX * MAX) / MSE;
-        fraction = (float) Math.log(fraction);
-        fraction *= 10;
-
-        Log.d(TAG, "PSNR : " + fraction);
-
-        return (fraction > mThreshold);
-    }
-
-    private boolean inspectRegion(int[] ideal, int index) {
-        int regionColor = ideal[index];
-        for (int i = 0 ; i < REGION_SIZE ; i++) {
-            if (regionColor != ideal[index + i]) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PassComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PassComparer.java
deleted file mode 100644
index 79923cd..0000000
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PassComparer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2014 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.uirendering.cts.bitmapcomparers;
-
-/**
- * This class is purely for debug purposes. It will automatically pass any tests.
- */
-public class PassComparer extends BitmapComparer {
-    @Override
-    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
-            int height) {
-        return true;
-    }
-}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java
deleted file mode 100644
index b7a608a..0000000
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2014 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.uirendering.cts.bitmapcomparers;
-
-import android.graphics.Color;
-import android.util.Log;
-
-/**
- * Compares two images to see if each pixel is the same, within a certain threshold value
- */
-public class ThresholdDifferenceComparer extends BitmapComparer {
-    private static final String TAG = "ThresholdDifference";
-    private int mThreshold;
-
-    /**
-     * @param threshold Each pixel is compared against each other, in each of the individual
-     *                  channels. If the sum of the errors amongst the channels is greater than some
-     *                  threshold, then this test will fail.
-     */
-    public ThresholdDifferenceComparer(int threshold) {
-        mThreshold = threshold;
-    }
-
-    @Override
-    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
-            int height) {
-        int differentPixels = 0;
-        for (int y = 0 ; y < height ; y++) {
-            for (int x = 0 ; x < width ; x++) {
-                int index = indexFromXAndY(x, y, stride, offset);
-                int error = Math.abs(Color.red(ideal[index]) - Color.red(given[index]));
-                error += Math.abs(Color.blue(ideal[index]) - Color.blue(given[index]));
-                error += Math.abs(Color.green(ideal[index]) - Color.green(given[index]));
-                if (error > mThreshold) {
-                    Log.d(TAG, "Failure at position x = " + x + " y = " + y);
-                    Log.d(TAG, "Expected color " + Integer.toHexString(ideal[index]) +
-                            " given color " + Integer.toHexString(given[index]));
-                    differentPixels++;
-                }
-            }
-        }
-        Log.d(TAG, "Number of different pixels : " + differentPixels);
-        return (differentPixels == 0);
-    }
-}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/WeightedPixelDifference.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/WeightedPixelDifference.java
deleted file mode 100644
index f243c29..0000000
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/WeightedPixelDifference.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2014 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.uirendering.cts.bitmapcomparers;
-
-import android.graphics.Color;
-import android.util.Log;
-
-/**
- * This class contains methods to add the error amongst all pixels in two images while taking into
- * account the number of pixels that are non-white. Note only use this if the content background is
- * white.
- */
-public class WeightedPixelDifference extends BitmapComparer {
-    private static final String TAG = "WeightedPixel";
-    private static final int NUM_OF_COLUMNS = 10;
-    private static final float TOTAL_ERROR_DIVISOR = 1024.0f;
-
-    private float mThreshold;
-
-    public WeightedPixelDifference(float threshold) {
-        mThreshold = threshold;
-    }
-
-    /**
-     * Calculates if pixels in a specific line are the same color
-     * @return true if the pixels are the same color
-     */
-    private static boolean inspectRegions(int[] ideal, int start, int stride, int regionSize) {
-        int regionColor = ideal[start];
-        for (int y = 0 ; y < regionSize ; y++) {
-            for (int x = 0 ; x < regionSize ; x++) {
-                int index = indexFromXAndY(x, y, stride, start);
-                if (ideal[index] != regionColor) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Finds the error between each individual channel in the color.
-     */
-    private static float errorBetweenPixels(int color1, int color2) {
-        float error = 0f;
-        error += Math.abs(Color.red(color1) - Color.red(color2));
-        error += Math.abs(Color.green(color1) - Color.green(color2));
-        error += Math.abs(Color.blue(color1) - Color.blue(color2));
-        error += Math.abs(Color.alpha(color1) - Color.alpha(color2));
-        return error;
-    }
-
-    /**
-     * Calculates the error between the pixels in the ideal and given
-     * @return true if the accumulated error is smaller than the threshold
-     */
-    @Override
-    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
-            int height) {
-        int interestingRegions = 0;
-        int regionSize = width / NUM_OF_COLUMNS;
-
-        for (int y = 0 ; y < height ; y += regionSize) {
-            for (int x = 0 ; x < width ; x += regionSize) {
-                int index = indexFromXAndY(x, y,stride, offset);
-                if (inspectRegions(ideal, index, stride, regionSize)) {
-                    interestingRegions++;
-                }
-            }
-        }
-
-        int interestingPixels = Math.max(1, interestingRegions) * regionSize * regionSize;
-
-        float totalError = 0;
-
-        for (int y = 0 ; y < height ; y++) {
-            for (int x = 0 ; x < width ; x++) {
-                int index = indexFromXAndY(x, y, stride, offset);
-                int idealColor = ideal[index];
-                int givenColor = given[index];
-                if (idealColor == givenColor) {
-                    continue;
-                }
-                totalError += errorBetweenPixels(idealColor, givenColor);
-            }
-        }
-
-        totalError /= TOTAL_ERROR_DIVISOR;
-        totalError /= interestingPixels;
-
-        Log.d(TAG, "Total error : " + totalError);
-
-        return totalError < mThreshold;
-    }
-}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/InvertVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/InvertVerifier.java
deleted file mode 100644
index fe0db96..0000000
--- a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/InvertVerifier.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2014 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.uirendering.cts.bitmapverifiers;
-
-/**
- * Used when the tester wants to find the opposite result from a Verifier
- */
-public class InvertVerifier extends BitmapVerifier {
-    private BitmapVerifier mBitmapVerifier;
-
-    public InvertVerifier(BitmapVerifier bitmapVerifier) {
-        mBitmapVerifier = bitmapVerifier;
-    }
-
-    @Override
-    public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
-        boolean success = mBitmapVerifier.verify(bitmap, offset, stride, width, height);
-        mDifferenceBitmap = mBitmapVerifier.getDifferenceBitmap();
-        return !success;
-    }
-}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
index 5d875ab..4991aac 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
@@ -17,12 +17,14 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.PorterDuffXfermode;
-import android.support.test.filters.MediumTest;
+import android.graphics.drawable.ColorDrawable;
+import android.support.test.filters.LargeTest;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
@@ -33,7 +35,7 @@
 
 import java.util.List;
 
-@MediumTest
+@LargeTest // Temporarily hidden from presubmit
 @RunWith(Parameterized.class)
 public class ColorFilterAlphaTest extends ActivityTestBase {
     // We care about one point in each of the four rectangles of different alpha values, as well as
@@ -120,12 +122,25 @@
         return bitmap;
     }
 
+
+    @Override
+    public void setUp() {
+        super.setUp();
+
+        // temporary - ensure test isn't capturing window bg only
+        getInstrumentation().runOnMainSync(() -> getActivity().getWindow().setBackgroundDrawable(
+                        new ColorDrawable(Color.GREEN)));
+
+    }
+
     private CanvasClient mCanvasClient = new CanvasClient() {
         final Paint mPaint = new Paint();
         private final Bitmap mBitmap = createMultiRectBitmap();
 
         @Override
         public void draw(Canvas canvas, int width, int height) {
+            canvas.drawColor(Color.WHITE); // temporary - ensure test isn't capturing window bg only
+
             mPaint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR, mConfig.mode));
             canvas.drawBitmap(mBitmap, 0, 0, mPaint);
         }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
index ae4fee1..d78972f 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
@@ -29,6 +29,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.uirendering.cts.R;
 import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
@@ -71,18 +72,38 @@
         canvas.restore();
     };
 
+    // draw circle with hole in it, by path operations + path clipping
+    static final CanvasClient sTorusClipOutCanvasClient = (canvas, width, height) -> {
+        canvas.save();
+
+        Path path1 = new Path();
+        path1.addCircle(30, 30, 50, Path.Direction.CW);
+
+        Path path2 = new Path();
+        path2.addCircle(30, 30, 30, Path.Direction.CW);
+
+        canvas.clipPath(path1);
+        canvas.clipOutPath(path2);
+        canvas.drawColor(Color.BLUE);
+
+        canvas.restore();
+    };
+
     @Test
     public void testCircleWithCircle() {
         createTest()
                 .addCanvasClient("TorusDraw", sTorusDrawCanvasClient, false)
                 .addCanvasClient("TorusClip", sTorusClipCanvasClient)
-                .runWithComparer(new MSSIMComparer(0.90));
+                .addCanvasClient("TorusClipOut", sTorusClipOutCanvasClient)
+                .runWithVerifier(new GoldenImageVerifier(getActivity(),
+                        R.drawable.pathclippingtest_torus, new MSSIMComparer(0.95)));
     }
 
     @Test
     public void testCircleWithPoints() {
         createTest()
                 .addCanvasClient("TorusClip", sTorusClipCanvasClient)
+                .addCanvasClient("TorusClipOut", sTorusClipOutCanvasClient)
                 .runWithVerifier(new SamplePointVerifier(
                         new Point[] {
                                 // inside of circle
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
index 38a4d40..acae80f 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
@@ -17,12 +17,14 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.RectF;
-import android.support.test.filters.MediumTest;
+import android.graphics.drawable.ColorDrawable;
+import android.support.test.filters.LargeTest;
 import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
 import android.uirendering.cts.testinfrastructure.ActivityTestBase;
 import android.uirendering.cts.testinfrastructure.CanvasClient;
@@ -34,7 +36,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-@MediumTest
+@LargeTest // Temporarily hidden from presubmit
 @RunWith(Parameterized.class)
 public class XfermodeTest extends ActivityTestBase {
     /**
@@ -137,6 +139,17 @@
         mConfig = config;
     }
 
+
+    @Override
+    public void setUp() {
+        super.setUp();
+
+        // temporary - ensure test isn't capturing window bg only
+        getInstrumentation().runOnMainSync(() -> getActivity().getWindow().setBackgroundDrawable(
+                        new ColorDrawable(Color.GREEN)));
+
+    }
+
     private CanvasClient mCanvasClient = new CanvasClient() {
         final Paint mPaint = new Paint();
         private final RectF mSrcRect = new RectF(30, 30, 80, 80);
@@ -146,6 +159,8 @@
 
         @Override
         public void draw(Canvas canvas, int width, int height) {
+            canvas.drawColor(Color.WHITE); // temporary - ensure test isn't capturing window bg only
+
             int sc = canvas.saveLayer(0, 0, TEST_WIDTH, TEST_HEIGHT, null);
 
             canvas.drawBitmap(mDstBitmap, 0, 0, null);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
index 94c981f..d6a196a 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -127,6 +127,7 @@
                     TEST_WIDTH, TEST_HEIGHT, Config.ARGB_8888);
             Rect srcRect = new Rect(testOffset.x, testOffset.y,
                     testOffset.x + TEST_WIDTH, testOffset.y + TEST_HEIGHT);
+            Log.d("UiRendering", "capturing screenshot of " + srcRect.toShortString());
             int copyResult = copy.request(getActivity().getWindow(), srcRect, dest);
             Assert.assertEquals(PixelCopy.SUCCESS, copyResult);
             return dest;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
index 4784cbd..2b8f3b3 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
@@ -15,18 +15,27 @@
  */
 package android.uirendering.cts.testinfrastructure;
 
+import static org.junit.Assert.fail;
+
 import android.app.Activity;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Message;
 import android.support.annotation.Nullable;
 import android.uirendering.cts.R;
+import android.util.Log;
+import android.view.FrameMetrics;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStub;
 import android.view.ViewTreeObserver;
+import android.view.Window;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A generic activity that uses a view specified by the user.
@@ -47,6 +56,33 @@
         mHandler = new RenderSpecHandler();
         int uiMode = getResources().getConfiguration().uiMode;
         mOnTv = (uiMode & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION;
+
+        // log frame metrics
+        HandlerThread handlerThread = new HandlerThread("FrameMetrics");
+        handlerThread.start();
+        getWindow().addOnFrameMetricsAvailableListener(
+                new Window.OnFrameMetricsAvailableListener() {
+                    int mRtFrameCount = 0;
+                    @Override
+                    public void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics,
+                            int dropCountSinceLastInvocation) {
+                        Log.d("UiRendering", "Window frame count " + mRtFrameCount
+                                + ", frame drops " + dropCountSinceLastInvocation);
+                        mRtFrameCount++;
+                    }
+                }, new Handler(handlerThread.getLooper()));
+
+        // log draw metrics
+        View view = new View(this);
+        setContentView(view);
+        view.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
+            int mFrameCount;
+            @Override
+            public void onDraw() {
+                Log.d("UiRendering", "View tree frame count " + mFrameCount);
+                mFrameCount++;
+            }
+        });
     }
 
     public boolean getOnTv() {
@@ -77,7 +113,15 @@
     }
 
     public void reset() {
-        mHandler.sendEmptyMessage(RenderSpecHandler.RESET_MSG);
+        CountDownLatch fence = new CountDownLatch(1);
+        mHandler.obtainMessage(RenderSpecHandler.RESET_MSG, fence).sendToTarget();
+        try {
+            if (!fence.await(10, TimeUnit.SECONDS)) {
+                fail("Timeout exception");
+            }
+        } catch (InterruptedException ex) {
+            fail(ex.getMessage());
+        }
     }
 
     private ViewInitializer mViewInitializer;
@@ -99,8 +143,10 @@
         }
 
         public void handleMessage(Message message) {
+            Log.d("UiRendering", "message of type " + message.what);
             if (message.what == RESET_MSG) {
                 ((ViewGroup)findViewById(android.R.id.content)).removeAllViews();
+                ((CountDownLatch)message.obj).countDown();
                 return;
             }
             setContentView(R.layout.test_container);
@@ -163,6 +209,7 @@
         @Override
         public void onDraw() {
             mView.post(() -> {
+                Log.d("UiRendering", "notifying capture");
                 mView.getViewTreeObserver().removeOnDrawListener(this);
                 synchronized (mLock) {
                     mViewWrapper.getLocationOnScreen(mLocationOnScreen);
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index 5f50e9c..5d23183 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -177,7 +177,8 @@
 
         <activity android:name="android.view.cts.PixelCopyViewProducerActivity"
                   android:label="PixelCopyViewProducerActivity"
-                  android:screenOrientation="locked"
+                  android:screenOrientation="portrait"
+                  android:rotationAnimation="jumpcut"
                   android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
                   android:configChanges="orientation|screenSize" />
 
diff --git a/tests/tests/view/src/android/view/cts/FocusFinderTest.java b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
index 8d56087..a8015ab 100644
--- a/tests/tests/view/src/android/view/cts/FocusFinderTest.java
+++ b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Rect;
@@ -244,6 +245,19 @@
         assertTrue(nextFocus == mBottomRight || nextFocus == mBottomLeft);
     }
 
+    @Test
+    public void testChainVisibility() {
+        mBottomRight.setNextFocusForwardId(mBottomLeft.getId());
+        mBottomLeft.setNextFocusForwardId(mTopRight.getId());
+        mBottomLeft.setVisibility(View.INVISIBLE);
+        View next = mFocusFinder.findNextFocus(mLayout, mBottomRight, View.FOCUS_FORWARD);
+        assertSame(mTopRight, next);
+
+        mBottomLeft.setNextFocusForwardId(View.NO_ID);
+        next = mFocusFinder.findNextFocus(mLayout, mBottomRight, View.FOCUS_FORWARD);
+        assertSame(mTopLeft, next);
+    }
+
     private void verifyNextCluster(View currentCluster, int direction, View expectedNextCluster) {
         View actualNextCluster = mFocusFinder.findNextKeyboardNavigationCluster(
                 mLayout, currentCluster, direction);
diff --git a/tests/tests/view/src/android/view/cts/MenuTest.java b/tests/tests/view/src/android/view/cts/MenuTest.java
index d01cd8b..d931c0d 100644
--- a/tests/tests/view/src/android/view/cts/MenuTest.java
+++ b/tests/tests/view/src/android/view/cts/MenuTest.java
@@ -49,6 +49,7 @@
     public ActivityTestRule<MenuTestActivity> mActivityRule =
             new ActivityTestRule<>(MenuTestActivity.class);
 
+    @UiThreadTest
     @Before
     public void setup() {
         mActivity = (MenuTestActivity) mActivityRule.getActivity();
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
index ab59f3a..e553aa5 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
@@ -16,10 +16,11 @@
 
 package android.view.cts;
 
+import static org.junit.Assert.fail;
+
 import android.app.Activity;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
@@ -42,8 +43,7 @@
     private int mCurrentOrientation = 0;
     private View mContent;
     private Rect mContentBounds = new Rect();
-    private CountDownLatch mFence = new CountDownLatch(1);
-    private boolean mListenForRotate = false;
+    private CountDownLatch mFence = new CountDownLatch(3);
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -55,19 +55,65 @@
     }
 
     @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        if (mListenForRotate) {
-            mListenForRotate = false;
-            mContent.getViewTreeObserver().addOnDrawListener(this);
+    public void onDraw() {
+        final int requestedOrientation = ORIENTATIONS[mCurrentOrientation];
+        boolean screenPortrait =
+                requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+                || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+        boolean contentPortrait = mContent.getHeight() > mContent.getWidth();
+        if (screenPortrait != contentPortrait) {
+            return;
         }
+        mContent.post(() -> {
+            Point offset = new Point();
+            // We pass mContentBounds here just as a throwaway rect, we don't care about
+            // the visible rect just the global offset.
+            mContent.getGlobalVisibleRect(mContentBounds, offset);
+            mContentBounds.set(offset.x, offset.y,
+                    offset.x + mContent.getWidth(), offset.y + mContent.getHeight());
+            mFence.countDown();
+            if (mFence.getCount() > 0) {
+                mContent.invalidate();
+            }
+        });
+    }
+
+    public void waitForFirstDrawCompleted(int timeout, TimeUnit unit) {
+        try {
+            if (!mFence.await(timeout, unit)) {
+                fail("Timeout");
+            }
+        } catch (InterruptedException ex) {
+            fail(ex.getMessage());
+        }
+    }
+
+    public boolean rotate() {
+        mFence = new CountDownLatch(3);
+        runOnUiThread(() -> {
+            mCurrentOrientation = (mCurrentOrientation + 1) % ORIENTATIONS.length;
+            setRequestedOrientation(ORIENTATIONS[mCurrentOrientation]);
+        });
+        waitForFirstDrawCompleted(3, TimeUnit.SECONDS);
+        return mCurrentOrientation != 0;
+    }
+
+    // Convert a rect in normalized 0-100 dimensions to the bounds of the actual View.
+    public void normalizedToSurface(Rect inOut) {
+        float sx = mContentBounds.width() / 100.0f;
+        float sy = mContentBounds.height() / 100.0f;
+        inOut.left = (int) (inOut.left * sx);
+        inOut.top = (int) (inOut.top * sy);
+        inOut.right = (int) (inOut.right * sx + 0.5f);
+        inOut.bottom = (int) (inOut.bottom * sy + 0.5f);
+        inOut.offset(mContentBounds.left, mContentBounds.top);
     }
 
     private static final class ColoredGrid extends View {
         private Paint mPaint = new Paint();
         private Rect mRect = new Rect();
 
-        public ColoredGrid(Context context) {
+        ColoredGrid(Context context) {
             super(context);
             setWillNotDraw(false);
         }
@@ -96,53 +142,4 @@
             canvas.drawRect(mRect, mPaint);
         }
     }
-
-    @Override
-    public void onDraw() {
-        mContent.post(() -> {
-            mContent.getViewTreeObserver().removeOnDrawListener(PixelCopyViewProducerActivity.this);
-            Point offset = new Point();
-            // We pass mContentBounds here just as a throwaway rect, we don't care about
-            // the visible rect just the global offset.
-            mContent.getGlobalVisibleRect(mContentBounds, offset);
-            mContentBounds.set(offset.x, offset.y,
-                    offset.x + mContent.getWidth(), offset.y + mContent.getHeight());
-            mFence.countDown();
-        });
-    }
-
-    public void waitForFirstDrawCompleted(int timeout, TimeUnit unit) {
-        boolean succeeded = false;
-        Exception reason = null;
-        try {
-            succeeded = mFence.await(timeout, unit);
-        } catch (Exception e) {
-            reason = e;
-        }
-        if (!succeeded) {
-            throw new AssertionError("Timed out waiting for fence", reason);
-        }
-    }
-
-    public boolean rotate() {
-        mFence = new CountDownLatch(1);
-        runOnUiThread(() -> {
-            mCurrentOrientation = (mCurrentOrientation + 1) % ORIENTATIONS.length;
-            mListenForRotate = true;
-            setRequestedOrientation(ORIENTATIONS[mCurrentOrientation]);
-        });
-        waitForFirstDrawCompleted(3, TimeUnit.SECONDS);
-        return mCurrentOrientation != 0;
-    }
-
-    // Convert a rect in normalized 0-100 dimensions to the bounds of the actual View.
-    public void normalizedToSurface(Rect inOut) {
-        float sx = mContentBounds.width() / 100.0f;
-        float sy = mContentBounds.height() / 100.0f;
-        inOut.left = (int) (inOut.left * sx);
-        inOut.top = (int) (inOut.top * sy);
-        inOut.right = (int) (inOut.right * sx + 0.5f);
-        inOut.bottom = (int) (inOut.bottom * sy + 0.5f);
-        inOut.offset(mContentBounds.left, mContentBounds.top);
-    }
 }
diff --git a/tests/tests/view/src/android/view/cts/SurfaceViewCtsActivity.java b/tests/tests/view/src/android/view/cts/SurfaceViewCtsActivity.java
index cb85712..590a4be 100644
--- a/tests/tests/view/src/android/view/cts/SurfaceViewCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/SurfaceViewCtsActivity.java
@@ -23,6 +23,7 @@
 import android.graphics.Paint;
 import android.graphics.PorterDuff.Mode;
 import android.os.Bundle;
+import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 
@@ -75,6 +76,8 @@
         private int mOldHOnSizeChanged;
         private int mVisibilityOnWindowVisibilityChanged;
 
+        Surface mSurface;
+
         public MockSurfaceView(Context context) {
             super(context);
             mHolder = getHolder();
@@ -174,6 +177,8 @@
         public void surfaceCreated(SurfaceHolder holder) {
             mSurfaceCreatedCalled = true;
 
+            mSurface = holder.getSurface();
+
             // Use mock canvas listening to the drawColor() calling.
             mCanvas = new Canvas(Bitmap.createBitmap( BITMAP_WIDTH,
                             BITMAP_HEIGHT,
diff --git a/tests/tests/view/src/android/view/cts/SurfaceViewTest.java b/tests/tests/view/src/android/view/cts/SurfaceViewTest.java
index 5d90c73..3ccca48 100644
--- a/tests/tests/view/src/android/view/cts/SurfaceViewTest.java
+++ b/tests/tests/view/src/android/view/cts/SurfaceViewTest.java
@@ -32,10 +32,12 @@
 import android.view.KeyEvent;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
+import android.view.ViewGroup;
 import android.view.cts.SurfaceViewCtsActivity.MockSurfaceView;
 
 import com.android.compatibility.common.util.CtsKeyEventUtil;
 import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.WidgetTestUtils;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -161,4 +163,15 @@
         PollingCheck.waitFor(() -> mMockSurfaceView.isDetachedFromWindow() &&
                 !mMockSurfaceView.isShown());
     }
+
+    @Test
+    public void surfaceInvalidatedWhileDetaching() throws Throwable {
+        assertTrue(mMockSurfaceView.mSurface.isValid());
+        assertFalse(mMockSurfaceView.isDetachedFromWindow());
+        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
+            ((ViewGroup)mMockSurfaceView.getParent()).removeView(mMockSurfaceView);
+        }, false);
+        assertTrue(mMockSurfaceView.isDetachedFromWindow());
+        assertFalse(mMockSurfaceView.mSurface.isValid());
+    }
 }
diff --git a/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java b/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java
index 16bbc18..e71e275 100644
--- a/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java
@@ -35,6 +35,7 @@
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGLConfig;
@@ -50,6 +51,7 @@
     private TextureView mTextureView;
     private HandlerThread mGLThreadLooper;
     private Handler mGLThread;
+    private CountDownLatch mEnterAnimationFence = new CountDownLatch(1);
 
     private SurfaceTexture mSurface;
     private int mSurfaceUpdatedCount;
@@ -88,6 +90,18 @@
         setContentView(content);
     }
 
+    @Override
+    public void onEnterAnimationComplete() {
+        super.onEnterAnimationComplete();
+        mEnterAnimationFence.countDown();
+    }
+
+    public void waitForEnterAnimationComplete() throws TimeoutException, InterruptedException {
+        if (!mEnterAnimationFence.await(TIME_OUT_MS, TimeUnit.MILLISECONDS)) {
+            throw new TimeoutException();
+        }
+    }
+
     private class RunSignalAndCatch implements Runnable {
         public Throwable error;
         private Runnable mRunnable;
@@ -114,7 +128,9 @@
         CountDownLatch fence = new CountDownLatch(1);
         RunSignalAndCatch wrapper = new RunSignalAndCatch(r, fence);
         mGLThread.post(wrapper);
-        fence.await(TIME_OUT_MS, TimeUnit.MILLISECONDS);
+        if (!fence.await(TIME_OUT_MS, TimeUnit.MILLISECONDS)) {
+            throw new TimeoutException();
+        }
         if (wrapper.error != null) {
             throw wrapper.error;
         }
diff --git a/tests/tests/view/src/android/view/cts/TextureViewTest.java b/tests/tests/view/src/android/view/cts/TextureViewTest.java
index a9e215b..c771c18 100644
--- a/tests/tests/view/src/android/view/cts/TextureViewTest.java
+++ b/tests/tests/view/src/android/view/cts/TextureViewTest.java
@@ -59,8 +59,9 @@
 
     @Test
     public void testFirstFrames() throws Throwable {
+        mActivity.waitForEnterAnimationComplete();
+
         final Point center = new Point();
-        mInstrumentation.waitForIdleSync();
         mActivityRule.runOnUiThread(() -> {
             View content = mActivity.findViewById(android.R.id.content);
             int[] outLocation = new int[2];
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java
index 10369c6..7661013 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java
@@ -18,6 +18,8 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.webkit.CookieSyncManager;
 import android.webkit.WebView;
 
@@ -51,6 +53,18 @@
     }
 
     @Override
+    public void onDestroy() {
+        if (mWebView != null) {
+            ViewParent parent =  mWebView.getParent();
+            if (parent instanceof ViewGroup) {
+                ((ViewGroup) parent).removeView(mWebView);
+            }
+            mWebView.destroy();
+        }
+        super.onDestroy();
+    }
+
+    @Override
     protected void onStop() {
         super.onStop();
         try {
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewTest.java b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
index 4b1e6bb..8cd85b1 100644
--- a/tests/tests/widget/src/android/widget/cts/ListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
@@ -348,6 +348,8 @@
     public void testAccessHeaderView() {
         final TextView headerView1 = (TextView) mActivity.findViewById(R.id.headerview1);
         final TextView headerView2 = (TextView) mActivity.findViewById(R.id.headerview2);
+        ((ViewGroup) headerView1.getParent()).removeView(headerView1);
+        ((ViewGroup) headerView2.getParent()).removeView(headerView2);
 
         mListView.setHeaderDividersEnabled(true);
         assertTrue(mListView.areHeaderDividersEnabled());
@@ -574,6 +576,7 @@
     public void testFindViewTraversal() {
         MyListView listView = new MyListView(mActivity, mAttributeSet);
         TextView headerView = (TextView) mActivity.findViewById(R.id.headerview1);
+        ((ViewGroup) headerView.getParent()).removeView(headerView);
 
         assertNull(listView.findViewTraversal(R.id.headerview1));
 
@@ -587,6 +590,7 @@
     public void testFindViewWithTagTraversal() {
         MyListView listView = new MyListView(mActivity, mAttributeSet);
         TextView headerView = (TextView) mActivity.findViewById(R.id.headerview1);
+        ((ViewGroup) headerView.getParent()).removeView(headerView);
 
         assertNull(listView.findViewWithTagTraversal("header"));
 
diff --git a/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
index 4d25740..e8e0eb8 100644
--- a/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/NumberPickerTest.java
@@ -28,12 +28,14 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 
 import android.app.Instrumentation;
+import android.app.UiAutomation;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.NumberPicker;
 
 import com.android.compatibility.common.util.CtsTouchUtils;
@@ -50,8 +52,10 @@
     private static final String[] NUMBER_NAMES3 = {"One", "Two", "Three"};
     private static final String[] NUMBER_NAMES_ALT3 = {"Three", "Four", "Five"};
     private static final String[] NUMBER_NAMES5 = {"One", "Two", "Three", "Four", "Five"};
+    private static final long TIMEOUT_ACCESSIBILITY_EVENT = 5 * 1000;
 
     private Instrumentation mInstrumentation;
+    private UiAutomation mUiAutomation;
     private NumberPickerCtsActivity mActivity;
     private NumberPicker mNumberPicker;
 
@@ -62,6 +66,7 @@
     @Before
     public void setup() {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mUiAutomation = mInstrumentation.getUiAutomation();
         mActivity = mActivityRule.getActivity();
         mNumberPicker = (NumberPicker) mActivity.findViewById(R.id.number_picker);
     }
@@ -260,32 +265,41 @@
                 mNumberPicker.getDisplayedValueForCurrentSelection()));
     }
 
-    @UiThreadTest
     @Test
-    public void testAccessValue() {
-        mNumberPicker.setMinValue(20);
-        mNumberPicker.setMaxValue(22);
-        mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
-
+    public void testAccessValue() throws Throwable {
         final NumberPicker.OnValueChangeListener mockValueChangeListener =
                 mock(NumberPicker.OnValueChangeListener.class);
-        mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
 
-        mNumberPicker.setValue(21);
-        assertEquals(21, mNumberPicker.getValue());
+        mInstrumentation.runOnMainSync(() -> {
+            mNumberPicker.setMinValue(20);
+            mNumberPicker.setMaxValue(22);
+            mNumberPicker.setDisplayedValues(NUMBER_NAMES3);
 
-        mNumberPicker.setValue(20);
-        assertEquals(20, mNumberPicker.getValue());
+            mNumberPicker.setOnValueChangedListener(mockValueChangeListener);
+        });
 
-        mNumberPicker.setValue(22);
-        assertEquals(22, mNumberPicker.getValue());
+        mUiAutomation.executeAndWaitForEvent(() ->
+                    mInstrumentation.runOnMainSync(() -> mNumberPicker.setValue(21)),
+                (AccessibilityEvent event) ->
+                        event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED,
+                TIMEOUT_ACCESSIBILITY_EVENT);
 
-        // Check trying to set value out of min/max range
-        mNumberPicker.setValue(10);
-        assertEquals(20, mNumberPicker.getValue());
+        mInstrumentation.runOnMainSync(() -> {
+            assertEquals(21, mNumberPicker.getValue());
 
-        mNumberPicker.setValue(100);
-        assertEquals(22, mNumberPicker.getValue());
+            mNumberPicker.setValue(20);
+            assertEquals(20, mNumberPicker.getValue());
+
+            mNumberPicker.setValue(22);
+            assertEquals(22, mNumberPicker.getValue());
+
+            // Check trying to set value out of min/max range
+            mNumberPicker.setValue(10);
+            assertEquals(20, mNumberPicker.getValue());
+
+            mNumberPicker.setValue(100);
+            assertEquals(22, mNumberPicker.getValue());
+        });
 
         // Since all changes to value are via API calls, we should have no interactions /
         // callbacks on our listener.
@@ -362,11 +376,15 @@
         final int[] numberPickerLocationOnScreen = new int[2];
         mNumberPicker.getLocationOnScreen(numberPickerLocationOnScreen);
 
-        CtsTouchUtils.emulateDragGesture(mInstrumentation,
-                numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
-                numberPickerLocationOnScreen[1] + mNumberPicker.getHeight() - 1,
-                0,
-                - (mNumberPicker.getHeight() - 2));
+        mUiAutomation.executeAndWaitForEvent(() ->
+                CtsTouchUtils.emulateDragGesture(mInstrumentation,
+                        numberPickerLocationOnScreen[0] + mNumberPicker.getWidth() / 2,
+                        numberPickerLocationOnScreen[1] + mNumberPicker.getHeight() - 1,
+                        0,
+                        -(mNumberPicker.getHeight() - 2)),
+                (AccessibilityEvent event) ->
+                        event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED,
+                TIMEOUT_ACCESSIBILITY_EVENT);
 
         // At this point we expect that the drag-up gesture has selected the value
         // that was "below" the previously selected one, and that our value change listener
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index a70fd54..b40b2f1 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -162,7 +162,6 @@
 
 import java.io.IOException;
 import java.lang.annotation.Retention;
-import java.util.Arrays;
 import java.util.Locale;
 
 /**
@@ -2809,12 +2808,18 @@
         mInstrumentation.waitForIdleSync();
         assertTrue(mTextView.isFocused());
 
-        // Arrows should not cause focus to leave the textfield
+        // Pure-keyboard arrows should not cause focus to leave the textfield
         CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_DPAD_UP);
         mInstrumentation.waitForIdleSync();
         assertTrue(mTextView.isFocused());
 
-        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_DPAD_DOWN);
+        // Non-pure-keyboard arrows, however, should.
+        int dpadRemote = InputDevice.SOURCE_DPAD | InputDevice.SOURCE_KEYBOARD;
+        sendSourceKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_DPAD_UP, dpadRemote);
+        mInstrumentation.waitForIdleSync();
+        assertFalse(mTextView.isFocused());
+
+        sendSourceKeyDownUp(mInstrumentation, mTextView, KeyEvent.KEYCODE_DPAD_DOWN, dpadRemote);
         mInstrumentation.waitForIdleSync();
         assertTrue(mTextView.isFocused());
 
@@ -2824,6 +2829,16 @@
         assertFalse(mTextView.isFocused());
     }
 
+    private void sendSourceKeyDownUp(Instrumentation instrumentation, View targetView, int key,
+            int source) {
+        KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, key);
+        event.setSource(source);
+        CtsKeyEventUtil.sendKey(instrumentation, targetView, event);
+        event = new KeyEvent(KeyEvent.ACTION_UP, key);
+        event.setSource(source);
+        CtsKeyEventUtil.sendKey(instrumentation, targetView, event);
+    }
+
     @Test
     public void testSetIncludeFontPadding() throws Throwable {
         mTextView = findTextView(R.id.textview_text);
@@ -3537,6 +3552,7 @@
     public void testGetOffsetForPositionSingleLineLtr() throws Throwable {
         // asserts getOffsetPosition returns correct values for a single line LTR text
         final String text = "aaaaa";
+
         mActivityRule.runOnUiThread(() -> {
             mTextView = new TextView(mActivity);
             mTextView.setText(text);
@@ -3560,17 +3576,21 @@
         mActivityRule.runOnUiThread(() -> mActivity.setContentView(layout));
         mInstrumentation.waitForIdleSync();
 
+        final float halfCharWidth = (float) Math.ceil(mTextView.getPaint().measureText("a") / 2f);
+        final int paddingTop = mTextView.getTotalPaddingTop();
+        final int paddingLeft = mTextView.getTotalPaddingLeft();
+
         final int firstOffset = 0;
         final int lastOffset = text.length() - 1;
         final int midOffset = text.length() / 2;
 
         // left edge of view
         float x = 0f;
-        float y = mTextView.getHeight() / 2f;
+        float y = mTextView.getHeight() / 2f + paddingTop;
         assertEquals(firstOffset, mTextView.getOffsetForPosition(x, y));
 
         // right edge of text
-        x = mTextView.getLayout().getLineWidth(0) - 1f;
+        x = mTextView.getLayout().getLineWidth(0) + paddingLeft - halfCharWidth;
         assertEquals(lastOffset, mTextView.getOffsetForPosition(x, y));
 
         // right edge of view
@@ -3582,7 +3602,7 @@
         assertEquals(firstOffset, mTextView.getOffsetForPosition(x, y));
 
         // horizontal center of text
-        x = (float) Math.floor(mTextView.getLayout().getLineWidth(0) / 2f + 0.5f);
+        x = mTextView.getLayout().getLineWidth(0) / 2f + paddingLeft - halfCharWidth;
         assertEquals(midOffset, mTextView.getOffsetForPosition(x, y));
     }
 
@@ -3616,9 +3636,13 @@
         final Rect lineBounds = new Rect();
         mTextView.getLayout().getLineBounds(0, lineBounds);
 
+        final float halfCharWidth = (float) Math.ceil(mTextView.getPaint().measureText("a") / 2f);
+        final int paddingTop = mTextView.getTotalPaddingTop();
+        final int paddingLeft = mTextView.getTotalPaddingLeft();
+
         // left edge of view at first line
         float x = 0f;
-        float y = lineBounds.height() / 2f;
+        float y = lineBounds.height() / 2f + paddingTop;
         assertEquals(0, mTextView.getOffsetForPosition(x, y));
 
         // right edge of view at first line
@@ -3627,14 +3651,14 @@
 
         // update lineBounds to be the second line
         mTextView.getLayout().getLineBounds(1, lineBounds);
-        y = lineBounds.top + lineBounds.height() / 2;
+        y = lineBounds.top + lineBounds.height() / 2f + paddingTop;
 
         // left edge of view at second line
         x = 0f;
         assertEquals(line.length(), mTextView.getOffsetForPosition(x, y));
 
         // right edge of text at second line
-        x = mTextView.getLayout().getLineWidth(1) - 1f;
+        x = mTextView.getLayout().getLineWidth(1) + paddingLeft - halfCharWidth;
         assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
 
         // right edge of view at second line
@@ -3642,7 +3666,7 @@
         assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
 
         // horizontal center of text at second line
-        x = (float) Math.floor(mTextView.getLayout().getLineWidth(1) / 2f + 0.5f);
+        x = mTextView.getLayout().getLineWidth(1) / 2f + paddingLeft - halfCharWidth;
         // second line mid offset should not include next line, therefore subtract one
         assertEquals(line.length() + (line.length() - 1) / 2, mTextView.getOffsetForPosition(x, y));
     }
@@ -3677,9 +3701,14 @@
         final Rect lineBounds = new Rect();
         mTextView.getLayout().getLineBounds(0, lineBounds);
 
+        final float halfCharWidth = (float) Math.ceil(
+                mTextView.getPaint().measureText("\u0635") / 2f);
+        final int paddingTop = mTextView.getTotalPaddingTop();
+        final int paddingRight = mTextView.getTotalPaddingRight();
+
         // right edge of view at first line
         float x = mTextView.getWidth() - 1f;
-        float y = lineBounds.height() / 2f;
+        float y = lineBounds.height() / 2f + paddingTop;
         assertEquals(0, mTextView.getOffsetForPosition(x, y));
 
         // left edge of view at first line
@@ -3688,7 +3717,7 @@
 
         // update lineBounds to be the second line
         mTextView.getLayout().getLineBounds(1, lineBounds);
-        y = lineBounds.top + lineBounds.height() / 2f;
+        y = lineBounds.top + lineBounds.height() / 2f + paddingTop;
 
         // right edge of view at second line
         x = mTextView.getWidth() - 1f;
@@ -3698,13 +3727,14 @@
         x = 0f;
         assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
 
-        // right edge of text at second line
-        x = mTextView.getWidth() - mTextView.getLayout().getLineWidth(1) + 1f;
+        // left edge of text at second line
+        x = mTextView.getWidth() - (mTextView.getLayout().getLineWidth(1) + paddingRight
+                - halfCharWidth);
         assertEquals(line.length() + line.length() - 1, mTextView.getOffsetForPosition(x, y));
 
         // horizontal center of text at second line
-        x = mTextView.getWidth() - (float) Math.floor(
-                mTextView.getLayout().getLineWidth(1) / 2f + 0.5f);
+        x = mTextView.getWidth() - (mTextView.getLayout().getLineWidth(1) / 2f + paddingRight
+                - halfCharWidth);
         // second line mid offset should not include next line, therefore subtract one
         assertEquals(line.length() + (line.length() - 1) / 2, mTextView.getOffsetForPosition(x, y));
     }
@@ -6988,13 +7018,6 @@
                 (int) (0.5f + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, 10f, m)),
                 (int) (0.5f + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_IN, 10f, m)),
                 (int) (0.5f + TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 10f, m))};
-        expectedSizesInPx = Arrays.stream(expectedSizesInPx)
-                .filter(x -> x > 0)
-                .distinct()
-                .sorted()
-                .toArray();
-        assertArrayEquals(expectedSizesInPx,
-                autoSizeTextViewUniform.getAutoSizeTextAvailableSizes());
 
         boolean containsValueFromExpectedSizes = false;
         int textSize = (int) autoSizeTextViewUniform.getTextSize();
@@ -7317,12 +7340,17 @@
         PollingCheck.waitFor(() -> mTextView.getSelectionStart() == SMARTSELECT_START
                 && mTextView.getSelectionEnd() == SMARTSELECT_END);
 
-        // Click to reset selection. Expect selection of original selection.
+        // Tap to reset selection. Expect tapped word to be selected.
+        startIndex = text.indexOf("Filip");
+        endIndex = startIndex + "Filip".length();
+        offset = getCenterPositionOfTextAt(mTextView, startIndex, endIndex);
         emulateClickOnView(mTextView, offset.x, offset.y);
-        PollingCheck.waitFor(() -> mTextView.getSelectionStart() == startIndex
-                && mTextView.getSelectionEnd() == endIndex);
+        final int selStart = startIndex;
+        final int selEnd = endIndex;
+        PollingCheck.waitFor(() -> mTextView.getSelectionStart() == selStart
+                && mTextView.getSelectionEnd() == selEnd);
 
-        // Click one more time to dismiss the selection.
+        // Tap one more time to dismiss the selection.
         emulateClickOnView(mTextView, offset.x, offset.y);
         assertFalse(mTextView.hasSelection());
     }
diff --git a/tools/cts-tradefed/res/config/cts-device-files.xml b/tools/cts-tradefed/res/config/cts-device-files.xml
new file mode 100644
index 0000000..e558a56
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-device-files.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="CTS device files collection">
+    <option name="plan" value="cts-device-files" />
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
+        <option name="src-file" value="/sys/fs/selinux/policy" />
+        <option name="dest-file" value="selinux-files/policy"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
+        <option name="src-file" value="/system/manifest.xml" />
+        <option name="dest-file" value="vintf-files/system/manifest.xml"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
+        <option name="src-file" value="/system/compatibility_matrix.xml" />
+        <option name="dest-file" value="vintf-files/system/compatibility_matrix.xml"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
+        <option name="src-file" value="/vendor/manifest.xml" />
+        <option name="dest-file" value="vintf-files/vendor/manifest.xml"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
+        <option name="src-file" value="/vendor/compatibility_matrix.xml" />
+        <option name="dest-file" value="vintf-files/vendor/compatibility_matrix.xml"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DeviceFileCollector">
+        <option name="src-file" value="/proc/config.gz" />
+        <option name="dest-file" value="vintf-files/proc/config.gz"/>
+    </target_preparer>
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 1d86477..f694daa 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -19,12 +19,6 @@
     <!-- <option name="compatibility:exclude-filter" value="MODULE_NAME PACKAGE_NAME.CLASS_NAME" /> Excludes whole class -->
     <!-- <option name="compatibility:exclude-filter" value="MODULE_NAME PACKAGE_NAME.CLASS_NAME#TEST_NAME" /> Excludes individual test -->
 
-    <!-- b/37519234 -->
-    <!-- Turn off VR virtual display tests till VR mode issues are resolved -->
-    <option name="compatibility:exclude-filter" value="CtsServicesHostTestCases android.server.cts.ActivityManagerDisplayTests#testVrActivityLaunch" />
-    <option name="compatibility:exclude-filter" value="CtsServicesHostTestCases android.server.cts.ActivityManagerDisplayTests#testVrActivityReLaunch" />
-    <option name="compatibility:exclude-filter" value="CtsServicesHostTestCases android.server.cts.ActivityManagerDisplayTests#testActivityLaunchPostVr" />
-
     <!-- b/35314835 -->
     <option name="compatibility:exclude-filter" value="CtsServicesHostTestCases android.server.cts.ActivityManagerPinnedStackTests#testAlwaysFocusablePipActivity" />
     <option name="compatibility:exclude-filter" value="CtsServicesHostTestCases android.server.cts.ActivityManagerPinnedStackTests#testLaunchIntoPinnedStack" />
diff --git a/tools/cts-tradefed/res/config/cts-preconditions.xml b/tools/cts-tradefed/res/config/cts-preconditions.xml
index 90c7b7c..21215df 100644
--- a/tools/cts-tradefed/res/config/cts-preconditions.xml
+++ b/tools/cts-tradefed/res/config/cts-preconditions.xml
@@ -15,6 +15,8 @@
 -->
 <configuration description="CTS precondition configs">
 
+    <include name="cts-device-files" />
+
     <option name="plan" value="cts-preconditions" />
 
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
diff --git a/tools/cts-tradefed/res/config/cts-reference-aosp.xml b/tools/cts-tradefed/res/config/cts-reference-aosp.xml
new file mode 100644
index 0000000..88ef596
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-reference-aosp.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs a subset of CTS tests using a reference AOSP system image">
+
+    <include name="cts" />
+
+    <option name="plan" value="cts-reference-aosp" />
+
+    <option name="compatibility:primary-abi-only" value="true" />
+
+    <!-- Tell all AndroidJUnitTests to exclude certain annotations -->
+    <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:exclude-annotation:android.platform.test.annotations.RestrictedBuildTest" />
+
+    <!-- Tell all HostTests to exclude certain annotations -->
+    <option name="compatibility:test-arg" value="com.android.tradefed.testtype.HostTest:exclude-annotation:android.platform.test.annotations.RestrictedBuildTest" />
+    <option name="compatibility:test-arg" value="com.android.compatibility.common.tradefed.testtype.JarHostTest:exclude-annotation:android.platform.test.annotations.RestrictedBuildTest" />
+
+    <!-- Radio system of a reference AOSP system image is not checked -->
+    <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases" />
+    <option name="compatibility:exclude-filter" value="CtsTelephony2TestCases" />
+</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-vendor-interface.xml b/tools/cts-tradefed/res/config/cts-vendor-interface.xml
index 6785dd8..73ec49b 100644
--- a/tools/cts-tradefed/res/config/cts-vendor-interface.xml
+++ b/tools/cts-tradefed/res/config/cts-vendor-interface.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Runs a subset of CTS tests for the Treble 'CTS on AOSP' requirement">
+<configuration description="Runs a subset of CTS tests that can heavily exercise HALs">
 
     <include name="cts" />