Merge "Skip testDelegatedCertInstaller if feature is not available" into nyc-dev
diff --git a/OldCtsTestCaseList.mk b/OldCtsTestCaseList.mk
index c28f3cf..185059e 100644
--- a/OldCtsTestCaseList.mk
+++ b/OldCtsTestCaseList.mk
@@ -23,6 +23,8 @@
     CtsNetSecPolicyUsesCleartextTrafficFalse \
     CtsNetSecPolicyUsesCleartextTrafficTrue \
     CtsNetSecPolicyUsesCleartextTrafficUnspecified \
+    CtsNoRestartBase \
+    CtsNoRestartFeature \
     CtsUsePermissionApp \
     CtsUsePermissionAppCompat \
     CtsPermissionDeclareApp \
@@ -46,6 +48,7 @@
     CtsSplitAppFeature \
     CtsTargetInstrumentationApp \
     CtsUsePermissionDiffCert \
+    CtsUsesLibraryApp \
     CtsWriteExternalStorageApp \
     CtsMultiUserStorageApp
 
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 02466c9..ca525ee 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1184,8 +1184,8 @@
         user preferences about relative package priorities.
     </string>
     <string name="package_priority_bot">Verifying that the CTS Robot helper package is installed.</string>
-    <string name="package_priority_high">Find \"%s\" under \"App notifications\" in the \"Sound &amp; notifications\" settings panel, and mark it as having notification priority.</string>
-    <string name="package_priority_default">Find \"%s\" under \"App notifications\" in the \"Sound &amp; notifications\" settings panel, and make sure it has default priority.</string>
+    <string name="package_priority_high">Find \"%s\" in the \"Notifications\" settings panel, and allow it to Override Do Not Disturb.</string>
+    <string name="package_priority_default">Find \"%s\" in the \"Notifications\" settings panel, and disallow it to Override Do Not Disturb.</string>
     <string name="package_priority_user_order">Check that ranker respects user priorities.</string>
 
     <string name="attention_test">Notification Attention Management Test</string>
@@ -1208,7 +1208,7 @@
     <string name="attention_email_order">Check that ranker respects mailto URIs for contacts.</string>
     <string name="attention_phone_order">Check that ranker respects telephone URIs for contacts.</string>
     <string name="attention_interruption_order">Check that ranker temporarily boosts interruptions.
-    This test takes 15 seconds to complete.</string>
+    This test takes 30 seconds to complete.</string>
     <string name="attention_none_are_filtered">Check that \"All\" mode doesn\'t filter any notifications.</string>
     <string name="attention_some_are_filtered">Check that \"Priority\" mode doesn\'t filter priority notifications.</string>
     <string name="attention_all_are_filtered">Check that \"None\" mode filters all notifications.</string>
@@ -1236,9 +1236,9 @@
         <string name="vr_disable_service">Please disable \"VR Listener for CTS Verifier\"
         under Apps > Gear Icon > Special Access > VR Helper Services and return here.</string>
     <string name="nls_enable_service">Please enable \"Notification Listener for CTS Verifier\"
-        under Security > Notification Access and return here.</string>
+        under Apps > Gear Icon > Special Access > Notification Access and return here.</string>
     <string name="nls_disable_service">Please disable \"Notification Listener for CTS Verifier\"
-        under Security > Notification Access and return here.</string>
+        under Apps > Gear Icon > Special Access > Notification Access and return here.</string>
     <string name="nls_start_settings">Launch Settings</string>
     <string name="nls_service_started">Service should start once enabled.</string>
     <string name="nls_note_received">Check that notification was received.</string>
@@ -2245,12 +2245,19 @@
     <string name="device_owner_request_bugreport">Request bugreport</string>
     <string name="bugreport_sharing_declined">Bugreport sharing declined</string>
     <string name="bugreport_shared_successfully">Bugreport shared successfully</string>
+    <string name="bugreport_already_in_progress">Bugreport is already being collected on this device</string>
+    <string name="bugreport_failed_completing">Bugreport collection operation failed</string>
     <string name="device_owner_bugreport_sharing_declined_while_being_taken">Sharing of requested bugreport declined while being taken</string>
     <string name="device_owner_bugreport_sharing_declined_while_being_taken_info">
         Please press the \"Request bugreport\" button to invoke the bugreport sharing operation.
         Open the notifications panel and verify that:\n
         \n
         - Notification titled \"Taking bugreport...\" with an indefinite progress bar is present.\n
+        \n
+        Press the \"Request bugreport\" button again to try to invoke a second bugreport sharing operation.
+        Open the notifications panel and verify that:\n
+        \n
+        - Notification titled \"Device Owner Requesting Bugreport Tests\" with message \"Bugreport is already being collected on this device\" is present. Dismiss that notification.\n
         - Tapping on the \"Taking bugreport...\" notification opens a dialog titled \"Share bug report?\", that contains a message \"Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared, and your device may temporarily slow down.\" and two buttons - \"DECLINE\" and \"SHARE\".\n
         \n
         Tap the \"DECLINE\" button and verify that:\n
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
index 4e39720..1349694 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
@@ -26,6 +26,9 @@
 import android.os.UserManager;
 import android.util.Log;
 
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.managedprovisioning.Utils;
+
 import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
 
@@ -149,7 +152,12 @@
                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
                         return;
                     }
-                    mDpm.requestBugreport(mAdmin);
+                    final boolean bugreportStarted = mDpm.requestBugreport(mAdmin);
+                    if (!bugreportStarted) {
+                        Utils.showBugreportNotification(this, getString(
+                                R.string.bugreport_already_in_progress),
+                                Utils.BUGREPORT_NOTIFICATION_ID);
+                    }
                 } break;
                 case COMMAND_DEVICE_OWNER_CLEAR_POLICIES: {
                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
index 6ca07ce..e6ba855 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -16,8 +16,6 @@
 
 package com.android.cts.verifier.managedprovisioning;
 
-import android.app.Notification;
-import android.app.NotificationManager;
 import android.app.admin.DeviceAdminReceiver;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
@@ -29,6 +27,7 @@
 
 import com.android.cts.verifier.R;
 import com.android.cts.verifier.location.LocationListenerActivity;
+import com.android.cts.verifier.managedprovisioning.Utils;
 
 /**
  * Profile owner receiver for BYOD flow test.
@@ -42,7 +41,6 @@
                 DEVICE_OWNER_PKG + ".managedprovisioning.DeviceAdminTestReceiver";
         private static final ComponentName RECEIVER_COMPONENT_NAME = new ComponentName(
                 DEVICE_OWNER_PKG, ADMIN_RECEIVER_TEST_CLASS);
-        private static final int BUGREPORT_NOTIFICATION_ID = 12345;
 
         public static ComponentName getReceiverComponentName() {
             return RECEIVER_COMPONENT_NAME;
@@ -57,15 +55,22 @@
         @Override
         public void onBugreportSharingDeclined(Context context, Intent intent) {
             Log.i(TAG, "Bugreport sharing declined");
-            showBugreportNotification(context, context.getString(
-                    R.string.bugreport_sharing_declined), BUGREPORT_NOTIFICATION_ID);
+            Utils.showBugreportNotification(context, context.getString(
+                    R.string.bugreport_sharing_declined), Utils.BUGREPORT_NOTIFICATION_ID);
         }
 
         @Override
         public void onBugreportShared(Context context, Intent intent, String bugreportFileHash) {
             Log.i(TAG, "Bugreport shared");
-            showBugreportNotification(context, context.getString(
-                    R.string.bugreport_shared_successfully), BUGREPORT_NOTIFICATION_ID);
+            Utils.showBugreportNotification(context, context.getString(
+                    R.string.bugreport_shared_successfully), Utils.BUGREPORT_NOTIFICATION_ID);
+        }
+
+        @Override
+        public void onBugreportFailed(Context context, Intent intent, int failureCode) {
+            Log.i(TAG, "Bugreport collection operation failed, code: " + failureCode);
+            Utils.showBugreportNotification(context, context.getString(
+                    R.string.bugreport_failed_completing), Utils.BUGREPORT_NOTIFICATION_ID);
         }
 
         private void setupProfile(Context context) {
@@ -124,17 +129,4 @@
             context.startActivity(intent);
         }
 
-        private void showBugreportNotification(Context context, String msg,
-                int notificationId) {
-            NotificationManager mNotificationManager =
-                    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-            Notification notification = new Notification.Builder(context)
-                    .setSmallIcon(R.drawable.icon)
-                    .setContentTitle(context.getString(
-                            R.string.device_owner_requesting_bugreport_tests))
-                    .setContentText(msg)
-                    .setStyle(new Notification.BigTextStyle().bigText(msg))
-                    .build();
-            mNotificationManager.notify(notificationId, notification);
-        }
 }
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 abccb43..17e83c1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
@@ -17,6 +17,8 @@
 package com.android.cts.verifier.managedprovisioning;
 
 import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
 import android.widget.Toast;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
@@ -32,6 +34,7 @@
 public class Utils {
 
     private static final String TAG = "CtsVerifierByodUtils";
+    static final int BUGREPORT_NOTIFICATION_ID = 12345;
 
     static TestListItem createInteractiveTestItem(Activity activity, String id, int titleRes,
             int infoRes, ButtonInfo[] buttonInfos) {
@@ -61,4 +64,17 @@
             Log.d(TAG, "requestDeleteProfileOwner: ActivityNotFoundException", e);
         }
     }
+
+    static void showBugreportNotification(Context context, String msg, int notificationId) {
+        NotificationManager mNotificationManager =
+                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        Notification notification = new Notification.Builder(context)
+                .setSmallIcon(R.drawable.icon)
+                .setContentTitle(context.getString(
+                        R.string.device_owner_requesting_bugreport_tests))
+                .setContentText(msg)
+                .setStyle(new Notification.BigTextStyle().bigText(msg))
+                .build();
+        mNotificationManager.notify(notificationId, notification);
+    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
index 4898ab2..9d9a4bc 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
@@ -60,6 +60,11 @@
     private static final int MODE_URI = 1;
     private static final int MODE_PHONE = 2;
     private static final int MODE_EMAIL = 3;
+    private static final int SEND_A = 0x1;
+    private static final int SEND_B = 0x2;
+    private static final int SEND_C = 0x4;
+    private static final int SEND_ALL = SEND_A | SEND_B | SEND_C;
+
 
     private Uri mAliceUri;
     private Uri mBobUri;
@@ -129,7 +134,17 @@
             if (mAliceUri == null) { status = FAIL; }
             if (mBobUri == null) { status = FAIL; }
             if (mCharlieUri != null) { status = FAIL; }
-            next();
+
+            if (status == PASS && !isStarred(mAliceUri)) {
+                status = RETEST;
+                Log.i("InsertContactsTest", "Alice is not yet starred");
+                delay();
+            } else {
+                Log.i("InsertContactsTest", "Alice is: " + mAliceUri);
+                Log.i("InsertContactsTest", "Bob is: " + mBobUri);
+                Log.i("InsertContactsTest", "Charlie is: " + mCharlieUri);
+                next();
+            }
         }
     }
 
@@ -528,6 +543,8 @@
 
     // A starts at the top then falls to the bottom
     protected class InterruptionOrderTest extends InteractiveTestCase {
+        boolean mSawElevation = false;
+
         @Override
         View inflate(ViewGroup parent) {
             return createAutoItem(parent, R.string.attention_interruption_order);
@@ -535,15 +552,21 @@
 
         @Override
         void setUp() {
-            sendNotifications(MODE_NONE, false, true);
+            // send B & C noisy
+            sendNotifications(SEND_B | SEND_C, MODE_NONE, false, true);
             status = READY;
-            // wait for notifications to move through the system
-            delay();
+            // wait for then to not be recently noisy any more
+            delay(15000);
         }
 
         @Override
         void test() {
             if (status == READY) {
+                // send A noisy
+                sendNotifications(SEND_A, MODE_NONE, false, true);
+                status = RETEST;
+                delay();
+            } else if (status == RETEST) {
                 MockListener.probeListenerOrder(mContext,
                         new MockListener.StringListResultCatcher() {
                             @Override
@@ -551,36 +574,28 @@
                                 int rankA = findTagInKeys(ALICE, orderedKeys);
                                 int rankB = findTagInKeys(BOB, orderedKeys);
                                 int rankC = findTagInKeys(CHARLIE, orderedKeys);
-                                if (rankA < rankB && rankA < rankC) {
-                                    status = RETEST;
-                                    delay(12000);
+                                if (!mSawElevation) {
+                                    if (rankA < rankB && rankA < rankC) {
+                                        mSawElevation = true;
+                                        status = RETEST;
+                                        delay(15000);
+                                    } else {
+                                        logFail("noisy notification did not sort to top.");
+                                        status = FAIL;
+                                        next();
+                                    }
                                 } else {
-                                    logFail("noisy notification did not sort to top.");
-                                    status = FAIL;
-                                    next();
+                                    if (rankA > rankB && rankA > rankC) {
+                                        status = PASS;
+                                    } else {
+                                        logFail("noisy notification did not fade back into the list.");
+                                        status = FAIL;
+                                    }
                                 }
                             }
                         });
                 delay();  // in case the catcher never returns
-            } else {
-                MockListener.probeListenerOrder(mContext,
-                        new MockListener.StringListResultCatcher() {
-                            @Override
-                            public void accept(List<String> orderedKeys) {
-                                int rankA = findTagInKeys(ALICE, orderedKeys);
-                                int rankB = findTagInKeys(BOB, orderedKeys);
-                                int rankC = findTagInKeys(CHARLIE, orderedKeys);
-                                if (rankA > rankB && rankA > rankC) {
-                                    status = PASS;
-                                } else {
-                                    logFail("noisy notification did not fade back into the list.");
-                                    status = FAIL;
-                                }
-                                next();
-                            }
-                        });
-                delay();  // in case the catcher never returns
-            }
+           }
         }
 
         @Override
@@ -796,11 +811,12 @@
     // usePriorities false:
     //   MODE_NONE: C, B, A
     //   otherwise: A, B ,C
-    private void sendNotifications(int annotationMode, boolean usePriorities, boolean noisy) {
-        // TODO(cwren) Fixes flakey tests due to bug 17644321. Remove this line when it is fixed.
-        int baseId = NOTIFICATION_ID + (noisy ? 3 : 0);
+    private void sendNotifications(int annotationMode, boolean uriMode, boolean noisy) {
+        sendNotifications(SEND_ALL, annotationMode, uriMode, noisy);
+    }
 
-        // C, B, A when sorted by time.  Times must be in the past.
+    private void sendNotifications(int which, int uriMode, boolean usePriorities, boolean noisy) {
+        // C, B, A when sorted by time.  Times must be in the past
         long whenA = System.currentTimeMillis() - 4000000L;
         long whenB = System.currentTimeMillis() - 2000000L;
         long whenC = System.currentTimeMillis() - 1000000L;
@@ -810,36 +826,42 @@
         int priorityB = usePriorities ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT;
         int priorityC = usePriorities ? Notification.PRIORITY_LOW : Notification.PRIORITY_DEFAULT;
 
-        Notification.Builder alice = new Notification.Builder(mContext)
-                .setContentTitle(ALICE)
-                .setContentText(ALICE)
-                .setSmallIcon(R.drawable.ic_stat_alice)
-                .setPriority(priorityA)
-                .setCategory(Notification.CATEGORY_MESSAGE)
-                .setWhen(whenA);
-        alice.setDefaults(noisy ? Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE : 0);
-        addPerson(annotationMode, alice, mAliceUri, ALICE_PHONE, ALICE_EMAIL);
-        mNm.notify(ALICE, baseId + 1, alice.build());
-
-        Notification.Builder bob = new Notification.Builder(mContext)
-                .setContentTitle(BOB)
-                .setContentText(BOB)
-                .setSmallIcon(R.drawable.ic_stat_bob)
-                .setPriority(priorityB)
-                .setCategory(Notification.CATEGORY_MESSAGE)
-                .setWhen(whenB);
-        addPerson(annotationMode, bob, mBobUri, BOB_PHONE, BOB_EMAIL);
-        mNm.notify(BOB, baseId + 2, bob.build());
-
-        Notification.Builder charlie = new Notification.Builder(mContext)
-                .setContentTitle(CHARLIE)
-                .setContentText(CHARLIE)
-                .setSmallIcon(R.drawable.ic_stat_charlie)
-                .setPriority(priorityC)
-                .setCategory(Notification.CATEGORY_MESSAGE)
-                .setWhen(whenC);
-        addPerson(annotationMode, charlie, mCharlieUri, CHARLIE_PHONE, CHARLIE_EMAIL);
-        mNm.notify(CHARLIE, baseId + 3, charlie.build());
+        if ((which & SEND_B) != 0) {
+            Notification.Builder bob = new Notification.Builder(mContext)
+                    .setContentTitle(BOB)
+                    .setContentText(BOB)
+                    .setSmallIcon(R.drawable.ic_stat_bob)
+                    .setPriority(priorityB)
+                    .setCategory(Notification.CATEGORY_MESSAGE)
+                    .setWhen(whenB);
+            bob.setDefaults(noisy ? Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE : 0);
+            addPerson(uriMode, bob, mBobUri, BOB_PHONE, BOB_EMAIL);
+            mNm.notify(BOB, NOTIFICATION_ID + 2, bob.build());
+        }
+        if ((which & SEND_C) != 0) {
+            Notification.Builder charlie = new Notification.Builder(mContext)
+                    .setContentTitle(CHARLIE)
+                    .setContentText(CHARLIE)
+                    .setSmallIcon(R.drawable.ic_stat_charlie)
+                    .setPriority(priorityC)
+                    .setCategory(Notification.CATEGORY_MESSAGE)
+                    .setWhen(whenC);
+            charlie.setDefaults(noisy ? Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE : 0);
+            addPerson(uriMode, charlie, mCharlieUri, CHARLIE_PHONE, CHARLIE_EMAIL);
+            mNm.notify(CHARLIE, NOTIFICATION_ID + 3, charlie.build());
+        }
+        if ((which & SEND_A) != 0) {
+            Notification.Builder alice = new Notification.Builder(mContext)
+                    .setContentTitle(ALICE)
+                    .setContentText(ALICE)
+                    .setSmallIcon(R.drawable.ic_stat_alice)
+                    .setPriority(priorityA)
+                    .setCategory(Notification.CATEGORY_MESSAGE)
+                    .setWhen(whenA);
+            alice.setDefaults(noisy ? Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE : 0);
+            addPerson(uriMode, alice, mAliceUri, ALICE_PHONE, ALICE_EMAIL);
+            mNm.notify(ALICE, NOTIFICATION_ID + 1, alice.build());
+        }
     }
 
     private void addPerson(int mode, Notification.Builder note,
@@ -920,6 +942,28 @@
         return null;
     }
 
+    private boolean isStarred(Uri uri) {
+        Cursor c = null;
+        boolean starred = false;
+        try {
+            String[] projection = new String[] { ContactsContract.Contacts.STARRED };
+            c = mContext.getContentResolver().query(uri, projection, null, null, null);
+            if (c != null && c.getCount() > 0) {
+                int starredIdx = c.getColumnIndex(ContactsContract.Contacts.STARRED);
+                while (c.moveToNext()) {
+                    starred |= c.getInt(starredIdx) == 1;
+                }
+            }
+        } catch (Throwable t) {
+            Log.w(TAG, "Problem getting content resolver or performing contacts query.", t);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        return starred;
+    }
+
     /** Search a list of notification keys for a givcen tag. */
     private int findTagInKeys(String tag, List<String> orderedKeys) {
         for (int i = 0; i < orderedKeys.size(); i++) {
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java b/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java
index fd61b08..504a02d 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java
@@ -27,10 +27,12 @@
 public class ReportLogDeviceInfoStore extends DeviceInfoStore {
 
     private final String mStreamName;
+    private final File tempJsonFile;
 
     public ReportLogDeviceInfoStore(File jsonFile, String streamName) throws Exception {
         mJsonFile = jsonFile;
         mStreamName = streamName;
+        tempJsonFile = File.createTempFile(streamName, "-temp-report-log");
     }
 
     /**
@@ -38,30 +40,32 @@
      */
     @Override
     public void open() throws IOException {
+        // Write new metrics to a temp file to avoid invalid JSON files due to failed tests.
         BufferedWriter formatWriter;
-        String oldMetrics;
+        tempJsonFile.createNewFile();
+        formatWriter = new BufferedWriter(new FileWriter(tempJsonFile));
         if (mJsonFile.exists()) {
             BufferedReader jsonReader = new BufferedReader(new FileReader(mJsonFile));
-            StringBuilder oldMetricsBuilder = new StringBuilder();
-            String line;
-            while ((line = jsonReader.readLine()) != null) {
-                oldMetricsBuilder.append(line);
+            String currentLine;
+            String nextLine = jsonReader.readLine();
+            while ((currentLine = nextLine) != null) {
+                nextLine = jsonReader.readLine();
+                if (nextLine == null && currentLine.charAt(currentLine.length() - 1) == '}') {
+                    // Reopen overall JSON object to write new metrics.
+                    currentLine = currentLine.substring(0, currentLine.length() - 1) + ",";
+                }
+                // Copy to temp file directly to avoid large metrics string in memory.
+                formatWriter.write(currentLine, 0, currentLine.length());
             }
-            oldMetrics = oldMetricsBuilder.toString().trim();
-            if (oldMetrics.charAt(oldMetrics.length() - 1) == '}') {
-                oldMetrics = oldMetrics.substring(0, oldMetrics.length() - 1);
-            }
-            oldMetrics = oldMetrics + ",";
+            jsonReader.close();
         } else {
-            oldMetrics = "{";
+            formatWriter.write("{", 0 , 1);
         }
-        mJsonFile.createNewFile();
-        formatWriter = new BufferedWriter(new FileWriter(mJsonFile));
-        formatWriter.write(oldMetrics + "\"" + mStreamName + "\":", 0, oldMetrics.length() +
-                mStreamName.length() + 3);
+        // Start new JSON object for new metrics.
+        formatWriter.write("\"" + mStreamName + "\":", 0, mStreamName.length() + 3);
         formatWriter.flush();
         formatWriter.close();
-        mJsonWriter = new JsonWriter(new FileWriter(mJsonFile, true));
+        mJsonWriter = new JsonWriter(new FileWriter(tempJsonFile, true));
         mJsonWriter.beginObject();
     }
 
@@ -70,12 +74,24 @@
      */
     @Override
     public void close() throws IOException {
+        // Close JSON Writer.
         mJsonWriter.endObject();
         mJsonWriter.close();
-        // Close the overall JSON object
-        BufferedWriter formatWriter = new BufferedWriter(new FileWriter(mJsonFile, true));
-        formatWriter.write("}", 0, 1);
-        formatWriter.flush();
-        formatWriter.close();
+        // Close overall JSON Object.
+        try (BufferedWriter formatWriter = new BufferedWriter(new FileWriter(tempJsonFile, true))) {
+            formatWriter.write("}", 0, 1);
+        }
+        // Copy metrics from temp file and delete temp file.
+        mJsonFile.createNewFile();
+        try (
+                BufferedReader jsonReader = new BufferedReader(new FileReader(tempJsonFile));
+                BufferedWriter metricsWriter = new BufferedWriter(new FileWriter(mJsonFile))
+        ) {
+            String line;
+            while ((line = jsonReader.readLine()) != null) {
+                // Copy from temp file directly to avoid large metrics string in memory.
+                metricsWriter.write(line, 0, line.length());
+            }
+        }
     }
 }
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/ReportLogHostInfoStore.java b/common/host-side/util/src/com/android/compatibility/common/util/ReportLogHostInfoStore.java
index 65114d9..38b742b 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/ReportLogHostInfoStore.java
+++ b/common/host-side/util/src/com/android/compatibility/common/util/ReportLogHostInfoStore.java
@@ -27,10 +27,12 @@
 public class ReportLogHostInfoStore extends HostInfoStore {
 
     private final String mStreamName;
+    private final File tempJsonFile;
 
     public ReportLogHostInfoStore(File jsonFile, String streamName) throws Exception {
         mJsonFile = jsonFile;
         mStreamName = streamName;
+        tempJsonFile = File.createTempFile(streamName, "-temp-report-log");
     }
 
     /**
@@ -38,30 +40,32 @@
      */
     @Override
     public void open() throws IOException {
+        // Write new metrics to a temp file to avoid invalid JSON files due to failed tests.
         BufferedWriter formatWriter;
-        String oldMetrics;
+        tempJsonFile.createNewFile();
+        formatWriter = new BufferedWriter(new FileWriter(tempJsonFile));
         if (mJsonFile.exists()) {
             BufferedReader jsonReader = new BufferedReader(new FileReader(mJsonFile));
-            StringBuilder oldMetricsBuilder = new StringBuilder();
-            String line;
-            while ((line = jsonReader.readLine()) != null) {
-                oldMetricsBuilder.append(line);
+            String currentLine;
+            String nextLine = jsonReader.readLine();
+            while ((currentLine = nextLine) != null) {
+                nextLine = jsonReader.readLine();
+                if (nextLine == null && currentLine.charAt(currentLine.length() - 1) == '}') {
+                    // Reopen overall JSON object to write new metrics.
+                    currentLine = currentLine.substring(0, currentLine.length() - 1) + ",";
+                }
+                // Copy to temp file directly to avoid large metrics string in memory.
+                formatWriter.write(currentLine, 0, currentLine.length());
             }
-            oldMetrics = oldMetricsBuilder.toString().trim();
-            if (oldMetrics.charAt(oldMetrics.length() - 1) == '}') {
-                oldMetrics = oldMetrics.substring(0, oldMetrics.length() - 1);
-            }
-            oldMetrics = oldMetrics + ",";
+            jsonReader.close();
         } else {
-            oldMetrics = "{";
+            formatWriter.write("{", 0 , 1);
         }
-        mJsonFile.createNewFile();
-        formatWriter = new BufferedWriter(new FileWriter(mJsonFile));
-        formatWriter.write(oldMetrics + "\"" + mStreamName + "\":", 0, oldMetrics.length() +
-                mStreamName.length() + 3);
+        // Start new JSON object for new metrics.
+        formatWriter.write("\"" + mStreamName + "\":", 0, mStreamName.length() + 3);
         formatWriter.flush();
         formatWriter.close();
-        mJsonWriter = new JsonWriter(new FileWriter(mJsonFile, true));
+        mJsonWriter = new JsonWriter(new FileWriter(tempJsonFile, true));
         mJsonWriter.beginObject();
     }
 
@@ -70,12 +74,24 @@
      */
     @Override
     public void close() throws IOException {
+        // Close JSON Writer.
         mJsonWriter.endObject();
         mJsonWriter.close();
-        // Close the overall JSON object
-        BufferedWriter formatWriter = new BufferedWriter(new FileWriter(mJsonFile, true));
-        formatWriter.write("}", 0, 1);
-        formatWriter.flush();
-        formatWriter.close();
+        // Close overall JSON Object.
+        try (BufferedWriter formatWriter = new BufferedWriter(new FileWriter(tempJsonFile, true))) {
+            formatWriter.write("}", 0, 1);
+        }
+        // Copy metrics from temp file and delete temp file.
+        mJsonFile.createNewFile();
+        try (
+                BufferedReader jsonReader = new BufferedReader(new FileReader(tempJsonFile));
+                BufferedWriter metricsWriter = new BufferedWriter(new FileWriter(mJsonFile))
+        ) {
+            String line;
+            while ((line = jsonReader.readLine()) != null) {
+                // Copy from temp file directly to avoid large metrics string in memory.
+                metricsWriter.write(line, 0, line.length());
+            }
+        }
     }
 }
diff --git a/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java b/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java
index 0f4b597..a7b1153 100644
--- a/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java
+++ b/common/util/src/com/android/compatibility/common/util/MetricsXmlSerializer.java
@@ -38,7 +38,6 @@
             return;
         }
         ReportLog.Metric summary = reportLog.getSummary();
-        List<ReportLog.Metric> detailedMetrics = reportLog.getDetailedMetrics();
         // <Summary message="Average" scoreType="lower_better" unit="ms">195.2</Summary>
         if (summary != null) {
             mXmlSerializer.startTag(null, "Summary");
@@ -48,24 +47,5 @@
             mXmlSerializer.text(Double.toString(summary.getValues()[0]));
             mXmlSerializer.endTag(null, "Summary");
         }
-
-        if (!detailedMetrics.isEmpty()) {
-            mXmlSerializer.startTag(null, "Details");
-            for (ReportLog.Metric result : detailedMetrics) {
-                mXmlSerializer.startTag(null, "ValueArray");
-                mXmlSerializer.attribute(null, "source", result.getSource());
-                mXmlSerializer.attribute(null, "message", result.getMessage());
-                mXmlSerializer.attribute(null, "scoreType", result.getType().toReportString());
-                mXmlSerializer.attribute(null, "unit", result.getUnit().toReportString());
-
-                for (double value : result.getValues()) {
-                    mXmlSerializer.startTag(null, "Value");
-                    mXmlSerializer.text(Double.toString(value));
-                    mXmlSerializer.endTag(null, "Value");
-                }
-                mXmlSerializer.endTag(null, "ValueArray");
-            }
-            mXmlSerializer.endTag(null, "Details");
-        }
     }
 }
\ No newline at end of file
diff --git a/common/util/src/com/android/compatibility/common/util/ReportLog.java b/common/util/src/com/android/compatibility/common/util/ReportLog.java
index 76ff1cd..08b1d76 100644
--- a/common/util/src/com/android/compatibility/common/util/ReportLog.java
+++ b/common/util/src/com/android/compatibility/common/util/ReportLog.java
@@ -38,7 +38,6 @@
     private static final String TYPE = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer";
 
     // XML constants
-    private static final String DETAIL_TAG = "Detail";
     private static final String METRIC_TAG = "Metric";
     private static final String MESSAGE_ATTR = "message";
     private static final String SCORETYPE_ATTR = "score_type";
@@ -51,9 +50,7 @@
     protected Metric mSummary;
     protected String mReportLogName;
     protected String mStreamName;
-    protected final List<Metric> mDetails = new ArrayList<>();
 
-    // TODO(mishragaurav): Remove Metric class after removing details from result report.
     public static class Metric implements Serializable {
         private static final int MAX_SOURCE_LENGTH = 200;
         private static final int MAX_MESSAGE_LENGTH = 200;
@@ -174,18 +171,11 @@
         mStreamName = streamName;
     }
 
-    /* package */ void addMetric(Metric elem) {
-        mDetails.add(elem);
-    }
-
-    // TODO(mishragaurav): Make addValue functions no-op after removing details from report.
-
     /**
      * Adds a double array of metrics to the report.
      */
     public void addValues(String message, double[] values, ResultType type, ResultUnit unit) {
-        addMetric(new Metric(Stacktrace.getTestCallerClassMethodNameLineNumber(),
-                message, values, type, unit));
+        // Do nothing. Subclasses may implement using InfoStore to write metrics to files.
     }
 
     /**
@@ -193,15 +183,14 @@
      */
     public void addValues(String source, String message, double[] values, ResultType type,
             ResultUnit unit) {
-        addMetric(new Metric(source, message, values, type, unit));
+        // Do nothing. Subclasses may implement using InfoStore to write metrics to files.
     }
 
     /**
      * Adds a double metric to the report.
      */
     public void addValue(String message, double value, ResultType type, ResultUnit unit) {
-        addMetric(new Metric(Stacktrace.getTestCallerClassMethodNameLineNumber(), message,
-                value, type, unit));
+        // Do nothing. Subclasses may implement using InfoStore to write metrics to files.
     }
 
     /**
@@ -209,7 +198,7 @@
      */
     public void addValue(String source, String message, double value, ResultType type,
             ResultUnit unit) {
-        addMetric(new Metric(source, message, value, type, unit));
+        // Do nothing. Subclasses may implement using InfoStore to write metrics to files.
     }
 
     /**
@@ -303,10 +292,6 @@
         return mSummary;
     }
 
-    public List<Metric> getDetailedMetrics() {
-        return new ArrayList<Metric>(mDetails);
-    }
-
     /**
      * Serializes a given {@link ReportLog} to a String.
      * @throws XmlPullParserException
@@ -338,20 +323,11 @@
             throw new IllegalArgumentException("Metrics reports was null");
         }
         Metric summary = reportLog.getSummary();
-        List<Metric> detailedMetrics = reportLog.getDetailedMetrics();
-        if (summary == null) {
-            throw new IllegalArgumentException("Metrics reports must have a summary");
-        }
-        serializer.startTag(null, SUMMARY_TAG);
-        summary.serialize(serializer);
-        serializer.endTag(null, SUMMARY_TAG);
-
-        if (!detailedMetrics.isEmpty()) {
-            serializer.startTag(null, DETAIL_TAG);
-            for (Metric elem : detailedMetrics) {
-                elem.serialize(serializer);
-            }
-            serializer.endTag(null, DETAIL_TAG);
+        // Summary is optional. Details are not included in result report.
+        if (summary != null) {
+            serializer.startTag(null, SUMMARY_TAG);
+            summary.serialize(serializer);
+            serializer.endTag(null, SUMMARY_TAG);
         }
     }
 
@@ -361,13 +337,22 @@
      * @throws IOException
      */
     public static ReportLog parse(String result) throws XmlPullParserException, IOException {
-        if (result == null || result.trim().isEmpty()) {
-            throw new IllegalArgumentException("Metrics string was empty");
+        if (result == null){
+            throw new IllegalArgumentException("Metrics string was null");
+        }
+        if (result.trim().isEmpty()) {
+            // Empty report.
+            return new ReportLog();
         }
         XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
         XmlPullParser parser = factory.newPullParser();
         parser.setInput(new ByteArrayInputStream(result.getBytes(ENCODING)), ENCODING);
-        parser.nextTag();
+        try {
+            parser.nextTag();
+        } catch (XmlPullParserException e) {
+            // Empty Report.
+            return new ReportLog();
+        }
         return parse(parser);
     }
 
@@ -384,18 +369,6 @@
         report.setSummary(Metric.parse(parser));
         parser.nextTag();
         parser.require(XmlPullParser.END_TAG, null, SUMMARY_TAG);
-        try {
-            parser.nextTag();
-        } catch (XmlPullParserException e) {
-            // Report doesn't have any details, it's ok
-            return report;
-        }
-        if (parser.getName().equals(DETAIL_TAG)) {
-            while (parser.nextTag() == XmlPullParser.START_TAG) {
-                report.addMetric(Metric.parse(parser));
-            }
-            parser.require(XmlPullParser.END_TAG, null, DETAIL_TAG);
-        }
         return report;
     }
 }
diff --git a/common/util/src/com/android/compatibility/common/util/ResultHandler.java b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
index 655add8..8e435d8 100644
--- a/common/util/src/com/android/compatibility/common/util/ResultHandler.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
@@ -53,7 +53,6 @@
     private static final String BUILD_PRODUCT = "build_product";
     private static final String BUILD_TAG = "Build";
     private static final String CASE_TAG = "TestCase";
-    private static final String DETAIL_TAG = "Detail";
     private static final String DEVICES_ATTR = "devices";
     private static final String END_DISPLAY_TIME_ATTR = "end_display";
     private static final String END_TIME_ATTR = "end";
@@ -172,11 +171,7 @@
                                     parser.nextTag();
                                 } else {
                                     test.setReportLog(ReportLog.parse(parser));
-                                    // Details are optional; parser is at next tag if report log
-                                    // does not have details.
-                                    if (parser.getName().equals(DETAIL_TAG)) {
-                                        parser.nextTag();
-                                    }
+                                    parser.nextTag();
                                 }
                             }
                             parser.require(XmlPullParser.END_TAG, NS, TEST_TAG);
