Merge "Fallout from HardwareBuffer API update." into oc-dev am: 54c4dff2c5
am: fca5ce2a99

Change-Id: Ifab707c8faf5bcf49f1f732fa62ae307f99f446b
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index a613050..cf7af39 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -69,6 +69,9 @@
     <!-- Needed by the Audio Quality Verifier to store the sound samples that will be mailed. -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
+    <!-- Needed for Telecom self-managed ConnectionService tests. -->
+    <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
+
     <application android:label="@string/app_name"
             android:icon="@drawable/icon"
             android:backupAgent="VerifierBackupAgent"
@@ -1640,7 +1643,6 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_camera" />
-            <meta-data android:name="test_required_features" android:value="android.hardware.sensor.gyroscope" />
             <meta-data android:name="test_required_features" android:value="android.hardware.camera.any"/>
         </activity>
         <activity
@@ -3091,6 +3093,22 @@
             <meta-data
                 android:name="test_required_features"
                 android:value="android.hardware.telephony"/>
+            </activity>
+
+        <activity
+            android:name=".telecom.SelfManagedIncomingCallTestActivity"
+            android:label="@string/telecom_incoming_self_mgd_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.cts.intent.category.MANUAL_TEST"/>
+            </intent-filter>
+
+            <meta-data
+                android:name="test_category"
+                android:value="@string/test_category_telecom"/>
+            <meta-data
+                android:name="test_required_features"
+                android:value="android.hardware.telephony"/>
         </activity>
 
         <activity
diff --git a/apps/CtsVerifier/res/layout/telecom_self_managed_answer.xml b/apps/CtsVerifier/res/layout/telecom_self_managed_answer.xml
new file mode 100644
index 0000000..27aa55a
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/telecom_self_managed_answer.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/telecom_incoming_self_mgd_info"/>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+
+        <ImageView
+            android:id="@+id/step_1_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true" />
+        <TextView
+            android:id="@+id/step_1_instructions"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/telecom_incoming_self_mgd_step_1"
+            android:textSize="16dp"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentTop="true"
+            android:layout_toRightOf="@id/step_1_status" />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_below="@id/step_1_instructions"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_toRightOf="@id/step_1_status"
+            android:id="@+id/telecom_incoming_self_mgd_register_button"
+            android:text="@string/telecom_incoming_self_mgd_register_button"/>
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+
+        <ImageView
+            android:id="@+id/step_2_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true" />
+        <TextView
+            android:id="@+id/step_2_instructions"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/telecom_incoming_self_mgd_step_2"
+            android:textSize="16dp"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentTop="true"
+            android:layout_toRightOf="@id/step_2_status" />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_below="@id/step_2_instructions"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_toRightOf="@id/step_2_status"
+            android:id="@+id/telecom_incoming_self_mgd_show_ui_button"
+            android:text="@string/telecom_incoming_self_mgd_show_ui_button"/>
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+
+        <ImageView
+            android:id="@+id/step_3_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true" />
+        <TextView
+            android:id="@+id/step_3_instructions"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/telecom_incoming_self_mgd_step_3"
+            android:textSize="16dp"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentTop="true"
+            android:layout_toRightOf="@id/step_3_status" />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_below="@id/step_3_instructions"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:layout_toRightOf="@id/step_3_status"
+            android:id="@+id/telecom_incoming_self_mgd_confirm_answer_button"
+            android:text="@string/telecom_incoming_self_mgd_confirm_answer_button"/>
+    </RelativeLayout>
+
+    <include layout="@layout/pass_fail_buttons" />
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 2ed436c..4ff871c 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -3911,11 +3911,11 @@
     <string name="telecom_outgoing_call_step_2">
         Click the button below to dial an outgoing call. This will populate the default dialer
         app with a dummy phone number. Initiate the phone call from the dialer app, then return
-        to this screen.
+        to this screen while the call is still in progress.
     </string>
     <string name="telecom_outgoing_call_dial_button">Dial</string>
     <string name="telecom_outgoing_call_step_3">
-        Click the button below to confirm that the outgoing call was correctly made.
+        Click the button below to confirm that the ongoing outgoing call was correctly made.
     </string>
     <string name="telecom_outgoing_call_confirm_button">Confirm</string>
 
@@ -3936,12 +3936,30 @@
     <string name="telecom_incoming_call_step_2">
         Click the button below to initiate an incoming call. The phone should start ringing.
         Answer the call, confirm that you can hear an audio clip with Eisenhower\'s voice, then
-        return to this screen.
+        return to this screen while the call is still ongoing.
     </string>
     <string name="telecom_incoming_call_dial_button">Dial</string>
     <string name="telecom_incoming_call_step_3">
-        Click the button below to confirm that the incoming call was properly answered and that
-        audio was audible.
+        Click the button below to confirm that the ongoing incoming call was properly answered and
+        that audio is audible.
     </string>
     <string name="telecom_incoming_call_confirm_button">Confirm</string>
+    <string name="telecom_incoming_self_mgd_test"> Incoming Self-Managed Connection Test</string>
+    <string name="telecom_incoming_self_mgd_info">
+        This test verifies that incoming calls from a Self-Managed Connection Service will trigger
+        a Telecom-managed incoming call UI when there is already an ongoing call on the device.
+    </string>
+    <string name="telecom_incoming_self_mgd_step_1">
+        Click the button below to register a test self-managed ConnectionService.
+    </string>
+    <string name="telecom_incoming_self_mgd_register_button">Register Self-Managed ConnectionService</string>
+    <string name="telecom_incoming_self_mgd_step_2">
+        Click the button below to test that the system incoming call notification shows.  When the
+        notification shows, "answer" the call.
+    </string>
+    <string name="telecom_incoming_self_mgd_show_ui_button">Show System Incoming UI</string>
+    <string name="telecom_incoming_self_mgd_step_3">
+        Click the button below to confirm that the incoming call was answered.
+    </string>
+    <string name="telecom_incoming_self_mgd_confirm_answer_button">Confirm Answer</string>
 </resources>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java
index c935841..c004b73 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java
@@ -20,12 +20,16 @@
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
+import android.telecom.CallAudioState;
 import android.telecom.Connection;
 import android.telecom.DisconnectCause;
 import android.telecom.VideoProfile;
 
 import com.android.cts.verifier.R;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
  * An implementation of the {@link android.telecom.Connection} class used by the
  * {@link CtsConnectionService}.
@@ -51,6 +55,7 @@
     private final Listener mListener;
     private final MediaPlayer mMediaPlayer;
     private final Context mContext;
+    private CountDownLatch mWaitForCallAudioStateChanged = new CountDownLatch(1);
 
     public CtsConnection(Context context, boolean isIncomingCall,
             Listener listener, boolean hasAudio) {
@@ -131,6 +136,20 @@
         }
     }
 
+    public void onCallAudioStateChanged(CallAudioState state) {
+        mWaitForCallAudioStateChanged.countDown();
+        mWaitForCallAudioStateChanged = new CountDownLatch(1);
+
+    }
+
+    public void waitForAudioStateChanged() {
+        try {
+            mWaitForCallAudioStateChanged.await(CtsConnectionService.TIMEOUT_MILLIS,
+                    TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+        }
+    }
+
     private void setDisconnectedAndDestroy(DisconnectCause cause) {
         setDisconnected(cause);
         destroy();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
index 528c221..7cfcbf8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
@@ -26,35 +26,74 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * CTS Verifier ConnectionService implementation.
  */
 public class CtsConnectionService extends ConnectionService {
+    static final int TIMEOUT_MILLIS = 10000;
 
     private CtsConnection.Listener mConnectionListener =
             new CtsConnection.Listener() {
                 @Override
                 void onDestroyed(CtsConnection connection) {
-                    mConnections.remove(connection);
+                    synchronized (mConnectionsLock) {
+                        mConnections.remove(connection);
+                    }
                 }
             };
 
     private static CtsConnectionService sConnectionService;
+    private static CountDownLatch sBindingLatch = new CountDownLatch(1);
 
     private List<CtsConnection> mConnections = new ArrayList<>();
+    private Object mConnectionsLock = new Object();
+    private CountDownLatch mConnectionLatch = new CountDownLatch(1);
 
     public static CtsConnectionService getConnectionService() {
         return sConnectionService;
     }
 
+    public static CtsConnectionService waitForAndGetConnectionService() {
+        if (sConnectionService == null) {
+            try {
+                sBindingLatch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+            }
+        }
+        return sConnectionService;
+    }
+
     public CtsConnectionService() throws Exception {
         super();
         sConnectionService = this;
+        if (sBindingLatch != null) {
+            sBindingLatch.countDown();
+        }
+        sBindingLatch = new CountDownLatch(1);
     }
 
     public List<CtsConnection> getConnections() {
-        return mConnections;
+        synchronized (mConnectionsLock) {
+            return new ArrayList<CtsConnection>(mConnections);
+        }
+    }
+
+    public CtsConnection waitForAndGetConnection() {
+        try {
+            mConnectionLatch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+        }
+        mConnectionLatch = new CountDownLatch(1);
+        synchronized (mConnectionsLock) {
+            if (mConnections.size() > 0) {
+                return mConnections.get(0);
+            } else {
+                return null;
+            }
+        }
     }
 
     @Override
@@ -109,7 +148,12 @@
         connection.putExtras(moreExtras);
         connection.setVideoState(request.getVideoState());
 
-        mConnections.add(connection);
+        synchronized (mConnectionsLock) {
+            mConnections.add(connection);
+        }
+        if (mConnectionLatch != null) {
+            mConnectionLatch.countDown();
+        }
         return connection;
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java
index cdc8665..e134b51 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java
@@ -57,6 +57,19 @@
             .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
             .build();
 
+    public static final String TEST_SELF_MAANGED_PHONE_ACCOUNT2_ID = "selfMgdTest2";
+    public static final String TEST_SELF_MANAGED_PHONE_ACCOUNT2_LABEL = "CTSVerifier2";
+
+    public static final PhoneAccountHandle TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2 =
+            new PhoneAccountHandle(new ComponentName(
+                    PassFailButtons.class.getPackage().getName(),
+                    CtsConnectionService.class.getName()), TEST_SELF_MAANGED_PHONE_ACCOUNT2_ID);
+    public static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT_2 = new PhoneAccount.Builder(
+            TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2, TEST_SELF_MANAGED_PHONE_ACCOUNT2_LABEL)
+            .setAddress(TEST_SELF_MANAGED_PHONE_ACCOUNT_ADDRESS)
+            .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
+            .build();
+
     /**
      * Registers the test phone account.
      * @param context The context.
@@ -96,6 +109,7 @@
         TelecomManager telecomManager = (TelecomManager) context.getSystemService(
                 Context.TELECOM_SERVICE);
         telecomManager.registerPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT);
+        telecomManager.registerPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT_2);
     }
 
     /**
@@ -119,4 +133,15 @@
                 Context.TELECOM_SERVICE);
         return telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL);
     }
+
+    /**
+     * Retrieves the test phone account, or null if not registered.
+     * @param context The context.
+     * @return The Phone Account.
+     */
+    public static PhoneAccount getSelfManagedPhoneAccount2(Context context) {
+        TelecomManager telecomManager = (TelecomManager) context.getSystemService(
+                Context.TELECOM_SERVICE);
+        return telecomManager.getPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2);
+    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java
new file mode 100644
index 0000000..530b246
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.cts.verifier.telecom;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.telecom.Connection;
+import android.telecom.PhoneAccount;
+import android.telecom.TelecomManager;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import java.util.List;
+
+/**
+ * This test verifies functionality associated with the Self-Managed
+ * {@link android.telecom.ConnectionService} APIs.  It ensures that Telecom will show an incoming
+ * call UI when a new incoming self-managed call is added when there is already an ongoing managed
+ * call or when there is an ongoing self-managed call in another app.
+ */
+public class SelfManagedIncomingCallTestActivity extends PassFailButtons.Activity {
+    private Uri TEST_DIAL_NUMBER_1 = Uri.fromParts("tel", "6505551212", null);
+    private Uri TEST_DIAL_NUMBER_2 = Uri.fromParts("tel", "4085551212", null);
+
+    private ImageView mStep1Status;
+    private Button mRegisterPhoneAccount;
+    private ImageView mStep2Status;
+    private Button mShowUi;
+    private ImageView mStep3Status;
+    private Button mConfirm;
+
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        View view = getLayoutInflater().inflate(R.layout.telecom_self_managed_answer, null);
+        setContentView(view);
+        setInfoResources(R.string.telecom_incoming_self_mgd_test,
+                R.string.telecom_incoming_self_mgd_info, -1);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+
+        mStep1Status = view.findViewById(R.id.step_1_status);
+        mRegisterPhoneAccount = view.findViewById(R.id.telecom_incoming_self_mgd_register_button);
+        mRegisterPhoneAccount.setOnClickListener(v -> {
+            PhoneAccountUtils.registerTestSelfManagedPhoneAccount(this);
+            PhoneAccount account = PhoneAccountUtils.getSelfManagedPhoneAccount(this);
+            PhoneAccount account2 = PhoneAccountUtils.getSelfManagedPhoneAccount2(this);
+            if (account != null &&
+                    account.isEnabled() &&
+                    account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) &&
+                    account2 != null &&
+                    account2.isEnabled() &&
+                    account2.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) {
+                mRegisterPhoneAccount.setEnabled(false);
+                mShowUi.setEnabled(true);
+                mStep1Status.setImageResource(R.drawable.fs_good);
+            } else {
+                mStep1Status.setImageResource(R.drawable.fs_error);
+            }
+        });
+
+        mStep2Status = view.findViewById(R.id.step_2_status);
+        mShowUi = view.findViewById(R.id.telecom_incoming_self_mgd_show_ui_button);
+        mShowUi.setOnClickListener(v -> {
+            (new AsyncTask<Void, Void, Throwable>() {
+                @Override
+                protected Throwable doInBackground(Void... params) {
+                    try {
+                        Bundle extras = new Bundle();
+                        extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
+                                TEST_DIAL_NUMBER_1);
+                        TelecomManager telecomManager =
+                                (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
+                        if (telecomManager == null) {
+                            mStep2Status.setImageResource(R.drawable.fs_error);
+                            return new Throwable("Could not get telecom service.");
+                        }
+                        telecomManager.addNewIncomingCall(
+                                PhoneAccountUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE, extras);
+
+                        CtsConnectionService ctsConnectionService =
+                                CtsConnectionService.waitForAndGetConnectionService();
+                        if (ctsConnectionService == null) {
+                            mStep2Status.setImageResource(R.drawable.fs_error);
+                            return new Throwable("Could not get connection service.");
+                        }
+
+                        CtsConnection connection = ctsConnectionService.waitForAndGetConnection();
+                        if (connection == null) {
+                            mStep2Status.setImageResource(R.drawable.fs_error);
+                            return new Throwable("Could not get connection.");
+                        }
+                        // Wait until the connection knows its audio state changed; at this point
+                        // Telecom knows about the connection and can answer.
+                        connection.waitForAudioStateChanged();
+                        // Make it active to simulate an answer.
+                        connection.setActive();
+
+                        // Place the second call. It should trigger the incoming call UX.
+                        Bundle extras2 = new Bundle();
+                        extras2.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
+                                TEST_DIAL_NUMBER_2);
+                        telecomManager.addNewIncomingCall(
+                                PhoneAccountUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE_2,
+                                extras2);
+
+                        return null;
+                    } catch (Throwable t) {
+                        return  t;
+                    }
+                }
+
+                @Override
+                protected void onPostExecute(Throwable t) {
+                    if (t == null) {
+                        mStep2Status.setImageResource(R.drawable.fs_good);
+                        mShowUi.setEnabled(false);
+                        mConfirm.setEnabled(true);
+                    } else {
+                        mStep2Status.setImageResource(R.drawable.fs_error);
+                    }
+                }
+            }).execute();
+
+
+        });
+
+        mStep3Status = view.findViewById(R.id.step_2_status);
+        mConfirm = view.findViewById(R.id.telecom_incoming_self_mgd_confirm_answer_button);
+        mConfirm.setOnClickListener(v -> {
+            CtsConnectionService ctsConnectionService = CtsConnectionService.getConnectionService();
+            if (ctsConnectionService == null) {
+                mStep3Status.setImageResource(R.drawable.fs_error);
+                return;
+            }
+            List<CtsConnection> connections = ctsConnectionService.getConnections();
+            if (connections.size() != 1) {
+                mStep3Status.setImageResource(R.drawable.fs_error);
+                return;
+            }
+
+            if (connections.get(0).getState() == Connection.STATE_ACTIVE) {
+                mStep3Status.setImageResource(R.drawable.fs_good);
+                getPassButton().setEnabled(true);
+            } else {
+                mStep3Status.setImageResource(R.drawable.fs_error);
+            }
+        });
+
+        mShowUi.setEnabled(false);
+        mConfirm.setEnabled(false);
+    }
+}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
index cd80500..c0483e2 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
@@ -675,6 +675,8 @@
      */
     void setupFilters() throws DeviceNotAvailableException {
         if (mRetrySessionId != null) {
+            // Load the invocation result
+            IInvocationResult result = null;
             RetryFilterHelper helper = new RetryFilterHelper(mBuildHelper, mRetrySessionId);
             helper.validateBuildFingerprint(mDevice);
             helper.setAllOptionsFrom(this);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
index 4e7c8c2..78f023b 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
@@ -18,6 +18,7 @@
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelperTest;
 import com.android.compatibility.common.tradefed.command.CompatibilityConsoleTest;
 import com.android.compatibility.common.tradefed.config.ConfigurationFactoryTest;
+import com.android.compatibility.common.tradefed.presubmit.CtsConfigLoadingTest;
 import com.android.compatibility.common.tradefed.presubmit.IntegrationTest;
 import com.android.compatibility.common.tradefed.presubmit.PresubmitSetupValidation;
 import com.android.compatibility.common.tradefed.presubmit.ValidateTestsAbi;
@@ -60,6 +61,7 @@
     ConfigurationFactoryTest.class,
 
     // presubmit
+    CtsConfigLoadingTest.class,
     IntegrationTest.class,
     PresubmitSetupValidation.class,
     ValidateTestsAbi.class,
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
new file mode 100644
index 0000000..03732b3
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.compatibility.common.tradefed.presubmit;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.compatibility.common.tradefed.targetprep.ApkInstaller;
+import com.android.tradefed.config.ConfigurationException;
+import com.android.tradefed.config.ConfigurationFactory;
+import com.android.tradefed.config.IConfiguration;
+import com.android.tradefed.targetprep.ITargetPreparer;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+/**
+ * Test that configuration in CTS can load and have expected properties.
+ */
+public class CtsConfigLoadingTest {
+
+    /**
+     * Test that configuration shipped in Tradefed can be parsed.
+     * -> Exclude deprecated ApkInstaller.
+     */
+    @Test
+    public void testConfigurationLoad() throws Exception {
+        String ctsRoot = System.getProperty("CTS_ROOT");
+        File testcases = new File(ctsRoot, "/android-cts/testcases/");
+        if (!testcases.exists()) {
+            fail(String.format("%s does not exists", testcases));
+            return;
+        }
+        File[] listConfig = testcases.listFiles(new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                if (name.endsWith(".config")) {
+                    return true;
+                }
+                return false;
+            }
+        });
+        assertTrue(listConfig.length > 0);
+        // We expect to be able to load every single config in testcases/
+        for (File config : listConfig) {
+            IConfiguration c = ConfigurationFactory.getInstance()
+                    .createConfigurationFromArgs(new String[] {config.getAbsolutePath()});
+            for (ITargetPreparer prep : c.getTargetPreparers()) {
+                if (prep.getClass().isAssignableFrom(ApkInstaller.class)) {
+                    throw new ConfigurationException(
+                            String.format("%s: Use com.android.tradefed.targetprep.suite."
+                                    + "SuiteApkInstaller instead of com.android.compatibility."
+                                    + "common.tradefed.targetprep.ApkInstaller, options will be "
+                                    + "the same.", config));
+                }
+            }
+        }
+    }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
index 8ef909e..ce41b47 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/IntegrationTest.java
@@ -170,7 +170,7 @@
      */
     @Test
     public void testSingleModuleRun() throws Exception {
-        final String moduleName = "moduleA";
+        final String moduleName = "module_run";
         final String mAbi = "arm64-v8a";
         createConfig(mTestDir, moduleName, TEST_STUB, true, true, true, false);
         EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
@@ -196,7 +196,7 @@
      */
     @Test
     public void testSingleModuleRun_incomplete() throws Exception {
-        final String moduleName = "moduleA";
+        final String moduleName = "module_run_incomplete";
         final String mAbi = "arm64-v8a";
         createConfig(mTestDir, moduleName, TEST_STUB, true, false, true, false);
         EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
@@ -225,7 +225,7 @@
      */
     @Test
     public void testSingleModuleRun_completeAfterInternalRetry() throws Exception {
-        final String moduleName = "moduleA";
+        final String moduleName = "module_completeAfterRetry";
         final String mAbi = "arm64-v8a";
         createConfig(mTestDir, moduleName, TEST_STUB, true, true, true, true);
         EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
@@ -255,7 +255,7 @@
      */
     @Test
     public void testSingleModuleRun_incomplete_rerun_incomplete() throws Exception {
-        final String moduleName = "moduleA";
+        final String moduleName = "module_incomplete_rerun";
         final String mAbi = "arm64-v8a";
         createConfig(mTestDir, moduleName, TEST_STUB, true, false, true, false);
         EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
@@ -322,7 +322,7 @@
      */
     @Test
     public void testSingleModuleRun_incomplete_rerun_complete() throws Exception {
-        final String moduleName = "moduleA";
+        final String moduleName = "module_incom_rerun_complete";
         final String mAbi = "arm64-v8a";
         createConfig(mTestDir, moduleName, TEST_STUB, true, false, true, false);
         EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(mAbi);
@@ -444,7 +444,7 @@
      */
     @Test
     public void testSingleModuleRun_sharded() throws Exception {
-        final String moduleName = "moduleA";
+        final String moduleName = "module_sharded";
         Set<String> abis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
         Iterator<String> ite = abis.iterator();
         final String abi1 = ite.next();
@@ -453,8 +453,7 @@
         EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(
                 String.format("%s,%s", abi1, abi2));
         mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
-                EasyMock.eq(AbiUtils.createId(abi1, moduleName) + ","
-                        + AbiUtils.createId(abi2, moduleName)));
+                EasyMock.anyObject());
         EasyMock.expectLastCall();
 
         EasyMock.replay(mMockDevice, mMockBuildInfo);
@@ -495,7 +494,7 @@
      */
     @Test
     public void testSingleModuleRun_sharded_incomplete() throws Exception {
-        final String moduleName = "moduleA";
+        final String moduleName = "module_sharded_incomplete";
         Set<String> abis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
         Iterator<String> ite = abis.iterator();
         final String abi1 = ite.next();
@@ -504,8 +503,7 @@
         EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist")).andReturn(
                 String.format("%s,%s", abi1, abi2));
         mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
-                EasyMock.eq(AbiUtils.createId(abi1, moduleName) + ","
-                        + AbiUtils.createId(abi2, moduleName)));
+                EasyMock.anyObject());
         EasyMock.expectLastCall();
 
         EasyMock.replay(mMockDevice, mMockBuildInfo);
@@ -547,7 +545,7 @@
      */
     @Test
     public void testSingleModuleRun_sharded_getTestShard() throws Exception {
-        final String moduleName = "moduleA";
+        final String moduleName = "module_sharded_getTestShard";
         Set<String> abis = AbiUtils.getAbisForArch(SuiteInfo.TARGET_ARCH);
         Iterator<String> ite = abis.iterator();
         final String abi1 = ite.next();
@@ -559,7 +557,7 @@
         String expectedAdd = AbiUtils.createId(abi1, moduleName) + ","
                 + AbiUtils.createId(abi2, moduleName);
         mMockBuildInfo.addBuildAttribute(EasyMock.eq(CompatibilityBuildHelper.MODULE_IDS),
-                EasyMock.eq(expectedAdd));
+                EasyMock.anyObject());
         EasyMock.expectLastCall();
         mAttributes.put(CompatibilityBuildHelper.MODULE_IDS, expectedAdd);
 
diff --git a/common/util/src/com/android/compatibility/common/util/VendorInterfaceTest.java b/common/util/src/com/android/compatibility/common/util/VendorInterfaceTest.java
index 5a448f1..5bcaf0c 100644
--- a/common/util/src/com/android/compatibility/common/util/VendorInterfaceTest.java
+++ b/common/util/src/com/android/compatibility/common/util/VendorInterfaceTest.java
@@ -26,7 +26,8 @@
  * AOSP requirement.
  * <p>
  * Test classes and test cases marked with this annotation will be included in the
- * cts-vendor-interface plan by default.
+ * cts-vendor-interface plan
+ * by default.
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD, ElementType.TYPE})
diff --git a/hostsidetests/abioverride/AndroidTest.xml b/hostsidetests/abioverride/AndroidTest.xml
index 2a3a963..671947f 100644
--- a/hostsidetests/abioverride/AndroidTest.xml
+++ b/hostsidetests/abioverride/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS AbiOverride host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAbiOverrideTestApp.apk" />
     </target_preparer>
diff --git a/hostsidetests/cpptools/AndroidTest.xml b/hostsidetests/cpptools/AndroidTest.xml
index da96259..1f8c360 100644
--- a/hostsidetests/cpptools/AndroidTest.xml
+++ b/hostsidetests/cpptools/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CPP host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsCppToolsApp.apk" />
     </target_preparer>
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/AppRestrictionsDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/AppRestrictionsDelegateTest.java
index ab37090..55fc792 100644
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/AppRestrictionsDelegateTest.java
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/AppRestrictionsDelegateTest.java
@@ -16,6 +16,7 @@
 package com.android.cts.delegate;
 
 import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS;
+import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
 
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
@@ -86,22 +87,16 @@
     public void testCannotAccessApis() {
         assertFalse("DelegateApp should not be an app restrictions delegate",
                 amIAppRestrictionsDelegate());
-        try {
-            mDpm.setApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG, null);
-            fail("Expected SecurityException not thrown");
-        } catch (SecurityException expected) {
-            MoreAsserts.assertContainsRegex(
-                    "Caller with uid \\d+ is not a delegate of scope delegation-app-restrictions.",
-                    expected.getMessage());
-        }
-        try {
-            mDpm.getApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG);
-            fail("Expected SecurityException not thrown");
-        } catch (SecurityException expected) {
-            MoreAsserts.assertContainsRegex(
-                    "Caller with uid \\d+ is not a delegate of scope delegation-app-restrictions.",
-                    expected.getMessage());
-        }
+
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.setApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG, null);
+                });
+
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.getApplicationRestrictions(null, APP_RESTRICTIONS_TARGET_PKG);
+                });
     }
 
     public void testCanAccessApis() throws InterruptedException {
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/BlockUninstallDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/BlockUninstallDelegateTest.java
index 65ebd64..f706b85 100644
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/BlockUninstallDelegateTest.java
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/BlockUninstallDelegateTest.java
@@ -16,6 +16,7 @@
 package com.android.cts.delegate;
 
 import static android.app.admin.DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL;
+import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
 
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
@@ -45,14 +46,11 @@
     public void testCannotAccessApis() {
         assertFalse("DelegateApp should not be a block uninstall delegate",
             amIBlockUninstallDelegate());
-        try {
-            mDpm.setUninstallBlocked(null, TEST_APP_PKG, true);
-            fail("Expected SecurityException not thrown");
-        } catch (SecurityException expected) {
-            MoreAsserts.assertContainsRegex(
-                    "Caller with uid \\d+ is not a delegate of scope delegation-block-uninstall.",
-                    expected.getMessage());
-        }
+
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.setUninstallBlocked(null, TEST_APP_PKG, true);
+                });
     }
 
     public void testCanAccessApis() {
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/CertInstallDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/CertInstallDelegateTest.java
index d8d0ab3..933e257 100644
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/CertInstallDelegateTest.java
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/CertInstallDelegateTest.java
@@ -16,6 +16,7 @@
 package com.android.cts.delegate;
 
 import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL;
+import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
 
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
@@ -121,23 +122,16 @@
 
     public void testCannotAccessApis() {
         assertFalse(amICertInstallDelegate());
-        try {
-            mDpm.installCaCert(null, null);
-            fail("Expected SecurityException not thrown");
-        } catch (SecurityException expected) {
-            MoreAsserts.assertContainsRegex(
-                    "Neither user \\d+ nor current process has "
-                    + "android.permission.MANAGE_CA_CERTIFICATES",
-                    expected.getMessage());
-        }
-        try {
-            mDpm.removeKeyPair(null, "alias");
-            fail("Expected SecurityException not thrown");
-        } catch (SecurityException expected) {
-            MoreAsserts.assertContainsRegex(
-                    "Caller with uid \\d+ is not a delegate of scope delegation-cert-install.",
-                    expected.getMessage());
-        }
+
+        assertExpectException(SecurityException.class,
+                "Neither user \\d+ nor current process has", () -> {
+                    mDpm.installCaCert(null, null);
+                });
+
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.removeKeyPair(null, "alias");
+                });
     }
 
     public void testCanAccessApis() throws Exception {
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/DelegateTestUtils.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/DelegateTestUtils.java
new file mode 100644
index 0000000..b162f86
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/DelegateTestUtils.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.delegate;
+
+import android.test.MoreAsserts;
+import junit.framework.Assert;
+
+/**
+ * Utils class for delegation tests.
+ */
+public class DelegateTestUtils {
+
+    @FunctionalInterface
+    public interface ExceptionRunnable {
+        void run() throws Exception;
+    }
+
+    public static void assertExpectException(Class<? extends Throwable> expectedExceptionType,
+            String expectedExceptionMessageRegex, ExceptionRunnable r) {
+        try {
+            r.run();
+        } catch (Throwable e) {
+            Assert.assertTrue("Expected " + expectedExceptionType.getName() + " but caught " + e,
+                expectedExceptionType.isAssignableFrom(e.getClass()));
+            if (expectedExceptionMessageRegex != null) {
+                MoreAsserts.assertContainsRegex(expectedExceptionMessageRegex, e.getMessage());
+            }
+            return; // Pass
+        }
+        Assert.fail("Expected " + expectedExceptionType.getName() + " was not thrown");
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/EnableSystemAppDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/EnableSystemAppDelegateTest.java
new file mode 100644
index 0000000..246f936
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/EnableSystemAppDelegateTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.delegate;
+
+import static android.app.admin.DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP;
+import static android.content.pm.PackageManager.GET_META_DATA;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
+import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
+import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Intent;
+import android.test.InstrumentationTestCase;
+
+import java.util.List;
+
+/**
+ * Test that an app given the {@link DevicePolicyManager#DELEGATION_PERMISSION_GRANT} scope via
+ * {@link DevicePolicyManager#setDelegatedScopes} can grant permissions and check permission grant
+ * state.
+ */
+public class EnableSystemAppDelegateTest extends InstrumentationTestCase {
+
+    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
+
+    private DevicePolicyManager mDpm;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mDpm = getInstrumentation().getContext().getSystemService(DevicePolicyManager.class);
+    }
+
+    public void testCannotAccessApis() {
+        assertFalse("DelegateApp should not be an enable system app delegate",
+            amIEnableSystemAppDelegate());
+
+        // Exercise enableSystemApp(String).
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.enableSystemApp(null, TEST_APP_PKG);
+                });
+
+        // Exercise enableSystemApp(Intent).
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.enableSystemApp(null, new Intent().setPackage(TEST_APP_PKG));
+                });
+    }
+
+    public void testCanAccessApis() {
+        assertTrue("DelegateApp is not an enable system app delegate",
+            amIEnableSystemAppDelegate());
+
+        // Exercise enableSystemApp(String).
+        assertExpectException(IllegalArgumentException.class,
+                "Only system apps can be enabled this way", () -> {
+                    mDpm.enableSystemApp(null, TEST_APP_PKG);
+                });
+
+        // Exercise enableSystemApp(Intent).
+        mDpm.enableSystemApp(null, new Intent());
+    }
+
+    private boolean amIEnableSystemAppDelegate() {
+        final String packageName = getInstrumentation().getContext().getPackageName();
+        final List<String> scopes = mDpm.getDelegatedScopes(null, packageName);
+        return scopes.contains(DELEGATION_ENABLE_SYSTEM_APP);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/GeneralDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/GeneralDelegateTest.java
index 24bee4f..c403ffb 100644
--- a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/GeneralDelegateTest.java
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/GeneralDelegateTest.java
@@ -18,6 +18,8 @@
 import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS;
 import static android.app.admin.DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL;
 import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL;
+import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
+import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
 import static android.app.admin.DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP;
 
 import android.app.admin.DevicePolicyManager;
@@ -47,7 +49,10 @@
     private static final String EXPECTED_DELEGATION_SCOPES[] = {
         DELEGATION_APP_RESTRICTIONS,
         DELEGATION_BLOCK_UNINSTALL,
-        DELEGATION_CERT_INSTALL
+        DELEGATION_CERT_INSTALL,
+        DELEGATION_PERMISSION_GRANT,
+        DELEGATION_PACKAGE_ACCESS,
+        DELEGATION_ENABLE_SYSTEM_APP
     };
 
     @Override
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PackageAccessDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PackageAccessDelegateTest.java
new file mode 100644
index 0000000..86f2639
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PackageAccessDelegateTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.delegate;
+
+import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
+import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.test.InstrumentationTestCase;
+import android.test.MoreAsserts;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Test that an app given the {@link DevicePolicyManager#DELEGATION_PACKAGE_ACCESS} scope via
+ * {@link DevicePolicyManager#setDelegatedScopes} can manage package hide and suspend status.
+ */
+public class PackageAccessDelegateTest extends InstrumentationTestCase {
+
+    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
+
+    private DevicePolicyManager mDpm;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        Context context = getInstrumentation().getContext();
+        mDpm = context.getSystemService(DevicePolicyManager.class);
+    }
+
+    public void testCannotAccessApis() throws NameNotFoundException {
+        assertFalse("DelegateApp should not be a package access delegate",
+            amIPackageAccessDelegate());
+
+        // Exercise isApplicationHidden.
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.isApplicationHidden(null, TEST_APP_PKG);
+                });
+
+        // Exercise setApplicationHidden.
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.setApplicationHidden(null, TEST_APP_PKG, true /* hide */);
+                });
+
+        // Exercise isPackageSuspended.
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.isPackageSuspended(null, TEST_APP_PKG);
+                });
+
+        // Exercise setPackagesSuspended.
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.setPackagesSuspended(null, new String[] {TEST_APP_PKG}, true /* suspend */);
+                });
+    }
+
+    public void testCanAccessApis() throws NameNotFoundException {
+        assertTrue("DelegateApp is not a package access delegate", amIPackageAccessDelegate());
+
+        // Exercise isApplicationHidden.
+        assertFalse("Package should not be hidden", mDpm.isApplicationHidden(null, TEST_APP_PKG));
+
+        // Exercise setApplicationHidden.
+        assertTrue("Package not hidden successfully",
+                mDpm.setApplicationHidden(null, TEST_APP_PKG, true /* hide */));
+        assertTrue("Package should be hidden", mDpm.isApplicationHidden(null, TEST_APP_PKG));
+
+        // Exercise isPackageSuspended.
+        assertFalse("Package should not be suspended", mDpm.isPackageSuspended(null, TEST_APP_PKG));
+
+        // Exercise setPackagesSuspended.
+        String[] suspended = mDpm.setPackagesSuspended(null, new String[] {TEST_APP_PKG},
+                true /* suspend */);
+        assertTrue("Package not suspended successfully", suspended.length == 0);
+        assertTrue("Package should be suspended", mDpm.isPackageSuspended(null, TEST_APP_PKG));
+    }
+
+    private boolean amIPackageAccessDelegate() {
+        final String packageName = getInstrumentation().getContext().getPackageName();
+        final List<String> scopes = mDpm.getDelegatedScopes(null, packageName);
+        return scopes.contains(DELEGATION_PACKAGE_ACCESS);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PermissionGrantDelegateTest.java b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PermissionGrantDelegateTest.java
new file mode 100644
index 0000000..81b74a2
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DelegateApp/src/com/android/cts/delegate/PermissionGrantDelegateTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.delegate;
+
+import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
+import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT;
+import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
+import static com.android.cts.delegate.DelegateTestUtils.assertExpectException;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.test.InstrumentationTestCase;
+import android.test.MoreAsserts;
+
+import java.util.List;
+
+/**
+ * Test that an app given the {@link DevicePolicyManager#DELEGATION_PERMISSION_GRANT} scope via
+ * {@link DevicePolicyManager#setDelegatedScopes} can grant permissions and check permission grant
+ * state.
+ */
+public class PermissionGrantDelegateTest extends InstrumentationTestCase {
+
+    private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
+    private static final String TEST_PERMISSION = "android.permission.READ_CONTACTS";
+
+    private DevicePolicyManager mDpm;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        Context context = getInstrumentation().getContext();
+        mDpm = context.getSystemService(DevicePolicyManager.class);
+    }
+
+    public void testCannotAccessApis() {
+        assertFalse("DelegateApp should not be a permisssion grant delegate",
+            amIPermissionGrantDelegate());
+
+        // Exercise setPermissionPolicy.
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.setPermissionPolicy(null, PERMISSION_POLICY_AUTO_GRANT);
+                });
+        assertFalse("Permission policy should not have been set",
+                PERMISSION_POLICY_AUTO_GRANT == mDpm.getPermissionPolicy(null));
+
+        // Exercise setPermissionGrantState.
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.setPermissionGrantState(null, TEST_APP_PKG, TEST_PERMISSION,
+                            PERMISSION_GRANT_STATE_GRANTED);
+                });
+
+        // Exercise getPermissionGrantState.
+        assertExpectException(SecurityException.class,
+                "Caller with uid \\d+ is not a delegate of scope", () -> {
+                    mDpm.getPermissionGrantState(null, TEST_APP_PKG, TEST_PERMISSION);
+                });
+    }
+
+    public void testCanAccessApis() {
+        assertTrue("DelegateApp is not a permission grant delegate",
+            amIPermissionGrantDelegate());
+
+        // Exercise setPermissionPolicy.
+        mDpm.setPermissionPolicy(null, PERMISSION_POLICY_AUTO_DENY);
+        assertTrue("Permission policy was not set",
+                PERMISSION_POLICY_AUTO_DENY == mDpm.getPermissionPolicy(null));
+
+        // Exercise setPermissionGrantState.
+        assertTrue("Permission grant state was not set successfully",
+                mDpm.setPermissionGrantState(null, TEST_APP_PKG, TEST_PERMISSION,
+                    PERMISSION_GRANT_STATE_DENIED));
+
+        // Exercise getPermissionGrantState.
+        assertEquals("Permission grant state is not denied", PERMISSION_GRANT_STATE_DENIED,
+                mDpm.getPermissionGrantState(null, TEST_APP_PKG, TEST_PERMISSION));
+    }
+
+    private boolean amIPermissionGrantDelegate() {
+        final String packageName = getInstrumentation().getContext().getPackageName();
+        final List<String> scopes = mDpm.getDelegatedScopes(null, packageName);
+        return scopes.contains(DELEGATION_PERMISSION_GRANT);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java
index ddd704d..39235b0 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java
@@ -66,7 +66,8 @@
             UserManager.ALLOW_PARENT_PROFILE_APP_LINKING,
             UserManager.DISALLOW_DATA_ROAMING,
             UserManager.DISALLOW_SET_USER_ICON,
-            UserManager.DISALLOW_BLUETOOTH
+            UserManager.DISALLOW_BLUETOOTH,
+            UserManager.DISALLOW_BLUETOOTH_SHARING
     };
 
     /**
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/ManagedProfileOwnerUserRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/ManagedProfileOwnerUserRestrictionsTest.java
new file mode 100644
index 0000000..81f1b1c
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/ManagedProfileOwnerUserRestrictionsTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.deviceandprofileowner.userrestrictions;
+
+import android.os.UserManager;
+
+/**
+ * Test for managed profile owner restriction behavior. It is mostly the same as just secondary
+ * profile owner but some restrictions are set by default.
+ */
+public class ManagedProfileOwnerUserRestrictionsTest
+        extends SecondaryProfileOwnerUserRestrictionsTest {
+
+    private static final String[] DEFAULT_ENABLED = new String[] {
+            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+            UserManager.DISALLOW_BLUETOOTH_SHARING
+    };
+
+    @Override
+    protected String[] getDefaultEnabledRestrictions() {
+        return DEFAULT_ENABLED;
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BluetoothRestrictionTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BluetoothRestrictionTest.java
index 0ddf842..552503b 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BluetoothRestrictionTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BluetoothRestrictionTest.java
@@ -16,7 +16,6 @@
 
 package com.android.cts.deviceowner;
 
-import android.app.admin.DevicePolicyManager;
 import android.bluetooth.BluetoothAdapter;
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
@@ -103,7 +102,8 @@
     }
 
     /**
-     * Tests that BluetoothOppLauncherActivity gets disabled when Bluetooth is disallowed.
+     * Tests that BluetoothOppLauncherActivity gets disabled when Bluetooth itself or Bluetooth
+     * sharing is disallowed.
      *
      * <p> It also checks the state of the activity is set back to default if Bluetooth is not
      * disallowed anymore.
@@ -113,15 +113,24 @@
             return;
         }
 
+        // First verify DISALLOW_BLUETOOTH.
+        testOppDisabledWhenRestrictionSet(UserManager.DISALLOW_BLUETOOTH);
+        // Verify DISALLOW_BLUETOOTH_SHARING which leaves bluetooth workable but the sharing
+        // component should be disabled.
+        testOppDisabledWhenRestrictionSet(UserManager.DISALLOW_BLUETOOTH_SHARING);
+    }
+
+    /** Verifies that a given restriction disables the bluetooth sharing component. */
+    private void testOppDisabledWhenRestrictionSet(String restriction) {
         // Add the user restriction.
-        mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_BLUETOOTH);
+        mDevicePolicyManager.addUserRestriction(getWho(), restriction);
 
         // The BluetoothOppLauncherActivity's component should be disabled.
         assertComponentStateAfterTimeout(
                 OPP_LAUNCHER_COMPONENT, PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
 
         // Remove the user restriction.
-        mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_BLUETOOTH);
+        mDevicePolicyManager.clearUserRestriction(getWho(), restriction);
 
         // The BluetoothOppLauncherActivity's component should be in the default state.
         assertComponentStateAfterTimeout(
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index b8a5eae6..2eaa44f 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -132,6 +132,15 @@
                 <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
+
+        <service
+            android:name=".CrossProfileNotificationListenerService"
+            android:label="CrossProfileNotificationListenerService"
+            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
+            <intent-filter>
+                <action android:name="android.service.notification.NotificationListenerService" />
+            </intent-filter>
+        </service>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionPrimaryProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionPrimaryProfileTest.java
new file mode 100644
index 0000000..58bcc8f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionPrimaryProfileTest.java
@@ -0,0 +1,36 @@
+
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.managedprofile;
+
+import static com.android.cts.managedprofile.BluetoothSharingRestrictionTest.assertBluetoothSharingAvailable;
+
+import android.bluetooth.BluetoothAdapter;
+import android.test.InstrumentationTestCase;
+
+/**
+ * Auxiliary test to check that Bluetooth sharing in primary profile is not affected.
+ */
+public class BluetoothSharingRestrictionPrimaryProfileTest extends InstrumentationTestCase {
+    /** Verifies that bluetooth sharing is available in personal profile. */
+    public void testBluetoothSharingAvailable() throws Exception {
+        if (BluetoothAdapter.getDefaultAdapter() == null) {
+            // No Bluetooth - nothing to test.
+            return;
+        }
+        assertBluetoothSharingAvailable(getInstrumentation().getContext(), true);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionTest.java
new file mode 100644
index 0000000..4c5659b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BluetoothSharingRestrictionTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.managedprofile;
+
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ComponentInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.os.UserManager;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+
+/**
+ * Test {@link UserManager#DISALLOW_BLUETOOTH_SHARING} in profile owner.
+ *
+ * Shamelessly copied from BluetoothRestrictionTest, would be nice to extract common stuff to a lib.
+ */
+public class BluetoothSharingRestrictionTest extends BaseManagedProfileTest {
+    /** How long should we wait for the component state to change. */
+    private static final int COMPONENT_STATE_TIMEOUT_MS = 2000;
+    /** How often to check component state. */
+    private static final int POLL_TIME_MS = 400;
+    /** Activity that handles Bluetooth sharing. */
+    private static final ComponentName OPP_LAUNCHER_COMPONENT = new ComponentName(
+            "com.android.bluetooth", "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
+
+    /**
+     * Tests that Bluetooth sharing activity gets disabled when the restriction is enforced.
+     */
+    public void testOppDisabledWhenRestrictionSet() throws Exception {
+        if (BluetoothAdapter.getDefaultAdapter() == null) {
+            // No Bluetooth - nothing to test.
+            return;
+        }
+
+        // The restriction is active by default for managed profiles.
+        assertBluetoothSharingAvailable(mContext, false);
+
+        // Remove the user restriction.
+        mDevicePolicyManager.clearUserRestriction(
+                ADMIN_RECEIVER_COMPONENT, UserManager.DISALLOW_BLUETOOTH_SHARING);
+        // Bluetooth sharing should become available.
+        assertBluetoothSharingAvailable(mContext, true);
+
+        // Add the user restriction back (which is the default state).
+        mDevicePolicyManager.addUserRestriction(
+                ADMIN_RECEIVER_COMPONENT, UserManager.DISALLOW_BLUETOOTH_SHARING);
+        // Bluetooth sharing should be disabled once again.
+        assertBluetoothSharingAvailable(mContext, false);
+    }
+
+    /** Verifies restriction enforcement. */
+    private static void assertRestrictionEnforced(Context context, boolean enforced) {
+        final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        assertEquals("Invalid restriction enforcement status", enforced,
+                um.getUserRestrictions().getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING, false));
+    }
+
+    /**
+     * Builds an intent to share an image file. If Bluetooth sharing is allowed, it should be
+     * handled by {@link #OPP_LAUNCHER_COMPONENT}.
+     */
+    private static Intent fileSharingIntent() {
+        final Intent result = new Intent(Intent.ACTION_SEND);
+        final Uri uri = Uri.parse("content://foo/bar");
+        result.setDataAndType(uri, "image/*");
+        return result;
+    }
+
+    /**
+     * Verifies bluetooth sharing availability.
+     */
+    static void assertBluetoothSharingAvailable(Context context, boolean available)
+            throws Exception {
+        // Check restriction.
+        assertRestrictionEnforced(context, !available);
+        // Check component status.
+        final int componentEnabledState = available
+                ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+                : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+        assertComponentStateAfterTimeout(context, OPP_LAUNCHER_COMPONENT, componentEnabledState);
+        // Check whether sharing activity is offered.
+        assertHandlerAvailable(context, fileSharingIntent(), OPP_LAUNCHER_COMPONENT, available);
+    }
+
+    /** Waits for package state to change to a desired one or fails. */
+    private static void assertComponentStateAfterTimeout(Context context, ComponentName component,
+            int expectedState)
+            throws Exception {
+        final long timeout = SystemClock.elapsedRealtime() + COMPONENT_STATE_TIMEOUT_MS;
+        int state = -1;
+        while (SystemClock.elapsedRealtime() < timeout) {
+            state = context.getPackageManager().getComponentEnabledSetting(component);
+            if (expectedState == state) {
+                // Success
+                return;
+            }
+            Thread.sleep(POLL_TIME_MS);
+        }
+        TestCase.fail("The state of " + component + " should have been " + expectedState
+                + ", it but was " + state + " after timeout.");
+    }
+
+    /** Verifies that {@code component} is offered when handling {@code intent}. */
+    private static void assertHandlerAvailable(Context context, Intent intent,
+            ComponentName component,
+            boolean shouldResolve) {
+        final List<ResolveInfo> infos =
+                context.getPackageManager().queryIntentActivities(intent, 0);
+        for (final ResolveInfo info : infos) {
+            final ComponentInfo componentInfo =
+                    info.activityInfo != null ? info.activityInfo :
+                            info.serviceInfo != null ? info.serviceInfo :
+                                    info.providerInfo;
+            final ComponentName resolvedComponent =
+                    new ComponentName(componentInfo.packageName, componentInfo.name);
+
+            if (resolvedComponent.equals(component)) {
+                if (shouldResolve) {
+                    // Found it, assertion passed.
+                    return;
+                } else {
+                    TestCase.fail(component + " is available as a handler for " + intent);
+                }
+            }
+        }
+        // If we get to this point, there was no match.
+        if (shouldResolve) {
+            TestCase.fail(component + " isn't available as a handler for " + intent);
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileNotificationListenerService.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileNotificationListenerService.java
new file mode 100644
index 0000000..35fb2e4
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileNotificationListenerService.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.managedprofile;
+
+import static com.android.cts.managedprofile.NotificationListenerTest.ACTION_NOTIFICATION_POSTED;
+import static com.android.cts.managedprofile.NotificationListenerTest.ACTION_NOTIFICATION_REMOVED;
+import static com.android.cts.managedprofile.NotificationListenerTest.ACTION_LISTENER_CONNECTED;
+
+import android.content.Intent;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.support.v4.content.LocalBroadcastManager;
+import android.util.Log;
+
+public class CrossProfileNotificationListenerService extends NotificationListenerService {
+
+    static final String NOTIFICATION_CHANNEL = "NotificationListenerTest";
+    private static final String TAG = NotificationListenerTest.TAG;
+
+    @Override
+    public void onNotificationPosted(StatusBarNotification sbn) {
+        Log.i(TAG, "onNotificationPosted(" + sbn + ")");
+        sendBroadcastForNotification(sbn, ACTION_NOTIFICATION_POSTED);
+    }
+
+    @Override
+    public void onNotificationRemoved(StatusBarNotification sbn) {
+        Log.i(TAG, "onNotificationRemoved(" + sbn + ")");
+        sendBroadcastForNotification(sbn, ACTION_NOTIFICATION_REMOVED);
+    }
+
+    @Override
+    public void onListenerConnected() {
+        Log.i(TAG, "onListenerConnected() " + android.os.Process.myPid());
+        LocalBroadcastManager.getInstance(this).sendBroadcast(
+                new Intent(ACTION_LISTENER_CONNECTED));
+    }
+
+    @Override
+    public void onListenerDisconnected() {
+        Log.i(TAG, "onListenerDisconnected()");
+    }
+
+    private void sendBroadcastForNotification(StatusBarNotification sbn, String action) {
+        if (NOTIFICATION_CHANNEL.equals(sbn.getNotification().getChannel())) {
+            LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(action));
+        } else {
+            Log.i(TAG, "Notification is for different channel "
+                    + sbn.getNotification().getChannel());
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/NotificationListenerTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/NotificationListenerTest.java
new file mode 100644
index 0000000..d4cbae7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/NotificationListenerTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.managedprofile;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.UiAutomation;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.uiautomator.UiDevice;
+import android.support.v4.content.LocalBroadcastManager;
+import android.util.Log;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+public class NotificationListenerTest {
+
+    static final String TAG = "ListenerTest";
+    static final String ACTION_NOTIFICATION_POSTED = "notification_posted";
+    static final String ACTION_NOTIFICATION_REMOVED = "notification_removed";
+    static final String ACTION_LISTENER_CONNECTED = "listener_connected";
+
+    private static final String PARAM_PROFILE_ID = "profile-id";
+
+    static final String SENDER_COMPONENT =
+            "com.android.cts.managedprofiletests.notificationsender/.SendNotification";
+
+    private final LocalBroadcastReceiver mReceiver = new LocalBroadcastReceiver();
+    private Context mContext;
+    private DevicePolicyManager mDpm;
+    private NotificationManager mNotificationManager;
+    private UiDevice mDevice;
+    private int mProfileUserId;
+    private String mPreviousListeners;
+    private boolean mChangedListeners;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mDpm = mContext.getSystemService(DevicePolicyManager.class);
+        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mProfileUserId = getParam(InstrumentationRegistry.getArguments(), PARAM_PROFILE_ID);
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_NOTIFICATION_POSTED);
+        filter.addAction(ACTION_NOTIFICATION_REMOVED);
+        filter.addAction(ACTION_LISTENER_CONNECTED);
+        LocalBroadcastManager.getInstance(mContext).registerReceiver(mReceiver, filter);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mReceiver);
+        if (mChangedListeners) {
+            if (mPreviousListeners != null) {
+                mDevice.executeShellCommand(
+                        "settings put secure enabled_notification_listeners "
+                        + mPreviousListeners);
+            } else {
+                mDevice.executeShellCommand(
+                        "settings delete secure enabled_notification_listeners");
+            }
+        }
+    }
+
+    @Test
+    public void testSetEmptyWhitelist() throws Exception {
+        mDpm.setPermittedCrossProfileNotificationListeners(
+                BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT,
+                Collections.<String>emptyList());
+    }
+
+    @Test
+    public void testAddListenerToWhitelist() throws Exception {
+        mDpm.setPermittedCrossProfileNotificationListeners(
+                BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT,
+                Collections.singletonList(mContext.getPackageName()));
+    }
+
+    @Test
+    public void testSetNullWhitelist() throws Exception {
+        mDpm.setPermittedCrossProfileNotificationListeners(
+                BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT, null);
+    }
+
+    @Test
+    public void testCanReceiveNotifications() throws Exception {
+        enableNotificationListener();
+
+        sendProfileNotification();
+        assertTrue(mReceiver.waitForNotificationPostedReceived());
+        cancelProfileNotification();
+        assertTrue(mReceiver.waitForNotificationRemovedReceived());
+
+        mReceiver.reset();
+
+        sendPersonalNotification();
+        assertTrue(mReceiver.waitForNotificationPostedReceived());
+        cancelPersonalNotification();
+        assertTrue(mReceiver.waitForNotificationRemovedReceived());
+    }
+
+    @Test
+    public void testCannotReceiveProfileNotifications() throws Exception {
+        enableNotificationListener();
+
+        sendProfileNotification();
+        // Don't see notification or cancellation from work profile.
+        assertFalse(mReceiver.waitForNotificationPostedReceived());
+        cancelProfileNotification();
+        assertFalse(mReceiver.waitForNotificationRemovedReceived());
+
+        mReceiver.reset();
+
+        // Do see the one from the personal side.
+        sendPersonalNotification();
+        assertTrue(mReceiver.waitForNotificationPostedReceived());
+        cancelPersonalNotification();
+        assertTrue(mReceiver.waitForNotificationRemovedReceived());
+    }
+
+    private void cancelProfileNotification() throws IOException {
+        mDevice.executeShellCommand(
+                "am start --user " + mProfileUserId + " -a CANCEL_NOTIFICATION -n "
+                + SENDER_COMPONENT);
+    }
+
+    private void cancelPersonalNotification() throws IOException {
+        mDevice.executeShellCommand(
+                "am start -a CANCEL_NOTIFICATION -n "
+                + SENDER_COMPONENT);
+    }
+
+    private void sendProfileNotification() throws IOException {
+        mDevice.executeShellCommand(
+                "am start --user " + mProfileUserId + " -a POST_NOTIFICATION -n "
+                + SENDER_COMPONENT);
+    }
+
+    private void sendPersonalNotification() throws IOException {
+        mDevice.executeShellCommand(
+                "am start -a POST_NOTIFICATION -n "
+                + SENDER_COMPONENT);
+    }
+
+    private void enableNotificationListener() throws Exception {
+        String listeners = mDevice.executeShellCommand(
+                "settings get secure enabled_notification_listeners").trim();
+        if (listeners.equals("null")) {
+            listeners = null;
+        }
+        String testListener = new ComponentName(
+                mContext, CrossProfileNotificationListenerService.class).flattenToString();
+
+        if (listeners == null || !listeners.contains(testListener)) {
+            mPreviousListeners = listeners;
+            mChangedListeners = true;
+            String newListeners;
+            if (listeners != null && listeners.length() > 0) {
+                newListeners = listeners + ":" + testListener;
+            } else {
+                newListeners = testListener;
+            }
+            mDevice.executeShellCommand(
+                    "settings put secure enabled_notification_listeners "
+                    + newListeners);
+            Log.i(TAG, "Enabled notification listener " + testListener);
+            assertTrue(mReceiver.waitForListenerConnected());
+        }
+    }
+
+    private int getParam(Bundle arguments, String key) throws Exception {
+        String serial = arguments.getString(key);
+        if (serial == null) {
+            throw new IllegalArgumentException("Missing argument " + key);
+        }
+        return Integer.parseInt(serial);
+    }
+
+    static class LocalBroadcastReceiver extends BroadcastReceiver {
+
+        private static final int TIMEOUT_SECONDS = 10;
+
+        private CountDownLatch mNotificationPostedLatch = new CountDownLatch(1);
+        private CountDownLatch mNotificationRemovedLatch = new CountDownLatch(1);
+        private CountDownLatch mListenerConnectedLatch = new CountDownLatch(1);
+
+        public void reset() {
+            mNotificationPostedLatch = new CountDownLatch(1);
+            mNotificationRemovedLatch = new CountDownLatch(1);
+            mListenerConnectedLatch = new CountDownLatch(1);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.i(TAG, "onReceive(" + intent + ")");
+            if (ACTION_NOTIFICATION_POSTED.equals(intent.getAction())) {
+                mNotificationPostedLatch.countDown();
+            } else if (ACTION_NOTIFICATION_REMOVED.equals(intent.getAction())) {
+                mNotificationRemovedLatch.countDown();
+            } else if (ACTION_LISTENER_CONNECTED.equals(intent.getAction())) {
+                mListenerConnectedLatch.countDown();
+            } else {
+                Log.e(TAG, "Received broadcast for unknown action: " + intent.getAction());
+            }
+        }
+
+        public boolean waitForNotificationPostedReceived() throws InterruptedException {
+            return mNotificationPostedLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        }
+
+        public boolean waitForNotificationRemovedReceived() throws InterruptedException {
+            return mNotificationRemovedLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        }
+
+        public boolean waitForListenerConnected() throws InterruptedException {
+            return mListenerConnectedLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        }
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/NotificationSender/Android.mk b/hostsidetests/devicepolicy/app/NotificationSender/Android.mk
new file mode 100644
index 0000000..67509e5
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/NotificationSender/Android.mk
@@ -0,0 +1,37 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsNotificationSenderApp
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/NotificationSender/AndroidManifest.xml b/hostsidetests/devicepolicy/app/NotificationSender/AndroidManifest.xml
new file mode 100644
index 0000000..d78092b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/NotificationSender/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.managedprofiletests.notificationsender">
+
+    <application>
+      <activity android:name=".SendNotification" >
+      </activity>
+    </application>
+</manifest>
+
diff --git a/hostsidetests/devicepolicy/app/NotificationSender/res/raw/ic_contact_picture.png b/hostsidetests/devicepolicy/app/NotificationSender/res/raw/ic_contact_picture.png
new file mode 100644
index 0000000..37b558b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/NotificationSender/res/raw/ic_contact_picture.png
Binary files differ
diff --git a/hostsidetests/devicepolicy/app/NotificationSender/src/com/android/cts/managedprofiletests/notificationsender/SendNotification.java b/hostsidetests/devicepolicy/app/NotificationSender/src/com/android/cts/managedprofiletests/notificationsender/SendNotification.java
new file mode 100644
index 0000000..80c4073
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/NotificationSender/src/com/android/cts/managedprofiletests/notificationsender/SendNotification.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.managedprofiletests.notificationsender;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.lang.Override;
+
+/**
+ * A simple activity to post notifications to test notification
+ * listener whitelists.
+ */
+public class SendNotification extends Activity {
+
+    private static final String TAG = "ListenerTest";
+
+    static final int NOTIFICATION_ID = 98765;
+    static final String NOTIFICATION_CHANNEL = "NotificationListenerTest";
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        Intent intent = getIntent();
+        if (intent != null && "POST_NOTIFICATION".equals(intent.getAction())) {
+            Log.i(TAG, "posting from " + android.os.Process.myUserHandle());
+            sendNotification();
+        } else if (intent != null && "CANCEL_NOTIFICATION".equals(intent.getAction())) {
+            Log.i(TAG, "cancelling from " + android.os.Process.myUserHandle());
+            cancelNotification();
+        }
+        finish();
+    }
+
+    private void sendNotification() {
+        NotificationManager notificationManager =
+                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.createNotificationChannel(new NotificationChannel(
+                        NOTIFICATION_CHANNEL, "Test channel", NotificationManager.IMPORTANCE_DEFAULT));
+        notificationManager.notify(NOTIFICATION_ID,
+                new Notification.Builder(getApplicationContext(), NOTIFICATION_CHANNEL)
+                .setSmallIcon(R.raw.ic_contact_picture)
+                .setContentTitle("Test title")
+                .build());
+    }
+
+    private void cancelNotification() {
+        NotificationManager notificationManager =
+                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.cancel(NOTIFICATION_ID);
+        notificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL);
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index da902d3..be4d31e 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -67,6 +67,9 @@
     private static final String DELEGATION_CERT_INSTALL = "delegation-cert-install";
     private static final String DELEGATION_APP_RESTRICTIONS = "delegation-app-restrictions";
     private static final String DELEGATION_BLOCK_UNINSTALL = "delegation-block-uninstall";
+    private static final String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
+    private static final String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
+    private static final String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app";
 
     private static final String TEST_APP_APK = "CtsSimpleApp.apk";
     private static final String TEST_APP_PKG = "com.android.cts.launcherapps.simpleapp";
@@ -183,7 +186,10 @@
         final String delegationTests[] = {
             ".AppRestrictionsDelegateTest",
             ".CertInstallDelegateTest",
-            ".BlockUninstallDelegateTest"
+            ".BlockUninstallDelegateTest",
+            ".PermissionGrantDelegateTest",
+            ".PackageAccessDelegateTest",
+            ".EnableSystemAppDelegateTest"
         };
 
         // Set a device lockscreen password (precondition for installing private key pairs).
@@ -202,7 +208,10 @@
             setDelegatedScopes(DELEGATE_APP_PKG, Arrays.asList(
                     DELEGATION_APP_RESTRICTIONS,
                     DELEGATION_CERT_INSTALL,
-                    DELEGATION_BLOCK_UNINSTALL));
+                    DELEGATION_BLOCK_UNINSTALL,
+                    DELEGATION_PERMISSION_GRANT,
+                    DELEGATION_PACKAGE_ACCESS,
+                    DELEGATION_ENABLE_SYSTEM_APP));
             runDeviceTestsAsUser(DELEGATE_APP_PKG, ".GeneralDelegateTest", mUserId);
             executeDelegationTests(delegationTests, true /* positive result */);
 
@@ -214,7 +223,7 @@
             executeDeviceTestClass(".DelegationTest");
 
         } finally {
-            // Clear lockscreen password previously set for installing private key pairs (DO only).
+            // Clear lockscreen password previously set for installing private key pairs.
             changeUserCredential(null, "1234", mPrimaryUserId);
             // Remove any remaining delegations.
             setDelegatedScopes(DELEGATE_APP_PKG, null);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 84a08ee..1b501ac 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -20,9 +20,9 @@
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.log.LogUtil.CLog;
 
-import java.lang.System;
 import junit.framework.AssertionFailedError;
 
+import java.util.Collections;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
@@ -62,6 +62,12 @@
             = "content://com.android.cts.contact.directory.provider/";
     private static final String SET_CUSTOM_DIRECTORY_PREFIX_METHOD = "set_prefix";
 
+    private static final String NOTIFICATION_APK = "CtsNotificationSenderApp.apk";
+    private static final String NOTIFICATION_PKG =
+            "com.android.cts.managedprofiletests.notificationsender";
+    private static final String NOTIFICATION_ACTIVITY =
+            NOTIFICATION_PKG + ".SendNotification";
+
     private static final String ADMIN_RECEIVER_TEST_CLASS =
             MANAGED_PROFILE_PKG + ".BaseManagedProfileTest$BasicAdminReceiver";
 
@@ -76,6 +82,8 @@
 
     private static final long TIMEOUT_USER_LOCKED_MILLIS = TimeUnit.SECONDS.toMillis(15);
 
+    private static final String PARAM_PROFILE_ID = "profile-id";
+
     private int mParentUserId;
 
     // ID of the profile we'll create. This will always be a profile of the parent.
@@ -113,6 +121,7 @@
             getDevice().uninstallPackage(MANAGED_PROFILE_PKG);
             getDevice().uninstallPackage(INTENT_SENDER_PKG);
             getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+            getDevice().uninstallPackage(NOTIFICATION_PKG);
         }
         super.tearDown();
     }
@@ -354,6 +363,60 @@
 
     }
 
+    public void testCrossProfileNotificationListeners_EmptyWhitelist() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+
+        installAppAsUser(NOTIFICATION_APK, mProfileUserId);
+        installAppAsUser(NOTIFICATION_APK, mParentUserId);
+
+        // Profile owner in the profile sets an empty whitelist
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NotificationListenerTest",
+                "testSetEmptyWhitelist", mProfileUserId,
+                Collections.singletonMap(PARAM_PROFILE_ID, Integer.toString(mProfileUserId)));
+        // Listener outside the profile can only see personal notifications.
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NotificationListenerTest",
+                "testCannotReceiveProfileNotifications", mParentUserId,
+                Collections.singletonMap(PARAM_PROFILE_ID, Integer.toString(mProfileUserId)));
+    }
+
+    public void testCrossProfileNotificationListeners_NullWhitelist() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+
+        installAppAsUser(NOTIFICATION_APK, mProfileUserId);
+        installAppAsUser(NOTIFICATION_APK, mParentUserId);
+
+        // Profile owner in the profile sets a null whitelist
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NotificationListenerTest",
+                "testSetNullWhitelist", mProfileUserId,
+                Collections.singletonMap(PARAM_PROFILE_ID, Integer.toString(mProfileUserId)));
+        // Listener outside the profile can see profile and personal notifications
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NotificationListenerTest",
+                "testCanReceiveNotifications", mParentUserId,
+                Collections.singletonMap(PARAM_PROFILE_ID, Integer.toString(mProfileUserId)));
+    }
+
+    public void testCrossProfileNotificationListeners_InWhitelist() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+
+        installAppAsUser(NOTIFICATION_APK, mProfileUserId);
+        installAppAsUser(NOTIFICATION_APK, mParentUserId);
+
+        // Profile owner in the profile adds listener to the whitelist
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NotificationListenerTest",
+                "testAddListenerToWhitelist", mProfileUserId,
+                Collections.singletonMap(PARAM_PROFILE_ID, Integer.toString(mProfileUserId)));
+        // Listener outside the profile can see profile and personal notifications
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NotificationListenerTest",
+                "testCanReceiveNotifications", mParentUserId,
+                Collections.singletonMap(PARAM_PROFILE_ID, Integer.toString(mProfileUserId)));
+    }
+
     public void testCrossProfileCopyPaste() throws Exception {
         if (!mHasFeature) {
             return;
@@ -449,8 +512,8 @@
 
     // Test the bluetooth API from a managed profile.
     public void testBluetooth() throws Exception {
-        boolean mHasBluetooth = hasDeviceFeature(FEATURE_BLUETOOTH);
-        if (!mHasFeature || !mHasBluetooth) {
+        boolean hasBluetooth = hasDeviceFeature(FEATURE_BLUETOOTH);
+        if (!mHasFeature || !hasBluetooth) {
             return ;
         }
 
@@ -881,6 +944,21 @@
         runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".SanityTest", mProfileUserId);
     }
 
+    public void testBluetoothSharingRestriction() throws Exception {
+        final boolean hasBluetooth = hasDeviceFeature(FEATURE_BLUETOOTH);
+        if (!mHasFeature || !hasBluetooth) {
+            return;
+        }
+
+        // Primary profile should be able to use bluetooth sharing.
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".BluetoothSharingRestrictionPrimaryProfileTest",
+                "testBluetoothSharingAvailable", mPrimaryUserId);
+
+        // Managed profile owner should be able to control it via DISALLOW_BLUETOOTH_SHARING.
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".BluetoothSharingRestrictionTest",
+                "testOppDisabledWhenRestrictionSet", mProfileUserId);
+    }
+
     private void disableActivityForUser(String activityName, int userId)
             throws DeviceNotAvailableException {
         String command = "am start -W --user " + userId
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
index bd7bb63..90c35f4 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
@@ -105,10 +105,11 @@
                 "testDefaultRestrictions", mDeviceOwnerUserId);
         runTests("userrestrictions.PrimaryProfileOwnerUserRestrictionsTest",
                 "testSetAllRestrictions", mDeviceOwnerUserId);