diff --git a/common/util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java b/common/util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java
index c6f3ec1..dbbb479 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/MetricsXmlSerializerTest.java
@@ -34,18 +34,7 @@
     private static final double[] VALUES = new double[] {1, 11, 21, 1211, 111221};
     private static final String HEADER = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>";
     private static final String EXPECTED_XML = HEADER
-            + "<Summary message=\"Sample\" scoreType=\"higher_better\" unit=\"byte\">1.0</Summary>"
-            + "<Details>"
-                    + "<ValueArray source=\"com.android.compatibility.common.util."
-                    + "MetricsXmlSerializerTest#testSerialize:84\""
-                    + " message=\"Details\" scoreType=\"neutral\" unit=\"fps\">"
-                        + "<Value>1.0</Value>"
-                        + "<Value>11.0</Value>"
-                        + "<Value>21.0</Value>"
-                        + "<Value>1211.0</Value>"
-                        + "<Value>111221.0</Value>"
-                    + "</ValueArray>"
-            + "</Details>";
+            + "<Summary message=\"Sample\" scoreType=\"higher_better\" unit=\"byte\">1.0</Summary>";
 
     private LocalReportLog mLocalReportLog;
     private MetricsXmlSerializer mMetricsXmlSerializer;
diff --git a/common/util/tests/src/com/android/compatibility/common/util/ReportLogTest.java b/common/util/tests/src/com/android/compatibility/common/util/ReportLogTest.java
index 0b4a639..c8d4682 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/ReportLogTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/ReportLogTest.java
@@ -42,18 +42,7 @@
             "    <Value>1.0</Value>\r\n" +
             "  </Metric>\r\n" +
             "</Summary>";
-    private static final String DETAIL_XML =
-            "<Detail>\r\n" +
-            "  <Metric source=\"com.android.compatibility.common.util.ReportLogTest#%s\" message=\"Details\" score_type=\"neutral\" score_unit=\"fps\">\r\n" +
-            "    <Value>0.1</Value>\r\n" +
-            "    <Value>124.0</Value>\r\n" +
-            "    <Value>4736.0</Value>\r\n" +
-            "    <Value>835.683</Value>\r\n" +
-            "    <Value>98.0</Value>\r\n" +
-            "    <Value>395.0</Value>\r\n" +
-            "  </Metric>\r\n" +
-            "</Detail>";
-    private static final String FULL_XML = SUMMARY_XML + "\r\n" + DETAIL_XML;
+    private static final String FULL_XML = SUMMARY_XML;
 
     private ReportLog mReportLog;
 
@@ -72,34 +61,24 @@
     }
 
     public void testSerialize_noData() throws Exception {
-        try {
-            ReportLog.serialize(mReportLog);
-            fail("Expected IllegalArgumentException when serializing an empty report");
-        } catch (IllegalArgumentException e) {
-            // Expected
-        }
+        ReportLog.serialize(mReportLog);
     }
 
     public void testSerialize_summaryOnly() throws Exception {
         mReportLog.setSummary("Sample", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
-        assertEquals(String.format(SUMMARY_XML, "testSerialize_summaryOnly:84"),
+        assertEquals(String.format(SUMMARY_XML, "testSerialize_summaryOnly:68"),
                 ReportLog.serialize(mReportLog));
     }
 
     public void testSerialize_detailOnly() throws Exception {
         mReportLog.addValues("Details", VALUES, ResultType.NEUTRAL, ResultUnit.FPS);
-        try {
-            ReportLog.serialize(mReportLog);
-            fail("Expected IllegalArgumentException when serializing report without summary");
-        } catch(IllegalArgumentException e) {
-            // Expected
-        }
+        assertEquals(HEADER_XML, ReportLog.serialize(mReportLog));
     }
 
     public void testSerialize_full() throws Exception {
         mReportLog.setSummary("Sample", 1.0, ResultType.HIGHER_BETTER, ResultUnit.BYTE);
         mReportLog.addValues("Details", VALUES, ResultType.NEUTRAL, ResultUnit.FPS);
-        assertEquals(String.format(FULL_XML, "testSerialize_full:100", "testSerialize_full:101"),
+        assertEquals(String.format(FULL_XML, "testSerialize_full:79"),
                 ReportLog.serialize(mReportLog));
     }
 
@@ -113,12 +92,8 @@
     }
 
     public void testParse_noData() throws Exception {
-        try {
-            ReportLog.parse(HEADER_XML);
-            fail("Expected XmlPullParserException when passing a report with no content");
-        } catch(XmlPullParserException e) {
-            // Expected
-        }
+        ReportLog report = ReportLog.parse(HEADER_XML);
+        assertNull(report.getSummary());
     }
 
     public void testParse_summaryOnly() throws Exception {
@@ -127,23 +102,10 @@
         assertEquals("Sample", report.getSummary().getMessage());
     }
 
-    public void testParse_detailOnly() throws Exception {
-        try {
-            ReportLog.parse(String.format(DETAIL_XML, "testParse_detailOnly:132"));
-            fail("Expected XmlPullParserException when serializing report without summary");
-        } catch (XmlPullParserException e) {
-            // Expected
-        }
-    }
-
     public void testParse_full() throws Exception {
-        ReportLog report = ReportLog.parse(String.format(FULL_XML, "testParse_full:140",
-                "testParse_full:138"));
+        ReportLog report = ReportLog.parse(String.format(FULL_XML, "testParse_full:140"));
         assertNotNull(report);
         assertEquals("Sample", report.getSummary().getMessage());
-        List<Metric> details = report.getDetailedMetrics();
-        assertEquals(1, details.size());
-        assertEquals("Details", details.get(0).getMessage());
     }
 
     public void testLimits_source() throws Exception {
diff --git a/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
index c88fe8e..3009ec4 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
@@ -122,13 +122,6 @@
             "             <Value>%s</Value>\n" +
             "          </Metric>\n" +
             "        </Summary>\n" +
-            "        <Detail>\n" +
-            "          <Metric source=\"%s\" message=\"%s\" score_type=\"%s\" score_unit=\"%s\">\n" +
-            "            <Value>%s</Value>\n" +
-            "            <Value>%s</Value>\n" +
-            "            <Value>%s</Value>\n" +
-            "          </Metric>\n" +
-            "        </Detail>\n" +
             "      </Test>\n";
     private File resultsDir = null;
     private File resultDir = null;
@@ -173,10 +166,6 @@
         ReportLog.Metric summary = new ReportLog.Metric(SUMMARY_SOURCE, SUMMARY_MESSAGE,
                 SUMMARY_VALUE, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
         report.setSummary(summary);
-        ReportLog.Metric details = new ReportLog.Metric(DETAILS_SOURCE, DETAILS_MESSAGE,
-                new double[] {DETAILS_VALUE_1, DETAILS_VALUE_2, DETAILS_VALUE_3},
-                ResultType.LOWER_BETTER, ResultUnit.MS);
-        report.addMetric(details);
         moduleBTest4.setReportLog(report);
 
         // Serialize to file
@@ -332,14 +321,5 @@
         assertEquals("Incorrect unit", ResultUnit.SCORE, summary.getUnit());
         assertTrue("Incorrect values", Arrays.equals(new double[] { SUMMARY_VALUE },
                 summary.getValues()));
-        List<ReportLog.Metric> details = report.getDetailedMetrics();
-        assertEquals("Expected 1 report detail", 1, details.size());
-        ReportLog.Metric detail = details.get(0);
-        assertEquals("Incorrect source", DETAILS_SOURCE, detail.getSource());
-        assertEquals("Incorrect message", DETAILS_MESSAGE, detail.getMessage());
-        assertEquals("Incorrect type", ResultType.LOWER_BETTER, detail.getType());
-        assertEquals("Incorrect unit", ResultUnit.MS, detail.getUnit());
-        assertTrue("Incorrect values", Arrays.equals(new double[] { DETAILS_VALUE_1,
-                DETAILS_VALUE_2, DETAILS_VALUE_3 }, detail.getValues()));
     }
 }
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-two-signers-second-signer-no-sig.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-two-signers-second-signer-no-sig.apk
new file mode 100644
index 0000000..1133085
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-two-signers-second-signer-no-sig.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v2-only-two-signers-second-signer-no-supported-sig.apk b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-two-signers-second-signer-no-supported-sig.apk
new file mode 100644
index 0000000..2fab38a
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v2-only-two-signers-second-signer-no-supported-sig.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
index 6c5e4a5..461bcd7 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
@@ -31,8 +31,9 @@
 public class PermissionsHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
     private static final String PKG = "com.android.cts.usepermission";
 
-    private static final String APK = "CtsUsePermissionApp.apk";
-    private static final String APK_COMPAT = "CtsUsePermissionAppCompat.apk";
+    private static final String APK_22 = "CtsUsePermissionApp22.apk";
+    private static final String APK_23 = "CtsUsePermissionApp23.apk";
+    private static final String APK_24 = "CtsUsePermissionApp24.apk";
 
     private IAbi mAbi;
     private IBuildInfo mCtsBuild;
@@ -67,9 +68,10 @@
     public void testFail() throws Exception {
         // Sanity check that remote failure is host failure
         assertNull(getDevice().installPackage(
-                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
         try {
-            runDeviceTests(PKG, ".UsePermissionTest", "testFail");
+            runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                    "testFail");
             fail("Expected remote failure");
         } catch (AssertionError expected) {
         }
@@ -78,82 +80,216 @@
     public void testKill() throws Exception {
         // Sanity check that remote kill is host failure
         assertNull(getDevice().installPackage(
-                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
         try {
-            runDeviceTests(PKG, ".UsePermissionTest", "testKill");
+            runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                    "testKill");
             fail("Expected remote failure");
         } catch (AssertionError expected) {
         }
     }
 
-    public void testDefault() throws Exception {
+    public void testCompatDefault22() throws Exception {
         assertNull(getDevice().installPackage(
-                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
-        runDeviceTests(PKG, ".UsePermissionTest", "testDefault");
-    }
-
-    public void testGranted() throws Exception {
-        assertNull(getDevice().installPackage(
-                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
-        grantPermission(PKG, "android.permission.READ_EXTERNAL_STORAGE");
-        grantPermission(PKG, "android.permission.WRITE_EXTERNAL_STORAGE");
-        runDeviceTests(PKG, ".UsePermissionTest", "testGranted");
-    }
-
-    public void testInteractiveGrant() throws Exception {
-        assertNull(getDevice().installPackage(
-                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
-        runDeviceTests(PKG, ".UsePermissionTest", "testInteractiveGrant");
-    }
-
-    public void testRuntimeGroupGrantSpecificity() throws Exception {
-        assertNull(getDevice().installPackage(
-                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
-        runDeviceTests(PKG, ".UsePermissionTest", "testRuntimeGroupGrantSpecificity");
-    }
-
-    public void testRuntimeGroupGrantExpansion() throws Exception {
-        assertNull(getDevice().installPackage(
-                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
-        runDeviceTests(PKG, ".UsePermissionTest", "testRuntimeGroupGrantExpansion");
-    }
-
-    public void testCompatDefault() throws Exception {
-        assertNull(getDevice().installPackage(MigrationHelper.getTestFile(mCtsBuild, APK_COMPAT),
+                MigrationHelper.getTestFile(mCtsBuild, APK_22),
                 false, false));
-        runDeviceTests(PKG, ".UsePermissionCompatTest", "testCompatDefault");
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest22",
+                "testCompatDefault");
     }
 
-    public void testCompatRevoked() throws Exception {
-        assertNull(getDevice().installPackage(MigrationHelper.getTestFile(mCtsBuild, APK_COMPAT),
+    public void testCompatRevoked22() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_22),
                 false, false));
-        setAppOps(PKG, "android:read_external_storage", "deny");
-        setAppOps(PKG, "android:write_external_storage", "deny");
-        runDeviceTests(PKG, ".UsePermissionCompatTest", "testCompatRevoked");
+        try {
+            runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest22",
+                    "testCompatRevoked_part1");
+            fail("App must be killed on a permission revoke");
+        } catch (AssertionError expected) {
+        }
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest22",
+                "testCompatRevoked_part2");
+    }
+
+    public void testNoRuntimePrompt22() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_22),
+                false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest22",
+                "testNoRuntimePrompt");
+    }
+
+    public void testDefault23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testDefault");
+    }
+
+    public void testGranted23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testGranted");
+    }
+
+    public void testInteractiveGrant23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testInteractiveGrant");
+    }
+
+    public void testRuntimeGroupGrantSpecificity23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testRuntimeGroupGrantSpecificity");
+    }
+
+    public void testRuntimeGroupGrantExpansion23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testRuntimeGroupGrantExpansion");
+    }
+
+    public void testCancelledPermissionRequest23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testCancelledPermissionRequest");
+    }
+
+    public void testRequestGrantedPermission23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testRequestGrantedPermission");
+    }
+
+    public void testDenialWithPrejudice23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testDenialWithPrejudice");
+    }
+
+    public void testRevokeAffectsWholeGroup23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        try {
+            runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23_part1",
+                    "testRevokeAffectsWholeGroup");
+        } catch (AssertionError expected) {
+        }
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23_part2",
+                "testRevokeAffectsWholeGroup");
+    }
+
+    public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        try {
+            runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                    "testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part1");
+            fail("App must be killed on a permission revoke");
+        } catch (Throwable expected) {
+        }
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part2");
+    }
+
+    public void testRequestNonRuntimePermission23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testRequestNonRuntimePermission");
+    }
+
+    public void testRequestNonExistentPermission23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testRequestNonExistentPermission");
+    }
+
+    public void testRequestPermissionFromTwoGroups23() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testRequestPermissionFromTwoGroups");
+    }
+
+    public void testOnlyRequestedPermissionsGranted24() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_24), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest24",
+                "testOnlyRequestedPermissionsGranted");
+    }
+
+    public void testUpgradeKeepsPermissions() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_22), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest22",
+                "testAllPermissionsGrantedByDefault");
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), true, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testAllPermissionsGrantedOnUpgrade");
+    }
+
+    public void testNoDowngradePermissionModel() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        try {
+            assertNull(getDevice().installPackage(
+                    MigrationHelper.getTestFile(mCtsBuild, APK_22), true, false));
+            fail("Permission mode downgrade not allowed");
+        } catch (AssertionError expected) {
+        }
+    }
+
+    public void testNoResidualPermissionsOnUninstall() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testNoResidualPermissionsOnUninstall_part1");
+        assertNull(getDevice().uninstallPackage(PKG));
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testNoResidualPermissionsOnUninstall_part2");
+    }
+
+    public void testRevokePropagatedOnUpgradeOldToNewModel() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_22), false, false));
+        try {
+            runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest22",
+                    "testRevokePropagatedOnUpgradeOldToNewModel_part1");
+            fail("App must be killed on a permission revoke");
+        } catch (AssertionError expected) {
+        }
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), true, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testRevokePropagatedOnUpgradeOldToNewModel_part2");
+    }
+
+    public void testRevokePropagatedOnUpgradeNewToNewModel() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), false, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testRevokePropagatedOnUpgradeNewToNewModel_part1");
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK_23), true, false));
+        runDeviceTests(PKG, "com.android.cts.usepermission.UsePermissionTest23",
+                "testRevokePropagatedOnUpgradeNewToNewModel_part2");
     }
 
     private void runDeviceTests(String packageName, String testClassName, String testMethodName)
             throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
     }
-
-    private void grantPermission(String pkg, String permission) throws Exception {
-        assertEmpty(getDevice().executeShellCommand("pm grant " + pkg + " " + permission));
-    }
-
-    private void revokePermission(String pkg, String permission) throws Exception {
-        assertEmpty(getDevice().executeShellCommand("pm revoke " + pkg + " " + permission));
-    }
-
-    private void setAppOps(String pkg, String op, String mode) throws Exception {
-        assertEmpty(getDevice().executeShellCommand("appops set " + pkg + " " + op + " " + mode));
-    }
-
-    private static void assertEmpty(String str) {
-        if (str == null || str.length() == 0) {
-            return;
-        } else {
-            fail("Expected empty string but found " + str);
-        }
-    }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index f6c6f18..254dda8 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -317,6 +317,21 @@
                 "two-signers-second-signer-v2-broken.apk", "signature did not verify");
     }
 
+    public void testInstallV2TwoSignersRejectsWhenOneWithoutSignatures() throws Exception {
+        // APK v2-signed by two different signers. However, there are no signatures for the second
+        // signer.
+        assertInstallFailsWithError(
+                "v2-only-two-signers-second-signer-no-sig.apk", "No signatures");
+    }
+
+    public void testInstallV2TwoSignersRejectsWhenOneWithoutSupportedSignatures() throws Exception {
+        // APK v2-signed by two different signers. However, there are no supported signatures for
+        // the second signer.
+        assertInstallFailsWithError(
+                "v2-only-two-signers-second-signer-no-supported-sig.apk",
+                "No supported signatures");
+    }
+
     public void testInstallV2RejectsWhenMissingCode() throws Exception {
         // Obtained by removing classes.dex from original.apk and then signing with v2 only.
         // Although this has nothing to do with v2 signature verification, package manager wants
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
new file mode 100644
index 0000000..b2b4476
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
@@ -0,0 +1,101 @@
+/*
+ * 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.appsecurity.cts;
+
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.cts.migration.MigrationHelper;
+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.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+/**
+ * Tests that verify intent filters.
+ */
+public class PrivilegedUpdateTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+    private static final String SHIM_PKG = "com.android.cts.priv.ctsshim";
+    /** Package name of the tests to be run */
+    private static final String TEST_PKG = "com.android.cts.privilegedupdate";
+
+    /** APK that contains the shim; to test upgrading */
+    private static final String SHIM_UPDATE_APK = "CtsShimPrivUpgradePrebuilt.apk";
+    /** APK that contains individual shim test cases */
+    private static final String TEST_APK = "CtsPrivilegedUpdateTests.apk";
+
+    private IAbi mAbi;
+    private IBuildInfo mCtsBuild;
+
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = buildInfo;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertNotNull(mAbi);
+        assertNotNull(mCtsBuild);
+
+        getDevice().uninstallPackage(SHIM_PKG);
+        getDevice().uninstallPackage(TEST_PKG);
+
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, TEST_APK), false));
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        getDevice().uninstallPackage(SHIM_PKG);
+        getDevice().uninstallPackage(TEST_PKG);
+    }
+
+    public void testSystemAppPriorities() throws Exception {
+        runDeviceTests(TEST_PKG, ".PrivilegedUpdateTest", "testSystemAppPriorities");
+    }
+
+    public void testPrivilegedAppPriorities() throws Exception {
+        runDeviceTests(TEST_PKG, ".PrivilegedUpdateTest", "testPrivilegedAppPriorities");
+    }
+
+    public void testPrivilegedAppUpgradePriorities() throws Exception {
+        getDevice().uninstallPackage(SHIM_PKG);
+        
+        try {
+            assertNull(getDevice().installPackage(
+                    MigrationHelper.getTestFile(mCtsBuild, SHIM_UPDATE_APK), true));
+            runDeviceTests(TEST_PKG, ".PrivilegedUpdateTest", "testPrivilegedAppUpgradePriorities");
+        } finally {
+            getDevice().uninstallPackage(SHIM_PKG);
+        }
+    }
+
+    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/UsesLibraryHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
new file mode 100644
index 0000000..c8e608e
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appsecurity.cts;
+
+import com.android.cts.migration.MigrationHelper;
+import com.android.tradefed.build.IBuildInfo;
+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;
+
+/**
+ * Set of tests that verify behavior of runtime permissions, including both
+ * dynamic granting and behavior of legacy apps.
+ */
+public class UsesLibraryHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+    private static final String PKG = "com.android.cts.useslibrary";
+
+    private static final String APK = "CtsUsesLibraryApp.apk";
+    private static final String APK_COMPAT = "CtsUsesLibraryAppCompat.apk";
+
+    private IAbi mAbi;
+    private IBuildInfo mCtsBuild;
+
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = buildInfo;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertNotNull(mAbi);
+        assertNotNull(mCtsBuild);
+
+        getDevice().uninstallPackage(PKG);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        getDevice().uninstallPackage(PKG);
+    }
+
+    public void testUsesLibrary() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+        runDeviceTests(PKG, ".UsesLibraryTest", "testUsesLibrary");
+    }
+
+    public void testMissingLibrary() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+        runDeviceTests(PKG, ".UsesLibraryTest", "testMissingLibrary");
+    }
+
+    public void testDuplicateLibrary() throws Exception {
+        assertNull(getDevice().installPackage(
+                MigrationHelper.getTestFile(mCtsBuild, APK), false, false));
+        runDeviceTests(PKG, ".UsesLibraryTest", "testDuplicateLibrary");
+    }
+
+    private void runDeviceTests(String packageName, String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
index c528ad4..f5666d1 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
@@ -355,15 +355,22 @@
         }
     }
 
-    public static void assertMediaNoAccess(ContentResolver resolver) throws Exception {
+    public static void assertMediaNoAccess(ContentResolver resolver, boolean legacyApp)
+            throws Exception {
         final ContentValues values = new ContentValues();
         values.put(Images.Media.MIME_TYPE, "image/jpeg");
         values.put(Images.Media.DATA,
                 buildProbeFile(Environment.getExternalStorageDirectory()).getAbsolutePath());
 
         try {
-            resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
-            fail("Expected access to be blocked");
+            Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
+            if (legacyApp) {
+                // For legacy apps we do not crash - just make the operation do nothing
+                assertEquals(MediaStore.Images.Media.EXTERNAL_CONTENT_URI
+                        .buildUpon().appendPath("0").build().toString(), uri.toString());
+            } else {
+                fail("Expected access to be blocked");
+            }
         } catch (Exception expected) {
         }
     }
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/Android.mk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/Android.mk
new file mode 100644
index 0000000..6d6e805
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/Android.mk
@@ -0,0 +1,67 @@
+#
+# 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)
+
+###########################################################
+# Package w/ tests
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctsdeviceutil ctstestrunner
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+LOCAL_PACKAGE_NAME := CtsPrivilegedUpdateTests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+include $(BUILD_CTS_SUPPORT_PACKAGE)
+
+
+###########################################################
+# Variant: Privileged app upgrade
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CtsShimPrivUpgradePrebuilt
+LOCAL_MODULE_TAGS := tests
+#LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MODULE_CLASS := APPS
+LOCAL_BUILT_MODULE_STEM := package.apk
+# Make sure the build system doesn't try to resign the APK
+LOCAL_CERTIFICATE := PRESIGNED
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_SRC_FILES := CtsShimPrivUpgrade.apk
+
+include $(BUILD_PREBUILT)
+
+# Add package to the set of APKs available to CTS
+# Unceremoneously ripped from cts/build/support_package.mk
+cts_support_apks :=
+$(foreach fp, $(ALL_MODULES.$(LOCAL_MODULE).BUILT_INSTALLED),\
+  $(eval pair := $(subst :,$(space),$(fp)))\
+  $(eval built := $(word 1,$(pair)))\
+  $(eval installed := $(CTS_TESTCASES_OUT)/$(notdir $(word 2,$(pair))))\
+  $(eval $(call copy-one-file, $(built), $(installed)))\
+  $(eval cts_support_apks += $(installed)))
+
+# Have the module name depend on the cts files; so the cts files get generated when you run mm/mmm/mma/mmma.
+$(my_register_name) : $(cts_support_apks)
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/AndroidManifest.xml
similarity index 73%
copy from hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/AndroidManifest.xml
copy to hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/AndroidManifest.xml
index 253d85d..58f34b9 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -15,13 +15,16 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.usepermission">
-    <application>
+        package="com.android.cts.privilegedupdate">
+
+    <application android:label="PrivilegedUpdateApp">
         <uses-library android:name="android.test.runner" />
-        <activity android:name=".MyActivity" />
+        <activity android:name=".MainActivity" />
     </application>
+
     <instrumentation
         android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:targetPackage="com.android.cts.usepermission" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+        android:targetPackage="com.android.cts.privilegedupdate" />
+
 </manifest>
+
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/CtsShimPrivUpgrade.apk
new file mode 100644
index 0000000..c71163d
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/CtsShimPrivUpgrade.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/src/com/android/cts/privilegedupdate/PrivilegedUpdateTest.java b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/src/com/android/cts/privilegedupdate/PrivilegedUpdateTest.java
new file mode 100644
index 0000000..7b92bea
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/src/com/android/cts/privilegedupdate/PrivilegedUpdateTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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 com.android.cts.intentfilter;
+
+import java.util.List;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.test.InstrumentationTestCase;
+
+/**
+ * Tests for intent filter.
+ */
+public class PrivilegedUpdateTest extends InstrumentationTestCase {
+    /** Package name of the privileged CTS shim */
+    private static final String PRIVILEGED_SHIM_PKG = "com.android.cts.priv.ctsshim";
+    /** Package name of the system CTS shim */
+    private static final String SYSTEM_SHIM_PKG = "com.android.cts.ctsshim";
+    /** Class name for the install tests */
+    private static final String INSTALL_CLASS = ".InstallPriority";
+
+    /**
+     * Tests the filter priorities for a system package are set correctly.
+     * <p>
+     * System packages can NOT obtain higher priorities for any action.
+     */
+    public void testSystemAppPriorities() throws Exception {
+        final ComponentName testComponent =
+                new ComponentName(SYSTEM_SHIM_PKG, SYSTEM_SHIM_PKG + INSTALL_CLASS);
+        assertFilterPriority(testComponent, Intent.ACTION_SEARCH, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_VIEW, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_SEND, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_SEND_MULTIPLE, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_SENDTO, 0);
+    }
+
+    /**
+     * Tests the filter priorities for a privileged package are set correctly.
+     * <p>
+     * Privileged packages can obtain higher priorities except for those on
+     * protected actions. 
+     */
+    public void testPrivilegedAppPriorities() throws Exception {
+        final ComponentName testComponent =
+                new ComponentName(PRIVILEGED_SHIM_PKG, PRIVILEGED_SHIM_PKG + INSTALL_CLASS);
+        assertFilterPriority(testComponent, Intent.ACTION_SEARCH, 100);
+        assertFilterPriority(testComponent, Intent.ACTION_VIEW, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_SEND, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_SEND_MULTIPLE, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_SENDTO, 0);
+    }
+
+    /**
+     * Tests the filter priorities for a privileged package are set correctly after update.
+     * <p>
+     * Test various forms of filter equivalency [eg. action, category, scheme and host].
+     * Also, don't allow any filter obtain a higher priority than what was defined on
+     * system image.
+     */
+    public void testPrivilegedAppUpgradePriorities() throws Exception {
+        final ComponentName testComponent =
+                new ComponentName(PRIVILEGED_SHIM_PKG, PRIVILEGED_SHIM_PKG + INSTALL_CLASS);
+        assertFilterPriority(testComponent, Intent.ACTION_VIEW, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_SEND, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_SEND_MULTIPLE, 0);
+        assertFilterPriority(testComponent, Intent.ACTION_SENDTO, 0);
+
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeMatch"),
+                "com.android.cts.action.MATCH", 100);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeMatchMultiple"),
+                "com.android.cts.action.MATCH_MULTIPLE", 150);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeLowerPriority"),
+                "com.android.cts.action.LOWER_PRIORITY", 75);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeActionSubset"),
+                "com.android.cts.action.ACTION_SUB_2", 100);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeCategorySubset"),
+                "com.android.cts.action.CATEGORY_SUB", 100);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeSchemeSubset"),
+                "com.android.cts.action.SCHEME_SUB", "flubber:", 100);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeAuthoritySubset"),
+                "com.android.cts.action.AUTHORITY_SUB", 100);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeNewActivity"),
+                "com.android.cts.action.NEW_ACTIVITY", 0);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeNewAction"),
+                "com.android.cts.action.NEW_ACTION", 0);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeNewCategory"),
+                "com.android.cts.action.NEW_CATEGORY", 0);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeNewScheme"),
+                "com.android.cts.action.NEW_SCHEME", "zowie:", 0);
+        assertFilterPriority(
+                new ComponentName(PRIVILEGED_SHIM_PKG,
+                        PRIVILEGED_SHIM_PKG + ".UpgradeNewAuthority"),
+                "com.android.cts.action.NEW_AUTHORITY", 0);
+    }
+
+    private void assertFilterPriority(ComponentName component, String action, int priority) {
+        assertFilterPriority(component, action, null /*data*/, priority);
+    }
+    private void assertFilterPriority(
+            ComponentName component, String action, String data, int priority) {
+        final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+        final String className = component.getClassName();
+        final Intent intent = new Intent(action);
+        intent.setPackage(component.getPackageName());
+        if (data != null) {
+            intent.setData(Uri.parse(data));
+        }
+        final List<ResolveInfo> entries =
+                pm.queryIntentActivities(intent, PackageManager.GET_RESOLVED_FILTER);
+        assertNotNull(entries);
+        ResolveInfo foundInfo = null;
+        for (ResolveInfo ri : entries) {
+            if (ri.activityInfo.name.equals(className)) {
+                foundInfo = ri;
+                break;
+            }
+        }
+        assertTrue(action + "; didn't find class \"" + className + "\"", foundInfo != null);
+        assertEquals(action + "; wrong priority", priority, foundInfo.filter.getPriority());
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp/AndroidManifest.xml
deleted file mode 100644
index ece4ebe..0000000
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp/AndroidManifest.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.usepermission">
-    <application>
-        <uses-library android:name="android.test.runner" />
-        <activity android:name=".MyActivity" />
-    </application>
-    <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:targetPackage="com.android.cts.usepermission" />
-
-    <!-- Note that WRITE_EXTERNAL_STORAGE implies READ_EXTERNAL_STORAGE;
-         this is a special case. -->
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
-    <!-- Deliberately request WRITE_CONTACTS but *not* READ_CONTACTS -->
-    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
-
-    <!-- Request two different permissions within the same group -->
-    <uses-permission android:name="android.permission.SEND_SMS" />
-    <uses-permission android:name="android.permission.RECEIVE_SMS" />
-
-</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp/src/com/android/cts/usepermission/UsePermissionTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp/src/com/android/cts/usepermission/UsePermissionTest.java
deleted file mode 100644
index 8d3b976..0000000
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp/src/com/android/cts/usepermission/UsePermissionTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.usepermission;
-
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirReadWriteAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertMediaNoAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertMediaReadWriteAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.logCommand;
-
-import android.content.pm.PackageManager;
-import android.os.Environment;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiSelector;
-import android.test.InstrumentationTestCase;
-
-public class UsePermissionTest extends InstrumentationTestCase {
-    private static final String TAG = "UsePermissionTest";
-
-    private UiDevice mDevice;
-    private MyActivity mActivity;
-
-    public void testFail() throws Exception {
-        fail("Expected");
-    }
-
-    public void testKill() throws Exception {
-        android.os.Process.killProcess(android.os.Process.myPid());
-    }
-
-    public void testDefault() throws Exception {
-        logCommand("/system/bin/cat", "/proc/self/mountinfo");
-
-        // New permission model is denied by default
-        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE));
-        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE));
-        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
-        assertDirNoAccess(Environment.getExternalStorageDirectory());
-        assertDirReadWriteAccess(getInstrumentation().getContext().getExternalCacheDir());
-        assertMediaNoAccess(getInstrumentation().getContext().getContentResolver());
-    }
-
-    public void testGranted() throws Exception {
-        logCommand("/system/bin/cat", "/proc/self/mountinfo");
-
-        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE));
-        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE));
-        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
-        assertDirReadWriteAccess(Environment.getExternalStorageDirectory());
-        assertDirReadWriteAccess(getInstrumentation().getContext().getExternalCacheDir());
-        assertMediaReadWriteAccess(getInstrumentation().getContext().getContentResolver());
-    }
-
-    public void testInteractiveGrant() throws Exception {
-        logCommand("/system/bin/cat", "/proc/self/mountinfo");
-
-        // Start out without permission
-        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE));
-        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE));
-        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
-        assertDirNoAccess(Environment.getExternalStorageDirectory());
-        assertDirReadWriteAccess(getInstrumentation().getContext().getExternalCacheDir());
-        assertMediaNoAccess(getInstrumentation().getContext().getContentResolver());
-
-        // Go through normal grant flow
-        mDevice = UiDevice.getInstance(getInstrumentation());
-        mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
-                MyActivity.class, null);
-        mDevice.waitForIdle();
-
-        mActivity.requestPermissions(new String[] {
-                android.Manifest.permission.READ_EXTERNAL_STORAGE,
-                android.Manifest.permission.WRITE_EXTERNAL_STORAGE }, 42);
-        mDevice.waitForIdle();
-
-        new UiObject(new UiSelector()
-                .resourceId("com.android.packageinstaller:id/permission_allow_button")).click();
-        mDevice.waitForIdle();
-
-        MyActivity.Result result = mActivity.getResult();
-        assertEquals(42, result.requestCode);
-        assertEquals(android.Manifest.permission.READ_EXTERNAL_STORAGE, result.permissions[0]);
-        assertEquals(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, result.permissions[1]);
-        assertEquals(PackageManager.PERMISSION_GRANTED, result.grantResults[0]);
-        assertEquals(PackageManager.PERMISSION_GRANTED, result.grantResults[1]);
-
-        logCommand("/system/bin/cat", "/proc/self/mountinfo");
-
-        // We should have permission now!
-        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE));
-        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE));
-        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
-        assertDirReadWriteAccess(Environment.getExternalStorageDirectory());
-        assertDirReadWriteAccess(getInstrumentation().getContext().getExternalCacheDir());
-        assertMediaReadWriteAccess(getInstrumentation().getContext().getContentResolver());
-
-        mActivity.finish();
-    }
-
-    public void testRuntimeGroupGrantSpecificity() throws Exception {
-        // Start out without permission
-        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.WRITE_CONTACTS));
-        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.READ_CONTACTS));
-
-        // Go through normal grant flow
-        mDevice = UiDevice.getInstance(getInstrumentation());
-        mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
-                MyActivity.class, null);
-        mDevice.waitForIdle();
-
-        // request only one permission from the 'contacts' permission group
-        mActivity.requestPermissions(new String[] {
-                android.Manifest.permission.WRITE_CONTACTS }, 43);
-        mDevice.waitForIdle();
-
-        new UiObject(new UiSelector()
-                .resourceId("com.android.packageinstaller:id/permission_allow_button")).click();
-        mDevice.waitForIdle();
-
-        MyActivity.Result result = mActivity.getResult();
-        assertEquals(43, result.requestCode);
-        assertEquals(android.Manifest.permission.WRITE_CONTACTS, result.permissions[0]);
-        assertEquals(PackageManager.PERMISSION_GRANTED, result.grantResults[0]);
-
-        // We should have only the explicitly requested permission from this group
-        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.WRITE_CONTACTS));
-        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.READ_CONTACTS));
-
-        mActivity.finish();
-    }
-
-    public void testRuntimeGroupGrantExpansion() throws Exception {
-        // Start out without permission
-        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.RECEIVE_SMS));
-        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.SEND_SMS));
-
-        // Go through normal grant flow
-        mDevice = UiDevice.getInstance(getInstrumentation());
-        mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
-                MyActivity.class, null);
-        mDevice.waitForIdle();
-
-        // request only one permission from the 'SMS' permission group at runtime,
-        // but two from this group are <uses-permission> in the manifest
-        mActivity.requestPermissions(new String[] {
-                android.Manifest.permission.RECEIVE_SMS }, 44);
-        mDevice.waitForIdle();
-
-        new UiObject(new UiSelector()
-                .resourceId("com.android.packageinstaller:id/permission_allow_button")).click();
-        mDevice.waitForIdle();
-
-        MyActivity.Result result = mActivity.getResult();
-        assertEquals(44, result.requestCode);
-        assertEquals(android.Manifest.permission.RECEIVE_SMS, result.permissions[0]);
-        assertEquals(PackageManager.PERMISSION_GRANTED, result.grantResults[0]);
-
-        // We should now have been granted both of the permissions from this group
-        // that are mentioned in our manifest
-        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.RECEIVE_SMS));
-        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
-                .checkSelfPermission(android.Manifest.permission.SEND_SMS));
-
-        mActivity.finish();
-    }
-}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk
similarity index 81%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
copy to hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk
index 4630f1f..9ee5921 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk
@@ -19,13 +19,14 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctsdeviceutil ctstestrunner ub-uiautomator
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-    ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
+    ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java \
+    ../UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionActivity.java \
+    ../UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
 