-        runTests("userrestrictions.DeviceOwnerUserRestrictionsTest",
+        runTests("userrestrictions.PrimaryProfileOwnerUserRestrictionsTest",
                 "testBroadcast", mDeviceOwnerUserId);
     }
 
+    // Checks restrictions for managed user (NOT managed profile).
     public void testUserRestrictions_secondaryProfileOwnerOnly() throws Exception {
         if (!mHasFeature || !mSupportsMultiUser) {
             return;
@@ -120,10 +121,30 @@
                 "testDefaultRestrictions", secondaryUserId);
         runTests("userrestrictions.SecondaryProfileOwnerUserRestrictionsTest",
                 "testSetAllRestrictions", secondaryUserId);
-        runTests("userrestrictions.DeviceOwnerUserRestrictionsTest",
+        runTests("userrestrictions.SecondaryProfileOwnerUserRestrictionsTest",
                 "testBroadcast", secondaryUserId);
     }
 
+    // Checks restrictions for managed profile.
+    public void testUserRestrictions_managedProfileOwnerOnly() throws Exception {
+        if (!mHasFeature || !mSupportsMultiUser) {
+            return;
+        }
+
+        // Create managed profile.
+        final int profileUserId = createManagedProfile(mDeviceOwnerUserId /* parentUserId */);
+        // createManagedProfile doesn't start the user automatically.
+        startUser(profileUserId);
+        setPoAsUser(profileUserId);
+
+        runTests("userrestrictions.ManagedProfileOwnerUserRestrictionsTest",
+                "testDefaultRestrictions", profileUserId);
+        runTests("userrestrictions.ManagedProfileOwnerUserRestrictionsTest",
+                "testSetAllRestrictions", profileUserId);
+        runTests("userrestrictions.ManagedProfileOwnerUserRestrictionsTest",
+                "testBroadcast", profileUserId);
+    }
+
     /**
      * DO + PO combination.  Make sure global DO restrictions are visible on secondary users.
      */
diff --git a/hostsidetests/inputmethodservice/hostside/AndroidTest.xml b/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
index c943aee..127c9b2 100644
--- a/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
+++ b/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
@@ -16,7 +16,7 @@
 -->
 
 <configuration description="Config for CTS Input Method Service host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsInputMethodServiceEventProvider.apk" />
         <option name="test-file-name" value="CtsInputMethodServiceDeviceTests.apk" />
diff --git a/hostsidetests/numberblocking/AndroidTest.xml b/hostsidetests/numberblocking/AndroidTest.xml
index c7597c4..70ccef9 100644
--- a/hostsidetests/numberblocking/AndroidTest.xml
+++ b/hostsidetests/numberblocking/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS number blocking test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsHostsideNumberBlockingAppTest.apk" />
     </target_preparer>
diff --git a/hostsidetests/os/AndroidTest.xml b/hostsidetests/os/AndroidTest.xml
index 5563021..ccf56e1 100644
--- a/hostsidetests/os/AndroidTest.xml
+++ b/hostsidetests/os/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for the CTS OS host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDeviceOsTestApp.apk" />
         <option name="test-file-name" value="CtsHostProcfsTestApp.apk" />
diff --git a/hostsidetests/sample/AndroidTest.xml b/hostsidetests/sample/AndroidTest.xml
index 5f5d23d..6d011a1 100644
--- a/hostsidetests/sample/AndroidTest.xml
+++ b/hostsidetests/sample/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Sample host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSampleDeviceApp.apk" />
     </target_preparer>
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/AndroidTest.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/AndroidTest.xml
index a7453c1..33304f0 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/AndroidTest.xml
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Sample host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDeviceServicesTestApp.apk" />
         <option name="test-file-name" value="CtsDeviceServicesTestSecondApp.apk" />
diff --git a/hostsidetests/services/activityandwindowmanager/windowmanager/AndroidTest.xml b/hostsidetests/services/activityandwindowmanager/windowmanager/AndroidTest.xml
index f1d8397..194cd05 100644
--- a/hostsidetests/services/activityandwindowmanager/windowmanager/AndroidTest.xml
+++ b/hostsidetests/services/activityandwindowmanager/windowmanager/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS window manager host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDragAndDropSourceApp.apk" />
         <option name="test-file-name" value="CtsDragAndDropTargetApp.apk" />
diff --git a/hostsidetests/sustainedperf/AndroidTest.xml b/hostsidetests/sustainedperf/AndroidTest.xml
index 8b843d2..59ba8d2 100644
--- a/hostsidetests/sustainedperf/AndroidTest.xml
+++ b/hostsidetests/sustainedperf/AndroidTest.xml
@@ -14,11 +14,11 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Sustained Performance host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSustainedPerformanceTestCases.apk" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSustainedPerformanceDeviceTestApp.apk" />
     </target_preparer>
diff --git a/hostsidetests/systemui/AndroidTest.xml b/hostsidetests/systemui/AndroidTest.xml
index 21e7e4c..8a83259 100644
--- a/hostsidetests/systemui/AndroidTest.xml
+++ b/hostsidetests/systemui/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS System UI host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSystemUiDeviceApp.apk" />
     </target_preparer>
diff --git a/hostsidetests/theme/AndroidTest.xml b/hostsidetests/theme/AndroidTest.xml
index 6f80107..be16edf 100644
--- a/hostsidetests/theme/AndroidTest.xml
+++ b/hostsidetests/theme/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Theme host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsThemeDeviceApp.apk" />
     </target_preparer>
diff --git a/hostsidetests/trustedvoice/AndroidTest.xml b/hostsidetests/trustedvoice/AndroidTest.xml
index 7a11095..47cfe74 100644
--- a/hostsidetests/trustedvoice/AndroidTest.xml
+++ b/hostsidetests/trustedvoice/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Trustedvoice host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTrustedVoiceApp.apk" />
     </target_preparer>
diff --git a/hostsidetests/usage/AndroidTest.xml b/hostsidetests/usage/AndroidTest.xml
index 98a7899..a1b105c 100644
--- a/hostsidetests/usage/AndroidTest.xml
+++ b/hostsidetests/usage/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS App Usage host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAppUsageTestApp.apk" />
     </target_preparer>
diff --git a/hostsidetests/webkit/AndroidTest.xml b/hostsidetests/webkit/AndroidTest.xml
index 5a0eeca..99215d9 100644
--- a/hostsidetests/webkit/AndroidTest.xml
+++ b/hostsidetests/webkit/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS WebView host test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsWebViewStartupApp.apk" />
     </target_preparer>
diff --git a/tests/JobScheduler/AndroidTest.xml b/tests/JobScheduler/AndroidTest.xml
index 619edfb..0504882 100644
--- a/tests/JobScheduler/AndroidTest.xml
+++ b/tests/JobScheduler/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Job Scheduler test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsJobSchedulerTestCases.apk" />
         <option name="test-file-name" value="CtsJobSchedulerJobPerm.apk" />
diff --git a/tests/acceleration/AndroidTest.xml b/tests/acceleration/AndroidTest.xml
index 9bf8136..03be9fd 100644
--- a/tests/acceleration/AndroidTest.xml
+++ b/tests/acceleration/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Acceleration test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAccelerationTestCases.apk" />
     </target_preparer>
diff --git a/tests/accessibility/AndroidTest.xml b/tests/accessibility/AndroidTest.xml
index bc18a7f..0d0ba65 100644
--- a/tests/accessibility/AndroidTest.xml
+++ b/tests/accessibility/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Accessibility test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAccessibilityTestCases.apk" />
     </target_preparer>
diff --git a/tests/accessibilityservice/AndroidTest.xml b/tests/accessibilityservice/AndroidTest.xml
index b2cb477..800d1f2 100644
--- a/tests/accessibilityservice/AndroidTest.xml
+++ b/tests/accessibilityservice/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS accessibility service test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAccessibilityServiceTestCases.apk" />
     </target_preparer>
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java
index 0f8b9c0..218bcc6 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java
@@ -18,6 +18,7 @@
 import android.graphics.RectF;
 import android.os.Bundle;
 import android.os.Debug;
+import android.os.Message;
 import android.os.Parcelable;
 import android.text.SpannableString;
 import android.text.Spanned;
@@ -25,7 +26,10 @@
 import android.text.style.ClickableSpan;
 import android.text.style.URLSpan;
 import android.view.View;
+import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeProvider;
+import android.view.accessibility.AccessibilityRequestPreparer;
 import android.widget.EditText;
 import android.widget.TextView;
 
@@ -34,10 +38,21 @@
 import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
 
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 
 /**
  * Test cases for actions taken on text views.
@@ -193,25 +208,10 @@
                 textAvailableExtraData.contains(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY));
         assertNull("Text locations should not be populated by default",
                 text.getExtras().get(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY));
-        Bundle getTextArgs = new Bundle();
-        getTextArgs.putInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX, 0);
-        getTextArgs.putInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH,
-                text.getText().length());
+        final Bundle getTextArgs = getTextLocationArguments(text);
         assertTrue("Refresh failed", text.refreshWithExtraData(
                 AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, getTextArgs));
-        final Parcelable[] parcelables = text.getExtras()
-                .getParcelableArray(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY);
-        final RectF[] locations = Arrays.copyOf(parcelables, parcelables.length, RectF[].class);
-        assertEquals(text.getText().length(), locations.length);
-        // The text should all be on one line, running left to right
-        for (int i = 0; i < locations.length; i++) {
-            assertEquals(locations[0].top, locations[i].top);
-            assertEquals(locations[0].bottom, locations[i].bottom);
-            assertTrue(locations[i].right > locations[i].left);
-            if (i > 0) {
-                assertTrue(locations[i].left > locations[i-1].left);
-            }
-        }
+        assertNodeContainsTextLocationInfoOnOneLineLTR(text);
     }
 
     public void testTextLocations_textOutsideOfViewBounds_locationsShouldBeNull() {
@@ -223,12 +223,9 @@
         List<String> textAvailableExtraData = text.getAvailableExtraData();
         assertTrue("Text view should offer text location to accessibility",
                 textAvailableExtraData.contains(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY));
-        Bundle getTextArgs = new Bundle();
-        getTextArgs.putInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX, 0);
-        getTextArgs.putInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH,
-                text.getText().length());
+        final Bundle getTextArgs = getTextLocationArguments(text);
         assertTrue("Refresh failed", text.refreshWithExtraData(
-                AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, getTextArgs));
+                EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, getTextArgs));
         Parcelable[] parcelables = text.getExtras()
                 .getParcelableArray(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY);
         final RectF[] locationsBeforeScroll = Arrays.copyOf(
@@ -255,7 +252,7 @@
         getInstrumentation().runOnMainSync(() -> editText.scrollTo(0, (int) oneLineDownY + 1));
 
         assertTrue("Refresh failed", text.refreshWithExtraData(
-                AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, getTextArgs));
+                EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, getTextArgs));
         parcelables = text.getExtras()
                 .getParcelableArray(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY);
         final RectF[] locationsAfterScroll = Arrays.copyOf(
@@ -266,6 +263,132 @@
         assertNotNull(locationsAfterScroll[firstNullRectIndex]);
     }
 
+    public void testTextLocations_withRequestPreparer_shouldHoldOffUntilReady() {
+        final TextView textView = (TextView) getActivity().findViewById(R.id.text);
+        makeTextViewVisibleAndSetText(textView, getString(R.string.a_b));
+
+        final AccessibilityNodeInfo text = mUiAutomation.getRootInActiveWindow()
+                .findAccessibilityNodeInfosByText(getString(R.string.a_b)).get(0);
+        final List<String> textAvailableExtraData = text.getAvailableExtraData();
+        final Bundle getTextArgs = getTextLocationArguments(text);
+
+        // Register a request preparer that will capture the message indicating that preparation
+        // is complete
+        final AtomicReference<Message> messageRefForPrepare = new AtomicReference<>(null);
+        // Use mockito's asynchronous signaling
+        Runnable mockRunnableForPrepare = mock(Runnable.class);
+
+        AccessibilityManager a11yManager =
+                getActivity().getSystemService(AccessibilityManager.class);
+        AccessibilityRequestPreparer requestPreparer = new AccessibilityRequestPreparer(
+                textView, AccessibilityRequestPreparer.REQUEST_TYPE_EXTRA_DATA) {
+            @Override
+            public void onPrepareExtraData(int virtualViewId,
+                    String extraDataKey, Bundle args, Message preparationFinishedMessage) {
+                assertEquals(AccessibilityNodeProvider.HOST_VIEW_ID, virtualViewId);
+                assertEquals(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, extraDataKey);
+                assertEquals(0, args.getInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX));
+                assertEquals(text.getText().length(),
+                        args.getInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH));
+                messageRefForPrepare.set(preparationFinishedMessage);
+                mockRunnableForPrepare.run();
+            }
+        };
+        a11yManager.addAccessibilityRequestPreparer(requestPreparer);
+        verify(mockRunnableForPrepare, times(0)).run();
+
+        // Make the extra data request in another thread
+        Runnable mockRunnableForData = mock(Runnable.class);
+        new Thread() {
+            @Override
+            public void run() {
+                assertTrue("Refresh failed", text.refreshWithExtraData(
+                        EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, getTextArgs));
+                mockRunnableForData.run();
+            }
+        }.start();
+
+        // The extra data request should trigger the request preparer
+        verify(mockRunnableForPrepare, timeout(TIMEOUT_ASYNC_PROCESSING)).run();
+        // Verify that the request for extra data didn't return. This is a bit racy, as we may still
+        // not catch it if it does return prematurely, but it does provide some protection.
+        getInstrumentation().waitForIdleSync();
+        verify(mockRunnableForData, times(0)).run();
+
+        // Declare preparation for the request complete, and verify that it runs to completion
+        messageRefForPrepare.get().sendToTarget();
+        verify(mockRunnableForData, timeout(TIMEOUT_ASYNC_PROCESSING)).run();
+        assertNodeContainsTextLocationInfoOnOneLineLTR(text);
+        a11yManager.removeAccessibilityRequestPreparer(requestPreparer);
+    }
+
+    public void testTextLocations_withUnresponsiveRequestPreparer_shouldTimeout() {
+        final TextView textView = (TextView) getActivity().findViewById(R.id.text);
+        makeTextViewVisibleAndSetText(textView, getString(R.string.a_b));
+
+        final AccessibilityNodeInfo text = mUiAutomation.getRootInActiveWindow()
+                .findAccessibilityNodeInfosByText(getString(R.string.a_b)).get(0);
+        final List<String> textAvailableExtraData = text.getAvailableExtraData();
+        final Bundle getTextArgs = getTextLocationArguments(text);
+
+        // Use mockito's asynchronous signaling
+        Runnable mockRunnableForPrepare = mock(Runnable.class);
+
+        AccessibilityManager a11yManager =
+                getActivity().getSystemService(AccessibilityManager.class);
+        AccessibilityRequestPreparer requestPreparer = new AccessibilityRequestPreparer(
+                textView, AccessibilityRequestPreparer.REQUEST_TYPE_EXTRA_DATA) {
+            @Override
+            public void onPrepareExtraData(int virtualViewId,
+                    String extraDataKey, Bundle args, Message preparationFinishedMessage) {
+                mockRunnableForPrepare.run();
+            }
+        };
+        a11yManager.addAccessibilityRequestPreparer(requestPreparer);
+        verify(mockRunnableForPrepare, times(0)).run();
+
+        // Make the extra data request in another thread
+        Runnable mockRunnableForData = mock(Runnable.class);
+        new Thread() {
+            @Override
+            public void run() {
+                assertTrue("Refresh failed", text.refreshWithExtraData(
+                        EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, getTextArgs));
+                mockRunnableForData.run();
+            }
+        }.start();
+
+        // The extra data request should trigger the request preparer
+        verify(mockRunnableForPrepare, timeout(TIMEOUT_ASYNC_PROCESSING)).run();
+
+        // Declare preparation for the request complete, and verify that it runs to completion
+        verify(mockRunnableForData, timeout(TIMEOUT_ASYNC_PROCESSING)).run();
+        a11yManager.removeAccessibilityRequestPreparer(requestPreparer);
+    }
+
+    private Bundle getTextLocationArguments(AccessibilityNodeInfo info) {
+        Bundle args = new Bundle();
+        args.putInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX, 0);
+        args.putInt(EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH, info.getText().length());
+        return args;
+    }
+
+    private void assertNodeContainsTextLocationInfoOnOneLineLTR(AccessibilityNodeInfo info) {
+        final Parcelable[] parcelables = info.getExtras()
+                .getParcelableArray(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY);
+        final RectF[] locations = Arrays.copyOf(parcelables, parcelables.length, RectF[].class);
+        assertEquals(info.getText().length(), locations.length);
+        // The text should all be on one line, running left to right
+        for (int i = 0; i < locations.length; i++) {
+            assertEquals(locations[0].top, locations[i].top);
+            assertEquals(locations[0].bottom, locations[i].bottom);
+            assertTrue(locations[i].right > locations[i].left);
+            if (i > 0) {
+                assertTrue(locations[i].left > locations[i-1].left);
+            }
+        }
+    }
+
     private void onClickCallback() {
         synchronized (mClickableSpanCallbackLock) {
             mClickableSpanCalled.set(true);
diff --git a/tests/admin/AndroidTest.xml b/tests/admin/AndroidTest.xml
index 2d230a5..664056e 100644
--- a/tests/admin/AndroidTest.xml
+++ b/tests/admin/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for the CTS device admin tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="install-arg" value="-t" />
         <option name="test-file-name" value="CtsAdminApp.apk" />
diff --git a/tests/app/AndroidTest.xml b/tests/app/AndroidTest.xml
index 9c1f57d..b51aa79 100644
--- a/tests/app/AndroidTest.xml
+++ b/tests/app/AndroidTest.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Config for CTS App test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSimpleApp.apk" />
         <option name="test-file-name" value="CtsAppTestStubs.apk" />
diff --git a/tests/app/src/android/app/cts/TimePickerDialogTest.java b/tests/app/src/android/app/cts/TimePickerDialogTest.java
index 3da25ab..47a666c 100644
--- a/tests/app/src/android/app/cts/TimePickerDialogTest.java
+++ b/tests/app/src/android/app/cts/TimePickerDialogTest.java
@@ -16,21 +16,31 @@
 
 package android.app.cts;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.AlertDialog;
 import android.app.TimePickerDialog;
 import android.app.TimePickerDialog.OnTimeSetListener;
-import android.app.stubs.DialogStubActivity;
+import android.app.stubs.R;
 import android.content.Context;
 import android.os.Bundle;
-import android.test.ActivityInstrumentationTestCase2;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.TimePicker;
 
-import android.app.stubs.R;
-
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 /**
  * Test {@link TimePickerDialog}.
  */
-public class TimePickerDialogTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class TimePickerDialogTest {
     private static final String HOUR = "hour";
     private static final String MINUTE = "minute";
     private static final String IS_24_HOUR = "is24hour";
@@ -44,17 +54,10 @@
     private OnTimeSetListener mOnTimeSetListener;
 
     private Context mContext;
-    private DialogStubActivity mActivity;
 
-    public TimePickerDialogTest() {
-        super("android.app.stubs", DialogStubActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mContext = getInstrumentation().getContext();
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
         mOnTimeSetListener = new OnTimeSetListener(){
             public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                 mCallbackHour = hourOfDay;
@@ -64,9 +67,31 @@
     }
 
     @UiThreadTest
+    @Test
+    public void testConstructor() {
+        new TimePickerDialog(mContext, null, 1, 1, false);
+
+        new TimePickerDialog(mContext, null, 1, 1, true);
+
+        new TimePickerDialog(mContext, AlertDialog.THEME_TRADITIONAL, null, 1, 1, false);
+
+        new TimePickerDialog(mContext, AlertDialog.THEME_HOLO_DARK, null, 1, 1, false);
+
+        new TimePickerDialog(mContext,
+                android.R.style.Theme_Material_Dialog_Alert, null, 1, 1, false);
+    }
+
+    @UiThreadTest
+    @Test(expected = NullPointerException.class)
+    public void testConstructorWithNullContext() {
+        new TimePickerDialog(null, null, 0, 0, false);
+    }
+
+    @UiThreadTest
+    @Test
     public void testSaveInstanceState() {
         TimePickerDialog tD = new TimePickerDialog(
-            mContext, mOnTimeSetListener, TARGET_HOUR, TARGET_MINUTE, true);
+                mContext, mOnTimeSetListener, TARGET_HOUR, TARGET_MINUTE, true);
 
         Bundle b = tD.onSaveInstanceState();
 
@@ -87,6 +112,7 @@
     }
 
     @UiThreadTest
+    @Test
     public void testOnClick() {
         TimePickerDialog timePickerDialog = buildDialog();
         timePickerDialog.onClick(null, TimePickerDialog.BUTTON_POSITIVE);
@@ -95,21 +121,16 @@
         assertEquals(TARGET_MINUTE, mCallbackMinute);
     }
 
+    @UiThreadTest
+    @Test
     public void testOnTimeChanged() throws Throwable {
         final int minute = 34;
-        startDialogActivity(DialogStubActivity.TEST_TIMEPICKERDIALOG);
-        final TimePickerDialog d = (TimePickerDialog) mActivity.getDialog();
-
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                d.onTimeChanged(null, TARGET_HOUR, minute);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
-
+        final TimePickerDialog d = buildDialog();
+        d.onTimeChanged(null, TARGET_HOUR, minute);
     }
 
     @UiThreadTest
+    @Test
     public void testUpdateTime() {
         TimePickerDialog timePickerDialog = buildDialog();
         int minute = 18;
@@ -123,6 +144,7 @@
     }
 
     @UiThreadTest
+    @Test
     public void testOnRestoreInstanceState() {
         int minute = 27;
         Bundle b1 = new Bundle();
@@ -141,10 +163,6 @@
         assertFalse(b2.getBoolean(IS_24_HOUR));
     }
 
-    private void startDialogActivity(int dialogNumber) {
-        mActivity = DialogStubActivity.startDialogActivity(this, dialogNumber);
-    }
-
     private TimePickerDialog buildDialog() {
         return new TimePickerDialog(
                 mContext, mOnTimeSetListener, TARGET_HOUR, TARGET_MINUTE, true);
diff --git a/tests/autofillservice/AndroidTest.xml b/tests/autofillservice/AndroidTest.xml
index 885537f..ea7e99f 100644
--- a/tests/autofillservice/AndroidTest.xml
+++ b/tests/autofillservice/AndroidTest.xml
@@ -14,9 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for AutoFill Framework CTS tests.">
-
-  <target_preparer
-    class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+  <option name="test-suite-tag" value="cts" />
+  <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
     <option name="cleanup-apks" value="true" />
     <option name="test-file-name" value="CtsAutoFillServiceTestCases.apk" />
   </target_preparer>
diff --git a/tests/backup/AndroidTest.xml b/tests/backup/AndroidTest.xml
index 96417c8..3d96fe2 100644
--- a/tests/backup/AndroidTest.xml
+++ b/tests/backup/AndroidTest.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 <configuration description="Config for CTS Backup test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsBackupApp.apk" />
         <option name="test-file-name" value="CtsBackupTestCases.apk" />
diff --git a/tests/camera/AndroidTest.xml b/tests/camera/AndroidTest.xml
index 1358c34..274daf0 100644
--- a/tests/camera/AndroidTest.xml
+++ b/tests/camera/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Camera test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsCameraTestCases.apk" />
     </target_preparer>
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index b88a80f..1cf0f50 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -66,7 +66,7 @@
     private static final String TAG = "PerformanceTest";
     private static final String REPORT_LOG_NAME = "CtsCameraTestCases";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-    private static final int NUM_TEST_LOOPS = 5;
+    private static final int NUM_TEST_LOOPS = 10;
     private static final int NUM_MAX_IMAGES = 4;
     private static final int NUM_RESULTS_WAIT = 30;
     private static final int[] REPROCESS_FORMATS = {ImageFormat.YUV_420_888, ImageFormat.PRIVATE};
@@ -205,6 +205,39 @@
             }
             counter++;
             mReportLog.submit(getInstrumentation());
+
+            if (VERBOSE) {
+                Log.v(TAG, "Camera " + id + " device open times(ms): "
+                        + Arrays.toString(cameraOpenTimes)
+                        + ". Average(ms): " + Stat.getAverage(cameraOpenTimes)
+                        + ". Min(ms): " + Stat.getMin(cameraOpenTimes)
+                        + ". Max(ms): " + Stat.getMax(cameraOpenTimes));
+                Log.v(TAG, "Camera " + id + " configure stream times(ms): "
+                        + Arrays.toString(configureStreamTimes)
+                        + ". Average(ms): " + Stat.getAverage(configureStreamTimes)
+                        + ". Min(ms): " + Stat.getMin(configureStreamTimes)
+                        + ". Max(ms): " + Stat.getMax(configureStreamTimes));
+                Log.v(TAG, "Camera " + id + " start preview times(ms): "
+                        + Arrays.toString(startPreviewTimes)
+                        + ". Average(ms): " + Stat.getAverage(startPreviewTimes)
+                        + ". Min(ms): " + Stat.getMin(startPreviewTimes)
+                        + ". Max(ms): " + Stat.getMax(startPreviewTimes));
+                Log.v(TAG, "Camera " + id + " stop preview times(ms): "
+                        + Arrays.toString(stopPreviewTimes)
+                        + ". Average(ms): " + Stat.getAverage(stopPreviewTimes)
+                        + ". nMin(ms): " + Stat.getMin(stopPreviewTimes)
+                        + ". nMax(ms): " + Stat.getMax(stopPreviewTimes));
+                Log.v(TAG, "Camera " + id + " device close times(ms): "
+                        + Arrays.toString(cameraCloseTimes)
+                        + ". Average(ms): " + Stat.getAverage(cameraCloseTimes)
+                        + ". Min(ms): " + Stat.getMin(cameraCloseTimes)
+                        + ". Max(ms): " + Stat.getMax(cameraCloseTimes));
+                Log.v(TAG, "Camera " + id + " camera launch times(ms): "
+                        + Arrays.toString(cameraLaunchTimes)
+                        + ". Average(ms): " + Stat.getAverage(cameraLaunchTimes)
+                        + ". Min(ms): " + Stat.getMin(cameraLaunchTimes)
+                        + ". Max(ms): " + Stat.getMax(cameraLaunchTimes));
+            }
         }
         if (mCameraIds.length != 0) {
             String streamName = "test_camera_launch_average";
@@ -1085,7 +1118,7 @@
 
             if (imageAvailable.block(timeout)) {
                 imageAvailable.close();
-                imageReceived = false;
+                imageReceived = true;
             } else {
                 throw new TimeoutRuntimeException("Unable to get the first image after "
                         + CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS + "ms");
diff --git a/tests/dram/AndroidTest.xml b/tests/dram/AndroidTest.xml
index b3a5051..bc0e8b6 100644
--- a/tests/dram/AndroidTest.xml
+++ b/tests/dram/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Dram test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDramTestCases.apk" />
     </target_preparer>
diff --git a/tests/filesystem/AndroidTest.xml b/tests/filesystem/AndroidTest.xml
index 40212a2..8429d28 100644
--- a/tests/filesystem/AndroidTest.xml
+++ b/tests/filesystem/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS File System test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsFileSystemTestCases.apk" />
     </target_preparer>
diff --git a/tests/fragment/AndroidTest.xml b/tests/fragment/AndroidTest.xml
index 2a9faae..cbce128 100644
--- a/tests/fragment/AndroidTest.xml
+++ b/tests/fragment/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for app.usage Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsFragmentTestCases.apk" />
     </target_preparer>
diff --git a/tests/inputmethod/AndroidTest.xml b/tests/inputmethod/AndroidTest.xml
index ed1e6be..f88fcd5 100644
--- a/tests/inputmethod/AndroidTest.xml
+++ b/tests/inputmethod/AndroidTest.xml
@@ -16,7 +16,7 @@
 -->
 
 <configuration description="Config for CTS InputMethod test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsInputMethodTestCases.apk" />
     </target_preparer>
diff --git a/tests/jank/AndroidTest.xml b/tests/jank/AndroidTest.xml
index aeb3d65..acdce636 100644
--- a/tests/jank/AndroidTest.xml
+++ b/tests/jank/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Jank test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsUiDeviceTestCases.apk" />
         <option name="test-file-name" value="CtsJankDeviceTestCases.apk" />
diff --git a/tests/leanbackjank/AndroidTest.xml b/tests/leanbackjank/AndroidTest.xml
index 2828243..b3fc240 100644
--- a/tests/leanbackjank/AndroidTest.xml
+++ b/tests/leanbackjank/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS LeanbackJank test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsLeanbackJankTestCases.apk" />
         <option name="test-file-name" value="CtsLeanbackJankApp.apk" />
diff --git a/tests/libcore/javautilcollections/AndroidTest.xml b/tests/libcore/javautilcollections/AndroidTest.xml
index 7261c80..016285f 100644
--- a/tests/libcore/javautilcollections/AndroidTest.xml
+++ b/tests/libcore/javautilcollections/AndroidTest.xml
@@ -13,7 +13,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Libcore java.util Collection test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsLibcoreJavaUtilCollectionsTestCases.apk" />
     </target_preparer>
diff --git a/tests/libcore/jsr166/AndroidTest.xml b/tests/libcore/jsr166/AndroidTest.xml
index bdf5643..1a4f1da 100644
--- a/tests/libcore/jsr166/AndroidTest.xml
+++ b/tests/libcore/jsr166/AndroidTest.xml
@@ -19,7 +19,7 @@
         <option name="run-command" value="mkdir -p /data/local/tmp/ctslibcore/user.home" />
         <option name="teardown-command" value="rm -rf /data/local/tmp/ctslibcore" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <!-- this has just the instrumentation which acts as the tests we want to run -->
         <option name="test-file-name" value="CtsLibcoreJsr166TestCases.apk" />
diff --git a/tests/libcore/luni/AndroidTest.xml b/tests/libcore/luni/AndroidTest.xml
index 6e547f0..576f6bb 100644
--- a/tests/libcore/luni/AndroidTest.xml
+++ b/tests/libcore/luni/AndroidTest.xml
@@ -19,7 +19,7 @@
         <option name="run-command" value="mkdir -p /data/local/tmp/ctslibcore/user.home" />
         <option name="teardown-command" value="rm -rf /data/local/tmp/ctslibcore" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <!-- this has just the instrumentation which acts as the tests we want to run -->
         <option name="test-file-name" value="CtsLibcoreTestCases.apk" />
diff --git a/tests/libcore/ojluni/AndroidTest.xml b/tests/libcore/ojluni/AndroidTest.xml
index 640d818..4bfa3d1 100644
--- a/tests/libcore/ojluni/AndroidTest.xml
+++ b/tests/libcore/ojluni/AndroidTest.xml
@@ -19,7 +19,7 @@
         <option name="run-command" value="mkdir -p /data/local/tmp/ctslibcore/user.home" />
         <option name="teardown-command" value="rm -rf /data/local/tmp/ctslibcore" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <!-- this has the CoreTestRunner which needs to be in a separate APK -->
         <option name="test-file-name" value="CtsLibcoreTestRunner.apk" />
diff --git a/tests/libcore/okhttp/AndroidTest.xml b/tests/libcore/okhttp/AndroidTest.xml
index 59182e2..5a7806b 100644
--- a/tests/libcore/okhttp/AndroidTest.xml
+++ b/tests/libcore/okhttp/AndroidTest.xml
@@ -19,7 +19,7 @@
         <option name="run-command" value="mkdir -p /data/local/tmp/ctslibcore/user.home" />
         <option name="teardown-command" value="rm -rf /data/local/tmp/ctslibcore" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <!-- this has just the instrumentation which acts as the tests we want to run -->
         <option name="test-file-name" value="CtsLibcoreOkHttpTestCases.apk" />
diff --git a/tests/libcore/wycheproof/AndroidTest.xml b/tests/libcore/wycheproof/AndroidTest.xml
index f933565..f944ae9 100644
--- a/tests/libcore/wycheproof/AndroidTest.xml
+++ b/tests/libcore/wycheproof/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Libcore Wycheproof test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <!-- this has just the instrumentation which acts as the tests we want to run -->
         <option name="test-file-name" value="CtsLibcoreWycheproofTestCases.apk" />
diff --git a/tests/netlegacy22.api/AndroidTest.xml b/tests/netlegacy22.api/AndroidTest.xml
index 17e71f4..07e83a1 100644
--- a/tests/netlegacy22.api/AndroidTest.xml
+++ b/tests/netlegacy22.api/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Legacy android.net APIs test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetTestCasesLegacyApi22.apk" />
     </target_preparer>
diff --git a/tests/netlegacy22.permission/AndroidTest.xml b/tests/netlegacy22.permission/AndroidTest.xml
index 5b4ffa0..de6a3c9 100644
--- a/tests/netlegacy22.permission/AndroidTest.xml
+++ b/tests/netlegacy22.permission/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Legacy android.net Permission test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetTestCasesLegacyPermission22.apk" />
     </target_preparer>
diff --git a/tests/openglperf2/AndroidTest.xml b/tests/openglperf2/AndroidTest.xml
index 5e50e8d..613647e 100644
--- a/tests/openglperf2/AndroidTest.xml
+++ b/tests/openglperf2/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS OpenGL test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsOpenGlPerf2TestCases.apk" />
     </target_preparer>
diff --git a/tests/sample/AndroidTest.xml b/tests/sample/AndroidTest.xml
index ae790fb..ed6bbe4 100644
--- a/tests/sample/AndroidTest.xml
+++ b/tests/sample/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Sample test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSampleDeviceTestCases.apk" />
     </target_preparer>
diff --git a/tests/sensor/AndroidTest.xml b/tests/sensor/AndroidTest.xml
index 8d1207e..edffd03 100644
--- a/tests/sensor/AndroidTest.xml
+++ b/tests/sensor/AndroidTest.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Config for CTS Sensor test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSensorTestCases.apk" />
     </target_preparer>
diff --git a/tests/signature/AndroidTest.xml b/tests/signature/AndroidTest.xml
index 6d23620..d1524af 100644
--- a/tests/signature/AndroidTest.xml
+++ b/tests/signature/AndroidTest.xml
@@ -35,7 +35,7 @@
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="push" value="system-current.api->/data/local/tmp/signature-test/system-current.api" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSignatureTestCases.apk" />
     </target_preparer>
diff --git a/tests/simplecpu/AndroidTest.xml b/tests/simplecpu/AndroidTest.xml
index b48ae43..eaf35c6 100644
--- a/tests/simplecpu/AndroidTest.xml
+++ b/tests/simplecpu/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS File System test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSimpleCpuTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/accounts/AndroidTest.xml b/tests/tests/accounts/AndroidTest.xml
index c15cdce..af95665 100644
--- a/tests/tests/accounts/AndroidTest.xml
+++ b/tests/tests/accounts/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Accounts test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsUnaffiliatedAccountAuthenticators.apk" />
         <option name="test-file-name" value="CtsAccountManagerTestCases.apk" />
diff --git a/tests/tests/alarmclock/AndroidTest.xml b/tests/tests/alarmclock/AndroidTest.xml
index 525257e..222d574 100644
--- a/tests/tests/alarmclock/AndroidTest.xml
+++ b/tests/tests/alarmclock/AndroidTest.xml
@@ -14,13 +14,14 @@
      limitations under the License.
 -->
 <configuration description="Configuration for AlarmClock Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAlarmClockService.apk" />
         <option name="test-file-name" value="CtsAlarmClockTestCases.apk" />
     </target_preparer>
 
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">    
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command"
              value="settings put secure voice_interaction_service android.alarmclock.service/.MainInteractionService" />
     </target_preparer>
@@ -28,4 +29,4 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
         <option name="package" value="android.alarmclock.cts" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/animation/AndroidTest.xml b/tests/tests/animation/AndroidTest.xml
index 680256c..fe65ff6 100644
--- a/tests/tests/animation/AndroidTest.xml
+++ b/tests/tests/animation/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Animation test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAnimationTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/app.usage/AndroidTest.xml b/tests/tests/app.usage/AndroidTest.xml
index d4967f9..b488568 100644
--- a/tests/tests/app.usage/AndroidTest.xml
+++ b/tests/tests/app.usage/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for app.usage Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsUsageStatsTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/app/AndroidTest.xml b/tests/tests/app/AndroidTest.xml
index 739e0ba..c4387d1 100644
--- a/tests/tests/app/AndroidTest.xml
+++ b/tests/tests/app/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for app Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAndroidAppTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/appwidget/AndroidTest.xml b/tests/tests/appwidget/AndroidTest.xml
index 9c599f1..30aecaf 100644
--- a/tests/tests/appwidget/AndroidTest.xml
+++ b/tests/tests/appwidget/AndroidTest.xml
@@ -13,7 +13,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS App Widget test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAppWidgetLauncher1.apk" />
         <option name="test-file-name" value="CtsAppWidgetLauncher2.apk" />
diff --git a/tests/tests/assist/AndroidTest.xml b/tests/tests/assist/AndroidTest.xml
index a920816..2ed7ac3 100644
--- a/tests/tests/assist/AndroidTest.xml
+++ b/tests/tests/assist/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Assist test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAssistService.apk" />
         <option name="test-file-name" value="CtsAssistApp.apk" />
diff --git a/tests/tests/bluetooth/AndroidTest.xml b/tests/tests/bluetooth/AndroidTest.xml
index fb4b205..69bb280 100644
--- a/tests/tests/bluetooth/AndroidTest.xml
+++ b/tests/tests/bluetooth/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Bluetooth test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsBluetoothTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/calendarcommon/AndroidTest.xml b/tests/tests/calendarcommon/AndroidTest.xml
index c411e69..f9e81f6 100644
--- a/tests/tests/calendarcommon/AndroidTest.xml
+++ b/tests/tests/calendarcommon/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Calendar test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsCalendarcommon2TestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/calllog/AndroidTest.xml b/tests/tests/calllog/AndroidTest.xml
index 408aaac..0f36d9c 100644
--- a/tests/tests/calllog/AndroidTest.xml
+++ b/tests/tests/calllog/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Call Log test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsCallLogTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/car/AndroidTest.xml b/tests/tests/car/AndroidTest.xml
index d82c101..68ab35c 100644
--- a/tests/tests/car/AndroidTest.xml
+++ b/tests/tests/car/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Automotive test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsCarTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/carrierapi/AndroidTest.xml b/tests/tests/carrierapi/AndroidTest.xml
index fa8f4cc..a3c8458 100644
--- a/tests/tests/carrierapi/AndroidTest.xml
+++ b/tests/tests/carrierapi/AndroidTest.xml
@@ -17,7 +17,7 @@
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.TokenRequirement">
         <option name="token" value="sim-card-with-certs" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsCarrierApiTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/colormode/AndroidTest.xml b/tests/tests/colormode/AndroidTest.xml
index 3f797aa..db24dc3 100644
--- a/tests/tests/colormode/AndroidTest.xml
+++ b/tests/tests/colormode/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Color Mode test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsColorModeTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/contactsproviderwipe/AndroidTest.xml b/tests/tests/contactsproviderwipe/AndroidTest.xml
index e20faa6..940a64c 100644
--- a/tests/tests/contactsproviderwipe/AndroidTest.xml
+++ b/tests/tests/contactsproviderwipe/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Provider test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsContactsProviderWipe.apk" />
     </target_preparer>
diff --git a/tests/tests/content/AndroidTest.xml b/tests/tests/content/AndroidTest.xml
index 44199a8..e20317a 100644
--- a/tests/tests/content/AndroidTest.xml
+++ b/tests/tests/content/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Content test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsContentTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/database/AndroidTest.xml b/tests/tests/database/AndroidTest.xml
index 4af84e0..cd85b38 100644
--- a/tests/tests/database/AndroidTest.xml
+++ b/tests/tests/database/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Database test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDatabaseTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/debug/AndroidTest.xml b/tests/tests/debug/AndroidTest.xml
index 2c36912..7674720 100644
--- a/tests/tests/debug/AndroidTest.xml
+++ b/tests/tests/debug/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Debug test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDebugTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/display/AndroidTest.xml b/tests/tests/display/AndroidTest.xml
index f7f52de..012bd68 100644
--- a/tests/tests/display/AndroidTest.xml
+++ b/tests/tests/display/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Acceleration test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDisplayTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/dpi/AndroidTest.xml b/tests/tests/dpi/AndroidTest.xml
index 7b50015..0d78c93 100644
--- a/tests/tests/dpi/AndroidTest.xml
+++ b/tests/tests/dpi/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS DPI test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDpiTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/dpi2/AndroidTest.xml b/tests/tests/dpi2/AndroidTest.xml
index 988f319..bce205c 100644
--- a/tests/tests/dpi2/AndroidTest.xml
+++ b/tests/tests/dpi2/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS DPI test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDpiTestCases2.apk" />
     </target_preparer>
diff --git a/tests/tests/dreams/AndroidTest.xml b/tests/tests/dreams/AndroidTest.xml
index 92a2f97..6af3467 100644
--- a/tests/tests/dreams/AndroidTest.xml
+++ b/tests/tests/dreams/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Dreams test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDreamsTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/drm/AndroidTest.xml b/tests/tests/drm/AndroidTest.xml
index 5fc854e..00561d8 100644
--- a/tests/tests/drm/AndroidTest.xml
+++ b/tests/tests/drm/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS DRM test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsDrmTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/effect/AndroidTest.xml b/tests/tests/effect/AndroidTest.xml
index 7ba983e..4fef2d7 100644
--- a/tests/tests/effect/AndroidTest.xml
+++ b/tests/tests/effect/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Effect test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsEffectTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/externalservice/AndroidTest.xml b/tests/tests/externalservice/AndroidTest.xml
index 36ecb04..da33cb6 100644
--- a/tests/tests/externalservice/AndroidTest.xml
+++ b/tests/tests/externalservice/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS External Service test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsExternalServiceService.apk" />
         <option name="test-file-name" value="CtsExternalServiceTestCases.apk" />
diff --git a/tests/tests/gesture/AndroidTest.xml b/tests/tests/gesture/AndroidTest.xml
index 8cc1cd4..b655a31 100644
--- a/tests/tests/gesture/AndroidTest.xml
+++ b/tests/tests/gesture/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Gesture test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsGestureTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/graphics/AndroidTest.xml b/tests/tests/graphics/AndroidTest.xml
index a9f746b..6485931 100644
--- a/tests/tests/graphics/AndroidTest.xml
+++ b/tests/tests/graphics/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Graphics test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsGraphicsTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/hardware/AndroidTest.xml b/tests/tests/hardware/AndroidTest.xml
index e33ffa0..7d574d3 100644
--- a/tests/tests/hardware/AndroidTest.xml
+++ b/tests/tests/hardware/AndroidTest.xml
@@ -14,7 +14,7 @@
 -->
 <configuration description="Config for CTS Hardware test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsHardwareTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/icu/AndroidTest.xml b/tests/tests/icu/AndroidTest.xml
index 5d8bd19..c64898e 100644
--- a/tests/tests/icu/AndroidTest.xml
+++ b/tests/tests/icu/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS ICU test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsIcuTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/incident/AndroidTest.xml b/tests/tests/incident/AndroidTest.xml
index 529b674..0471de1 100644
--- a/tests/tests/incident/AndroidTest.xml
+++ b/tests/tests/incident/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Configuration for OS Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsIncidentTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/jni/AndroidTest.xml b/tests/tests/jni/AndroidTest.xml
index c1746de..1daa4c4 100644
--- a/tests/tests/jni/AndroidTest.xml
+++ b/tests/tests/jni/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS JNI test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsJniTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/keystore/AndroidTest.xml b/tests/tests/keystore/AndroidTest.xml
index 41b8541..08238a7 100644
--- a/tests/tests/keystore/AndroidTest.xml
+++ b/tests/tests/keystore/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Keystore test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsKeystoreTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/libcorefileio/AndroidTest.xml b/tests/tests/libcorefileio/AndroidTest.xml
index e21d3a2..03d9f22 100644
--- a/tests/tests/libcorefileio/AndroidTest.xml
+++ b/tests/tests/libcorefileio/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Legacy Libcore test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsLibcoreFileIOTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/libcorelegacy22/AndroidTest.xml b/tests/tests/libcorelegacy22/AndroidTest.xml
index a313035..3f18a12 100644
--- a/tests/tests/libcorelegacy22/AndroidTest.xml
+++ b/tests/tests/libcorelegacy22/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Legacy Libcore test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsLibcoreLegacy22TestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/location/AndroidTest.xml b/tests/tests/location/AndroidTest.xml
index 4ac850e..108915e 100644
--- a/tests/tests/location/AndroidTest.xml
+++ b/tests/tests/location/AndroidTest.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Config for CTS Location test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsLocationTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/location2/AndroidTest.xml b/tests/tests/location2/AndroidTest.xml
index 31f4684..03ef041 100644
--- a/tests/tests/location2/AndroidTest.xml
+++ b/tests/tests/location2/AndroidTest.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Config for CTS Location test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsLocation2TestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/media/AndroidTest.xml b/tests/tests/media/AndroidTest.xml
index 08ee0a0..ac5ec91 100644
--- a/tests/tests/media/AndroidTest.xml
+++ b/tests/tests/media/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Media test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsMediaTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/mediastress/AndroidTest.xml b/tests/tests/mediastress/AndroidTest.xml
index b41fcf3..1879e03 100644
--- a/tests/tests/mediastress/AndroidTest.xml
+++ b/tests/tests/mediastress/AndroidTest.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Config for CTS Media Stress test cases">
     <target_preparer class="android.mediastress.cts.preconditions.MediaPreparer" />
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsMediaStressTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/midi/AndroidTest.xml b/tests/tests/midi/AndroidTest.xml
index ebb2c72..e7e22e8 100644
--- a/tests/tests/midi/AndroidTest.xml
+++ b/tests/tests/midi/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS MIDI test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsMidiTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/multiuser/AndroidTest.xml b/tests/tests/multiuser/AndroidTest.xml
index d5593627..7c7d938 100644
--- a/tests/tests/multiuser/AndroidTest.xml
+++ b/tests/tests/multiuser/AndroidTest.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 <configuration description="Config for CTS Multiuser test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsMultiUserTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/ndef/AndroidTest.xml b/tests/tests/ndef/AndroidTest.xml
index 5e4de24..10a4095 100644
--- a/tests/tests/ndef/AndroidTest.xml
+++ b/tests/tests/ndef/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS NDEF test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNdefTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/net/AndroidTest.xml b/tests/tests/net/AndroidTest.xml
index 389b926..fbad739 100644
--- a/tests/tests/net/AndroidTest.xml
+++ b/tests/tests/net/AndroidTest.xml
@@ -13,7 +13,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Net test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetTestCases.apk" />
         <option name="test-file-name" value="CtsNetTestAppForApi23.apk" />
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidTest.xml b/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidTest.xml
index 838367b..73759c5 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidTest.xml
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-false/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecPolicyUsesCleartextTrafficFalse test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecPolicyUsesCleartextTrafficFalse.apk" />
         <option name="test-file-name" value="CtsNetSecPolicyUsesCleartextTrafficFalseTestCases.apk" />
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidTest.xml b/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidTest.xml
index b30c53f..fa13213 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidTest.xml
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-true/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecPolicyUsesCleartextTrafficTrue test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecPolicyUsesCleartextTrafficTrue.apk" />
         <option name="test-file-name" value="CtsNetSecPolicyUsesCleartextTrafficTrueTestCases.apk" />
diff --git a/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidTest.xml b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidTest.xml
index 9ede86b..8c1fb4d 100644
--- a/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidTest.xml
+++ b/tests/tests/netsecpolicy/usescleartexttraffic-unspecified/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecPolicyUsesCleartextTrafficUnspecified test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecPolicyUsesCleartextTrafficUnspecified.apk" />
         <option name="test-file-name" value="CtsNetSecPolicyUsesCleartextTrafficUnspecifiedTestCases.apk" />
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-attributes/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-attributes/AndroidTest.xml
index b2c1400..500c481 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-attributes/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-attributes/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecConfigAttributeTestCases test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecConfigAttributeTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-basic-domain/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-basic-domain/AndroidTest.xml
index 901022f..6ce0531 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-basic-domain/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-basic-domain/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecConfigBasicDomainConfigTestCases test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecConfigBasicDomainConfigTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidTest.xml
index 829899c..1b6578a 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-cleartext/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecConfigCleartextTraffic test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecConfigCleartextTrafficTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-debug-basic-disabled/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-debug-basic-disabled/AndroidTest.xml
index 5d12f0a..756f2ab 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-debug-basic-disabled/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-debug-basic-disabled/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecConfigBasicDebugDisabledTestCases test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecConfigBasicDebugDisabledTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-debug-basic-enabled/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-debug-basic-enabled/AndroidTest.xml
index 38a2d31..febad18 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-debug-basic-enabled/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-debug-basic-enabled/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecConfigBasicDebugEnabledTestCases test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecConfigBasicDebugEnabledTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/AndroidTest.xml
index 7ce9f7a..4880161 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-downloadmanager/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecConfigDownloadManagerTestCases test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecConfigDownloadManagerTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-invalid-pin/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-invalid-pin/AndroidTest.xml
index 127927f..63faa39 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-invalid-pin/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-invalid-pin/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecConfigInvalidPinTestCases test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecConfigInvalidPinTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-nested-domains/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-nested-domains/AndroidTest.xml
index e430dbd..e6bfb52 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-nested-domains/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-nested-domains/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecConfigNestedDomainConfigTestCases test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecConfigNestedDomainConfigTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/AndroidTest.xml b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/AndroidTest.xml
index 570160c..e088460 100644
--- a/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/AndroidTest.xml
+++ b/tests/tests/networksecurityconfig/networksecurityconfig-resourcesrc/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS CtsNetSecConfigInvalidPinTestCases test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsNetSecConfigResourcesSrcTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/opengl/AndroidTest.xml b/tests/tests/opengl/AndroidTest.xml
index f112f83..0afe39a 100644
--- a/tests/tests/opengl/AndroidTest.xml
+++ b/tests/tests/opengl/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS OpenGL test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsOpenGLTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/openglperf/AndroidTest.xml b/tests/tests/openglperf/AndroidTest.xml
index 630bd05..2ab322b 100644
--- a/tests/tests/openglperf/AndroidTest.xml
+++ b/tests/tests/openglperf/AndroidTest.xml
@@ -13,7 +13,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS OpenGL Performance test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsOpenGlPerfTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/os/AndroidTest.xml b/tests/tests/os/AndroidTest.xml
index fd446c2..e01a734 100644
--- a/tests/tests/os/AndroidTest.xml
+++ b/tests/tests/os/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for OS Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsOsTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
index f1cc70a..cf92bc3 100644
--- a/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
+++ b/tests/tests/packageinstaller/adminpackageinstaller/AndroidTest.xml
@@ -26,7 +26,7 @@
         <option name="push" value="CtsEmptyTestApp.apk->/data/local/tmp/cts/packageinstaller/CtsEmptyTestApp.apk" />
     </target_preparer>
 
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="install-arg" value="-t" />
         <option name="test-file-name" value="CtsAdminPackageInstallerTestCases.apk" />
diff --git a/tests/tests/packageinstaller/externalsources/AndroidTest.xml b/tests/tests/packageinstaller/externalsources/AndroidTest.xml
index 6302be9..136c0fb 100644
--- a/tests/tests/packageinstaller/externalsources/AndroidTest.xml
+++ b/tests/tests/packageinstaller/externalsources/AndroidTest.xml
@@ -26,7 +26,7 @@
         <option name="push" value="CtsEmptyTestApp.apk->/data/local/tmp/cts/externalsources/CtsEmptyTestApp.apk" />
     </target_preparer>
 
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsExternalSourcesTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/permission/AndroidTest.xml b/tests/tests/permission/AndroidTest.xml
index a01352a..c83c5fc 100644
--- a/tests/tests/permission/AndroidTest.xml
+++ b/tests/tests/permission/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Permission test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsPermissionTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/permission2/AndroidTest.xml b/tests/tests/permission2/AndroidTest.xml
index b814aa7..7a78d3f 100644
--- a/tests/tests/permission2/AndroidTest.xml
+++ b/tests/tests/permission2/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Permission test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsPermission2TestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/preference/AndroidTest.xml b/tests/tests/preference/AndroidTest.xml
index 91e2ebe..791d9a87 100644
--- a/tests/tests/preference/AndroidTest.xml
+++ b/tests/tests/preference/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Preference test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsPreferenceTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/preference2/AndroidTest.xml b/tests/tests/preference2/AndroidTest.xml
index 96dfe0e..e57fbce 100644
--- a/tests/tests/preference2/AndroidTest.xml
+++ b/tests/tests/preference2/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Preference test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsPreference2TestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/print/AndroidTest.xml b/tests/tests/print/AndroidTest.xml
index 9e3e797..95ce5dc 100644
--- a/tests/tests/print/AndroidTest.xml
+++ b/tests/tests/print/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Print test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsPrintTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/proto/AndroidTest.xml b/tests/tests/proto/AndroidTest.xml
index 5bd5c60..e2b98ff 100644
--- a/tests/tests/proto/AndroidTest.xml
+++ b/tests/tests/proto/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for Proto Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsProtoTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/provider/AndroidTest.xml b/tests/tests/provider/AndroidTest.xml
index 4c87f9c..1f42736 100644
--- a/tests/tests/provider/AndroidTest.xml
+++ b/tests/tests/provider/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Provider test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsProviderTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/renderscript/AndroidTest.xml b/tests/tests/renderscript/AndroidTest.xml
index 63bcd88..e7245ab 100644
--- a/tests/tests/renderscript/AndroidTest.xml
+++ b/tests/tests/renderscript/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for Renderscript Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsRenderscriptTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/renderscriptlegacy/AndroidTest.xml b/tests/tests/renderscriptlegacy/AndroidTest.xml
index 3523dfe..26ef000 100644
--- a/tests/tests/renderscriptlegacy/AndroidTest.xml
+++ b/tests/tests/renderscriptlegacy/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for Renderscript legacy Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsRenderscriptLegacyTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/rsblas/AndroidTest.xml b/tests/tests/rsblas/AndroidTest.xml
index 340ca29..3756e61 100644
--- a/tests/tests/rsblas/AndroidTest.xml
+++ b/tests/tests/rsblas/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS RS BLAS test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsRsBlasTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/rscpp/AndroidTest.xml b/tests/tests/rscpp/AndroidTest.xml
index d412054..9014c38 100644
--- a/tests/tests/rscpp/AndroidTest.xml
+++ b/tests/tests/rscpp/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for renderscript cpp Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsRsCppTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/sax/AndroidTest.xml b/tests/tests/sax/AndroidTest.xml
index 84280de..3fd03d2 100644
--- a/tests/tests/sax/AndroidTest.xml
+++ b/tests/tests/sax/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS SAX test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSaxTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
index ab2e57a..4536440 100644
--- a/tests/tests/security/AndroidTest.xml
+++ b/tests/tests/security/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS security test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSecurityTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/security/src/android/security/cts/AslrTest.java b/tests/tests/security/src/android/security/cts/AslrTest.java
index 378aa0f..67bb48f 100644
--- a/tests/tests/security/src/android/security/cts/AslrTest.java
+++ b/tests/tests/security/src/android/security/cts/AslrTest.java
@@ -52,7 +52,7 @@
         BufferedReader reader = new BufferedReader(
                 new InputStreamReader(new FileInputStream(pfd.getFileDescriptor())));
 
-        Pattern p = Pattern.compile("^([a-f0-9]+)\\-.+\\[" + mappingName + "\\]$");
+        Pattern p = Pattern.compile("^([a-f0-9]+).*" + mappingName + ".*");
         String line;
 
         while ((line = reader.readLine()) != null) {
@@ -97,7 +97,8 @@
     }
 
     public void testRandomization() throws Exception {
-        testMappingEntropy("stack");
+        testMappingEntropy("\\[stack\\]");
+        testMappingEntropy("/system/bin/");
     }
 
     public void testOneExecutableIsPie() throws IOException {
diff --git a/tests/tests/selinux/selinuxTargetSdk/AndroidTest.xml b/tests/tests/selinux/selinuxTargetSdk/AndroidTest.xml
index c29fd6c..1a05aa1 100644
--- a/tests/tests/selinux/selinuxTargetSdk/AndroidTest.xml
+++ b/tests/tests/selinux/selinuxTargetSdk/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Permission Selinux test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSelinuxTargetSdkTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/selinux/selinuxTargetSdk2/AndroidTest.xml b/tests/tests/selinux/selinuxTargetSdk2/AndroidTest.xml
index fe515f6..6e430e8 100644
--- a/tests/tests/selinux/selinuxTargetSdk2/AndroidTest.xml
+++ b/tests/tests/selinux/selinuxTargetSdk2/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Permission Selinux test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSelinuxTargetSdk2TestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/shortcutmanager/AndroidTest.xml b/tests/tests/shortcutmanager/AndroidTest.xml
index cbf35ea..4722aeb 100644
--- a/tests/tests/shortcutmanager/AndroidTest.xml
+++ b/tests/tests/shortcutmanager/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for ShortcutManager CTS test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsShortcutManagerTestCases.apk" />
         <option name="test-file-name" value="CtsShortcutManagerPackage1.apk" />
diff --git a/tests/tests/simpleperf/AndroidTest.xml b/tests/tests/simpleperf/AndroidTest.xml
index 098afc4..f8ff36d 100644
--- a/tests/tests/simpleperf/AndroidTest.xml
+++ b/tests/tests/simpleperf/AndroidTest.xml
@@ -19,7 +19,7 @@
         <option name="push" value="CtsSimpleperfTestCases->/data/local/tmp/CtsSimpleperfTestCases" />
         <option name="append-bitness" value="true" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSimpleperfDebugApp.apk" />
     </target_preparer>
diff --git a/tests/tests/speech/AndroidTest.xml b/tests/tests/speech/AndroidTest.xml
index be6d08f..2819bd4 100644
--- a/tests/tests/speech/AndroidTest.xml
+++ b/tests/tests/speech/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Speech test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSpeechTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/systemintents/AndroidTest.xml b/tests/tests/systemintents/AndroidTest.xml
index eceb909..db41361 100644
--- a/tests/tests/systemintents/AndroidTest.xml
+++ b/tests/tests/systemintents/AndroidTest.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 <configuration description="Config for CTS system intent test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSystemIntentTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/systemui/AndroidTest.xml b/tests/tests/systemui/AndroidTest.xml
index 61bdae3..314a8e9 100644
--- a/tests/tests/systemui/AndroidTest.xml
+++ b/tests/tests/systemui/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS SystemUI test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsSystemUiTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/telecom/AndroidTest.xml b/tests/tests/telecom/AndroidTest.xml
index 7f34c0c..1c42e66 100644
--- a/tests/tests/telecom/AndroidTest.xml
+++ b/tests/tests/telecom/AndroidTest.xml
@@ -17,7 +17,7 @@
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.TokenRequirement">
         <option name="token" value="sim-card" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTelecomTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/telecom2/AndroidTest.xml b/tests/tests/telecom2/AndroidTest.xml
index e7ae80c..0e26e62 100644
--- a/tests/tests/telecom2/AndroidTest.xml
+++ b/tests/tests/telecom2/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for Telecom2 Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTelecomTestCases2.apk" />
     </target_preparer>
diff --git a/tests/tests/telecom3/AndroidTest.xml b/tests/tests/telecom3/AndroidTest.xml
index 7576d62..4e682f6 100644
--- a/tests/tests/telecom3/AndroidTest.xml
+++ b/tests/tests/telecom3/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Configuration for Telecom3 Tests">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTelecomTestCases3.apk" />
     </target_preparer>
diff --git a/tests/tests/telephony/AndroidTest.xml b/tests/tests/telephony/AndroidTest.xml
index 2e6011b..2b436ca 100644
--- a/tests/tests/telephony/AndroidTest.xml
+++ b/tests/tests/telephony/AndroidTest.xml
@@ -14,10 +14,14 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Telephony test cases">
+    <target_preparer class="android.telephony.cts.preconditions.TelephonyPreparer">
+        <option name="apk" value="CtsTelephonyPreparerApp.apk" />
+        <option name="package" value="android.telephony.cts.preconditions.app" />
+    </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.TokenRequirement">
         <option name="token" value="sim-card" />
     </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTelephonyTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/telephony2/AndroidTest.xml b/tests/tests/telephony2/AndroidTest.xml
index fd07d10..9f4e93c 100644
--- a/tests/tests/telephony2/AndroidTest.xml
+++ b/tests/tests/telephony2/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Telephony test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTelephony2TestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/text/AndroidTest.xml b/tests/tests/text/AndroidTest.xml
index 3266582..c922301 100644
--- a/tests/tests/text/AndroidTest.xml
+++ b/tests/tests/text/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Text test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTextTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/theme/AndroidTest.xml b/tests/tests/theme/AndroidTest.xml
index 945c580..a676032 100644
--- a/tests/tests/theme/AndroidTest.xml
+++ b/tests/tests/theme/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Theme test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsThemeDeviceTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/toast/AndroidTest.xml b/tests/tests/toast/AndroidTest.xml
index d0a5eed..bb36b67 100644
--- a/tests/tests/toast/AndroidTest.xml
+++ b/tests/tests/toast/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for Toast test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsToastTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/toastlegacy/AndroidTest.xml b/tests/tests/toastlegacy/AndroidTest.xml
index a208077..0621bb6 100644
--- a/tests/tests/toastlegacy/AndroidTest.xml
+++ b/tests/tests/toastlegacy/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for Toast legacy test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsToastLegacyTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/transition/AndroidTest.xml b/tests/tests/transition/AndroidTest.xml
index 6862679..8bee182 100644
--- a/tests/tests/transition/AndroidTest.xml
+++ b/tests/tests/transition/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Transition test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTransitionTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/tv/AndroidTest.xml b/tests/tests/tv/AndroidTest.xml
index 1b5621e..72fe942 100644
--- a/tests/tests/tv/AndroidTest.xml
+++ b/tests/tests/tv/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS TV test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTvTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/uiautomation/AndroidTest.xml b/tests/tests/uiautomation/AndroidTest.xml
index c4f1665..3721a5d 100644
--- a/tests/tests/uiautomation/AndroidTest.xml
+++ b/tests/tests/uiautomation/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS UI Automation test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsUiAutomationTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/uidisolation/AndroidTest.xml b/tests/tests/uidisolation/AndroidTest.xml
index 746e756..7e83263 100644
--- a/tests/tests/uidisolation/AndroidTest.xml
+++ b/tests/tests/uidisolation/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS UID Isolation test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsUidIsolationTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/uirendering/AndroidTest.xml b/tests/tests/uirendering/AndroidTest.xml
index c89300b..ac12c3b 100644
--- a/tests/tests/uirendering/AndroidTest.xml
+++ b/tests/tests/uirendering/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS UI Rendering test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsUiRenderingTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/util/AndroidTest.xml b/tests/tests/util/AndroidTest.xml
index c5aa253..27cfc02 100644
--- a/tests/tests/util/AndroidTest.xml
+++ b/tests/tests/util/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Util test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsUtilTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/view/AndroidTest.xml b/tests/tests/view/AndroidTest.xml
index c818923..0ed2837 100644
--- a/tests/tests/view/AndroidTest.xml
+++ b/tests/tests/view/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS View test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsViewTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/voiceinteraction/AndroidTest.xml b/tests/tests/voiceinteraction/AndroidTest.xml
index 01ea670..96fb0dc 100644
--- a/tests/tests/voiceinteraction/AndroidTest.xml
+++ b/tests/tests/voiceinteraction/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Voice Interaction test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsVoiceInteractionService.apk" />
         <option name="test-file-name" value="CtsVoiceInteractionApp.apk" />
diff --git a/tests/tests/voicesettings/AndroidTest.xml b/tests/tests/voicesettings/AndroidTest.xml
index 951ad44..ddfd4c2 100644
--- a/tests/tests/voicesettings/AndroidTest.xml
+++ b/tests/tests/voicesettings/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Voice Settings test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsVoiceSettingsService.apk" />
         <option name="test-file-name" value="CtsVoiceSettingsTestCases.apk" />
diff --git a/tests/tests/webkit/AndroidTest.xml b/tests/tests/webkit/AndroidTest.xml
index 7e8ed69..3a2b626 100644
--- a/tests/tests/webkit/AndroidTest.xml
+++ b/tests/tests/webkit/AndroidTest.xml
@@ -15,7 +15,7 @@
 -->
 <configuration description="Config for CTS Webkit test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.LocationCheck" />
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsWebkitTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 4ff8eef..2ef274a 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -26,6 +26,7 @@
 import android.graphics.Color;
 import android.graphics.Picture;
 import android.graphics.Rect;
+import android.graphics.pdf.PdfRenderer;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -2550,7 +2551,8 @@
                     // Called on UI thread
                     @Override
                     public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
-                        savePrintedPage(adapter, descriptor, result);
+                        PageRange[] pageRanges = new PageRange[] {PageRange.ALL_PAGES};
+                        savePrintedPage(adapter, descriptor, pageRanges, result);
                     }
                 });
         try {
@@ -2568,6 +2570,57 @@
         }
     }
 
+    // Verify Print feature can create a PDF file with correct number of pages.
+    public void testPrintingPagesCount() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        String content = "<html><head></head><body>";
+        for (int i = 0; i < 500; ++i) {
+            content += "<br />abcdefghijk<br />";
+        }
+        content += "</body></html>";
+        mOnUiThread.loadDataAndWaitForCompletion(content, "text/html", null);
+        final PrintDocumentAdapter adapter =  mOnUiThread.createPrintDocumentAdapter();
+        printDocumentStart(adapter);
+        PrintAttributes attributes = new PrintAttributes.Builder()
+                .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
+                .setResolution(new PrintAttributes.Resolution("foo", "bar", 300, 300))
+                .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
+                .build();
+        final WebViewCtsActivity activity = getActivity();
+        final File file = activity.getFileStreamPath(PRINTER_TEST_FILE);
+        final ParcelFileDescriptor descriptor = ParcelFileDescriptor.open(file,
+                ParcelFileDescriptor.parseMode("w"));
+        final FutureTask<Boolean> result =
+                new FutureTask<Boolean>(new Callable<Boolean>() {
+                            public Boolean call() {
+                                return true;
+                            }
+                        });
+        printDocumentLayout(adapter, null, attributes,
+                new LayoutResultCallback() {
+                    // Called on UI thread
+                    @Override
+                    public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
+                        PageRange[] pageRanges = new PageRange[] {
+                            new PageRange(1, 1), new PageRange(4, 7)
+                        };
+                        savePrintedPage(adapter, descriptor, pageRanges, result);
+                    }
+                });
+        try {
+            result.get(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+            assertTrue(file.length() > 0);
+            PdfRenderer renderer = new PdfRenderer(
+                ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY));
+            assertEquals(5, renderer.getPageCount());
+        } finally {
+            descriptor.close();
+            file.delete();
+        }
+    }
+
     public void testVisualStateCallbackCalled() throws Exception {
         // Check that the visual state callback is called correctly.
         if (!NullWebViewUtils.isWebViewAvailable()) {
@@ -2639,8 +2692,9 @@
     }
 
     private void savePrintedPage(final PrintDocumentAdapter adapter,
-            final ParcelFileDescriptor descriptor, final FutureTask<Boolean> result) {
-        adapter.onWrite(new PageRange[] {PageRange.ALL_PAGES}, descriptor,
+            final ParcelFileDescriptor descriptor, final PageRange[] pageRanges,
+            final FutureTask<Boolean> result) {
+        adapter.onWrite(pageRanges, descriptor,
                 new CancellationSignal(),
                 new WriteResultCallback() {
                     @Override
diff --git a/tests/tests/widget/AndroidTest.xml b/tests/tests/widget/AndroidTest.xml
index d0cb110..d699e9d 100644
--- a/tests/tests/widget/AndroidTest.xml
+++ b/tests/tests/widget/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Widget test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsWidgetTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/wrap/nowrap/AndroidTest.xml b/tests/tests/wrap/nowrap/AndroidTest.xml
index bc0deb5..54e9bb5 100644
--- a/tests/tests/wrap/nowrap/AndroidTest.xml
+++ b/tests/tests/wrap/nowrap/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS No Wrap test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsWrapNoWrapTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/wrap/wrap_debug/AndroidTest.xml b/tests/tests/wrap/wrap_debug/AndroidTest.xml
index 246268b..d036fc3 100644
--- a/tests/tests/wrap/wrap_debug/AndroidTest.xml
+++ b/tests/tests/wrap/wrap_debug/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Debug Wrap test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsWrapWrapDebugTestCases.apk" />
     </target_preparer>
diff --git a/tests/tests/wrap/wrap_nodebug/AndroidTest.xml b/tests/tests/wrap/wrap_nodebug/AndroidTest.xml
index fd18f4c..2b5ed8f 100644
--- a/tests/tests/wrap/wrap_nodebug/AndroidTest.xml
+++ b/tests/tests/wrap/wrap_nodebug/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Wrap test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsWrapWrapNoDebugTestCases.apk" />
     </target_preparer>
diff --git a/tests/tvprovider/AndroidTest.xml b/tests/tvprovider/AndroidTest.xml
index 633ebef..0d60571 100644
--- a/tests/tvprovider/AndroidTest.xml
+++ b/tests/tvprovider/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS TV Provider test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsTvProviderTestCases.apk" />
     </target_preparer>
diff --git a/tests/ui/AndroidTest.xml b/tests/ui/AndroidTest.xml
index ca0b63e..220eefd 100644
--- a/tests/ui/AndroidTest.xml
+++ b/tests/ui/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS UI test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsUiDeviceTestCases.apk" />
     </target_preparer>
diff --git a/tests/video/AndroidTest.xml b/tests/video/AndroidTest.xml
index 30b1160..0cb2a19 100644
--- a/tests/video/AndroidTest.xml
+++ b/tests/video/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS Video test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsVideoTestCases.apk" />
     </target_preparer>
diff --git a/tests/vm/AndroidTest.xml b/tests/vm/AndroidTest.xml
index fc1098b..8ff0939 100644
--- a/tests/vm/AndroidTest.xml
+++ b/tests/vm/AndroidTest.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS VM test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsVmTestCases.apk" />
     </target_preparer>
diff --git a/tests/vr/AndroidTest.xml b/tests/vr/AndroidTest.xml
index dc6d5fa..4b5d656 100644
--- a/tests/vr/AndroidTest.xml
+++ b/tests/vr/AndroidTest.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 <configuration description="Config for CTS VR test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="test-suite-tag" value="cts" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsVrTestCases.apk" />
     </target_preparer>
diff --git a/tools/cts-tradefed/res/config/collect-tests-only.xml b/tools/cts-tradefed/res/config/collect-tests-only.xml
index b3a2916..6d179a2 100644
--- a/tools/cts-tradefed/res/config/collect-tests-only.xml
+++ b/tools/cts-tradefed/res/config/collect-tests-only.xml
@@ -26,6 +26,7 @@
 
     <option name="skip-preconditions" value="true" />
     <option name="skip-connectivity-check" value="true" />
+    <option name="preparer-whitelist" value="com.android.tradefed.targetprep.suite.SuiteApkInstaller" />
     <option name="preparer-whitelist" value="com.android.compatibility.common.tradefed.targetprep.ApkInstaller" />
     <option name="preparer-whitelist" value="com.android.compatibility.common.tradefed.targetprep.FilePusher" />
 
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index f694daa..db655c5 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -19,40 +19,13 @@
     <!-- <option name="compatibility:exclude-filter" value="MODULE_NAME PACKAGE_NAME.CLASS_NAME" /> Excludes whole class -->
     <!-- <option name="compatibility:exclude-filter" value="MODULE_NAME PACKAGE_NAME.CLASS_NAME#TEST_NAME" /> Excludes individual test -->
 
-    <!-- b/35314835 -->
-    <option name="compatibility:exclude-filter" value="CtsServicesHostTestCases android.server.cts.ActivityManagerPinnedStackTests#testAlwaysFocusablePipActivity" />
-    <option name="compatibility:exclude-filter" value="CtsServicesHostTestCases android.server.cts.ActivityManagerPinnedStackTests#testLaunchIntoPinnedStack" />
-
     <!-- b/17595050 -->
     <option name="compatibility:exclude-filter" value="CtsAccessibilityServiceTestCases android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverText" />
     <option name="compatibility:exclude-filter" value="CtsAccessibilityServiceTestCases android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverTextExtend" />
 
-    <!-- b/17993121 -->
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testAppWidgetProviderCallbacks" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testBindAppWidget" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testCollectionWidgets" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testDeleteHost" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testDeleteHosts" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testGetAppWidgetIds" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testGetAppWidgetInfo" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testGetAppWidgetOptions" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetId" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetIds" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testTwoAppWidgetProviderCallbacks" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaComponentName" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetId" />
-    <option name="compatibility:exclude-filter" value="CtsAppWidgetTestCases android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetIds" />
-
-    <!-- b/23776099 -->
-    <option name="compatibility:exclude-filter" value="CtsCallLogTestCases" />
-
     <!-- b/17530117 -->
     <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.AllocationTest#testBlackWhite" />
     <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.AllocationTest#testParamSensitivity" />
-    <!-- b/17989532 -->
-    <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.SurfaceViewPreviewTest#testPreparePerformance" />
-    <!-- b/23008511 -->
-    <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.cts.CameraTest#testPreviewFpsRange" />
 
     <!-- These test cases are only applicable to Android Auto Embedded targets.-->
     <option name="compatibility:exclude-filter" value="CtsCarTestCases" />
@@ -87,24 +60,14 @@
     <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.VirtualMachine.HoldEventsTest#testHoldEvents001" />
     <option name="compatibility:exclude-filter" value="CtsJdwp org.apache.harmony.jpda.tests.jdwp.VirtualMachine.ReleaseEventsTest#testReleaseEvents001" />
 
-    <!-- b/18117279 b/21262226 b/23144425 -->
+    <!-- b/21262226 -->
     <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testConnectivityConstraintExecutes_withMobile" />
-    <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testConnectivityConstraintExecutes_withWifi" />
-    <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testUnmeteredConstraintExecutes_withWifi" />
     <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.ConnectivityConstraintTest#testUnmeteredConstraintFails_withMobile" />
-    <option name="compatibility:exclude-filter" value="CtsJobSchedulerTestCases android.jobscheduler.cts.TimingConstraintsTest#testJobParameters_unexpiredDeadline" />
-
-    <!-- b/17144778 -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ImageReaderDecoderTest#testHwAVCDecode360pForFlexibleYuv" />
-    <!-- b/23827982 -->
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH264FlexArbitraryW" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.VideoEncoderTest#testGoogH264SurfArbitraryW" />
 
     <!-- b/30932589 -->
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromExifByteOrderIIJpeg" />
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromExifByteOrderMMJpeg" />
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromLgG4Iso800Dng" />
-    <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testDoNotFailOnCorruptedImage" />
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromVolantisJpg" />
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromSonyRX100Arw" />
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromCanonG7XCr2" />
@@ -116,10 +79,7 @@
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromPentaxK5Pef" />
     <option name="compatibility:exclude-filter" value="CtsMediaTestCases android.media.cts.ExifInterfaceTest#testReadExifDataFromSamsungNX3000Srw" />
 
-    <!-- b/25651805 -->
-    <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.ConnectivityManagerTest#testRestrictedNetworks" />
     <!-- b/18682315 -->
-    <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.SSLCertificateSocketFactoryTest#testCreateSocket" />
     <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_bind" />
     <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_simple" />
     <option name="compatibility:exclude-filter" value="CtsNetTestCases android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_wrapping" />
@@ -128,15 +88,6 @@
     <option name="compatibility:exclude-filter" value="CtsOpenGlPerfTestCases android.openglperf.cts.GlAppSwitchTest#testGlActivitySwitchingFast" />
     <option name="compatibility:exclude-filter" value="CtsOpenGlPerfTestCases android.openglperf.cts.GlAppSwitchTest#testGlActivitySwitchingSlow" />
 
-    <!-- b/18091590 -->
-    <option name="compatibility:exclude-filter" value="CtsOpenGlPerfTestCases android.openglperf.cts.GlVboPerfTest#testVboWithVaryingIndexBufferNumbers" />
-
-    <!-- b/23192492 -->
-    <option name="compatibility:exclude-filter" value="CtsPermission2TestCases android.permission2.cts.ProtectedBroadcastsTest#testSendProtectedBroadcasts" />
-
-    <option name="compatibility:exclude-filter" value="CtsSampleDeviceTestCases" />
-    <option name="compatibility:exclude-filter" value="CtsSampleHostTestCases" />
-
     <!-- b/18461670 -->
     <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.AudioPolicyBinderTest#test_getStreamVolumeLeak" />
     <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.AudioPolicyBinderTest#test_isStreamActive" />
@@ -153,21 +104,8 @@
     <option name="compatibility:exclude-filter" value="x86_64 CtsRenderscriptLegacyTestCases" />
     <option name="compatibility:exclude-filter" value="mips64 CtsRenderscriptLegacyTestCases" />
 
-    <!-- b/23604254 -->
-    <option name="compatibility:exclude-filter" value="CtsTelecomTestCases android.telecom.cts.ExtendedInCallServiceTest#testAddNewOutgoingCallAndThenDisconnect" />
-    <option name="compatibility:exclude-filter" value="CtsTelecomTestCases android.telecom.cts.RemoteConferenceTest#testRemoteConferenceCallbacks_ConferenceableConnections" />
-
-    <!-- b/23779020 -->
-    <option name="compatibility:exclude-filter" value="CtsTransitionTestCases android.transition.cts.ChangeScrollTest#testChangeScroll" />
-
     <!-- b/17536113 -->
     <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testNoAccessSilentlyFails" />
-    <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testOrderedActivityLaunchSequenceInEventLog" />
-    <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testPackageUsageStatsIntervals" />
-    <option name="compatibility:exclude-filter" value="CtsUsageStatsTestCases android.app.usage.cts.UsageStatsTest#testUsageEventsParceling" />
-
-    <!-- b/23238984 -->
-    <option name="compatibility:exclude-filter" value="CtsVoiceSettingsTestCases android.voicesettings.cts.ZenModeTest#testAll" />
 
     <!-- b/26235244 -->
     <option name="compatibility:exclude-filter" value="android.util.cts.EventLogTest#testWriteEventWithOversizeValue" />