-LOCAL_PACKAGE_NAME := CtsUsePermissionApp
+LOCAL_PACKAGE_NAME := CtsUsePermissionApp22
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/AndroidManifest.xml
new file mode 100644
index 0000000..ebb0cbf
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/AndroidManifest.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.usepermission">
+
+    <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22" />
+
+    <!-- Request two different permissions within the same group -->
+    <uses-permission android:name="android.permission.SEND_SMS" />
+    <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+    <!-- Contacts -->
+    <!-- Deliberately request WRITE_CONTACTS but *not* READ_CONTACTS -->
+    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+
+    <!-- Calendar -->
+    <uses-permission android:name="android.permission.READ_CALENDAR"/>
+    <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
+
+    <!-- SMS -->
+    <uses-permission android:name="android.permission.SEND_SMS"/>
+    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
+    <uses-permission android:name="android.permission.READ_SMS"/>
+    <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/>
+    <uses-permission android:name="android.permission.RECEIVE_MMS"/>
+    <uses-permission android:name="android.permission.READ_CELL_BROADCASTS"/>
+
+    <!-- Storage -->
+    <!-- Special case: WRITE_EXTERNAL_STORAGE implies READ_EXTERNAL_STORAGE -->
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+    <!-- Location -->
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+
+    <!-- Phone -->
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.CALL_PHONE"/>
+    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
+    <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
+    <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"/>
+    <uses-permission android:name="android.permission.USE_SIP"/>
+    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
+
+    <!-- Phone -->
+    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+
+    <!-- Camera -->
+    <uses-permission android:name="android.permission.CAMERA"/>
+
+    <!-- Body Sensors -->
+    <uses-permission android:name="android.permission.BODY_SENSORS"/>
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name=".BasePermissionActivity" />
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.usepermission" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/UsePermissionTest22.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/UsePermissionTest22.java
new file mode 100644
index 0000000..1478015
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/src/com/android/cts/usepermission/UsePermissionTest22.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.usepermission;
+
+import static junit.framework.Assert.assertEquals;
+
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoAccess;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirReadWriteAccess;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertMediaNoAccess;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertMediaReadWriteAccess;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPaths;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.logCommand;
+import static junit.framework.Assert.assertTrue;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Environment;
+import android.os.Process;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Arrays;
+
+/**
+ * Runtime permission behavior tests for apps targeting API 22
+ */
+public class UsePermissionTest22 extends BasePermissionsTest {
+    private static final int REQUEST_CODE_PERMISSIONS = 42;
+
+    @Test
+    public void testCompatDefault() throws Exception {
+        final Context context = getInstrumentation().getContext();
+        logCommand("/system/bin/cat", "/proc/self/mountinfo");
+
+        // Legacy permission model is granted by default
+        assertEquals(PackageManager.PERMISSION_GRANTED,
+                context.checkPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE,
+                        Process.myPid(), Process.myUid()));
+        assertEquals(PackageManager.PERMISSION_GRANTED,
+                context.checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                        Process.myPid(), Process.myUid()));
+        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
+        assertDirReadWriteAccess(Environment.getExternalStorageDirectory());
+        for (File path : getAllPackageSpecificPaths(context)) {
+            if (path != null) {
+                assertDirReadWriteAccess(path);
+            }
+        }
+        assertMediaReadWriteAccess(getInstrumentation().getContext().getContentResolver());
+    }
+
+    @Test
+    public void testCompatRevoked_part1() throws Exception {
+        // Revoke the permission
+        revokePermissions(new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, true);
+    }
+
+    @Test
+    public void testCompatRevoked_part2() throws Exception {
+        final Context context = getInstrumentation().getContext();
+        logCommand("/system/bin/cat", "/proc/self/mountinfo");
+
+        // Legacy permission model appears granted, but storage looks and
+        // behaves like it's ejected
+        assertEquals(PackageManager.PERMISSION_GRANTED,
+                context.checkPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE,
+                        Process.myPid(), Process.myUid()));
+        assertEquals(PackageManager.PERMISSION_GRANTED,
+                context.checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                        Process.myPid(), Process.myUid()));
+        assertEquals(Environment.MEDIA_UNMOUNTED, Environment.getExternalStorageState());
+
+        assertDirNoAccess(Environment.getExternalStorageDirectory());
+        for (File dir : getAllPackageSpecificPaths(context)) {
+            if (dir != null) {
+                assertDirNoAccess(dir);
+            }
+        }
+        assertMediaNoAccess(getInstrumentation().getContext().getContentResolver(), true);
+
+        // Just to be sure, poke explicit path
+        assertDirNoAccess(new File(Environment.getExternalStorageDirectory(),
+                "/Android/data/" + getInstrumentation().getContext().getPackageName()));
+    }
+
+    @Test
+    public void testAllPermissionsGrantedByDefault() throws Exception {
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.SEND_SMS));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.RECEIVE_SMS));
+        // The APK does not request because of other tests Manifest.permission.READ_CONTACTS
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CONTACTS));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CALENDAR));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.SEND_SMS));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.RECEIVE_SMS));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_SMS));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.RECEIVE_WAP_PUSH));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.RECEIVE_MMS));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission("android.permission.READ_CELL_BROADCASTS"));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_PHONE_STATE));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.CALL_PHONE));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_CALL_LOG));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CALL_LOG));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.ADD_VOICEMAIL));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.USE_SIP));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.PROCESS_OUTGOING_CALLS));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.CAMERA));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.BODY_SENSORS));
+    }
+
+    @Test
+    public void testNoRuntimePrompt() throws Exception {
+        // Request the permission and do nothing
+        BasePermissionActivity.Result result = requestPermissions(
+                new String[] {Manifest.permission.SEND_SMS}, REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class, null);
+
+        // Expect the permission is not granted
+        assertEquals(REQUEST_CODE_PERMISSIONS, result.requestCode);
+        assertTrue(Arrays.equals(result.permissions, new String[0]));
+        assertTrue(Arrays.equals(result.grantResults, new int[0]));
+    }
+
+    @Test
+    public void testRevokePropagatedOnUpgradeOldToNewModel_part1() throws Exception {
+        // Revoke a permission
+        revokePermissions(new String[] {Manifest.permission.WRITE_CALENDAR}, true);
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk
similarity index 94%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
copy to hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk
index 4630f1f..c8e05c5 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk
@@ -19,13 +19,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctsdeviceutil ctstestrunner ub-uiautomator
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
 
-LOCAL_PACKAGE_NAME := CtsUsePermissionApp
+LOCAL_PACKAGE_NAME := CtsUsePermissionApp23
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/AndroidManifest.xml
new file mode 100644
index 0000000..71eadaa
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/AndroidManifest.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.usepermission">
+
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23" />
+
+    <!-- Request two different permissions within the same group -->
+    <uses-permission android:name="android.permission.SEND_SMS" />
+    <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+    <!-- Contacts -->
+    <!-- Deliberately request WRITE_CONTACTS but *not* READ_CONTACTS -->
+    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+
+    <!-- Calendar -->
+    <uses-permission android:name="android.permission.READ_CALENDAR"/>
+    <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
+
+    <!-- SMS -->
+    <uses-permission android:name="android.permission.SEND_SMS"/>
+    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
+    <uses-permission android:name="android.permission.READ_SMS"/>
+    <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/>
+    <uses-permission android:name="android.permission.RECEIVE_MMS"/>
+    <uses-permission android:name="android.permission.READ_CELL_BROADCASTS"/>
+
+    <!-- Storage -->
+    <!-- Special case: WRITE_EXTERNAL_STORAGE implies READ_EXTERNAL_STORAGE -->
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+    <!-- Location -->
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+
+    <!-- Phone -->
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.CALL_PHONE"/>
+    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
+    <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
+    <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"/>
+    <uses-permission android:name="android.permission.USE_SIP"/>
+    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
+
+    <!-- Phone -->
+    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+
+    <!-- Camera -->
+    <uses-permission android:name="android.permission.CAMERA"/>
+
+    <!-- Body Sensors -->
+    <uses-permission android:name="android.permission.BODY_SENSORS"/>
+
+    <application>
+        <activity android:name="com.android.cts.usepermission.BasePermissionActivity" />
+    </application>
+
+    <instrumentation
+            android:name="android.support.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.cts.usepermission" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp/src/com/android/cts/usepermission/MyActivity.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionActivity.java
similarity index 78%
rename from hostsidetests/appsecurity/test-apps/UsePermissionApp/src/com/android/cts/usepermission/MyActivity.java
rename to hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionActivity.java
index 5af3886..cacfa80 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp/src/com/android/cts/usepermission/MyActivity.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionActivity.java
@@ -20,11 +20,15 @@
 import android.os.Bundle;
 import android.view.WindowManager;
 
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
 
-public class MyActivity extends Activity {
+public class BasePermissionActivity extends Activity {
+    private static final long OPERATION_TIMEOUT_MILLIS = 5000;
+
     private final SynchronousQueue<Result> mResult = new SynchronousQueue<>();
+    private final CountDownLatch mOnCreateSync = new CountDownLatch(1);
 
     public static class Result {
         public final int requestCode;
@@ -45,6 +49,8 @@
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                 | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+
+        mOnCreateSync.countDown();
     }
 
     @Override
@@ -57,9 +63,17 @@
         }
     }
 
+    public void waitForOnCreate() {
+        try {
+            mOnCreateSync.await(OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     public Result getResult() {
         try {
-            return mResult.take();
+            return mResult.poll(OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
new file mode 100644
index 0000000..5b7dfb6
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
@@ -0,0 +1,297 @@
+/*
+ * 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 com.android.cts.usepermission;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiSelector;
+import android.util.ArrayMap;
+import android.widget.Switch;
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+import java.util.Map;
+
+@RunWith(AndroidJUnit4.class)
+public abstract class BasePermissionsTest {
+    private static final String PLATFORM_PACKAGE_NAME = "android";
+
+    private static final long IDLE_TIMEOUT_MILLIS = 500;
+    private static final long GLOBAL_TIMEOUT_MILLIS = 5000;
+
+    private static Map<String, String> sPermissionToLabelResNameMap = new ArrayMap<>();
+    static {
+        // Contacts
+        sPermissionToLabelResNameMap.put(Manifest.permission.READ_CONTACTS,
+                "@android:string/permgrouplab_contacts");
+        sPermissionToLabelResNameMap.put(Manifest.permission.WRITE_CONTACTS,
+                "@android:string/permgrouplab_contacts");
+        // Calendar
+        sPermissionToLabelResNameMap.put(Manifest.permission.READ_CALENDAR,
+                "@android:string/permgrouplab_calendar");
+        sPermissionToLabelResNameMap.put(Manifest.permission.WRITE_CALENDAR,
+                "@android:string/permgrouplab_calendar");
+        // SMS
+        sPermissionToLabelResNameMap.put(Manifest.permission.SEND_SMS,
+                "@android:string/permgrouplab_sms");
+        sPermissionToLabelResNameMap.put(Manifest.permission.RECEIVE_SMS,
+                "@android:string/permgrouplab_sms");
+        sPermissionToLabelResNameMap.put(Manifest.permission.READ_SMS,
+                "@android:string/permgrouplab_sms");
+        sPermissionToLabelResNameMap.put(Manifest.permission.RECEIVE_WAP_PUSH,
+                "@android:string/permgrouplab_sms");
+        sPermissionToLabelResNameMap.put(Manifest.permission.RECEIVE_MMS,
+                "@android:string/permgrouplab_sms");
+        sPermissionToLabelResNameMap.put("android.permission.READ_CELL_BROADCASTS",
+                "@android:string/permgrouplab_sms");
+        // Storage
+        sPermissionToLabelResNameMap.put(Manifest.permission.READ_EXTERNAL_STORAGE,
+                "@android:string/permgrouplab_storage");
+        sPermissionToLabelResNameMap.put(Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                "@android:string/permgrouplab_storage");
+        // Location
+        sPermissionToLabelResNameMap.put(Manifest.permission.ACCESS_FINE_LOCATION,
+                "@android:string/permgrouplab_location");
+        sPermissionToLabelResNameMap.put(Manifest.permission.ACCESS_COARSE_LOCATION,
+                "@android:string/permgrouplab_location");
+        // Phone
+        sPermissionToLabelResNameMap.put(Manifest.permission.READ_PHONE_STATE,
+                "@android:string/permgrouplab_phone");
+        sPermissionToLabelResNameMap.put(Manifest.permission.CALL_PHONE,
+                "@android:string/permgrouplab_phone");
+        sPermissionToLabelResNameMap.put("android.permission.ACCESS_IMS_CALL_SERVICE",
+                "@android:string/permgrouplab_phone");
+        sPermissionToLabelResNameMap.put(Manifest.permission.READ_CALL_LOG,
+                "@android:string/permgrouplab_phone");
+        sPermissionToLabelResNameMap.put(Manifest.permission.WRITE_CALL_LOG,
+                "@android:string/permgrouplab_phone");
+        sPermissionToLabelResNameMap.put(Manifest.permission.ADD_VOICEMAIL,
+                "@android:string/permgrouplab_phone");
+        sPermissionToLabelResNameMap.put(Manifest.permission.USE_SIP,
+                "@android:string/permgrouplab_phone");
+        sPermissionToLabelResNameMap.put(Manifest.permission.PROCESS_OUTGOING_CALLS,
+                "@android:string/permgrouplab_phone");
+        // Microphone
+        sPermissionToLabelResNameMap.put(Manifest.permission.RECORD_AUDIO,
+                "@android:string/permgrouplab_microphone");
+        // Camera
+        sPermissionToLabelResNameMap.put(Manifest.permission.CAMERA,
+                "@android:string/permgrouplab_camera");
+        // Body sensors
+        sPermissionToLabelResNameMap.put(Manifest.permission.BODY_SENSORS,
+                "@android:string/permgrouplab_sensors");
+    }
+
+    private Context mContext;
+    private Resources mPlatformResources;
+
+    protected static Instrumentation getInstrumentation() {
+        return InstrumentationRegistry.getInstrumentation();
+    }
+
+    protected static void assertPermissionRequestResult(BasePermissionActivity.Result result,
+            int requestCode, String[] permissions, boolean[] granted) {
+        assertEquals(requestCode, result.requestCode);
+        for (int i = 0; i < permissions.length; i++) {
+            assertEquals(permissions[i], result.permissions[i]);
+            assertEquals(granted[i] ? PackageManager.PERMISSION_GRANTED
+                    : PackageManager.PERMISSION_DENIED, result.grantResults[i]);
+
+        }
+    }
+
+    protected static UiDevice getUiDevice() {
+        return UiDevice.getInstance(getInstrumentation());
+    }
+
+    protected static Activity launchActivity(String packageName,
+            Class<?> clazz, Bundle extras) {
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClassName(packageName, clazz.getName());
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        if (extras != null) {
+            intent.putExtras(extras);
+        }
+        Activity activity = getInstrumentation().startActivitySync(intent);
+        getInstrumentation().waitForIdleSync();
+
+        return activity;
+    }
+
+    @Before
+    public void beforeTest() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        try {
+            Context platformContext = mContext.createPackageContext(PLATFORM_PACKAGE_NAME, 0);
+            mPlatformResources = platformContext.getResources();
+        } catch (PackageManager.NameNotFoundException e) {
+            /* cannot happen */
+        }
+    }
+
+    protected BasePermissionActivity.Result requestPermissions(
+            String[] permissions, int requestCode, Class<?> clazz, Runnable postRequestAction)
+            throws Exception {
+        // Start an activity
+        BasePermissionActivity activity = (BasePermissionActivity) launchActivity(
+                getInstrumentation().getTargetContext().getPackageName(), clazz, null);
+
+        activity.waitForOnCreate();
+
+        // Request the permissions
+        activity.requestPermissions(permissions, requestCode);
+
+        // Define a more conservative idle criteria
+        getInstrumentation().getUiAutomation().waitForIdle(
+                IDLE_TIMEOUT_MILLIS, GLOBAL_TIMEOUT_MILLIS);
+
+        // Perform the post-request action
+        if (postRequestAction != null) {
+            postRequestAction.run();
+        }
+
+        BasePermissionActivity.Result result = activity.getResult();
+        activity.finish();
+        return result;
+    }
+
+    protected void clickAllowButton() throws Exception {
+        getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.packageinstaller:id/permission_allow_button")).click();
+    }
+
+    protected void clickDenyButton() throws Exception {
+        getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.packageinstaller:id/permission_deny_button")).click();
+    }
+
+    protected void clickDontAskAgainCheckbox() throws Exception {
+        getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.packageinstaller:id/do_not_ask_checkbox")).click();
+    }
+
+    protected void grantPermission(String permission) throws Exception {
+        grantPermissions(new String[]{permission});
+    }
+
+    protected void grantPermissions(String[] permissions) throws Exception {
+        setPermissionGrantState(permissions, true, false);
+    }
+
+    protected void revokePermission(String permission) throws Exception {
+        revokePermissions(new String[] {permission}, false);
+    }
+
+    protected void revokePermissions(String[] permissions, boolean legacyApp) throws Exception {
+        setPermissionGrantState(permissions, false, legacyApp);
+    }
+
+    private void setPermissionGrantState(String[] permissions, boolean granted,
+            boolean legacyApp) throws Exception {
+        getUiDevice().pressBack();
+        getUiDevice().waitForIdle();
+        getUiDevice().pressBack();
+        getUiDevice().waitForIdle();
+
+        // Open the app details settings
+        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        intent.setData(Uri.parse("package:" + mContext.getPackageName()));
+        mContext.startActivity(intent);
+
+        getUiDevice().waitForIdle();
+
+        // Open the permissions UI
+        UiObject permissionItem = getUiDevice().findObject(new UiSelector().text("Permissions"));
+        permissionItem.click();
+
+        getUiDevice().waitForIdle();
+
+        for (String permission : permissions) {
+            // Find the permission toggle
+            String permissionLabel = getPermissionLabel(permission);
+
+            UiObject2 toggleSwitch = null;
+            UiObject2 current = getUiDevice().findObject(By.text(permissionLabel));
+            Assert.assertNotNull("Permission should be present");
+
+            while (toggleSwitch == null) {
+                UiObject2 parent = current.getParent();
+                if (parent == null) {
+                    fail("Cannot find permission list item");
+                }
+                toggleSwitch = current.findObject(By.clazz(Switch.class));
+                current = parent;
+            }
+
+            final boolean wasGranted = toggleSwitch.isChecked();
+            if (granted != wasGranted) {
+                // Toggle the permission
+                toggleSwitch.click();
+
+                getUiDevice().waitForIdle();
+
+                if (wasGranted && legacyApp) {
+                    String packageName = getInstrumentation().getContext().getPackageManager()
+                            .getPermissionControllerPackageName();
+                    String resIdName = "com.android.packageinstaller"
+                            + ":string/grant_dialog_button_deny_anyway";
+                    Resources resources = getInstrumentation().getContext()
+                            .createPackageContext(packageName, 0).getResources();
+                    final int confirmResId = resources.getIdentifier(resIdName, null, null);
+                    String confirmTitle = resources.getString(confirmResId);
+                    UiObject denyAnyway = getUiDevice().findObject(new UiSelector()
+                            .text(confirmTitle.toUpperCase()));
+                    denyAnyway.click();
+
+                    getUiDevice().waitForIdle();
+                }
+            }
+        }
+
+        getUiDevice().pressBack();
+        getUiDevice().waitForIdle();
+        getUiDevice().pressBack();
+        getUiDevice().waitForIdle();
+    }
+
+    private String getPermissionLabel(String permission) throws Exception {
+        String labelResName = sPermissionToLabelResNameMap.get(permission);
+        assertNotNull("Unknown permisison " + permission, labelResName);
+        final int resourceId = mPlatformResources.getIdentifier(labelResName, null, null);
+        return mPlatformResources.getString(resourceId);
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
new file mode 100644
index 0000000..9908a45
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.usepermission;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoAccess;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirReadWriteAccess;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertMediaNoAccess;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertMediaReadWriteAccess;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.logCommand;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.os.Environment;
+import org.junit.Test;
+
+/**
+ * Runtime permission behavior tests for apps targeting API 23
+ */
+public class UsePermissionTest23 extends BasePermissionsTest {
+    private static final int REQUEST_CODE_PERMISSIONS = 42;
+
+    public void testFail() throws Exception {
+        fail("Expected");
+    }
+
+    @Test
+    public void testKill() throws Exception {
+        android.os.Process.killProcess(android.os.Process.myPid());
+    }
+
+    @Test
+    public void testDefault() throws Exception {
+        logCommand("/system/bin/cat", "/proc/self/mountinfo");
+
+        // New permission model is denied by default
+        assertAllPermissionsRevoked();
+
+        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
+        assertDirNoAccess(Environment.getExternalStorageDirectory());
+        assertDirReadWriteAccess(getInstrumentation().getContext().getExternalCacheDir());
+        assertMediaNoAccess(getInstrumentation().getContext().getContentResolver(), false);
+    }
+
+    @Test
+    public void testGranted() throws Exception {
+        logCommand("/system/bin/cat", "/proc/self/mountinfo");
+        grantPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE));
+        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
+        assertDirReadWriteAccess(Environment.getExternalStorageDirectory());
+        assertDirReadWriteAccess(getInstrumentation().getContext().getExternalCacheDir());
+        assertMediaReadWriteAccess(getInstrumentation().getContext().getContentResolver());
+    }
+
+    @Test
+    public void testInteractiveGrant() throws Exception {
+        logCommand("/system/bin/cat", "/proc/self/mountinfo");
+
+        // Start out without permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE));
+        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
+        assertDirNoAccess(Environment.getExternalStorageDirectory());
+        assertDirReadWriteAccess(getInstrumentation().getContext().getExternalCacheDir());
+        assertMediaNoAccess(getInstrumentation().getContext().getContentResolver(), false);
+
+        // Go through normal grant flow
+        BasePermissionActivity.Result result = requestPermissions(new String[] {
+                Manifest.permission.READ_EXTERNAL_STORAGE,
+                Manifest.permission.WRITE_EXTERNAL_STORAGE},
+                REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class,
+                () -> {
+                    try {
+                        clickAllowButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        assertEquals(REQUEST_CODE_PERMISSIONS, result.requestCode);
+        assertEquals(Manifest.permission.READ_EXTERNAL_STORAGE, result.permissions[0]);
+        assertEquals(Manifest.permission.WRITE_EXTERNAL_STORAGE, result.permissions[1]);
+        assertEquals(PackageManager.PERMISSION_GRANTED, result.grantResults[0]);
+        assertEquals(PackageManager.PERMISSION_GRANTED, result.grantResults[1]);
+
+        logCommand("/system/bin/cat", "/proc/self/mountinfo");
+
+        // We should have permission now!
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE));
+        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
+        assertDirReadWriteAccess(Environment.getExternalStorageDirectory());
+        assertDirReadWriteAccess(getInstrumentation().getContext().getExternalCacheDir());
+        assertMediaReadWriteAccess(getInstrumentation().getContext().getContentResolver());
+    }
+
+    @Test
+    public void testRuntimeGroupGrantSpecificity() throws Exception {
+        // Start out without permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CONTACTS));
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_CONTACTS));
+
+        String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS};
+
+        // request only one permission from the 'contacts' permission group
+        BasePermissionActivity.Result result = requestPermissions(permissions,
+                REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class,
+                () -> {
+                    try {
+                        clickAllowButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Expect the permission is granted
+        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
+                permissions, new boolean[] {true});
+
+        // Make sure no undeclared as used permissions are granted
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_CONTACTS));
+    }
+
+    @Test
+    public void testRuntimeGroupGrantExpansion() throws Exception {
+        // Start out without permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.RECEIVE_SMS));
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.SEND_SMS));
+
+        String[] permissions = new String[] {Manifest.permission.RECEIVE_SMS};
+
+        // request only one permission from the 'SMS' permission group at runtime,
+        // but two from this group are <uses-permission> in the manifest
+        // request only one permission from the 'contacts' permission group
+        BasePermissionActivity.Result result = requestPermissions(permissions,
+                REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class,
+                () -> {
+                    try {
+                        clickAllowButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Expect the permission is granted
+        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
+                permissions, new boolean[] {true});
+
+        // We should now have been granted both of the permissions from this group.
+        // NOTE: This is undesired behavior which will be fixed for target API 24.
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.SEND_SMS));
+    }
+
+    @Test
+    public void testCancelledPermissionRequest() throws Exception {
+        // Make sure we don't have the permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CONTACTS));
+
+        String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS};
+
+        // Request the permission and cancel the request
+        BasePermissionActivity.Result result = requestPermissions(permissions,
+                REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class,
+                () -> {
+                    try {
+                        clickDenyButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Expect the permission is not granted
+        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
+                permissions, new boolean[] {false});
+    }
+
+    @Test
+    public void testRequestGrantedPermission() throws Exception {
+        // Make sure we don't have the permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CONTACTS));
+
+        String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS};
+
+        // Request the permission and allow it
+        BasePermissionActivity.Result firstResult = requestPermissions(permissions,
+                REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class, () -> {
+                    try {
+                        clickAllowButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Expect the permission is granted
+        assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS,
+                permissions, new boolean[] {true});
+
+        // Request the permission and do nothing
+        BasePermissionActivity.Result secondResult = requestPermissions(new String[] {
+                Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_PERMISSIONS + 1,
+                BasePermissionActivity.class, null);
+
+        // Expect the permission is granted
+        assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1,
+                permissions, new boolean[] {true});
+    }
+
+    @Test
+    public void testDenialWithPrejudice() throws Exception {
+        // Make sure we don't have the permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CONTACTS));
+
+        String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS};
+
+        // Request the permission and deny it
+        BasePermissionActivity.Result firstResult = requestPermissions(
+                permissions, REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class, () -> {
+                    try {
+                        clickDenyButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Expect the permission is not granted
+        assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS,
+                permissions, new boolean[] {false});
+
+        // Request the permission and choose don't ask again
+        BasePermissionActivity.Result secondResult = requestPermissions(new String[] {
+                        Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_PERMISSIONS + 1,
+                BasePermissionActivity.class, () -> {
+                    try {
+                        clickDontAskAgainCheckbox();
+                        clickDenyButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Expect the permission is not granted
+        assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1,
+                permissions, new boolean[] {false});
+
+        // Request the permission and do nothing
+        BasePermissionActivity.Result thirdResult = requestPermissions(new String[] {
+                        Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_PERMISSIONS + 2,
+                BasePermissionActivity.class, null);
+
+        // Expect the permission is not granted
+        assertPermissionRequestResult(thirdResult, REQUEST_CODE_PERMISSIONS + 2,
+                permissions, new boolean[] {false});
+    }
+
+    @Test
+    public void testRevokeAffectsWholeGroup_part1() throws Exception {
+        // Grant the group
+        grantPermission(Manifest.permission.READ_CALENDAR);
+
+        // Make sure we have the permissions
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CALENDAR));
+
+        // Revoke the group
+        revokePermission(Manifest.permission.READ_CALENDAR);
+
+        // We just committed a suicide by revoking the permission. See part2 below...
+    }
+
+    public void testRevokeAffectsWholeGroup_part2() throws Exception {
+        // Make sure we don't have the permissions
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CALENDAR));
+    }
+
+    @Test
+    public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part1() throws Exception {
+        // Make sure we don't have the permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+
+        String[] permissions = new String[] {Manifest.permission.READ_CALENDAR};
+
+        // Request the permission and deny it
+        BasePermissionActivity.Result firstResult = requestPermissions(
+                permissions, REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class, () -> {
+                    try {
+                        clickDenyButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Expect the permission is not granted
+        assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS,
+                permissions, new boolean[] {false});
+
+        // Request the permission and choose don't ask again
+        BasePermissionActivity.Result secondResult = requestPermissions(new String[] {
+                        Manifest.permission.READ_CALENDAR}, REQUEST_CODE_PERMISSIONS + 1,
+                BasePermissionActivity.class, () -> {
+                    try {
+                        clickDontAskAgainCheckbox();
+                        clickDenyButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Expect the permission is not granted
+        assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1,
+                permissions, new boolean[] {false});
+
+        // Clear the denial with prejudice
+        grantPermission(Manifest.permission.READ_CALENDAR);
+        revokePermission(Manifest.permission.READ_CALENDAR);
+
+        // We just committed a suicide by revoking the permission. See part2 below...
+    }
+
+    @Test
+    public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part2() throws Exception {
+        // Make sure we don't have the permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+
+        // Request the permission and allow it
+        BasePermissionActivity.Result thirdResult = requestPermissions(new String[] {
+                        Manifest.permission.READ_CALENDAR}, REQUEST_CODE_PERMISSIONS + 2,
+                BasePermissionActivity.class, () -> {
+                    try {
+                        clickAllowButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Make sure the permission is granted
+        assertPermissionRequestResult(thirdResult, REQUEST_CODE_PERMISSIONS + 2,
+                new String[] {Manifest.permission.READ_CALENDAR}, new boolean[] {true});
+    }
+
+    @Test
+    public void testRequestNonRuntimePermission() throws Exception {
+        // Make sure we don't have the permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.BIND_PRINT_SERVICE));
+
+        String[] permissions = new String[] {Manifest.permission.BIND_PRINT_SERVICE};
+
+        // Request the permission and do nothing
+        BasePermissionActivity.Result result = requestPermissions(permissions,
+                REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, null);
+
+        // Expect the permission is not granted
+        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
+                permissions, new boolean[] {false});
+    }
+
+    @Test
+    public void testRequestNonExistentPermission() throws Exception {
+        // Make sure we don't have the permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission("permission.does.not.exist"));
+
+        String[] permissions = new String[] {"permission.does.not.exist"};
+
+        // Request the permission and do nothing
+        BasePermissionActivity.Result result = requestPermissions(permissions,
+                REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, null);
+
+        // Expect the permission is not granted
+        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
+                permissions, new boolean[] {false});
+    }
+
+    @Test
+    public void testRequestPermissionFromTwoGroups() throws Exception {
+        // Make sure we don't have the permissions
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CONTACTS));
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.WRITE_CALENDAR));
+
+        String[] permissions = new String[] {
+                Manifest.permission.WRITE_CONTACTS,
+                Manifest.permission.WRITE_CALENDAR
+        };
+
+        // Request the permission and do nothing
+        BasePermissionActivity.Result result = requestPermissions(permissions,
+                REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, () -> {
+            try {
+                clickAllowButton();
+                getUiDevice().waitForIdle();
+                clickAllowButton();
+                getUiDevice().waitForIdle();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+        // Expect the permission is not granted
+        assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS,
+                permissions, new boolean[] {true, true});
+    }
+
+    @Test
+    public void testNoResidualPermissionsOnUninstall_part1() throws Exception {
+        // Grant all permissions
+        grantPermissions(new String[] {
+                Manifest.permission.WRITE_CALENDAR,
+                Manifest.permission.WRITE_CONTACTS,
+                Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                Manifest.permission.READ_SMS,
+                Manifest.permission.CALL_PHONE,
+                Manifest.permission.RECORD_AUDIO,
+                Manifest.permission.BODY_SENSORS,
+                Manifest.permission.ACCESS_COARSE_LOCATION,
+                Manifest.permission.CAMERA
+        });
+    }
+
+    @Test
+    public void testNoResidualPermissionsOnUninstall_part2() throws Exception {
+        // Make no permissions are granted after uninstalling and installing the app
+        assertAllPermissionsRevoked();
+    }
+
+    @Test
+    public void testRevokePropagatedOnUpgradeOldToNewModel_part2() throws Exception {
+        assertPermissionsGrantState(new String[] {Manifest.permission.WRITE_CALENDAR},
+                PackageManager.PERMISSION_DENIED);
+    }
+
+
+    public void testRevokePropagatedOnUpgradeNewToNewModel_part1() throws Exception {
+        // Make sure we don't have the permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+
+        // Request the permission and allow it
+        BasePermissionActivity.Result thirdResult = requestPermissions(new String[] {
+                        Manifest.permission.READ_CALENDAR}, REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class, () -> {
+                    try {
+                        clickAllowButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Make sure the permission is granted
+        assertPermissionRequestResult(thirdResult, REQUEST_CODE_PERMISSIONS,
+                new String[] {Manifest.permission.READ_CALENDAR}, new boolean[] {true});
+    }
+
+    public void testRevokePropagatedOnUpgradeNewToNewModel_part2() throws Exception {
+        // Make sure the permission is still granted after the upgrade
+        assertPermissionsGrantState(new String[] {Manifest.permission.READ_CALENDAR},
+                PackageManager.PERMISSION_GRANTED);
+        // Also make sure one of the not granted permissions is still not granted
+        assertPermissionsGrantState(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE},
+                PackageManager.PERMISSION_DENIED);
+    }
+
+    private void assertAllPermissionsRevoked() {
+        assertAllPermissionsGrantState(PackageManager.PERMISSION_DENIED);
+    }
+
+    private void assertAllPermissionsGrantState(int grantState) {
+        assertPermissionsGrantState(new String[] {
+                Manifest.permission.SEND_SMS,
+                Manifest.permission.RECEIVE_SMS,
+                Manifest.permission.RECEIVE_WAP_PUSH,
+                Manifest.permission.RECEIVE_MMS,
+                Manifest.permission.READ_CALENDAR,
+                Manifest.permission.WRITE_CALENDAR,
+                Manifest.permission.WRITE_CONTACTS,
+                Manifest.permission.READ_EXTERNAL_STORAGE,
+                Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                Manifest.permission.READ_SMS,
+                Manifest.permission.READ_PHONE_STATE,
+                Manifest.permission.READ_CALL_LOG,
+                Manifest.permission.WRITE_CALL_LOG,
+                Manifest.permission.ADD_VOICEMAIL,
+                Manifest.permission.CALL_PHONE,
+                Manifest.permission.USE_SIP,
+                Manifest.permission.PROCESS_OUTGOING_CALLS,
+                Manifest.permission.RECORD_AUDIO,
+                Manifest.permission.BODY_SENSORS,
+                Manifest.permission.ACCESS_FINE_LOCATION,
+                Manifest.permission.ACCESS_COARSE_LOCATION,
+                Manifest.permission.CAMERA,
+                Manifest.permission.BODY_SENSORS,
+                "android.permission.READ_CELL_BROADCASTS"
+        }, grantState);
+    }
+
+    private void assertPermissionsGrantState(String[] permissions, int grantState) {
+        for (String permission : permissions) {
+            assertEquals(grantState, getInstrumentation().getContext()
+                    .checkSelfPermission(permission));
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp24/Android.mk
similarity index 79%
copy from hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
copy to hostsidetests/appsecurity/test-apps/UsePermissionApp24/Android.mk
index 4630f1f..d280372 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp24/Android.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2015 The Android Open Source Project
+# 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.
@@ -19,13 +19,13 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctsdeviceutil ctstestrunner ub-uiautomator
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-    ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
+    ../UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionActivity.java \
+    ../UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
 
-LOCAL_PACKAGE_NAME := CtsUsePermissionApp
+LOCAL_PACKAGE_NAME := CtsUsePermissionApp24
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp24/AndroidManifest.xml
similarity index 61%
copy from hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/AndroidManifest.xml
copy to hostsidetests/appsecurity/test-apps/UsePermissionApp24/AndroidManifest.xml
index 253d85d..64f3f34 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp24/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -16,12 +16,17 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.cts.usepermission">
+
+    <!-- Request two different permissions within the same group -->
+    <uses-permission android:name="android.permission.SEND_SMS" />
+    <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
     <application>
-        <uses-library android:name="android.test.runner" />
-        <activity android:name=".MyActivity" />
+        <activity android:name="com.android.cts.usepermission.BasePermissionActivity" />
     </application>
+
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:targetPackage="com.android.cts.usepermission" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+            android:name="android.support.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.cts.usepermission" />
+
 </manifest>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp24/src/com/android/cts/usepermission/UsePermissionTest24.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp24/src/com/android/cts/usepermission/UsePermissionTest24.java
new file mode 100644
index 0000000..f87c67f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp24/src/com/android/cts/usepermission/UsePermissionTest24.java
@@ -0,0 +1,78 @@
+/*
+ * 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 com.android.cts.usepermission;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+/**
+ * Runtime permission behavior tests for apps targeting API 24
+ */
+public class UsePermissionTest24 extends BasePermissionsTest {
+    private static final int REQUEST_CODE_PERMISSIONS = 42;
+
+    @Test
+    public void testOnlyRequestedPermissionsGranted() throws Exception {
+        // Start out without permission
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.RECEIVE_SMS));
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.SEND_SMS));
+
+        String[] firstPermissions = new String[] {Manifest.permission.RECEIVE_SMS};
+
+        // Request only one permission and confirm
+        BasePermissionActivity.Result firstResult = requestPermissions(firstPermissions,
+                REQUEST_CODE_PERMISSIONS,
+                BasePermissionActivity.class,
+                () -> {
+                    try {
+                        clickAllowButton();
+                        getUiDevice().waitForIdle();
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+
+        // Expect the permission is granted
+        assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS,
+                firstPermissions, new boolean[] {true});
+
+        // We should not have the other permission in the group
+        assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.SEND_SMS));
+
+        String[] secondPermissions = new String[] {Manifest.permission.SEND_SMS};
+
+        // Request the other permission which should be auto-granted
+        BasePermissionActivity.Result secondResult = requestPermissions(secondPermissions,
+                REQUEST_CODE_PERMISSIONS + 1, BasePermissionActivity.class, null);
+
+        // Expect the permission is granted
+        assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1,
+                secondPermissions, new boolean[] {true});
+
+        // We now should have both permissions
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.RECEIVE_SMS));
+        assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext()
+                .checkSelfPermission(Manifest.permission.SEND_SMS));
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/Android.mk
deleted file mode 100644
index 8727c43..0000000
--- a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := 21
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctsdeviceutil ctstestrunner ub-uiautomator
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-    ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
-
-LOCAL_PACKAGE_NAME := CtsUsePermissionAppCompat
-
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
-
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/src/com/android/cts/usepermission/UsePermissionCompatTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/src/com/android/cts/usepermission/UsePermissionCompatTest.java
deleted file mode 100644
index 7f21d3400..0000000
--- a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/src/com/android/cts/usepermission/UsePermissionCompatTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.usepermission;
-
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirReadWriteAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertMediaNoAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertMediaReadWriteAccess;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPaths;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.logCommand;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Environment;
-import android.os.Process;
-import android.test.InstrumentationTestCase;
-
-import java.io.File;
-
-public class UsePermissionCompatTest extends InstrumentationTestCase {
-    private static final String TAG = "UsePermissionTest";
-
-    public void testCompatDefault() throws Exception {
-        final Context context = getInstrumentation().getContext();
-        logCommand("/system/bin/cat", "/proc/self/mountinfo");
-
-        // Legacy permission model is granted by default
-        assertEquals(PackageManager.PERMISSION_GRANTED,
-                context.checkPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE,
-                        Process.myPid(), Process.myUid()));
-        assertEquals(PackageManager.PERMISSION_GRANTED,
-                context.checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                        Process.myPid(), Process.myUid()));
-        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
-        assertDirReadWriteAccess(Environment.getExternalStorageDirectory());
-        for (File path : getAllPackageSpecificPaths(context)) {
-            if (path != null) {
-                assertDirReadWriteAccess(path);
-            }
-        }
-        assertMediaReadWriteAccess(getInstrumentation().getContext().getContentResolver());
-    }
-
-    public void testCompatRevoked() throws Exception {
-        final Context context = getInstrumentation().getContext();
-        logCommand("/system/bin/cat", "/proc/self/mountinfo");
-
-        // Legacy permission model appears granted, but storage looks and
-        // behaves like it's ejected
-        assertEquals(PackageManager.PERMISSION_GRANTED,
-                context.checkPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE,
-                        Process.myPid(), Process.myUid()));
-        assertEquals(PackageManager.PERMISSION_GRANTED,
-                context.checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                        Process.myPid(), Process.myUid()));
-        assertEquals(Environment.MEDIA_UNMOUNTED, Environment.getExternalStorageState());
-        assertDirNoAccess(Environment.getExternalStorageDirectory());
-        for (File dir : getAllPackageSpecificPaths(context)) {
-            if (dir != null) {
-                assertDirNoAccess(dir);
-            }
-        }
-        assertMediaNoAccess(getInstrumentation().getContext().getContentResolver());
-
-        // Just to be sure, poke explicit path
-        assertDirNoAccess(new File(Environment.getExternalStorageDirectory(),
-                "/Android/data/" + getInstrumentation().getContext().getPackageName()));
-    }
-}
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk b/hostsidetests/appsecurity/test-apps/UsesLibraryApp/Android.mk
similarity index 96%
rename from hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
rename to hostsidetests/appsecurity/test-apps/UsesLibraryApp/Android.mk
index 4630f1f..2d5dd4f 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsesLibraryApp/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
 
-LOCAL_PACKAGE_NAME := CtsUsePermissionApp
+LOCAL_PACKAGE_NAME := CtsUsesLibraryApp
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/UsesLibraryApp/AndroidManifest.xml
similarity index 83%
rename from hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/AndroidManifest.xml
rename to hostsidetests/appsecurity/test-apps/UsesLibraryApp/AndroidManifest.xml
index 253d85d..4557af0 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionAppCompat/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/UsesLibraryApp/AndroidManifest.xml
@@ -15,13 +15,12 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.cts.usepermission">
+        package="com.android.cts.useslibrary">
     <application>
         <uses-library android:name="android.test.runner" />
         <activity android:name=".MyActivity" />
     </application>
     <instrumentation
         android:name="android.support.test.runner.AndroidJUnitRunner"
-        android:targetPackage="com.android.cts.usepermission" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+        android:targetPackage="com.android.cts.useslibrary" />
 </manifest>
diff --git a/hostsidetests/appsecurity/test-apps/UsesLibraryApp/src/com/android/cts/useslibrary/UsesLibraryTest.java b/hostsidetests/appsecurity/test-apps/UsesLibraryApp/src/com/android/cts/useslibrary/UsesLibraryTest.java
new file mode 100644
index 0000000..0a1f012
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/UsesLibraryApp/src/com/android/cts/useslibrary/UsesLibraryTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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 com.android.cts.useslibrary;
+
+import android.content.pm.PackageManager;
+import android.os.Environment;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+import android.test.InstrumentationTestCase;
+
+import dalvik.system.BaseDexClassLoader;
+import dalvik.system.DexFile;
+import dalvik.system.PathClassLoader;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class UsesLibraryTest extends InstrumentationTestCase {
+    private static final String TAG = "UsesLibraryTest";
+
+    public void testUsesLibrary() throws Exception {
+        ClassLoader loader = getClass().getClassLoader();
+        if (loader instanceof BaseDexClassLoader) {
+            Object[] dexElements = getDexElementsFromClassLoader((BaseDexClassLoader) loader);
+            for (Object dexElement : dexElements) {
+                DexFile dexFile = getDexFileFromDexElement(dexElement);
+                assertTrue(isDexFileBackedByOatFile(dexFile));
+            }
+        }
+    }
+
+    public void testMissingLibrary() throws Exception {
+        ClassLoader loader = getClass().getClassLoader();
+        if (loader instanceof BaseDexClassLoader) {
+            Object[] dexElements = getDexElementsFromClassLoader((BaseDexClassLoader) loader);
+            assertTrue(dexElements != null && dexElements.length > 1);
+
+            DexFile dexFile = getDexFileFromDexElement(dexElements[1]);
+            String testApkPath = dexFile.getName();
+            PathClassLoader testLoader = new PathClassLoader(testApkPath, null);
+            Object[] testDexElements = getDexElementsFromClassLoader(testLoader);
+            assertTrue(testDexElements != null && testDexElements.length == 1);
+
+            DexFile testDexFile = getDexFileFromDexElement(testDexElements[0]);
+            assertTrue(isDexFileBackedByOatFile(testDexFile));
+        }
+    }
+
+    public void testDuplicateLibrary() throws Exception {
+        ClassLoader loader = getClass().getClassLoader();
+        if (loader instanceof BaseDexClassLoader) {
+            Object[] dexElements = getDexElementsFromClassLoader((BaseDexClassLoader) loader);
+            assertTrue(dexElements != null && dexElements.length > 1);
+
+            DexFile libDexFile = getDexFileFromDexElement(dexElements[0]);
+            String libPath = libDexFile.getName();
+            DexFile apkDexFile = getDexFileFromDexElement(dexElements[1]);
+            String apkPath = apkDexFile.getName();
+            String testPath = libPath + File.pathSeparator + apkPath + File.pathSeparator + apkPath;
+            PathClassLoader testLoader = new PathClassLoader(testPath, null);
+            Object[] testDexElements = getDexElementsFromClassLoader(testLoader);
+            assertTrue(testDexElements != null && testDexElements.length == 3);
+
+            DexFile testDexFile = getDexFileFromDexElement(testDexElements[2]);
+            assertFalse(isDexFileBackedByOatFile(testDexFile));
+        }
+    }
+
+    private Object[] getDexElementsFromClassLoader(BaseDexClassLoader loader) throws Exception {
+        Field pathListField = BaseDexClassLoader.class.getDeclaredField("pathList");
+        pathListField.setAccessible(true);
+        // This is a DexPathList, but that class is package private.
+        Object pathList = pathListField.get(loader);
+        Field dexElementsField = pathList.getClass().getDeclaredField("dexElements");
+        dexElementsField.setAccessible(true);
+        // The objects in this array are Elements, but that class is package private.
+        return (Object[]) dexElementsField.get(pathList);
+    }
+
+    // The argument must be a DexPathList.Element.
+    private DexFile getDexFileFromDexElement(Object dexElement) throws Exception {
+        Field dexFileField = dexElement.getClass().getDeclaredField("dexFile");
+        dexFileField.setAccessible(true);
+        return (DexFile) dexFileField.get(dexElement);
+    }
+
+    private boolean isDexFileBackedByOatFile(DexFile dexFile) throws Exception {
+        Method isBackedByOatFileMethod = DexFile.class.getDeclaredMethod("isBackedByOatFile");
+        isBackedByOatFileMethod.setAccessible(true);
+        return (boolean) isBackedByOatFileMethod.invoke(dexFile);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
index 54c0716..18d1b8b 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner compatibility-device-util ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner compatibility-device-util
 
 LOCAL_SDK_VERSION := test_current
 
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/RemoteBugreportTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/RemoteBugreportTest.java
index efefde9..22dc38a 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/RemoteBugreportTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/RemoteBugreportTest.java
@@ -20,13 +20,6 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
 import android.test.InstrumentationTestCase;
 
 /**
@@ -39,17 +32,12 @@
  */
 public class RemoteBugreportTest extends InstrumentationTestCase {
 
-    private static final int UI_TIMEOUT_MILLIS = 5000; //5 seconds
-
     private static final String MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED =
             "There should only be one user, managed by Device Owner";
 
-    private static final String TAKING_BUG_REPORT = "Taking bug report";
-    private static final String DECLINE = "DECLINE";
 
     private DevicePolicyManager mDevicePolicyManager;
     private Context mContext;
-    private UiDevice mUiDevice;
     private ComponentName mComponentName;
 
     @Override
@@ -57,7 +45,6 @@
         super.setUp();
         Instrumentation instrumentation = getInstrumentation();
         mContext = instrumentation.getTargetContext();
-        mUiDevice = UiDevice.getInstance(instrumentation);
         mDevicePolicyManager = (DevicePolicyManager)
                 mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
         BaseDeviceOwnerTest.assertDeviceOwner(mDevicePolicyManager);
@@ -65,20 +52,6 @@
     }
 
     /**
-     * Test: only one remote bugreport flow can be running on the device at one time.
-     */
-    public void testSubsequentRemoteBugreportThrottled() {
-        boolean startedSuccessfully = mDevicePolicyManager.requestBugreport(mComponentName);
-        assertTrue(startedSuccessfully);
-
-        // subsequent attempts should be throttled
-        assertFalse(mDevicePolicyManager.requestBugreport(mComponentName));
-        assertFalse(mDevicePolicyManager.requestBugreport(mComponentName));
-
-        cancelRemoteBugreportFlowIfStartedSuccessfully(startedSuccessfully);
-    }
-
-    /**
      * Test: remote bugreport flow can only be started if there's one user on the device.
      */
     public void testRequestBugreportNotStartedIfMoreThanOneUserPresent() {
@@ -88,59 +61,7 @@
             fail("did not throw expected SecurityException");
         } catch (SecurityException e) {
             assertEquals(e.getMessage(), MESSAGE_ONLY_ONE_MANAGED_USER_ALLOWED);
-        } finally {
-            cancelRemoteBugreportFlowIfStartedSuccessfully(startedSuccessfully);
         }
     }
 
-    /**
-     * Clicks on "Taking bugreport..." notification, and then DECLINE button on the consent dialog
-     * to cancel the whole remote bugreport flow (including stopping the dumpstate service).
-     */
-    private void cancelRemoteBugreportFlowIfStartedSuccessfully(boolean startedSuccessfully) {
-        if (!startedSuccessfully) {
-            return;
-        }
-
-        UiObject2 bugreportNotification = findRemoteBugreportNotification();
-        assertNotNull(bugreportNotification);
-        bugreportNotification.click();
-
-        // give it max 5 seconds to find the DECLINE button on the dialog
-        boolean declineButtonPresent = mUiDevice.wait(
-                Until.hasObject(By.text(DECLINE)), UI_TIMEOUT_MILLIS);
-        assertTrue(declineButtonPresent);
-
-        UiObject declineButton = mUiDevice.findObject(new UiSelector().text(DECLINE));
-        assertNotNull(declineButton);
-        try {
-            declineButton.click();
-        } catch (UiObjectNotFoundException e) {
-            throw new IllegalStateException("Exception when clicking on 'DECLINE' button", e);
-        }
-    }
-
-    /**
-     * Attempts to find the remote bugreport notification scrolling down in the notification panel
-     * in between 10 attempts.
-     */
-    private UiObject2 findRemoteBugreportNotification() {
-        mUiDevice.openNotification();
-        final int displayWidth = mUiDevice.getDisplayWidth();
-        final int displayHeight = mUiDevice.getDisplayHeight();
-        for (int i = 0; i < 10; i++) {
-            UiObject2 notification = mUiDevice.wait(Until.findObject(
-                    By.textStartsWith(TAKING_BUG_REPORT)), UI_TIMEOUT_MILLIS);
-            if (notification != null) {
-                return notification;
-            } else {
-                /* makes a swipe from the middle of the screen upwards to the top of the screen
-                (the motion is upwards, so it scrolls downwards) half a screen, so that the
-                notification is always fully visible - never cut in two pieces) */
-                mUiDevice.swipe(displayWidth / 2, displayHeight / 2, displayWidth / 2,
-                        /* endY= */ 0, /* steps= */ 30);
-            }
-        }
-        return null;
-    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index afead29..e941b43 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -123,10 +123,6 @@
         }
     }
 
-    public void testRemoteBugreportWithSingleUser() throws Exception {
-        executeDeviceTestMethod(".RemoteBugreportTest", "testSubsequentRemoteBugreportThrottled");
-    }
-
     /** Tries to toggle the force-ephemeral-users on and checks it was really set. */
     public void testSetForceEphemeralUsers() throws Exception {
         if (!mHasEphemeralUserFeature) {
@@ -310,12 +306,18 @@
     }
 
     public void testSecurityLoggingWithSingleUser() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
         executeDeviceTestMethod(".SecurityLoggingTest",
                 "testRetrievingSecurityLogsNotPossibleImmediatelyAfterPreviousSuccessfulRetrieval");
         executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingAndDisablingSecurityLogging");
     }
 
     public void testLockTask() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
         try {
             installAppAsUser(INTENT_RECEIVER_APK, mPrimaryUserId);
             executeDeviceOwnerTest("LockTaskTest");
@@ -325,6 +327,9 @@
     }
 
     public void testSystemUpdatePolicy() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
         executeDeviceOwnerTest("SystemUpdatePolicyTest");
     }
 
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 27d4a2b..ce9d970 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
@@ -377,18 +377,24 @@
     private void assertRestrictBackground(String list, int uid, boolean expected) throws Exception {
         final int maxTries = 5;
         boolean actual = false;
+        final String expectedUid = Integer.toString(uid);
+        String uids = "";
         for (int i = 1; i <= maxTries; i++) {
             final String output =
                     executeShellCommand("cmd netpolicy list " + list);
-            actual = output.contains(Integer.toString(uid));
-            if (expected == actual) {
-                return;
+            uids = output.split(":")[1];
+            for (String candidate : uids.split(" ")) {
+                actual = candidate.trim().equals(expectedUid);
+                if (expected == actual) {
+                    return;
+                }
             }
             Log.v(TAG, list + " check for uid " + uid + " doesn't match yet (expected "
                     + expected + ", got " + actual + "); sleeping 1s before polling again");
             Thread.sleep(SECOND_IN_MS);
         }
-        fail(list + " check for uid " + uid + " failed: expected " + expected + ", got " + actual);
+        fail(list + " check for uid " + uid + " failed: expected " + expected + ", got " + actual
+                + ". Full list: " + uids);
     }
 
     protected void assertPowerSaveModeWhitelist(String packageName, boolean expected)
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index 62f670e..d760475 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -31,6 +31,10 @@
  */
 public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
 
+    private static final String[] REQUIRED_WHITELISTED_PACKAGES = {
+        "com.android.providers.downloads"
+    };
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -108,4 +112,24 @@
         assertRestrictBackgroundChangedReceived(5);
         assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
     }
+
+    public void testGetRestrictBackgroundStatus_requiredWhitelistedPackages() throws Exception {
+        final StringBuilder error = new StringBuilder();
+        for (String packageName : REQUIRED_WHITELISTED_PACKAGES) {
+            int uid = -1;
+            try {
+                uid = getUid(packageName);
+                assertRestrictBackgroundWhitelist(uid, true);
+            } catch (Throwable t) {
+                error.append("\nFailed for '").append(packageName).append("'");
+                if (uid > 0) {
+                    error.append(" (uid ").append(uid).append(")");
+                }
+                error.append(": ").append(t).append("\n");
+            }
+        }
+        if (error.length() > 0) {
+            fail(error.toString());
+        }
+    }
 }
diff --git a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index 15a4e0a..ca535bc 100644
--- a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -73,6 +73,11 @@
         assertRestrictBackgroundWhitelist(newUid, false);
     }
 
+    public void testDataSaverMode_requiredWhitelistedPackages() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".DataSaverModeTest",
+                "testGetRestrictBackgroundStatus_requiredWhitelistedPackages");
+    }
+
     public void testBatterySaverMode_disabled() throws Exception {
         runDeviceTests(TEST_PKG, TEST_PKG + ".BatterySaverModeTest",
                 "testBackgroundNetworkAccess_disabled");
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java b/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
index da346ac..f1f24c9 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
@@ -384,7 +384,6 @@
         }
 
         private void extract(LinkedList<String> dump, Pattern[] exitPatterns) {
-
             while (!doneExtracting(dump, exitPatterns)) {
                 final String line = dump.pop().trim();
 
@@ -417,7 +416,7 @@
     static abstract class WindowContainer {
         protected static final Pattern sFullscreenPattern = Pattern.compile("mFullscreen=(\\S+)");
         protected static final Pattern sBoundsPattern =
-                Pattern.compile("mBounds=\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]");
+                Pattern.compile("mBounds=\\[(-?\\d+),(-?\\d+)\\]\\[(-?\\d+),(-?\\d+)\\]");
 
         protected boolean mFullscreen;
         protected Rectangle mBounds;
diff --git a/tests/browser/AndroidTest.xml b/tests/browser/AndroidTest.xml
index 49c93fc..511e769 100644
--- a/tests/browser/AndroidTest.xml
+++ b/tests/browser/AndroidTest.xml
@@ -21,5 +21,7 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.browser.cts" />
         <option name="runtime-hint" value="4m14s" />
+        <!-- test-timeout unit is ms, value = 60 min -->
+        <option name="test-timeout" value="3600000" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java
index d8fae6d..5fbc682 100644
--- a/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java
@@ -99,18 +99,20 @@
         final long minStillFrameDuration =
                 config.getOutputMinFrameDuration(ImageFormat.YUV_420_888, stillSize);
 
-        // Find suitable target FPS range - as high as possible
-        List<Range<Integer> > fpsRanges = Arrays.asList(
-                mStaticInfo.getAeAvailableTargetFpsRangesChecked());
-        Range<Integer> targetRange = mStaticInfo.getAeMaxTargetFpsRange();
         // Add 0.05 here so Fps like 29.99 evaluated to 30
         int minBurstFps = (int) Math.floor(1e9 / minStillFrameDuration + 0.05f);
         boolean foundConstantMaxYUVRange = false;
         boolean foundYUVStreamingRange = false;
 
+        // Find suitable target FPS range - as high as possible that covers the max YUV rate
+        // Also verify that there's a good preview rate as well
+        List<Range<Integer> > fpsRanges = Arrays.asList(
+                mStaticInfo.getAeAvailableTargetFpsRangesChecked());
+        Range<Integer> targetRange = null;
         for (Range<Integer> fpsRange : fpsRanges) {
             if (fpsRange.getLower() == minBurstFps && fpsRange.getUpper() == minBurstFps) {
                 foundConstantMaxYUVRange = true;
+                targetRange = fpsRange;
             }
             if (fpsRange.getLower() <= 15 && fpsRange.getUpper() == minBurstFps) {
                 foundYUVStreamingRange = true;
@@ -122,10 +124,6 @@
         assertTrue(String.format(
                 "Cam %s: Target FPS range of (x, %d) where x <= 15 must be supported",
                 cameraId, minBurstFps), foundYUVStreamingRange);
-        assertTrue(String.format("Cam %s: No target FPS range found with minimum FPS above " +
-                        " 1/minFrameDuration (%d fps, duration %d ns) for full-resolution YUV",
-                        cameraId, minBurstFps, minStillFrameDuration),
-                targetRange.getLower() >= minBurstFps);
 
         Log.i(TAG, String.format("Selected frame rate range %d - %d for YUV burst",
                         targetRange.getLower(), targetRange.getUpper()));
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 3f84aa2..5ea4322 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -165,19 +165,6 @@
   bug: 23238984
 },
 {
-  description: "These tests fail on some devices.",
-  names: [
-    "android.uirendering.cts.testclasses.ExactCanvasTests#testBlueRect",
-    "android.uirendering.cts.testclasses.ExactCanvasTests#testBluePaddedSquare",
-    "android.uirendering.cts.testclasses.ViewClippingTests#testSimplePaddingClip",
-    "android.uirendering.cts.testclasses.ViewClippingTests#testSimpleClipBoundsClip",
-    "android.uirendering.cts.testclasses.ViewClippingTests#testSimpleOutlineClip",
-    "android.uirendering.cts.testclasses.ViewClippingTests#testSimpleBoundsClip",
-    "android.uirendering.cts.testclasses.InfrastructureTests#testViewInitializer"
-  ],
-  bug: 17511118
-},
-{
   description: "This test failed on devices that use effect off loading. In addition it uses hidden apis",
   names: [
     "android.media.cts.AudioEffectTest#test1_1ConstructorFromUuid"
diff --git a/tests/inputmethod/Android.mk b/tests/inputmethod/Android.mk
deleted file mode 100644
index 3a90fa9..0000000
--- a/tests/inputmethod/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsInputMethodTestCases
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/inputmethod/AndroidManifest.xml b/tests/inputmethod/AndroidManifest.xml
deleted file mode 100644
index 038b164..0000000
--- a/tests/inputmethod/AndroidManifest.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-    Copyright (C) 2015 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="android.inputmethod.cts">
-
-    <application >
-        <uses-library android:name="android.test.runner"/>
-
-        <activity android:name="android.inputmethod.cts.TestActivity" />
-        <service android:name="android.inputmethod.cts.MockInputMethodService"
-                 android:permission="android.permission.BIND_INPUT_METHOD">
-            <intent-filter>
-                <action android:name="android.view.InputMethod" />
-            </intent-filter>
-            <meta-data android:name="android.view.im" android:resource="@xml/method" />
-        </service>
-    </application>
-
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="android.inputmethod.cts"
-                     android:label="Tests for the InputMethod APIs."/>
-
-</manifest>
diff --git a/tests/inputmethod/AndroidTest.xml b/tests/inputmethod/AndroidTest.xml
deleted file mode 100644
index 3a52042..0000000
--- a/tests/inputmethod/AndroidTest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Config for CTS Input test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsInputMethodTestCases.apk" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.inputmethod.cts" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/tests/inputmethod/res/xml/method.xml b/tests/inputmethod/res/xml/method.xml
deleted file mode 100644
index fc2ec95..0000000
--- a/tests/inputmethod/res/xml/method.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-    Copyright (C) 2015 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<input-method xmlns:android="http://schemas.android.com/apk/res/android"
-              android:isDefault="True">
-    <subtype android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" />
-</input-method>
diff --git a/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java
deleted file mode 100644
index c68d448..0000000
--- a/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.inputmethod.cts;
-
-import android.annotation.NonNull;
-import android.content.pm.PackageManager;
-import android.os.IBinder;
-import android.inputmethodservice.InputMethodService;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.inputmethod.InputMethodManager;
-
-import java.util.List;
-
-public class InputMethodServiceTest extends InstrumentationTestCase {
-    private String mTestImeId;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mTestImeId = getInstrumentation().getContext().getPackageName() +
-                "/" + MockInputMethodService.class.getName();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    /**
-     * Ensures that the IME with {@code imeId} is not enabled.
-     *
-     * This method ensures that no IME with {@code imeId} is enabled. If the given IME is currently
-     * in use, switches to another IME first. Then, if the given IME is enabled, disables it.
-     */
-    private void ensureImeNotEnabled(@NonNull final String imeId) {
-        final String currentImeId =
-                InputMethodServiceTestUtil.getCurrentImeId(getInstrumentation());
-        if (currentImeId.equals(imeId)) {
-            // Requested IME is already used. This typically happens if the previous test case is
-            // not finished gracefully. In this case, selects another IME.
-            String otherImeCandidate = null;
-            final List<String> enabledImes =
-                    InputMethodServiceTestUtil.getEnabledImeIds(getInstrumentation());
-            for (final String enabledIme : enabledImes) {
-                if (!enabledIme.equals(imeId)) {
-                    otherImeCandidate = imeId;
-                    break;
-                }
-            }
-            if (otherImeCandidate == null) {
-                // When PackageManager.hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS)
-                // returns true, this case must not happen.
-                throw new IllegalStateException(
-                        "No other IME is available. Unable to continue tests.");
-            }
-            assertTrue(InputMethodServiceTestUtil.setIme(getInstrumentation(), otherImeCandidate));
-        }
-
-        if (InputMethodServiceTestUtil.isImeEnabled(getInstrumentation(), imeId)) {
-            assertTrue(InputMethodServiceTestUtil.disableIme(getInstrumentation(), imeId));
-        }
-    }
-
-    /**
-     * Asserts the given service is not running.
-     */
-    private void assertServiceNotRunning() {
-        assertTrue(MockInputMethodService.getInstance() == null ||
-                MockInputMethodService.getInstance().getCallCount("onCreate") == 0);
-    }
-
-    /**
-     * This test checks the following APIs.
-     * <ul>
-     *   <li>{@link InputMethodManager#getEnabledInputMethodList()}</li>
-     *   <li>{@link InputMethodManager#getInputMethodList()}</li>
-     *   <li>{@link InputMethodManager#setInputMethod(IBinder, String)}</li>
-     *   <li>{@link InputMethodService#onCreate()}</li>
-     *   <li>{@link InputMethodService#onDestroy()}</li>
-     * </ul>
-     */
-    @MediumTest
-    public void testCreateAndDestroy() {
-        if (!getInstrumentation().getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_INPUT_METHODS)) {
-            // The "input method" system feature is not supported on this device.
-            return;
-        }
-
-        // Clear the counter in the mock service, since it might have been used in a previous test.
-        MockInputMethodService.resetCounter();
-
-        ensureImeNotEnabled(mTestImeId);
-
-        final String ImeIdToRestore =
-                InputMethodServiceTestUtil.getCurrentImeId(getInstrumentation());
-        MockInputMethodService service = MockInputMethodService.getInstance();
-        assertServiceNotRunning();
-
-        try {
-            // Enable test IME.
-            assertTrue(InputMethodServiceTestUtil.enableIme(getInstrumentation(), mTestImeId));
-            service = MockInputMethodService.getInstance();
-            assertServiceNotRunning();
-
-            // Select test IME.
-            assertTrue(InputMethodServiceTestUtil.setIme(getInstrumentation(), mTestImeId));
-            service = MockInputMethodService.getInstance();
-            assertNotNull(service);
-            assertEquals(1, MockInputMethodService.getCallCount("<init>"));
-            assertEquals(1, MockInputMethodService.getCallCount("onCreate"));
-        } finally {
-            // Restores IMEs to original one.
-            InputMethodServiceTestUtil.setIme(getInstrumentation(), ImeIdToRestore);
-            InputMethodServiceTestUtil.disableIme(getInstrumentation(), mTestImeId);
-            assertEquals(1, MockInputMethodService.getCallCount("onDestroy"));
-        }
-    }
-}
diff --git a/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTestUtil.java b/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTestUtil.java
deleted file mode 100644
index aa46c38..0000000
--- a/tests/inputmethod/src/android/inputmethod/cts/InputMethodServiceTestUtil.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.inputmethod.cts;
-
-import android.annotation.NonNull;
-import android.app.Instrumentation;
-import android.app.UiAutomation;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Utility functions for testing of input method stuff.
- */
-public final class InputMethodServiceTestUtil {
-    private static final String TAG = InputMethodServiceTestUtil.class.getSimpleName();
-
-    // Prevents this from being instantiated.
-    private InputMethodServiceTestUtil() {}
-
-    @NonNull
-    private static String executeShellCommand(final UiAutomation uiAutomation, final String[] cmd) {
-        final String flattenCmd = TextUtils.join(" ", cmd);
-        List<String> output = new ArrayList<>();
-
-        try (final ParcelFileDescriptor fd = uiAutomation.executeShellCommand(flattenCmd);
-             final FileReader fr = new FileReader(fd.getFileDescriptor());
-             final BufferedReader br = new BufferedReader(fr)) {
-
-            String line;
-            while ((line = br.readLine()) != null) {
-                output.add(line);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-
-        // The output from the "ime" command should be only one line.
-        if (output.size() != 1) {
-            throw new IllegalStateException(
-                    "The output from 'ime' command should be one line, but it outputs multiples: " +
-                    TextUtils.join("\n", output));
-        }
-        return output.get(0);
-    }
-
-    @NonNull
-    public static String getCurrentImeId(final Instrumentation inst) {
-        return Settings.Secure.getString(inst.getContext().getContentResolver(),
-                Settings.Secure.DEFAULT_INPUT_METHOD);
-    }
-
-    public static boolean isImeEnabled(final Instrumentation inst, final String imeId) {
-        final List<String> enabledImes = getEnabledImeIds(inst);
-        return enabledImes.contains(imeId);
-    }
-
-    @NonNull
-    public static List<String> getEnabledImeIds(final Instrumentation inst) {
-        InputMethodManager imm = (InputMethodManager) inst.getContext().getSystemService(
-                Context.INPUT_METHOD_SERVICE);
-        final List<InputMethodInfo> enabledImes = imm.getEnabledInputMethodList();
-        List<String> result = new ArrayList<>();
-        for (final InputMethodInfo enabledIme : enabledImes) {
-            result.add(enabledIme.getId());
-        }
-        return result;
-    }
-
-    /**
-     * Puts the specified IME into the available input method list.
-     *
-     * This operation will be done synchronously in "ime" command using
-     * {@link com.android.server.InputMethodManagerService#setInputMethodEnabled(String, boolean)},
-     * which is synchronous.
-     *
-     * @param imeId IME ID to be enabled.
-     * @return {@code true} if the target IME gets enabled successfully. {@code false} if failed.
-     */
-    public static boolean enableIme(final Instrumentation inst, final String imeId) {
-        // Needs to check the output message from the checking command, since executeShellCommand()
-        // does not pass the exit status code back to the test.
-        final String output = executeShellCommand(
-                inst.getUiAutomation(), new String[]{"ime", "enable", imeId});
-        final String expectedOutput = "Input method " + imeId + ": now enabled";
-        if (!output.equals(expectedOutput)) {
-            Log.e(TAG, "Unexpected output message. Expected: " + expectedOutput +
-                    ", Actual: " + output);
-            return false;
-        }
-
-        final InputMethodManager imm = (InputMethodManager) inst.getContext().getSystemService(
-                Context.INPUT_METHOD_SERVICE);
-        final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
-        for (final InputMethodInfo imi : enabledInputMethods) {
-            if (imi.getId().equals(imeId))
-                return true;
-        }
-
-        Log.e(TAG, "Failed to enable the given IME (IME ID: " + imeId + ").");
-        return false;
-    }
-
-    /**
-     * Removes the specified IME from the available input method list.
-     *
-     * This operation will {@code @NonNull} final be done synchronously in "ime" command using
-     * {@link com.android.server.InputMethodManagerService#setInputMethodEnabled(String, boolean)},
-     * which is synchronous.
-     *
-     * @param imeId IME ID to be disabled.
-     * @return {@code true} if the target IME gets disabled successfully. {@code false} if failed.
-     */
-    public static boolean disableIme(final Instrumentation inst, final String imeId) {
-        // Needs to check the output message from the checking command, since executeShellCommand()
-        // does not pass the exit status code back to the test.
-        final String output = executeShellCommand(
-                inst.getUiAutomation(), new String[]{"ime", "disable", imeId});
-        final String expectedOutput = "Input method " + imeId + ": now disabled";
-        if (!output.equals(expectedOutput)) {
-            Log.w(TAG, "Unexpected output message. Expected: " + expectedOutput +
-                    ", Actual: " + output);
-            return false;
-        }
-
-        final InputMethodManager imm = (InputMethodManager) inst.getContext().getSystemService(
-                Context.INPUT_METHOD_SERVICE);
-        final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
-        for (final InputMethodInfo imi : enabledInputMethods) {
-            if (imi.getId().equals(imeId)) {
-                Log.e(TAG, "Failed to disable the given IME (IME ID: " + imeId + ").");
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Switches to the specified IME.
-     *
-     * This operation will be done synchronously in the "ime" command using
-     * {@link InputMethodManager#setInputMethod(IBinder, String)}, which is synchronous.
-     *
-     * @param imeId IME ID to be switched to.
-     * @return {@code true} if the target IME gets active successfully. {@code false} if failed.
-     */
-    public static boolean setIme(final Instrumentation inst, final String imeId) {
-        // Needs to check the output message from the checking command, since executeShellCommand()
-        // does not pass the exit status code back to the test.
-        final String output = executeShellCommand(
-                inst.getUiAutomation(), new String[]{"ime", "set", imeId});
-        final String expectedOutput = "Input method " + imeId + " selected";
-        if (!output.equals(expectedOutput)) {
-            Log.w(TAG, "Unexpected output message. Expected: " + expectedOutput +  ", Actual: " +
-                    output);
-            return false;
-        }
-
-        final String currentImeId = getCurrentImeId(inst);
-        if (!TextUtils.equals(currentImeId, imeId)) {
-            Log.e(TAG, "Failed to switch the current IME. Expected: " + imeId +  ", Actual: " +
-                    currentImeId);
-            return false;
-        }
-
-        return true;
-    }
-}
diff --git a/tests/inputmethod/src/android/inputmethod/cts/MockInputMethodService.java b/tests/inputmethod/src/android/inputmethod/cts/MockInputMethodService.java
deleted file mode 100644
index 12b80a5..0000000
--- a/tests/inputmethod/src/android/inputmethod/cts/MockInputMethodService.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.inputmethod.cts;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.inputmethodservice.InputMethodService;
-
-import java.util.HashMap;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * A mock implementation of {@link InputMethodService} for testing purpose.
- */
-public class MockInputMethodService extends InputMethodService {
-    private static AtomicReference<MockInputMethodService> sCurrentInstance =
-            new AtomicReference<>();
-    private static final HashMap<String, Integer> mCallCounter = new HashMap<>();
-
-    /**
-     * @return The instance of {@code MockInputMethodService}. If the service has not been created
-     * yet or already been destroyed, returns {@code null}.
-     */
-    @Nullable
-    public static MockInputMethodService getInstance() {
-        return sCurrentInstance.get();
-    }
-
-    public static void resetCounter() {
-        synchronized (mCallCounter) {
-            mCallCounter.clear();
-        }
-    }
-
-    private static void incrementCallCount(@NonNull final String methodName) {
-        synchronized (mCallCounter) {
-            if (!mCallCounter.containsKey(methodName)) {
-                mCallCounter.put(methodName, 0);
-            }
-            mCallCounter.put(methodName, mCallCounter.get(methodName) + 1);
-        }
-    }
-
-    public static int getCallCount(@NonNull final String methodName) {
-        synchronized (mCallCounter) {
-            if (!mCallCounter.containsKey(methodName)) {
-                return 0;
-            }
-            return mCallCounter.get(methodName);
-        }
-    }
-
-    public MockInputMethodService() {
-        incrementCallCount("<init>");
-    }
-
-    @Override
-    public void onCreate() {
-        if (!sCurrentInstance.compareAndSet(null, this)) {
-            throw new IllegalStateException("New MockInputMethodService instance is being created "
-                    + "before the existing instance is destroyed.");
-        }
-
-        super.onCreate();
-        incrementCallCount("onCreate");
-    }
-
-    @Override
-    public void onDestroy() {
-        sCurrentInstance.lazySet(null);
-        super.onDestroy();
-        incrementCallCount("onDestroy");
-    }
-}
-
diff --git a/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java b/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java
index b2a90f2..5750963 100644
--- a/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java
+++ b/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java
@@ -70,19 +70,19 @@
     public void testUriExtraOutputMigratedToClipData_imageCaptureIntent() {
         startActivityWithAction(MediaStore.ACTION_IMAGE_CAPTURE);
         waitForFileReady();
-        testFileContents();
+        assertFileContents();
     }
 
     public void testUriExtraOutputMigratedToClipData_imageCaptureSecureIntent() {
         startActivityWithAction(MediaStore.ACTION_IMAGE_CAPTURE_SECURE);
         waitForFileReady();
-        testFileContents();
+        assertFileContents();
     }
 
     public void testUriExtraOutputMigratedToClipData_videoCaptureIntent() {
         startActivityWithAction(MediaStore.ACTION_VIDEO_CAPTURE);
         waitForFileReady();
-        testFileContents();
+        assertFileContents();
     }
 
     private void startActivityWithAction(String action) {
@@ -102,7 +102,7 @@
         }
     }
 
-    private void testFileContents() {
+    private void assertFileContents() {
         char[] buffer = new char[TEST_INPUT.length()];
         try {
             FileReader reader = new FileReader(mTestFile);
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
index 4c59652..9dbf3f3 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
@@ -61,6 +61,7 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+import java.text.DecimalFormatSymbols;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
@@ -1138,6 +1139,32 @@
                         .build());
     }
 
+    // http://b/28384942
+    public void testGenerateWithFarsiLocale() throws Exception {
+        Locale defaultLocale = Locale.getDefault();
+        // Note that we use farsi here because its number formatter doesn't use
+        // arabic digits.
+        Locale fa_IR = Locale.forLanguageTag("fa-IR");
+        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(fa_IR);
+        assertFalse('0' == dfs.getZeroDigit());
+
+        Locale.setDefault(fa_IR);
+        try {
+            KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(
+                    KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
+
+            keyGenerator.initialize(new KeyGenParameterSpec.Builder(
+                   TEST_ALIAS_1, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+                   .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
+                   .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
+                   .build());
+
+            keyGenerator.generateKeyPair();
+        } finally {
+            Locale.setDefault(defaultLocale);
+        }
+    }
+
     private void assertKeyGenInitSucceeds(String algorithm, AlgorithmParameterSpec params)
             throws Exception {
         KeyPairGenerator generator = getGenerator(algorithm);
diff --git a/tests/tests/location/src/android/location/cts/GpsStatusTest.java b/tests/tests/location/src/android/location/cts/GpsStatusTest.java
index 92ec137..8e2d421 100644
--- a/tests/tests/location/src/android/location/cts/GpsStatusTest.java
+++ b/tests/tests/location/src/android/location/cts/GpsStatusTest.java
@@ -48,9 +48,11 @@
         int count = 0;
         while (iterator.hasNext()) {
             count++;
+            if (count > maxSatellites) {
+                // the real total could not be larger than maxSatellites
+                fail("Found more satellites than: " + maxSatellites);
+            }
         }
-        // the real total could not be larger than maxSatellites
-        assertTrue(count <= maxSatellites);
     }
 
     public void testGetTimeToFirstFix() {
diff --git a/tests/tests/media/src/android/media/cts/RoutingTest.java b/tests/tests/media/src/android/media/cts/RoutingTest.java
index c0e9a3e..22aaaa3 100644
--- a/tests/tests/media/src/android/media/cts/RoutingTest.java
+++ b/tests/tests/media/src/android/media/cts/RoutingTest.java
@@ -23,6 +23,7 @@
 import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioRecord;
+import android.media.AudioRouting;
 import android.media.AudioTrack;
 import android.media.MediaRecorder;
 
@@ -36,7 +37,12 @@
 import java.lang.Runnable;
 
 /**
- * TODO: Insert description here. (generated by pmclean)
+ * AudioTrack / AudioRecord preferred device and routing listener tests.
+ * The routing tests are mostly here to exercise the routing code, as an actual test would require
+ * adding / removing an audio device for the listeners to be called.
+ * The routing listener code is designed to run for two versions of the routing code:
+ *  - the deprecated AudioTrack.OnRoutingChangedListener and AudioRecord.OnRoutingChangedListener
+ *  - the N AudioRouting.OnRoutingChangedListener
  */
 public class RoutingTest extends AndroidTestCase {
     private static final String TAG = "RoutingTest";
@@ -115,29 +121,75 @@
         return myLooper;
     }
 
-    private class AudioTrackRoutingListener implements AudioTrack.OnRoutingChangedListener {
+    private class AudioTrackRoutingListener implements AudioTrack.OnRoutingChangedListener,
+            AudioRouting.OnRoutingChangedListener
+    {
         public void onRoutingChanged(AudioTrack audioTrack) {}
+        public void onRoutingChanged(AudioRouting audioRouting) {}
     }
 
+
     public void test_audioTrack_RoutingListener() {
+        test_audioTrack_RoutingListener(false /*usesAudioRouting*/);
+    }
+
+    public void test_audioTrack_audioRouting_RoutingListener() {
+        test_audioTrack_RoutingListener(true /*usesAudioRouting*/);
+    }
+
+    private void test_audioTrack_RoutingListener(boolean usesAudioRouting) {
         AudioTrack audioTrack = allocAudioTrack();
 
-        audioTrack.addOnRoutingChangedListener(null, null);
+        // null listener
+        if (usesAudioRouting) {
+            audioTrack.addOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) null, null);
+        } else {
+            audioTrack.addOnRoutingChangedListener(
+                    (AudioTrack.OnRoutingChangedListener) null, null);
+        }
 
         AudioTrackRoutingListener listener = new AudioTrackRoutingListener();
         AudioTrackRoutingListener someOtherListener = new AudioTrackRoutingListener();
 
-        audioTrack.addOnRoutingChangedListener(listener, null);
+        // add a listener
+        if (usesAudioRouting) {
+            audioTrack.addOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) listener, null);
+        } else {
+            audioTrack.addOnRoutingChangedListener(listener, null);
+        }
 
-        // remove a listener we didn't add
-        audioTrack.removeOnRoutingChangedListener(someOtherListener);
-
-        audioTrack.removeOnRoutingChangedListener(listener);
+        // remove listeners
+        if (usesAudioRouting) {
+            // remove a listener we didn't add
+            audioTrack.removeOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) someOtherListener);
+            // remove a valid listener
+            audioTrack.removeOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) listener);
+        } else {
+            // remove a listener we didn't add
+            audioTrack.removeOnRoutingChangedListener(
+                    (AudioTrack.OnRoutingChangedListener) someOtherListener);
+            // remove a valid listener
+            audioTrack.removeOnRoutingChangedListener(
+                    (AudioTrack.OnRoutingChangedListener) listener);
+        }
 
         Looper myLooper = prepareIfNeededLooper();
-        audioTrack.addOnRoutingChangedListener(listener, new Handler());
 
-        audioTrack.removeOnRoutingChangedListener(listener);
+        if (usesAudioRouting) {
+            audioTrack.addOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) listener, new Handler());
+            audioTrack.removeOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) listener);
+        } else {
+            audioTrack.addOnRoutingChangedListener(
+                    (AudioTrack.OnRoutingChangedListener) listener, new Handler());
+            audioTrack.removeOnRoutingChangedListener(
+                    (AudioTrack.OnRoutingChangedListener) listener);
+        }
 
         audioTrack.release();
         if (myLooper != null) {
@@ -160,33 +212,78 @@
         return audioRecord;
     }
 
-    private class AudioRecordRoutingListener implements AudioRecord.OnRoutingChangedListener {
+    private class AudioRecordRoutingListener implements AudioRecord.OnRoutingChangedListener,
+            AudioRouting.OnRoutingChangedListener
+    {
         public void onRoutingChanged(AudioRecord audioRecord) {}
+        public void onRoutingChanged(AudioRouting audioRouting) {}
     }
 
     public void test_audioRecord_RoutingListener() {
+        test_audioRecord_RoutingListener(false /*usesAudioRouting*/);
+    }
+
+    public void test_audioRecord_audioRouting_RoutingListener() {
+        test_audioRecord_RoutingListener(true /*usesAudioRouting*/);
+    }
+
+    private void test_audioRecord_RoutingListener(boolean usesAudioRouting) {
         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
             // Can't do it so skip this test
             return;
         }
         AudioRecord audioRecord = allocAudioRecord();
 
-        audioRecord.addOnRoutingChangedListener(null, null);
+        // null listener
+        if (usesAudioRouting) {
+            audioRecord.addOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) null, null);
+        } else {
+            audioRecord.addOnRoutingChangedListener(
+                    (AudioRecord.OnRoutingChangedListener) null, null);
+        }
 
         AudioRecordRoutingListener listener = new AudioRecordRoutingListener();
         AudioRecordRoutingListener someOtherListener = new AudioRecordRoutingListener();
 
-        audioRecord.addOnRoutingChangedListener(listener, null);
+        // add a listener
+        if (usesAudioRouting) {
+            audioRecord.addOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) listener, null);
+        } else {
+            audioRecord.addOnRoutingChangedListener(
+                    (AudioRecord.OnRoutingChangedListener) listener, null);
+        }
 
-        // remove a listener we didn't add
-        audioRecord.removeOnRoutingChangedListener(someOtherListener);
-
-        audioRecord.removeOnRoutingChangedListener(listener);
+        // remove listeners
+        if (usesAudioRouting) {
+            // remove a listener we didn't add
+            audioRecord.removeOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) someOtherListener);
+            // remove a valid listener
+            audioRecord.removeOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) listener);
+        } else {
+            // remove a listener we didn't add
+            audioRecord.removeOnRoutingChangedListener(
+                    (AudioRecord.OnRoutingChangedListener) someOtherListener);
+            // remove a valid listener
+            audioRecord.removeOnRoutingChangedListener(
+                    (AudioRecord.OnRoutingChangedListener) listener);
+        }
 
         Looper myLooper = prepareIfNeededLooper();
-        audioRecord.addOnRoutingChangedListener(listener, new Handler());
-
-        audioRecord.removeOnRoutingChangedListener(listener);
+        if (usesAudioRouting) {
+            audioRecord.addOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) listener, new Handler());
+            audioRecord.removeOnRoutingChangedListener(
+                    (AudioRouting.OnRoutingChangedListener) listener);
+        } else {
+            audioRecord.addOnRoutingChangedListener(
+                    (AudioRecord.OnRoutingChangedListener) listener, new Handler());
+            audioRecord.removeOnRoutingChangedListener(
+                    (AudioRecord.OnRoutingChangedListener) listener);
+        }
 
         audioRecord.release();
         if (myLooper != null) {
diff --git a/tests/tests/os/src/android/os/cts/RequiredComponentsTest.java b/tests/tests/os/src/android/os/cts/RequiredComponentsTest.java
new file mode 100644
index 0000000..378ac09
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/RequiredComponentsTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.cts;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.util.List;
+
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
+
+/**
+ * Tests whether all platform components that are implemented
+ * as APKs for various reasons are present.
+ */
+@RunWith(AndroidJUnit4.class)
+public class RequiredComponentsTest {
+    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+
+    @Test
+    public void testPackageInstallerPresent() throws Exception {
+        Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
+        installerIntent.addCategory(Intent.CATEGORY_DEFAULT);
+        installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
+        List<ResolveInfo> installers = InstrumentationRegistry.getContext()
+                .getPackageManager().queryIntentActivities(installerIntent, MATCH_SYSTEM_ONLY
+                        | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
+        if (installers.size() == 1) {
+            ResolveInfo resolveInfo = installers.get(0);
+            if (!resolveInfo.activityInfo.applicationInfo.isPrivilegedApp()) {
+                fail("The installer must be a privileged app");
+            }
+        } else {
+            fail("There must be exactly one installer; found " + installers);
+        }
+    }
+
+    @Test
+    public void testExtServicesPresent() throws Exception {
+        enforceSharedLibPresentAndProperlyHosted(
+                PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES,
+                ApplicationInfo.FLAG_SYSTEM,
+                ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+    }
+
+    @Test
+    public void testSharedServicesPresent() throws Exception {
+        enforceSharedLibPresentAndProperlyHosted(
+                PackageManager.SYSTEM_SHARED_LIBRARY_SHARED,
+                ApplicationInfo.FLAG_SYSTEM, 0);
+    }
+
+    private void enforceSharedLibPresentAndProperlyHosted(String libName,
+            int requiredHostAppFlags, int requiredHostAppPrivateFlags) throws Exception {
+        PackageManager packageManager = InstrumentationRegistry.getContext()
+                .getPackageManager();
+
+        // Is the lib present?
+        String[] libs = packageManager.getSystemSharedLibraryNames();
+        boolean libPresent = false;
+        for (String lib : libs) {
+            if (libName.equals(lib)) {
+                libPresent = true;
+                break;
+            }
+        }
+        if (!libPresent) {
+            fail("Missing required shared library:" + libName);
+        }
+
+        // Is it properly hosted?
+        String packageName = packageManager.getServicesSystemSharedLibraryPackageName();
+        PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0);
+
+        assertTrue(libName + " must be hosted by a system app with flags:"
+                + requiredHostAppFlags, (packageInfo.applicationInfo.flags
+                & requiredHostAppFlags) == requiredHostAppFlags);
+
+        assertTrue(libName + " must be hosted by a system app with private flags:"
+                + requiredHostAppPrivateFlags, (packageInfo.applicationInfo.privateFlags
+                & requiredHostAppPrivateFlags) == requiredHostAppPrivateFlags);
+    }
+}
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 9428695..22cf279 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 -->
@@ -141,43 +141,43 @@
     <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.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-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.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.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
     <protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
@@ -320,11 +320,11 @@
     <protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
 
     <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" />
@@ -347,9 +347,6 @@
     <protected-broadcast android:name="android.app.action.SYSTEM_UPDATE_POLICY_CHANGED" />
     <protected-broadcast android:name="android.app.action.DEVICE_OWNER_CHANGED" />
 
-    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_AVAILABLE" />
-    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNAVAILABLE" />
-
     <!-- Added in N -->
     <protected-broadcast android:name="android.intent.action.ANR" />
     <protected-broadcast android:name="android.intent.action.CALL" />
@@ -470,6 +467,9 @@
     <protected-broadcast android:name="com.android.internal.location.ALARM_TIMEOUT" />
     <protected-broadcast android:name="android.intent.action.GLOBAL_BUTTON" />
 
+    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_AVAILABLE" />
+    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNAVAILABLE" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
@@ -480,30 +480,31 @@
     <!-- ====================================================================== -->
     <eat-comment />
 
-    <!-- Used for runtime permissions related to user's contacts and profile. -->
+    <!-- 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                              -->
@@ -512,28 +513,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            -->
@@ -542,56 +543,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
@@ -606,10 +607,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                             -->
@@ -618,10 +619,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
@@ -646,10 +647,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
@@ -667,10 +668,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                          -->
@@ -679,28 +680,28 @@
 
     <!-- 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.
          <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" />
+        android:permissionGroup="android.permission-group.LOCATION"
+        android:label="@string/permlab_accessFineLocation"
+        android:description="@string/permdesc_accessFineLocation"
+        android:protectionLevel="dangerous" />
 
     <!-- Allows an app to access approximate 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" />
+        android:permissionGroup="android.permission-group.LOCATION"
+        android:label="@string/permlab_accessCoarseLocation"
+        android:description="@string/permdesc_accessCoarseLocation"
+        android:protectionLevel="dangerous" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device telephony                         -->
@@ -709,10 +710,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
@@ -728,21 +729,21 @@
          <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 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
@@ -750,10 +751,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
@@ -768,10 +769,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.
@@ -787,28 +788,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
@@ -816,10 +817,10 @@
          <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" />
 
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device microphone                        -->
@@ -830,19 +831,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                              -->
@@ -852,15 +853,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"/>
 
 
 
@@ -872,10 +873,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
@@ -887,10 +888,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" />
+        android:permissionGroup="android.permission-group.CAMERA"
+        android:label="@string/permlab_camera"
+        android:description="@string/permdesc_camera"
+        android:protectionLevel="dangerous" />
 
 
     <!-- ====================================================================== -->
@@ -901,28 +902,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                                                    -->
@@ -930,78 +931,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                                                    -->
@@ -1016,35 +1017,35 @@
          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. -->
     <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. -->
     <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. -->
@@ -1060,56 +1061,56 @@
          <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                    -->
     <!-- =============================================================== -->
     <eat-comment />
 
-    <!-- Allows an application to modify and remove existing voicemails in the system
+    <!-- Allows an application to modify and remove existing voicemails in the system.
         <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 -->
     <!-- ======================================= -->
     <eat-comment />
 
-    <!-- Allows an application to access extra location provider commands
+    <!-- Allows an application to access extra location provider commands.
          <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.
@@ -1117,7 +1118,7 @@
          @hide
     -->
     <permission android:name="android.permission.ACCESS_MOCK_LOCATION"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- ======================================= -->
     <!-- Permissions for accessing networks -->
@@ -1128,73 +1129,73 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.INTERNET"
-                android:description="@string/permdesc_createNetworkSockets"
-                android:label="@string/permlab_createNetworkSockets"
-                android:protectionLevel="normal" />
+        android:description="@string/permdesc_createNetworkSockets"
+        android:label="@string/permlab_createNetworkSockets"
+        android:protectionLevel="normal" />
 
-    <!-- Allows applications to access information about networks
+    <!-- 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" />
+        android:description="@string/permdesc_accessNetworkState"
+        android:label="@string/permlab_accessNetworkState"
+        android:protectionLevel="normal" />
 
     <!-- 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" />
 
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
@@ -1205,68 +1206,68 @@
          <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" />
 
     <!-- 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 -->
@@ -1274,18 +1275,26 @@
     <eat-comment />
 
     <!-- Allows access to the list of accounts in the Accounts Service.
-        <p>Protection level: normal
+
+    <p class="note"><strong>Note:</strong> Beginning with Android 6.0 (API level
+    23), if an app shares the signature of the authenticator that manages an
+    account, it does not need <code>"GET_ACCOUNTS"</code> permission to read
+    information about that account. On Android 5.1 and lower, all apps need
+    <code>"GET_ACCOUNTS"</code> permission to read information about any
+    account.</p>
+
+    <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" />
 
     <!-- @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-->
@@ -1296,34 +1305,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" />
+        android:label="@string/permlab_vibrate"
+        android:description="@string/permdesc_vibrate"
+        android:protectionLevel="normal" />
 
     <!-- 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" />
+        android:label="@string/permlab_wakeLock"
+        android:description="@string/permdesc_wakeLock"
+        android:protectionLevel="normal" />
 
     <!-- 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   -->
@@ -1334,9 +1343,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 -->
@@ -1346,68 +1355,68 @@
     <!-- @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" />
 
     <!-- @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 -->
@@ -1418,12 +1427,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 -->
@@ -1434,50 +1443,50 @@
          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 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.
@@ -1486,24 +1495,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" />
 
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
@@ -1513,7 +1522,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.
@@ -1523,14 +1532,14 @@
          <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" />
 
     <!-- ================================== -->
     <!-- Permissions for screenlock         -->
@@ -1541,9 +1550,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  -->
@@ -1552,9 +1561,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
@@ -1567,113 +1576,124 @@
          @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" />
 
-    <!-- @hide Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
+    <!-- @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. -->
+         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 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" />
 
     <!-- @SystemApi @hide Allows an application to retrieve a package's importance.
          This permission is not available to third party applications. -->
     <permission android:name="android.permission.GET_PACKAGE_IMPORTANCE"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- 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  -->
     <!-- ================================== -->
     <eat-comment />
 
-    <!-- Allows an application to open windows using the type
+    <!-- Allows an app to create windows using the type
          {@link android.view.WindowManager.LayoutParams#TYPE_SYSTEM_ALERT},
-         shown on top of all other applications.  Very few applications
+         shown on top of all other apps.  Very few apps
          should use this permission; these windows are intended for
-         system-level interaction with the user. -->
+         system-level interaction with the user.
+
+         <p class="note"><strong>Note:</strong> If the app
+         targets API level 23 or higher, the app user must explicitly grant
+         this permission to the app through a permission management screen. The app requests
+         the user's approval by sending an intent with action
+         {@link android.provider.Settings#ACTION_MANAGE_OVERLAY_PERMISSION}.
+         The app can check whether it has this authorization by calling
+         {@link android.provider.Settings#canDrawOverlays
+         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" />
 
     <!-- ================================== -->
     <!-- Permissions affecting the system wallpaper -->
@@ -1684,17 +1704,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 -->
@@ -1704,15 +1724,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>Protection level: normal
     -->
     <permission android:name="android.permission.SET_TIME_ZONE"
-                android:label="@string/permlab_setTimeZone"
-                android:description="@string/permdesc_setTimeZone"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_setTimeZone"
+        android:description="@string/permdesc_setTimeZone"
+        android:protectionLevel="normal" />
 
     <!-- ==================================================== -->
     <!-- Permissions related to changing status bar   -->
@@ -1723,9 +1743,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 -->
@@ -1736,17 +1756,17 @@
          <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"/>
 
     <!-- Allows an application to uninstall a shortcut in Launcher.
          <p>Protection level: normal
     -->
     <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   -->
@@ -1757,25 +1777,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 -->
@@ -1784,62 +1804,71 @@
 
     <!-- @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.
-         <p>Protection level: signature
+
+        <p class="note"><strong>Note:</strong> If the app targets API level 23
+        or higher, the app user
+        must explicitly grant this permission to the app through a permission management screen.
+        The app requests the user's approval by sending an intent with action
+        {@link android.provider.Settings#ACTION_MANAGE_WRITE_SETTINGS}. The app
+        can check whether it has this authorization by calling {@link
+        android.provider.Settings.System#canWrite Settings.System.canWrite()}.
+
+        <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" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to receive the
          {@link android.content.Intent#ACTION_BOOT_COMPLETED} that is
@@ -1855,9 +1884,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,
@@ -1866,90 +1895,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
@@ -1958,7 +1987,7 @@
          it off to the various individual installer components
          @hide -->
     <permission android:name="android.permission.UPDATE_CONFIG"
-                android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
@@ -1968,40 +1997,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                  -->
@@ -2010,34 +2039,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" />
 
-    <!-- @SystemApi Allows but does not guarantee access to user passwords at the conclusion of add
-         account -->
-    <permission android:name="android.permission.GET_PASSWORD_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" />
 
     <!-- @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.
@@ -2045,27 +2074,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 -->
+         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" />
 
-    <!-- Allows an application to update the user app op restrictions.
+    <!-- @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.
@@ -2073,7 +2103,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.
@@ -2081,17 +2111,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
@@ -2100,24 +2130,24 @@
          @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 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
@@ -2126,13 +2156,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
@@ -2140,7 +2170,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.
@@ -2148,42 +2178,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.
@@ -2192,7 +2222,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
@@ -2200,84 +2230,107 @@
          <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" />
+
+    <!-- @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" />
 
     <!-- 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 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}
+         to ensure that only the system can bind to it.
+         <p>Protection level: signature|privileged
+         <p>Not for use by third-party applications. </p>
+         @hide  -->
+    <permission android:name="android.permission.BIND_TV_REMOTE_SERVICE"
+        android:protectionLevel="signature|privileged" />
+
+    <!-- @SystemApi
+         Must be required for a virtual remote controller for TV.
+         <p>Protection level: signature|privileged
+         <p>Not for use by third-party applications. </p>
+         @hide  -->
+    <permission android:name="android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"
+        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" />
 
     <!-- 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.
@@ -2285,33 +2338,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 22 must hold this permission in
@@ -2319,292 +2372,290 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
-                android:label="@string/permlab_requestInstallPackages"
-                android:description="@string/permdesc_requestInstallPackages"
-                android:protectionLevel="normal" />
+        android:label="@string/permlab_requestInstallPackages"
+        android:description="@string/permdesc_requestInstallPackages"
+        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. -->
     <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" />
 
-    <!-- Allows an application to grant specific permissions.
+    <!-- @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" />
 
-    <!-- Allows an app that has this permission and the permissions to install packages
+    <!-- @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
-         @SystemApi -->
+         @hide -->
     <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
-                android:protectionLevel="signature|installer|verifier" />
+        android:protectionLevel="signature|installer|verifier" />
 
-    <!-- Allows an application to revoke specific permissions.
-        @hide
-        @SystemApi -->
+    <!-- @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 transforms applied to
          displays system-wide.
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM"
-                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 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. @hide -->
     <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:protectionLevel="normal" />
+        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
@@ -2613,25 +2664,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
@@ -2642,7 +2693,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
@@ -2652,33 +2703,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
@@ -2686,67 +2737,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,
@@ -2755,27 +2806,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" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- 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.
@@ -2786,42 +2837,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},
@@ -2829,7 +2880,7 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link
          android.service.notification.NotificationRankerService         to ensure that only the system can bind to it.
@@ -2837,7 +2888,7 @@
          @hide This is not a third-party API (intended for system apps). -->
     -->
     <permission android:name="android.permission.BIND_NOTIFICATION_RANKER_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
          android.service.chooser.ChooserTargetService}, to ensure that
@@ -2845,7 +2896,7 @@
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
-                android:protectionLevel="signature" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
          android.service.notification.ConditionProviderService},
@@ -2853,57 +2904,57 @@
          <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" />
 
     <!-- @SystemApi Allows an application to call into a carrier setup flow. It is up to the
          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
@@ -2911,9 +2962,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.
@@ -2921,7 +2972,7 @@
     <permission android:name="android.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT"
                 android:protectionLevel="signature" />
 
-    <!-- Allows applications to kill UIDs.
+    <!-- @SystemApi Allows applications to kill UIDs.
         <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.KILL_UID"
@@ -2959,7 +3010,7 @@
     <!-- Allows the holder to access the ephemeral applications on the device.
     @hide -->
     <permission android:name="android.permission.ACCESS_EPHEMERAL_APPS"
-                android:protectionLevel="signature" />
+            android:protectionLevel="signature" />
 
     <!-- Allows receiving the usage of media resource e.g. video/audio codec and
          graphic memory.
@@ -2971,7 +3022,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.
@@ -2995,17 +3046,17 @@
          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" />
 
     <!-- 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.
@@ -3026,12 +3077,12 @@
                  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:process=":ui">
+                android:theme="@style/Theme.DeviceDefault.Resolver"
+                android:finishOnCloseSystemDialogs="true"
+                android:excludeFromRecents="true"
+                android:documentLaunchMode="never"
+                android:relinquishTaskIdentity="true"
+                android:process=":ui">
             <intent-filter>
                 <action android:name="android.intent.action.CHOOSER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3039,102 +3090,102 @@
             </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.Material.Light.Dialog"
-                  android:label="@string/heavy_weight_switcher_title"
-                  android:finishOnCloseSystemDialogs="true"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Material.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.Material.Light.Dialog"
-                  android:label="@string/choose_account_label"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/choose_account_label"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/choose_account_label"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/choose_account_label"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
-                  android:excludeFromRecents="true"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/choose_account_label"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:theme="@style/Theme.Material.Light.Dialog"
+                android:label="@string/choose_account_label"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.CantAddAccountActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
-                  android:excludeFromRecents="true"
-                  android:exported="true"
-                  android:theme="@style/Theme.Material.Light.DialogWhenLarge"
-                  android:process=":ui">
+                android:excludeFromRecents="true"
+                android:exported="true"
+                android:theme="@style/Theme.Material.Light.DialogWhenLarge"
+                android:process=":ui">
         </activity>
 
         <activity android:name="android.content.SyncActivityTooManyDeletes"
-                  android:theme="@style/Theme.Material.Light.Dialog"
-                  android:label="@string/sync_too_many_deletes"
-                  android:process=":ui">
+               android:theme="@style/Theme.Material.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="android.intent.action.ACTION_REQUEST_SHUTDOWN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3146,9 +3197,9 @@
         </activity>
 
         <activity android:name="com.android.internal.app.NetInitiatedActivity"
-                  android:theme="@style/Theme.Material.Light.Dialog.Alert"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </activity>
 
         <activity android:name="com.android.internal.app.SystemUserHomeActivity"
@@ -3165,9 +3216,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.Material.Light.Dialog.Alert">
+                android:excludeFromRecents="true"
+                android:process=":ui"
+                android:theme="@style/Theme.Material.Light.Dialog.Alert">
             <intent-filter android:priority="1000">
                 <action android:name="android.os.action.CREATE_USER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3175,20 +3226,20 @@
         </activity>
 
         <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
-                  android:theme="@style/Theme.Material.Light.Dialog.Alert"
-                  android:excludeFromRecents="true"
-                  android:process=":ui">
+                android:theme="@style/Theme.Material.Light.Dialog.Alert"
+                android:excludeFromRecents="true"
+                android:process=":ui">
         </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="*/*" />
@@ -3196,7 +3247,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="*/*" />
@@ -3204,7 +3255,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="*/*" />
@@ -3212,7 +3263,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="android.intent.action.UPDATE_APN_DB" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3220,7 +3271,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="*/*" />
@@ -3228,7 +3279,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="*/*" />
@@ -3236,7 +3287,7 @@
         </receiver>
 
         <receiver android:name="com.android.server.updates.SELinuxPolicyInstallReceiver"
-                  android:permission="android.permission.UPDATE_CONFIG">
+                android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
                 <action android:name="android.intent.action.UPDATE_SEPOLICY" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
@@ -3244,7 +3295,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=MASTER_CLEAR -->
@@ -3257,12 +3308,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>
@@ -3287,9 +3338,9 @@
         </service>
 
         <service
-                android:name="com.android.server.pm.BackgroundDexOptService"
-                android:exported="true"
-                android:permission="android.permission.BIND_JOB_SERVICE">
+            android:name="com.android.server.pm.BackgroundDexOptService"
+            android:exported="true"
+            android:permission="android.permission.BIND_JOB_SERVICE">
         </service>
 
     </application>
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
index db7a974..18dc03d 100755
--- a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
@@ -29,6 +29,7 @@
 import android.telephony.SmsMessage;
 import android.telephony.TelephonyManager;
 import android.test.AndroidTestCase;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -262,6 +263,9 @@
             return;
         }
 
+        assertFalse("[RERUN] SIM card does not provide phone number. Use a suitable SIM Card.",
+                TextUtils.isEmpty(mDestAddr));
+
         String mccmnc = mTelephonyManager.getSimOperator();
 
         mSendIntent = new Intent(SMS_SEND_ACTION);
@@ -291,9 +295,11 @@
         // send single text sms
         init();
         sendTextMessage(mDestAddr, mDestAddr, mSentIntent, mDeliveredIntent);
-        assertTrue(mSendReceiver.waitForCalls(1, TIME_OUT));
+        assertTrue("[RERUN] Could not send SMS. Check signal.",
+                mSendReceiver.waitForCalls(1, TIME_OUT));
         if (mDeliveryReportSupported) {
-            assertTrue(mDeliveryReceiver.waitForCalls(1, TIME_OUT));
+            assertTrue("[RERUN] SMS message delivery notification not received. Check signal.",
+                    mDeliveryReceiver.waitForCalls(1, TIME_OUT));
         }
         // non-default app should receive only SMS_RECEIVED_ACTION
         assertTrue(mSmsReceivedReceiver.waitForCalls(1, TIME_OUT));
@@ -314,12 +320,14 @@
 
             init();
             sendDataMessage(mDestAddr, port, data, mSentIntent, mDeliveredIntent);
-            assertTrue(mSendReceiver.waitForCalls(1, TIME_OUT));
+            assertTrue("[RERUN] Could not send data SMS. Check signal.",
+                    mSendReceiver.waitForCalls(1, TIME_OUT));
             if (mDeliveryReportSupported) {
-                assertTrue(mDeliveryReceiver.waitForCalls(1, TIME_OUT));
+                assertTrue("[RERUN] Data SMS message delivery notification not received. " +
+                        "Check signal.", mDeliveryReceiver.waitForCalls(1, TIME_OUT));
             }
             mDataSmsReceiver.waitForCalls(1, TIME_OUT);
-            assertTrue(mReceivedDataSms);
+            assertTrue("[RERUN] Data SMS message not received. Check signal.", mReceivedDataSms);
             assertEquals(mReceivedText, mText);
         } else {
             // This GSM network doesn't support Data(binary) SMS message.
@@ -338,9 +346,11 @@
                 deliveryIntents.add(PendingIntent.getBroadcast(getContext(), 0, mDeliveryIntent, 0));
             }
             sendMultiPartTextMessage(mDestAddr, parts, sentIntents, deliveryIntents);
-            assertTrue(mSendReceiver.waitForCalls(numParts, TIME_OUT));
+            assertTrue("[RERUN] Could not send multi part SMS. Check signal.",
+                    mSendReceiver.waitForCalls(numParts, TIME_OUT));
             if (mDeliveryReportSupported) {
-              assertTrue(mDeliveryReceiver.waitForCalls(numParts, TIME_OUT));
+                assertTrue("[RERUN] Multi part SMS message delivery notification not received. " +
+                        "Check signal.", mDeliveryReceiver.waitForCalls(numParts, TIME_OUT));
             }
             // non-default app should receive only SMS_RECEIVED_ACTION
             assertTrue(mSmsReceivedReceiver.waitForCalls(1, TIME_OUT));
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index 366e061..ae9dda1 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -98,9 +98,7 @@
         });
         t.start();
         synchronized (mLock) {
-            while (!mOnCellLocationChangedCalled) {
-                mLock.wait();
-            }
+            mLock.wait(TOLERANCE);
         }
         assertTrue(mOnCellLocationChangedCalled);
 
diff --git a/tests/tests/text/res/layout/keylistener_layout.xml b/tests/tests/text/res/layout/keylistener_layout.xml
index cb8dbad..0ee015d 100644
--- a/tests/tests/text/res/layout/keylistener_layout.xml
+++ b/tests/tests/text/res/layout/keylistener_layout.xml
@@ -14,7 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  -->
-<EditText xmlns:android="http://schemas.android.com/apk/res/android"
+<android.text.method.cts.EditTextNoIme
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/keylistener_textview"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
diff --git a/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
index 3d5335d..87e1e1a 100644
--- a/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
@@ -982,7 +982,7 @@
         ArrowKeyMovementMethod method = new ArrowKeyMovementMethod();
         SpannableString spannable = new SpannableString("Test Content");
         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
-        TextView view = new TextView(getActivity());
+        TextView view = new TextViewNoIme(getActivity());
 
         assertFalse(method.onKeyUp(view, spannable, KeyEvent.KEYCODE_0, event));
         assertFalse(method.onKeyUp(null, null, 0, null));
@@ -1393,7 +1393,7 @@
     }
 
     private void initTextViewWithNullLayout(CharSequence text) {
-        mTextView = new TextView(getActivity());
+        mTextView = new TextViewNoIme(getActivity());
         mTextView.setText(text, BufferType.EDITABLE);
         assertNull(mTextView.getLayout());
         mEditable = (Editable) mTextView.getText();
diff --git a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
index fa2e262..1705326 100644
--- a/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
+++ b/tests/tests/text/src/android/text/method/cts/BackspaceTest.java
@@ -16,18 +16,14 @@
 
 package android.text.method.cts;
 
-import android.app.Activity;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.text.InputType;
 import android.text.method.BaseKeyListener;
-import android.text.method.cts.KeyListenerTestCase;
 import android.view.KeyEvent;
-import android.widget.EditText;
 import android.widget.TextView.BufferType;
 
 /**
- * Test backspace key handling of {@link android.text.method.BaseKeyListner}.
+ * Test backspace key handling of {@link android.text.method.BaseKeyListener}.
  */
 public class BackspaceTest extends KeyListenerTestCase {
     private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
diff --git a/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java
index 8fa8780..d913cf9 100644
--- a/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java
@@ -16,16 +16,15 @@
 
 package android.text.method.cts;
 
+import android.cts.util.KeyEventUtil;
 import android.os.SystemClock;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.method.BaseKeyListener;
-import android.text.method.cts.KeyListenerTestCase;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
-import android.widget.TextView;
 import android.widget.TextView.BufferType;
 
 /**
@@ -34,6 +33,14 @@
 public class BaseKeyListenerTest extends KeyListenerTestCase {
     private static final CharSequence TEST_STRING = "123456";
 
+    private KeyEventUtil mKeyEventUtil;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mKeyEventUtil = new KeyEventUtil(getInstrumentation());
+    }
+
     public void testBackspace() {
         testBackspace(0);
     }
@@ -129,12 +136,12 @@
 
         // Delete the first character '1'
         prepTextViewSync(TEST_STRING, mockBaseKeyListener, true, 1, 1);
-        sendKeys(KeyEvent.KEYCODE_DEL);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
         assertEquals("23456", mTextView.getText().toString());
 
         // Delete character '2' and '3'
         prepTextViewSync(TEST_STRING, mockBaseKeyListener, true, 1, 3);
-        sendKeys(KeyEvent.KEYCODE_DEL);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
         assertEquals("1456", mTextView.getText().toString());
 
         // Delete everything on the line the cursor is on.
@@ -149,7 +156,7 @@
 
         // DEL key does not take effect when TextView does not have BaseKeyListener.
         prepTextViewSync(TEST_STRING, null, true, 1, 1);
-        sendKeys(KeyEvent.KEYCODE_DEL);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
         assertEquals(TEST_STRING, mTextView.getText().toString());
     }
 
@@ -499,19 +506,19 @@
 
         // press '0' key.
         prepTextViewSync(TEST_STRING, mockBaseKeyListener, true, 0, 0);
-        sendKeys(KeyEvent.KEYCODE_0);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_0);
         assertEquals("123456", mTextView.getText().toString());
 
         // delete character '2'
         prepTextViewSync(mTextView.getText(), mockBaseKeyListener, true, 1, 2);
-        sendKeys(KeyEvent.KEYCODE_DEL);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_DEL);
         assertEquals("13456", mTextView.getText().toString());
 
         // test ACTION_MULTIPLE KEYCODE_UNKNOWN key event.
         KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), "abcd",
                 KeyCharacterMap.BUILT_IN_KEYBOARD, 0);
         prepTextViewSync(mTextView.getText(), mockBaseKeyListener, true, 2, 2);
-        mInstrumentation.sendKeySync(event);
+        mKeyEventUtil.sendKey(mTextView, event);
         mInstrumentation.waitForIdleSync();
         // the text of TextView is never changed, onKeyOther never works.
 //        assertEquals("13abcd456", mTextView.getText().toString());
@@ -558,12 +565,14 @@
      * Sends alt-delete key combo via {@link #sendKeys(int... keys)}.
      */
     private void sendAltDelete() {
-        mInstrumentation.sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ALT_LEFT));
-        mInstrumentation.sendKeySync(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
+        mKeyEventUtil.sendKey(mTextView, new KeyEvent(KeyEvent.ACTION_DOWN,
+                KeyEvent.KEYCODE_ALT_LEFT));
+        mKeyEventUtil.sendKey(mTextView, new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
                 KeyEvent.KEYCODE_DEL, 0, KeyEvent.META_ALT_ON));
-        mInstrumentation.sendKeySync(new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+        mKeyEventUtil.sendKey(mTextView, new KeyEvent(0, 0, KeyEvent.ACTION_UP,
                 KeyEvent.KEYCODE_DEL, 0, KeyEvent.META_ALT_ON));
-        mInstrumentation.sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ALT_LEFT));
+        mKeyEventUtil.sendKey(mTextView, new KeyEvent(KeyEvent.ACTION_UP,
+                KeyEvent.KEYCODE_ALT_LEFT));
     }
 
     /**
diff --git a/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java b/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java
index 6ab79ad..b348c28 100644
--- a/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java
+++ b/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java
@@ -18,17 +18,13 @@
 
 
 import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.method.CharacterPickerDialog;
 import android.view.View;
-import android.widget.AdapterView;
 import android.widget.Gallery;
-import android.widget.TextView;
 
 public class CharacterPickerDialogTest extends
         ActivityInstrumentationTestCase2<CtsActivity> {
@@ -48,7 +44,7 @@
     public void testConstructor() {
         final CharSequence str = "123456";
         final Editable content = Editable.Factory.getInstance().newEditable(str);
-        final View view = new TextView(mActivity);
+        final View view = new TextViewNoIme(mActivity);
         new CharacterPickerDialog(view.getContext(), view, content, "\u00A1", false);
 
         try {
@@ -68,7 +64,7 @@
         final Gallery parent = new Gallery(mActivity);
         final CharSequence str = "123456";
         Editable text = Editable.Factory.getInstance().newEditable(str);
-        final View view = new TextView(mActivity);
+        final View view = new TextViewNoIme(mActivity);
         CharacterPickerDialog replacePickerDialog =
                 new CharacterPickerDialog(view.getContext(), view, text, "abc", false);
 
@@ -109,7 +105,7 @@
     public void testOnClick() {
         final CharSequence str = "123456";
         final Editable content = Editable.Factory.getInstance().newEditable(str);
-        final View view = new TextView(mActivity);
+        final View view = new TextViewNoIme(mActivity);
         CharacterPickerDialog characterPickerDialog =
                 new CharacterPickerDialog(view.getContext(), view, content, "\u00A1", false);
 
diff --git a/tests/tests/text/src/android/text/method/cts/DateKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/DateKeyListenerTest.java
index 067a62e..7642d91 100644
--- a/tests/tests/text/src/android/text/method/cts/DateKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/DateKeyListenerTest.java
@@ -16,16 +16,24 @@
 
 package android.text.method.cts;
 
+import android.cts.util.KeyEventUtil;
 import android.text.InputType;
-import android.text.method.cts.KeyListenerTestCase;
 import android.text.method.DateKeyListener;
 import android.view.KeyEvent;
-import android.widget.TextView;
 
 /**
  * Test {@link android.text.method.DateKeyListener}.
  */
 public class DateKeyListenerTest extends KeyListenerTestCase {
+
+    private KeyEventUtil mKeyEventUtil;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mKeyEventUtil = new KeyEventUtil(getInstrumentation());
+    }
+
     public void testConstructor() {
         new DateKeyListener();
     }
@@ -69,26 +77,26 @@
         assertEquals("", mTextView.getText().toString());
 
         // press '1' key.
-        sendKeys(KeyEvent.KEYCODE_1);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_1);
         assertEquals("1", mTextView.getText().toString());
 
         // press '2' key.
-        sendKeys(KeyEvent.KEYCODE_2);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_2);
         assertEquals("12", mTextView.getText().toString());
 
         // press an unaccepted key if it exists.
         int keyCode = TextMethodUtils.getUnacceptedKeyCode(DateKeyListener.CHARACTERS);
         if (-1 != keyCode) {
-            sendKeys(keyCode);
+            mKeyEventUtil.sendKeys(mTextView, keyCode);
             assertEquals("12", mTextView.getText().toString());
         }
 
         // press '-' key.
-        sendKeys(KeyEvent.KEYCODE_MINUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_MINUS);
         assertEquals("12-", mTextView.getText().toString());
 
         // press '/' key.
-        sendKeys(KeyEvent.KEYCODE_SLASH);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_SLASH);
         assertEquals("12-/", mTextView.getText().toString());
 
         // remove DateKeyListener
@@ -96,7 +104,7 @@
         assertEquals("12-/", mTextView.getText().toString());
 
         // press '/' key, it will not be accepted.
-        sendKeys(KeyEvent.KEYCODE_SLASH);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_SLASH);
         assertEquals("12-/", mTextView.getText().toString());
     }
 
diff --git a/tests/tests/text/src/android/text/method/cts/DateTimeKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/DateTimeKeyListenerTest.java
index 03683dc..9dfc38a 100644
--- a/tests/tests/text/src/android/text/method/cts/DateTimeKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/DateTimeKeyListenerTest.java
@@ -16,16 +16,25 @@
 
 package android.text.method.cts;
 
+import android.cts.util.KeyEventUtil;
 import android.text.InputType;
-import android.text.method.cts.KeyListenerTestCase;
 import android.text.method.DateTimeKeyListener;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 
 /**
- * Test {@link android.DateTimeKeyListener}.
+ * Test {@link android.text.method.DateTimeKeyListener}.
  */
 public class DateTimeKeyListenerTest extends KeyListenerTestCase {
+
+    private KeyEventUtil mKeyEventUtil;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mKeyEventUtil = new KeyEventUtil(getInstrumentation());
+    }
+
     public void testConstructor() {
         new DateTimeKeyListener();
     }
@@ -71,12 +80,12 @@
         assertEquals(expectedText, mTextView.getText().toString());
 
         // press '1' key.
-        mInstrumentation.sendStringSync("1");
+        mKeyEventUtil.sendString(mTextView, "1");
         expectedText += "1";
         assertEquals(expectedText, mTextView.getText().toString());
 
         // press '2' key.
-        mInstrumentation.sendStringSync("2");
+        mKeyEventUtil.sendString(mTextView, "2");
         expectedText += "2";
         assertEquals(expectedText, mTextView.getText().toString());
 
@@ -84,28 +93,28 @@
         KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
         if ('a' == kcm.getMatch(KeyEvent.KEYCODE_A, DateTimeKeyListener.CHARACTERS)) {
             expectedText += "a";
-            mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_A);
+            mKeyEventUtil.sendKeyDownUp(mTextView, KeyEvent.KEYCODE_A);
             assertEquals(expectedText, mTextView.getText().toString());
         }
 
         // press 'p' key if producible
         if ('p' == kcm.getMatch(KeyEvent.KEYCODE_P, DateTimeKeyListener.CHARACTERS)) {
             expectedText += "p";
-            mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_P);
+            mKeyEventUtil.sendKeyDownUp(mTextView, KeyEvent.KEYCODE_P);
             assertEquals(expectedText, mTextView.getText().toString());
         }
 
         // press 'm' key if producible
         if ('m' == kcm.getMatch(KeyEvent.KEYCODE_M, DateTimeKeyListener.CHARACTERS)) {
             expectedText += "m";
-            mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_M);
+            mKeyEventUtil.sendKeyDownUp(mTextView, KeyEvent.KEYCODE_M);
             assertEquals(expectedText, mTextView.getText().toString());
         }
 
         // press an unaccepted key if it exists.
         int keyCode = TextMethodUtils.getUnacceptedKeyCode(DateTimeKeyListener.CHARACTERS);
         if (-1 != keyCode) {
-            sendKeys(keyCode);
+            mKeyEventUtil.sendKeys(mTextView, keyCode);
             assertEquals(expectedText, mTextView.getText().toString());
         }
 
@@ -113,7 +122,7 @@
         setKeyListenerSync(null);
         assertEquals(expectedText, mTextView.getText().toString());
 
-        mInstrumentation.sendStringSync("1");
+        mKeyEventUtil.sendString(mTextView, "1");
         assertEquals(expectedText, mTextView.getText().toString());
     }
 
diff --git a/tests/tests/text/src/android/text/method/cts/DialerKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/DialerKeyListenerTest.java
index 9456c7e..219869c 100644
--- a/tests/tests/text/src/android/text/method/cts/DialerKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/DialerKeyListenerTest.java
@@ -19,7 +19,6 @@
 import android.text.InputType;
 import android.text.Spannable;
 import android.text.SpannableString;
-import android.text.method.cts.KeyListenerTestCase;
 import android.text.method.DialerKeyListener;
 import android.view.KeyEvent;
 
diff --git a/tests/tests/text/src/android/text/method/cts/DigitsKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/DigitsKeyListenerTest.java
index 33a23e3..3170482 100644
--- a/tests/tests/text/src/android/text/method/cts/DigitsKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/DigitsKeyListenerTest.java
@@ -16,11 +16,11 @@
 
 package android.text.method.cts;
 
+import android.cts.util.KeyEventUtil;
 import android.text.InputType;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.Spanned;
-import android.text.method.cts.KeyListenerTestCase;
 import android.text.method.DigitsKeyListener;
 import android.view.KeyEvent;
 
@@ -28,6 +28,15 @@
  * Test {@link DigitsKeyListener}.
  */
 public class DigitsKeyListenerTest extends KeyListenerTestCase {
+
+    private KeyEventUtil mKeyEventUtil;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mKeyEventUtil = new KeyEventUtil(getInstrumentation());
+    }
+
     public void testConstructor() {
         new DigitsKeyListener();
 
@@ -394,19 +403,19 @@
         assertEquals("", mTextView.getText().toString());
 
         // press '-' key.
-        sendKeys(KeyEvent.KEYCODE_MINUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_MINUS);
         assertEquals("", mTextView.getText().toString());
 
         // press '1' key.
-        sendKeys(KeyEvent.KEYCODE_1);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_1);
         assertEquals("1", mTextView.getText().toString());
 
         // press '.' key.
-        sendKeys(KeyEvent.KEYCODE_PERIOD);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PERIOD);
         assertEquals("1", mTextView.getText().toString());
 
         // press '2' key.
-        sendKeys(KeyEvent.KEYCODE_2);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_2);
         assertEquals("12", mTextView.getText().toString());
     }
 
@@ -428,27 +437,27 @@
         assertEquals("", mTextView.getText().toString());
 
         // press '-' key.
-        sendKeys(KeyEvent.KEYCODE_MINUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_MINUS);
         assertEquals("-", mTextView.getText().toString());
 
         // press '1' key.
-        sendKeys(KeyEvent.KEYCODE_1);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_1);
         assertEquals("-1", mTextView.getText().toString());
 
         // press '.' key.
-        sendKeys(KeyEvent.KEYCODE_PERIOD);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PERIOD);
         assertEquals("-1", mTextView.getText().toString());
 
         // press '+' key.
-        sendKeys(KeyEvent.KEYCODE_PLUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PLUS);
         assertEquals("-1", mTextView.getText().toString());
 
         // press '2' key.
-        sendKeys(KeyEvent.KEYCODE_2);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_2);
         assertEquals("-12", mTextView.getText().toString());
 
         // press '-' key.
-        sendKeys(KeyEvent.KEYCODE_MINUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_MINUS);
         assertEquals("-12", mTextView.getText().toString());
     }
 
@@ -470,27 +479,27 @@
         assertEquals("", mTextView.getText().toString());
 
         // press '-' key.
-        sendKeys(KeyEvent.KEYCODE_MINUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_MINUS);
         assertEquals("", mTextView.getText().toString());
 
         // press '+' key.
-        sendKeys(KeyEvent.KEYCODE_PLUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PLUS);
         assertEquals("", mTextView.getText().toString());
 
         // press '1' key.
-        sendKeys(KeyEvent.KEYCODE_1);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_1);
         assertEquals("1", mTextView.getText().toString());
 
         // press '.' key.
-        sendKeys(KeyEvent.KEYCODE_PERIOD);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PERIOD);
         assertEquals("1.", mTextView.getText().toString());
 
         // press '2' key.
-        sendKeys(KeyEvent.KEYCODE_2);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_2);
         assertEquals("1.2", mTextView.getText().toString());
 
         // press '.' key.
-        sendKeys(KeyEvent.KEYCODE_PERIOD);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PERIOD);
         assertEquals("1.2", mTextView.getText().toString());
     }
 
@@ -514,27 +523,27 @@
         assertEquals("", mTextView.getText().toString());
 
         // press '+' key.
-        sendKeys(KeyEvent.KEYCODE_PLUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PLUS);
         assertEquals("+", mTextView.getText().toString());
 
         // press '1' key.
-        sendKeys(KeyEvent.KEYCODE_1);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_1);
         assertEquals("+1", mTextView.getText().toString());
 
         // press '.' key.
-        sendKeys(KeyEvent.KEYCODE_PERIOD);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PERIOD);
         assertEquals("+1.", mTextView.getText().toString());
 
         // press '2' key.
-        sendKeys(KeyEvent.KEYCODE_2);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_2);
         assertEquals("+1.2", mTextView.getText().toString());
 
         // press '-' key.
-        sendKeys(KeyEvent.KEYCODE_MINUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_MINUS);
         assertEquals("+1.2", mTextView.getText().toString());
 
         // press '.' key.
-        sendKeys(KeyEvent.KEYCODE_PERIOD);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PERIOD);
         assertEquals("+1.2", mTextView.getText().toString());
     }
 
@@ -555,19 +564,19 @@
         assertEquals("", mTextView.getText().toString());
 
         // press '1' key.
-        sendKeys(KeyEvent.KEYCODE_1);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_1);
         assertEquals("", mTextView.getText().toString());
 
         // press '5' key.
-        sendKeys(KeyEvent.KEYCODE_5);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_5);
         assertEquals("5", mTextView.getText().toString());
 
         // press '.' key.
-        sendKeys(KeyEvent.KEYCODE_PERIOD);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_PERIOD);
         assertEquals("5", mTextView.getText().toString());
 
         // press '-' key.
-        sendKeys(KeyEvent.KEYCODE_MINUS);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_MINUS);
         assertEquals("5", mTextView.getText().toString());
 
         // remove DigitsKeyListener
@@ -581,7 +590,7 @@
         assertEquals("5", mTextView.getText().toString());
 
         // press '5' key.
-        sendKeys(KeyEvent.KEYCODE_5);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_5);
         assertEquals("5", mTextView.getText().toString());
     }
 
diff --git a/tests/tests/text/src/android/text/method/cts/EditTextNoIme.java b/tests/tests/text/src/android/text/method/cts/EditTextNoIme.java
new file mode 100644
index 0000000..cdb7511
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/EditTextNoIme.java
@@ -0,0 +1,51 @@
+/*
+ * 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.text.method.cts;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.widget.EditText;
+
+/**
+ * An EditText that returns null for onCreateInputConnection.
+ */
+public class EditTextNoIme extends EditText {
+
+    public EditTextNoIme(Context context) {
+        super(context);
+    }
+
+    public EditTextNoIme(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public EditTextNoIme(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public EditTextNoIme(Context context, AttributeSet attrs, int defStyleAttr,
+                         int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        return null;
+    }
+}
diff --git a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
index 47c2795..40ed593 100644
--- a/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ForwardDeleteTest.java
@@ -16,14 +16,10 @@
 
 package android.text.method.cts;
 
-import android.app.Activity;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.text.InputType;
 import android.text.method.BaseKeyListener;
-import android.text.method.cts.KeyListenerTestCase;
 import android.view.KeyEvent;
-import android.widget.EditText;
 import android.widget.TextView.BufferType;
 
 /**
diff --git a/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
index 520b91f..d8de43d 100644
--- a/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
@@ -65,7 +65,7 @@
         mMethod = new LinkMovementMethod();
 
         // Set the content view with a text view which contains 3 lines,
-        mView = new TextView(getActivity());
+        mView = new TextViewNoIme(getActivity());
         mView.setText(CONTENT, BufferType.SPANNABLE);
         getInstrumentation().runOnMainSync(new Runnable() {
             public void run() {
@@ -129,7 +129,7 @@
 
         // null parameters
         try {
-            method.onTakeFocus(new TextView(getActivity()), null, View.FOCUS_RIGHT);
+            method.onTakeFocus(new TextViewNoIme(getActivity()), null, View.FOCUS_RIGHT);
             fail("The method did not throw NullPointerException when param spannable is null.");
         } catch (NullPointerException e) {
             // expected
@@ -228,7 +228,7 @@
         LinkMovementMethod method = new LinkMovementMethod();
         // always returns false
         assertFalse(method.onKeyUp(null, null, 0, null));
-        assertFalse(method.onKeyUp(new TextView(getActivity()), null, 0, null));
+        assertFalse(method.onKeyUp(new TextViewNoIme(getActivity()), null, 0, null));
         assertFalse(method.onKeyUp(null, new SpannableString("blahblah"), 0, null));
         assertFalse(method.onKeyUp(null, null, KeyEvent.KEYCODE_0,
                 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0)));
diff --git a/tests/tests/text/src/android/text/method/cts/NumberKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/NumberKeyListenerTest.java
index fa0db0d..09053f1 100644
--- a/tests/tests/text/src/android/text/method/cts/NumberKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/NumberKeyListenerTest.java
@@ -16,22 +16,28 @@
 
 package android.text.method.cts;
 
+import android.cts.util.KeyEventUtil;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.Spanned;
-import android.text.method.cts.KeyListenerTestCase;
 import android.text.method.NumberKeyListener;
 import android.view.KeyEvent;
-import android.view.View;
-import android.widget.TextView;
 import android.widget.TextView.BufferType;
 
 
 public class NumberKeyListenerTest extends KeyListenerTestCase {
     private MockNumberKeyListener mMockNumberKeyListener;
 
+    private KeyEventUtil mKeyEventUtil;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mKeyEventUtil = new KeyEventUtil(getInstrumentation());
+    }
+
     /**
      * Check point:
      * 1. Filter "Android test", return "".
@@ -138,13 +144,13 @@
         mInstrumentation.waitForIdleSync();
         assertEquals("123456", mTextView.getText().toString());
         // press '0' key.
-        sendKeys(KeyEvent.KEYCODE_0);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_0);
         assertEquals("0123456", mTextView.getText().toString());
 
         // an unaccepted key if it exists.
         int keyCode = TextMethodUtils.getUnacceptedKeyCode(MockNumberKeyListener.DIGITS);
         if (-1 != keyCode) {
-            sendKeys(keyCode);
+            mKeyEventUtil.sendKeys(mTextView, keyCode);
             // text of TextView will not be changed.
             assertEquals("0123456", mTextView.getText().toString());
         }
@@ -157,7 +163,7 @@
         });
         mInstrumentation.waitForIdleSync();
         // press '0' key.
-        sendKeys(KeyEvent.KEYCODE_0);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_0);
         assertEquals("0123456", mTextView.getText().toString());
     }
 
diff --git a/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java
index ea679c5..490a062 100644
--- a/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java
@@ -17,6 +17,7 @@
 package android.text.method.cts;
 
 
+import android.cts.util.KeyEventUtil;
 import android.cts.util.PollingCheck;
 import android.graphics.Rect;
 import android.os.ParcelFileDescriptor;
@@ -66,6 +67,8 @@
         super("android.text.cts", CtsActivity.class);
     }
 
+    private KeyEventUtil mKeyEventUtil;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -80,7 +83,7 @@
         try {
             runTestOnUiThread(new Runnable() {
                 public void run() {
-                    EditText editText = new EditText(mActivity);
+                    EditText editText = new EditTextNoIme(mActivity);
                     editText.setId(EDIT_TXT_ID);
                     editText.setTransformationMethod(mMethod);
                     Button button = new Button(mActivity);
@@ -102,6 +105,8 @@
         mEditText = (EditText) getActivity().findViewById(EDIT_TXT_ID);
         assertTrue(mEditText.isFocused());
 
+        mKeyEventUtil = new KeyEventUtil(getInstrumentation());
+
         enableAppOps();
         savePasswordPref();
         switchShowPassword(true);
@@ -157,10 +162,10 @@
         KeyCharacterMap keymap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
         if (keymap.getKeyboardType() == KeyCharacterMap.NUMERIC) {
             // "HELLO" in case of 12-key(NUMERIC) keyboard
-            sendKeys("6*4 6*3 7*5 DPAD_RIGHT 7*5 7*6 DPAD_RIGHT");
+            mKeyEventUtil.sendKeys(mEditText, "6*4 6*3 7*5 DPAD_RIGHT 7*5 7*6 DPAD_RIGHT");
         }
         else {
-            sendKeys("H E 2*L O");
+            mKeyEventUtil.sendKeys(mEditText, "H E 2*L O");
         }
         assertTrue(mMethod.hasCalledBeforeTextChanged());
         assertTrue(mMethod.hasCalledOnTextChanged());
@@ -221,14 +226,14 @@
         // lose focus
         mMethod.reset();
         assertTrue(mEditText.isFocused());
-        sendKeys("DPAD_DOWN");
+        mKeyEventUtil.sendKeys(mEditText, "DPAD_DOWN");
         assertFalse(mEditText.isFocused());
         assertTrue(mMethod.hasCalledOnFocusChanged());
 
         // gain focus
         mMethod.reset();
         assertFalse(mEditText.isFocused());
-        sendKeys("DPAD_UP");
+        mKeyEventUtil.sendKeys(mEditText, "DPAD_UP");
         assertTrue(mEditText.isFocused());
         assertTrue(mMethod.hasCalledOnFocusChanged());
     }
diff --git a/tests/tests/text/src/android/text/method/cts/QwertyKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/QwertyKeyListenerTest.java
index b66e19a..39deda3 100644
--- a/tests/tests/text/src/android/text/method/cts/QwertyKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/QwertyKeyListenerTest.java
@@ -20,12 +20,9 @@
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
-import android.text.method.cts.KeyListenerTestCase;
 import android.text.method.QwertyKeyListener;
-import android.text.method.TextKeyListener;
 import android.text.method.TextKeyListener.Capitalize;
 import android.view.KeyEvent;
-import android.widget.TextView;
 import android.widget.TextView.BufferType;
 
 public class QwertyKeyListenerTest extends KeyListenerTestCase {
diff --git a/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java
index 6b3e149..e0b8011 100644
--- a/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java
@@ -17,10 +17,8 @@
 package android.text.method.cts;
 
 
-import android.graphics.Rect;
 import android.test.ActivityInstrumentationTestCase2;
 import android.text.method.ReplacementTransformationMethod;
-import android.view.View;
 import android.widget.EditText;
 
 /**
@@ -43,7 +41,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mEditText = new EditText(getActivity());
+        mEditText = new EditTextNoIme(getActivity());
     }
 
     public void testGetTransformation() {
diff --git a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
index 49196bdc..3333a88 100644
--- a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
@@ -60,7 +60,7 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mTextView = new TextView(getActivity());
+        mTextView = new TextViewNoIme(getActivity());
         mTextView.setText(THREE_LINES_TEXT, BufferType.EDITABLE);
         mSpannable = (Spannable) mTextView.getText();
         mScaledTouchSlop = ViewConfiguration.get(getActivity()).getScaledTouchSlop();
@@ -649,7 +649,7 @@
         ScrollingMovementMethod method = new ScrollingMovementMethod();
         SpannableString spannable = new SpannableString("Test Content");
         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
-        TextView view = new TextView(getActivity());
+        TextView view = new TextViewNoIme(getActivity());
 
         assertFalse(method.onKeyUp(view, spannable, KeyEvent.KEYCODE_0, event));
         assertFalse(method.onKeyUp(null, null, 0, null));
diff --git a/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java
index 1756a0f..2f8789a 100644
--- a/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java
@@ -19,7 +19,6 @@
 
 import android.test.ActivityInstrumentationTestCase2;
 import android.text.method.SingleLineTransformationMethod;
-import android.view.View;
 import android.widget.EditText;
 
 /**
@@ -54,7 +53,7 @@
         CharSequence result = method.getTransformation("hello\nworld\r", null);
         assertEquals("hello world\uFEFF", result.toString());
 
-        EditText editText = new EditText(getActivity());
+        EditText editText = new EditTextNoIme(getActivity());
         editText.setText("hello\nworld\r");
         // TODO cannot get transformed text from the view
     }
diff --git a/tests/tests/text/src/android/text/method/cts/TextKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/TextKeyListenerTest.java
index 3e09a60..19003cf 100644
--- a/tests/tests/text/src/android/text/method/cts/TextKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/TextKeyListenerTest.java
@@ -16,6 +16,7 @@
 
 package android.text.method.cts;
 
+import android.cts.util.KeyEventUtil;
 import android.os.SystemClock;
 import android.test.UiThreadTest;
 import android.text.Editable;
@@ -23,13 +24,10 @@
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
-import android.text.method.cts.KeyListenerTestCase;
 import android.text.method.TextKeyListener;
 import android.text.method.TextKeyListener.Capitalize;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
-import android.view.View;
-import android.widget.TextView;
 import android.widget.TextView.BufferType;
 
 public class TextKeyListenerTest extends KeyListenerTestCase {
@@ -38,6 +36,14 @@
      */
     private static final long TIME_OUT = 3000;
 
+    private KeyEventUtil mKeyEventUtil;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mKeyEventUtil = new KeyEventUtil(getInstrumentation());
+    }
+
     public void testConstructor() {
         new TextKeyListener(Capitalize.NONE, true);
 
@@ -192,7 +198,7 @@
         mInstrumentation.waitForIdleSync();
         assertEquals("", mTextView.getText().toString());
 
-        sendKeys(KeyEvent.KEYCODE_4);
+        mKeyEventUtil.sendKeys(mTextView, KeyEvent.KEYCODE_4);
         waitForListenerTimeout();
         String text = mTextView.getText().toString();
         int keyType = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD).getKeyboardType();
@@ -226,7 +232,7 @@
         // test ACTION_MULTIPLE KEYCODE_UNKNOWN key event.
         KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), text,
                 1, KeyEvent.FLAG_WOKE_HERE);
-        mInstrumentation.sendKeySync(event);
+        mKeyEventUtil.sendKey(mTextView, event);
         mInstrumentation.waitForIdleSync();
         // the text of TextView is never changed, onKeyOther never works.
 //        assertEquals(text, mTextView.getText().toString()); issue 1731439
diff --git a/tests/tests/text/src/android/text/method/cts/TextViewNoIme.java b/tests/tests/text/src/android/text/method/cts/TextViewNoIme.java
new file mode 100644
index 0000000..1ff63ef
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/TextViewNoIme.java
@@ -0,0 +1,51 @@
+/*
+ * 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.text.method.cts;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.widget.TextView;
+
+/**
+ * A TextView that returns null for onCreateInputConnection.
+ */
+public class TextViewNoIme extends TextView {
+
+    public TextViewNoIme(Context context) {
+        super(context);
+    }
+
+    public TextViewNoIme(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public TextViewNoIme(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public TextViewNoIme(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        return null;
+    }
+}
diff --git a/tests/tests/text/src/android/text/method/cts/TimeKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/TimeKeyListenerTest.java
index 7d8631b..4f68d54 100644
--- a/tests/tests/text/src/android/text/method/cts/TimeKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/TimeKeyListenerTest.java
@@ -16,13 +16,22 @@
 
 package android.text.method.cts;
 
+import android.cts.util.KeyEventUtil;
 import android.text.InputType;
-import android.text.method.cts.KeyListenerTestCase;
 import android.text.method.TimeKeyListener;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 
 public class TimeKeyListenerTest extends KeyListenerTestCase {
+
+    private KeyEventUtil mKeyEventUtil;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mKeyEventUtil = new KeyEventUtil(getInstrumentation());
+    }
+
     public void testConstructor() {
         new TimeKeyListener();
     }
@@ -67,12 +76,12 @@
         assertEquals(expectedText, mTextView.getText().toString());
 
         // press '1' key.
-        mInstrumentation.sendStringSync("1");
+        mKeyEventUtil.sendString(mTextView, "1");
         expectedText += "1";
         assertEquals(expectedText, mTextView.getText().toString());
 
         // press '2' key.
-        mInstrumentation.sendStringSync("2");
+        mKeyEventUtil.sendString(mTextView, "2");
         expectedText += "2";
         assertEquals("12", mTextView.getText().toString());
 
@@ -80,35 +89,35 @@
         KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
         if ('a' == kcm.getMatch(KeyEvent.KEYCODE_A, TimeKeyListener.CHARACTERS)) {
             expectedText += "a";
-            mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_A);
+            mKeyEventUtil.sendKeyDownUp(mTextView, KeyEvent.KEYCODE_A);
             assertEquals(expectedText, mTextView.getText().toString());
         }
 
         // press 'p' key if producible
         if ('p' == kcm.getMatch(KeyEvent.KEYCODE_P, TimeKeyListener.CHARACTERS)) {
             expectedText += "p";
-            mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_P);
+            mKeyEventUtil.sendKeyDownUp(mTextView, KeyEvent.KEYCODE_P);
             assertEquals(expectedText, mTextView.getText().toString());
         }
 
         // press 'm' key if producible
         if ('m' == kcm.getMatch(KeyEvent.KEYCODE_M, TimeKeyListener.CHARACTERS)) {
             expectedText += "m";
-            mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_M);
+            mKeyEventUtil.sendKeyDownUp(mTextView, KeyEvent.KEYCODE_M);
             assertEquals(expectedText, mTextView.getText().toString());
         }
 
         // press an unaccepted key if it exists.
         int keyCode = TextMethodUtils.getUnacceptedKeyCode(TimeKeyListener.CHARACTERS);
         if (-1 != keyCode) {
-            sendKeys(keyCode);
+            mKeyEventUtil.sendKeys(mTextView, keyCode);
             assertEquals(expectedText, mTextView.getText().toString());
         }
 
         setKeyListenerSync(null);
 
         // press '1' key.
-        mInstrumentation.sendStringSync("1");
+        mKeyEventUtil.sendString(mTextView, "1");
         assertEquals(expectedText, mTextView.getText().toString());
     }
 
diff --git a/tests/tests/text/src/android/text/method/cts/TouchTest.java b/tests/tests/text/src/android/text/method/cts/TouchTest.java
index 3e26084..8204287 100644
--- a/tests/tests/text/src/android/text/method/cts/TouchTest.java
+++ b/tests/tests/text/src/android/text/method/cts/TouchTest.java
@@ -21,7 +21,6 @@
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.text.Layout;
-import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.TextPaint;
 import android.text.method.Touch;
@@ -53,7 +52,7 @@
     }
 
     public void testScrollTo() throws Throwable {
-        final TextView tv = new TextView(mActivity);
+        final TextView tv = new TextViewNoIme(mActivity);
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mActivity.setContentView(tv);
@@ -105,7 +104,7 @@
     }
 
     public void testOnTouchEvent() throws Throwable {
-        final TextView tv = new TextView(mActivity);
+        final TextView tv = new TextViewNoIme(mActivity);
 
         // Create a string that is wider than the screen.
         DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics();
diff --git a/tests/tests/util/src/android/util/cts/LocaleListTest.java b/tests/tests/util/src/android/util/cts/LocaleListTest.java
index e64d955..7693adf 100644
--- a/tests/tests/util/src/android/util/cts/LocaleListTest.java
+++ b/tests/tests/util/src/android/util/cts/LocaleListTest.java
@@ -32,22 +32,6 @@
         assertNull(ll.get(1));
         assertNull(ll.get(10));
 
-        ll = new LocaleList((Locale) null);
-        assertNotNull(ll);
-        assertTrue(ll.isEmpty());
-        assertEquals(0, ll.size());
-        assertNull(ll.get(0));
-        assertNull(ll.get(1));
-        assertNull(ll.get(10));
-
-        ll = new LocaleList((Locale[]) null);
-        assertNotNull(ll);
-        assertTrue(ll.isEmpty());
-        assertEquals(0, ll.size());
-        assertNull(ll.get(0));
-        assertNull(ll.get(1));
-        assertNull(ll.get(10));
-
         ll = new LocaleList(new Locale[0]);
         assertNotNull(ll);
         assertTrue(ll.isEmpty());
@@ -78,6 +62,21 @@
         assertNull(ll.get(10));
     }
 
+    public void testNullArgument() {
+        try {
+            LocaleList ll = new LocaleList((Locale) null);
+            fail("Initializing a LocaleList with a null argument should throw.");
+        } catch (Throwable e) {
+            assertEquals(NullPointerException.class, e.getClass());
+        }
+        try {
+            LocaleList ll = new LocaleList((Locale[]) null);
+            fail("Initializing a LocaleList with a null array should throw.");
+        } catch (Throwable e) {
+            assertEquals(NullPointerException.class, e.getClass());
+        }
+    }
+
     public void testNullArguments() {
         final Locale[] la = {Locale.US, null};
         LocaleList ll = null;
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index 31126f8..2862de5 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -147,6 +147,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.view.cts.PixelCopyVideoSourceActivity"
+            android:label="PixelCopyVideoSourceActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.view.cts.FocusFinderCtsActivity"
             android:label="FocusFinderCtsActivity">
             <intent-filter>
diff --git a/tests/tests/view/res/raw/colorgrid_video.mp4 b/tests/tests/view/res/raw/colorgrid_video.mp4
new file mode 100644
index 0000000..1be8bee
--- /dev/null
+++ b/tests/tests/view/res/raw/colorgrid_video.mp4
Binary files differ
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyTests.java b/tests/tests/view/src/android/view/cts/PixelCopyTests.java
index b54ecb9..1555d00 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyTests.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyTests.java
@@ -28,6 +28,7 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
+import android.util.Log;
 import android.view.PixelCopy;
 import android.view.Surface;
 import android.view.SurfaceView;
@@ -54,10 +55,16 @@
 
 @MediumTest
 public class PixelCopyTests {
+    private static final String TAG = "PixelCopyTests";
+
     @Rule
     public ActivityTestRule<GLSurfaceViewCtsActivity> mGLSurfaceViewActivityRule =
             new ActivityTestRule<>(GLSurfaceViewCtsActivity.class, false, false);
 
+    @Rule
+    public ActivityTestRule<PixelCopyVideoSourceActivity> mVideoSourceActivityRule =
+            new ActivityTestRule<>(PixelCopyVideoSourceActivity.class, false, false);
+
     private Instrumentation mInstrumentation;
 
     @Before
@@ -163,6 +170,36 @@
         }
     }
 
+    @Test
+    public void testVideoProducer() throws InterruptedException {
+        PixelCopyVideoSourceActivity activity =
+                mVideoSourceActivityRule.launchActivity(null);
+        if (!activity.canPlayVideo()) {
+            Log.i(TAG, "Skipping testVideoProducer, video codec isn't supported");
+        }
+        // This returns when the video has been prepared and playback has
+        // been started, it doesn't necessarily means a frame has actually been
+        // produced. There sadly isn't a callback for that.
+        // So we'll try for up to 300ms after this event to acquire a frame, otherwise
+        // it's considered a timeout.
+        activity.waitForPlaying();
+        SynchronousPixelCopy copyHelper = new SynchronousPixelCopy();
+        Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+        int copyResult = PixelCopy.ERROR_SOURCE_NO_DATA;
+        for (int i = 0; i < 30; i++) {
+            copyResult = copyHelper.request(activity.getVideoView(), bitmap);
+            if (copyResult != PixelCopy.ERROR_SOURCE_NO_DATA) {
+                break;
+            }
+            Thread.sleep(10);
+        }
+        assertEquals(PixelCopy.SUCCESS, copyResult);
+        // A large threshold is used because decoder accuracy is covered in the
+        // media CTS tests, so we are mainly interested in verifying that rotation
+        // and YUV->RGB conversion were handled properly.
+        assertBitmapQuadColor(bitmap, Color.RED, Color.GREEN, Color.BLUE, Color.BLACK, 30);
+    }
+
     private static int getPixelFloatPos(Bitmap bitmap, float xpos, float ypos) {
         return bitmap.getPixel((int) (bitmap.getWidth() * xpos), (int) (bitmap.getHeight() * ypos));
     }
@@ -176,6 +213,22 @@
         assertEquals("Bottom right", bottomRight, getPixelFloatPos(bitmap, .75f, .75f));
     }
 
+    private void assertBitmapQuadColor(Bitmap bitmap, int topLeft, int topRight,
+            int bottomLeft, int bottomRight, int threshold) {
+        // Just quickly sample 4 pixels in the various regions.
+        assertTrue("Top left", pixelsAreSame(topLeft, getPixelFloatPos(bitmap, .25f, .25f), threshold));
+        assertTrue("Top right", pixelsAreSame(topRight, getPixelFloatPos(bitmap, .75f, .25f), threshold));
+        assertTrue("Bottom left", pixelsAreSame(bottomLeft, getPixelFloatPos(bitmap, .25f, .75f), threshold));
+        assertTrue("Bottom right", pixelsAreSame(bottomRight, getPixelFloatPos(bitmap, .75f, .75f), threshold));
+    }
+
+    private boolean pixelsAreSame(int ideal, int given, int threshold) {
+        int error = Math.abs(Color.red(ideal) - Color.red(given));
+        error += Math.abs(Color.green(ideal) - Color.green(given));
+        error += Math.abs(Color.blue(ideal) - Color.blue(given));
+        return (error < threshold);
+    }
+
     private static class QuadColorGLRenderer implements Renderer {
 
         private final int mTopLeftColor;
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyVideoSourceActivity.java b/tests/tests/view/src/android/view/cts/PixelCopyVideoSourceActivity.java
new file mode 100644
index 0000000..08e3951
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/PixelCopyVideoSourceActivity.java
@@ -0,0 +1,60 @@
+/*
+ * 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.view.cts;
+
+import android.app.Activity;
+import android.cts.util.MediaUtils;
+import android.net.Uri;
+import android.os.Bundle;
+import android.widget.VideoView;
+
+import java.util.concurrent.CountDownLatch;
+
+public class PixelCopyVideoSourceActivity extends Activity {
+    private VideoView mVideoView;
+    private CountDownLatch mVideoPlayingFence = new CountDownLatch(1);
+    private boolean mCanPlayVideo;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mVideoView = new VideoView(this);
+        mVideoView.setOnPreparedListener(mp -> {
+            mp.setLooping(true);
+            mVideoView.start();
+            mVideoPlayingFence.countDown();
+        });
+        mCanPlayVideo = MediaUtils.hasCodecsForResource(this, R.raw.colorgrid_video);
+        if (mCanPlayVideo) {
+            Uri uri = Uri.parse("android.resource://android.view.cts/" + R.raw.colorgrid_video);
+            mVideoView.setVideoURI(uri);
+        }
+        setContentView(mVideoView);
+    }
+
+    public boolean canPlayVideo() {
+        return mCanPlayVideo;
+    }
+
+    public void waitForPlaying() throws InterruptedException {
+        mVideoPlayingFence.await();
+    }
+
+    public VideoView getVideoView() {
+        return mVideoView;
+    }
+}
diff --git a/tools/cts-device-info/Android.mk b/tools/cts-device-info/Android.mk
index 4b43d39..f4c0a5c 100644
--- a/tools/cts-device-info/Android.mk
+++ b/tools/cts-device-info/Android.mk
@@ -25,7 +25,8 @@
 
 DEVICE_INFO_ACTIVITIES := \
     com.android.compatibility.common.deviceinfo.GlesStubActivity \
-    com.android.cts.deviceinfo.CameraDeviceInfo
+    com.android.cts.deviceinfo.CameraDeviceInfo \
+    com.android.cts.deviceinfo.SensorDeviceInfo
 
 LOCAL_PACKAGE_NAME := CtsDeviceInfo
 
diff --git a/tools/cts-device-info/src/com/android/cts/deviceinfo/SensorDeviceInfo.java b/tools/cts-device-info/src/com/android/cts/deviceinfo/SensorDeviceInfo.java
new file mode 100644
index 0000000..1d266f5
--- /dev/null
+++ b/tools/cts-device-info/src/com/android/cts/deviceinfo/SensorDeviceInfo.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 com.android.cts.deviceinfo;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.os.Bundle;
+
+import com.android.compatibility.common.deviceinfo.DeviceInfo;
+import com.android.compatibility.common.util.DeviceInfoStore;
+
+import java.lang.Exception;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Sensor device info collector.
+ */
+public class SensorDeviceInfo extends DeviceInfo {
+
+    private static final String SENSOR = "sensor";
+    private static final String REPORTING_MODE = "reporting_mode";
+    private static final String NAME = "name";
+    private static final String VENDOR = "vendor";
+    private static final String TYPE = "type";
+    private static final String VERSION = "version";
+    private static final String MAXIMUM_RANGE = "maximum_range";
+    private static final String RESOLUTION = "resolution";
+    private static final String POWER = "power";
+    private static final String MIN_DELAY = "min_delay";
+    private static final String FIFO_RESERVED_EVENT_COUNT =
+            "fifo_reserved_event_count";
+    private static final String FIFO_MAX_EVENT_COUNT = "fifo_max_event_count";
+    private static final String STRING_TYPE = "string_type";
+    private static final String ID = "id";
+    private static final String MAX_DELAY = "max_delay";
+    private static final String IS_WAKE_UP_SENSOR = "is_wake_up_sensor";
+    private static final String IS_DYNAMIC_SENSOR = "is_dynamic_sensor";
+    private static final String IS_ADDITONAL_INFO_SUPPORTED =
+            "is_additional_info_supported";
+
+    @Override
+    protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
+        SensorManager sensorManager = (SensorManager)
+                getContext().getSystemService(Context.SENSOR_SERVICE);
+        List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
+        store.startArray(SENSOR);
+        for (Sensor sensor : sensors) {
+            store.startGroup();
+            store.addResult(REPORTING_MODE, sensor.getReportingMode());
+            store.addResult(NAME, sensor.getName());
+            store.addResult(VENDOR, sensor.getVendor());
+            store.addResult(TYPE, sensor.getType());
+            store.addResult(VERSION, sensor.getVersion());
+            store.addResult(MAXIMUM_RANGE, sensor.getMaximumRange());
+            store.addResult(RESOLUTION, sensor.getResolution());
+            store.addResult(POWER, sensor.getPower());
+            store.addResult(MIN_DELAY, sensor.getMinDelay());
+            store.addResult(FIFO_RESERVED_EVENT_COUNT,
+                    sensor.getFifoReservedEventCount());
+            store.addResult(FIFO_MAX_EVENT_COUNT,
+                    sensor.getFifoMaxEventCount());
+            store.addResult(STRING_TYPE, sensor.getStringType());
+            store.addResult(ID, sensor.getId());
+            store.addResult(MAX_DELAY, sensor.getMaxDelay());
+            store.addResult(IS_WAKE_UP_SENSOR, sensor.isWakeUpSensor());
+            store.addResult(IS_DYNAMIC_SENSOR, sensor.isDynamicSensor());
+            store.addResult(IS_ADDITONAL_INFO_SUPPORTED,
+                    sensor.isAdditionalInfoSupported());
+            store.endGroup();
+        }
+        store.endArray(); // Sensor
+    }
+}