Merge "Test permissions to launch activities on secondary displays"
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 1871be7..c85c3542 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -795,9 +795,12 @@
     <string name="snsr_device_admin_receiver">Sensor Tests Device Admin Receiver</string>
     <string name="snsr_test_summary">Tests passed: %1$d, Tests skipped: %2$d, Tests failed: %3$d</string>
     <string name="snsr_test_complete">Test completed without errors.</string>
-    <string name="snsr_test_complete_with_errors">Test completed with errors: those errors
-        might degrade the user experience and might cause some applications to misbehave. They are
-        not required for Android Compatibility at this time, but will in a future release.</string>
+    <string name="snsr_test_complete_with_errors">Test completed with errors which indicates
+      the device does not meet Android compatibility requirement.
+      This will degrade user experience and cause applications to misbehave.
+      To help debugging, please take a bug report and back up contents under
+      /sdcard/sensorTests of the device under test.
+    </string>
     <string name="snsr_test_pass">PASS</string>
     <string name="snsr_test_skipped">SKIPPED</string>
     <string name="snsr_test_fail">FAIL</string>
@@ -2313,6 +2316,13 @@
         6) Unlock the device.\n
         7) Repeat steps (1) through (6) for each screen lock type other than \"None\".
     </string>
+    <string name="enterprise_privacy_add_account_negative">Add account disclosure</string>
+    <string name="enterprise_privacy_add_account_negative_info">
+        Please do the following:\n
+        1) Press the Go button to open Settings.\n
+        2) In the screen that opens, verify that you are not told that the device is managed.\n
+        3) Use the Back button to return to this page.
+    </string>
 
     <!-- Strings for DeviceOwnerPositiveTestActivity -->
     <string name="positive_device_owner">Device Owner Tests</string>
@@ -2817,6 +2827,60 @@
     <string name="enterprise_privacy_retrieve_security_logs">Retrieve Security Logs</string>
     <string name="enterprise_privacy_clear_organization">Clear Org</string>
     <string name="enterprise_privacy_set_organization">Set Org</string>
+    <string name="enterprise_privacy_enterprise_installed_apps">Enterprise-installed apps</string>
+    <string name="enterprise_privacy_enterprise_installed_apps_info">
+        Please do the following:\n
+        1) You should have received NotificationBot.apk together with the CTS verifier. If you built the CTS verifier yourself, build the NotificationBot.apk by issuing the following command on the host:\n
+            make NotificationBot\n
+        2) Upload the NotificationBot.apk to your device by issuing the following command on the host:\n
+            adb push /path/to/NotificationBot.apk /sdcard\n
+        3) Press the Uninstall button.\n
+        4) Press the Open Settings button.\n
+        5) In the screen that opens, verify that you are not told that your administrator installed any apps.\n
+        6) Use the Back button to return to this page.\n
+        7) Press the Install button.\n
+        8) Repeat steps (4) through (6), verifying that in step (5), you are told now that your administrator installed one app.\n
+        9) Press the Uninstall button.\n
+        10) Issue the following command on the host:\n
+            adb shell rm /sdcard/NotificationBot.apk
+    </string>
+    <string name="enterprise_privacy_install">Install</string>
+    <string name="enterprise_privacy_uninstall">Uninstall</string>
+    <string name="enterprise_privacy_admin_granted_location_access">Location access permission</string>
+    <string name="enterprise_privacy_admin_granted_location_access_info">
+        Please do the following:\n
+        1) Press the Reset button.\n
+        2) Press the Open Settings button.\n
+        3) In the screen that opens, verify that you are not told that your administrator has allowed any apps to access your location.\n
+        4) Use the Back button to return to this page.\n
+        5) Press the Grant button.\n
+        6) Repeat steps (2) through (4), verifying that in step (3), you are told now that your administrator has allowed one app to access your location.\n
+        7) Press the Reset button.
+    </string>
+    <string name="enterprise_privacy_reset">Reset</string>
+    <string name="enterprise_privacy_grant">Grant</string>
+    <string name="enterprise_privacy_admin_granted_microphone_access">Microphone access permission</string>
+    <string name="enterprise_privacy_admin_granted_microphone_access_info">
+        Please do the following:\n
+        1) Press the Reset button.\n
+        2) Press the Open Settings button.\n
+        3) In the screen that opens, verify that you are not told that your administrator has allowed any apps to access your microphone.\n
+        4) Use the Back button to return to this page.\n
+        5) Press the Grant button.\n
+        6) Repeat steps (2) through (4), verifying that in step (3), you are told now that your administrator has allowed one app to access your microphone.\n
+        7) Press the Reset button.
+    </string>
+    <string name="enterprise_privacy_admin_granted_camera_access">Camera access permission</string>
+    <string name="enterprise_privacy_admin_granted_camera_access_info">
+        Please do the following:\n
+        1) Press the Reset button.\n
+        2) Press the Open Settings button.\n
+        3) In the screen that opens, verify that you are not told that your administrator has allowed any apps to access your camera.\n
+        4) Use the Back button to return to this page.\n
+        5) Press the Grant button.\n
+        6) Repeat steps (2) through (4), verifying that in step (3), you are told now that your administrator has allowed one app to access your camera.\n
+        7) Press the Reset button.
+    </string>
     <string name="enterprise_privacy_always_on_vpn">Always-on VPN</string>
     <string name="enterprise_privacy_always_on_vpn_info">
         Please do the following:\n
@@ -2886,6 +2950,20 @@
         11) Unlock the device.\n
         12) Repeat steps (1) through (11) for each screen lock type other than \"None\".
     </string>
+    <string name="enterprise_privacy_add_account">Add account disclosure</string>
+    <string name="enterprise_privacy_add_account_info">
+        Please do the following:\n
+        1) Press the Clear Org button.\n
+        2) Press the Open Settings button.\n
+        3) In the screen that opens, verify that you are told that the device is managed.\n
+        4) Use the Back button to return to this page.\n
+        5) Press the Set Org button.\n
+        6) Press the Open Settings button.\n
+        7) In the screen that opens, verify that you are told that the device is managed by \"Foo, Inc.\".\n
+        8) Tap the \"Learn more\" link.\n
+        9) Verify that a screen informing you what your managing organization can do is shown.\n
+        11) Use the Back button to return to this page.
+    </string>
 
     <!-- Strings for Network Logging Tests -->
     <string name="device_owner_network_logging_ui">Network Logging UI</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
index 4de0251..028639d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
@@ -16,11 +16,14 @@
 
 package com.android.cts.verifier.managedprovisioning;
 
+import android.Manifest;
 import android.app.Activity;
+import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageInstaller;
 import android.graphics.BitmapFactory;
 import android.net.ProxyInfo;
 import android.os.Bundle;
@@ -31,7 +34,10 @@
 import com.android.cts.verifier.R;
 import com.android.cts.verifier.managedprovisioning.Utils;
 
-import java.lang.reflect.Method;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -69,6 +75,9 @@
     public static final String COMMAND_SET_ORGANIZATION_NAME = "set-organization-name";
     public static final String COMMAND_ENABLE_NETWORK_LOGGING = "enable-network-logging";
     public static final String COMMAND_DISABLE_NETWORK_LOGGING = "disable-network-logging";
+    public static final String COMMAND_INSTALL_HELPER_PACKAGE = "install-helper-package";
+    public static final String COMMAND_UNINSTALL_HELPER_PACKAGE = "uninstall-helper-package";
+    public static final String COMMAND_SET_PERMISSION_GRANT_STATE = "set-permission-grant-state";
     public static final String COMMAND_CREATE_MANAGED_PROFILE = "create-managed-profile";
     public static final String COMMAND_REMOVE_MANAGED_PROFILE = "remove-managed-profile";
     public static final String COMMAND_SET_ALWAYS_ON_VPN = "set-always-on-vpn";
@@ -88,6 +97,20 @@
             "com.android.cts.verifier.managedprovisioning.extra.VALUE";
     public static final String EXTRA_ORGANIZATION_NAME =
             "com.android.cts.verifier.managedprovisioning.extra.ORGANIZATION_NAME";
+    public static final String EXTRA_PERMISSION =
+            "com.android.cts.verifier.managedprovisioning.extra.PERMISSION";
+    public static final String EXTRA_GRANT_STATE =
+            "com.android.cts.verifier.managedprovisioning.extra.GRANT_STATE";
+
+    // We care about installing and uninstalling only. It does not matter what apk is used.
+    // NotificationBot.apk is a good choice because it comes bundled with the CTS verifier.
+    protected static final String HELPER_APP_LOCATION = "/sdcard/NotificationBot.apk";
+    protected static final String HELPER_APP_PKG = "com.android.cts.robot";
+
+    public static final String ACTION_INSTALL_COMPLETE =
+            "com.android.cts.verifier.managedprovisioning.action.ACTION_INSTALL_COMPLETE";
+    public static final String ACTION_UNINSTALL_COMPLETE =
+            "com.android.cts.verifier.managedprovisioning.action.ACTION_UNINSTALL_COMPLETE";
 
     private ComponentName mAdmin;
     private DevicePolicyManager mDpm;
@@ -203,17 +226,9 @@
                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
                         return;
                     }
-                    // STOPSHIP(b/33068581): Network logging will be un-hidden for O. Remove
-                    // reflection when the un-hiding happens.
-                    final Method setNetworkLoggingEnabledMethod =
-                            DevicePolicyManager.class.getDeclaredMethod(
-                                    "setNetworkLoggingEnabled", ComponentName.class, boolean.class);
-                    final Method retrieveNetworkLogsMethod =
-                            DevicePolicyManager.class.getDeclaredMethod(
-                                    "retrieveNetworkLogs", ComponentName.class, long.class);
-                    setNetworkLoggingEnabledMethod.invoke(mDpm, mAdmin, true);
-                    retrieveNetworkLogsMethod.invoke(mDpm, mAdmin, 0 /* batchToken */);
-                    setNetworkLoggingEnabledMethod.invoke(mDpm, mAdmin, false);
+                    mDpm.setNetworkLoggingEnabled(mAdmin, true);
+                    mDpm.retrieveNetworkLogs(mAdmin, 0 /* batchToken */);
+                    mDpm.setNetworkLoggingEnabled(mAdmin, false);
                 } break;
                 case COMMAND_RETRIEVE_SECURITY_LOGS: {
                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
@@ -240,6 +255,18 @@
                     }
                     mDpm.setNetworkLoggingEnabled(mAdmin, false);
                 } break;
+                case COMMAND_INSTALL_HELPER_PACKAGE: {
+                    installHelperPackage();
+                } break;
+                case COMMAND_UNINSTALL_HELPER_PACKAGE: {
+                    uninstallHelperPackage();
+                } break;
+                case COMMAND_SET_PERMISSION_GRANT_STATE: {
+                    mDpm.setPermissionGrantState(mAdmin, getPackageName(),
+                            intent.getStringExtra(EXTRA_PERMISSION),
+                            intent.getIntExtra(EXTRA_GRANT_STATE,
+                                    DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT));
+                } break;
                 case COMMAND_CREATE_MANAGED_PROFILE: {
                     if (!mDpm.isDeviceOwnerApp(getPackageName())) {
                         return;
@@ -289,7 +316,6 @@
                     }
                     mDpm.setRecommendedGlobalProxy(mAdmin, null);
                 }
-
             }
         } catch (Exception e) {
             Log.e(TAG, "Failed to execute command: " + intent, e);
@@ -298,6 +324,32 @@
         }
     }
 
+    private void installHelperPackage() throws Exception {
+        final PackageInstaller packageInstaller = getPackageManager().getPackageInstaller();
+        final PackageInstaller.Session session = packageInstaller.openSession(
+                packageInstaller.createSession(new PackageInstaller.SessionParams(
+                        PackageInstaller.SessionParams.MODE_FULL_INSTALL)));
+        final File file = new File(HELPER_APP_LOCATION);
+        final InputStream in = new FileInputStream(file);
+        final OutputStream out = session.openWrite("CommandReceiverActivity", 0, file.length());
+        final byte[] buffer = new byte[65536];
+        int count;
+        while ((count = in.read(buffer)) != -1) {
+            out.write(buffer, 0, count);
+        }
+        session.fsync(out);
+        in.close();
+        out.close();
+        session.commit(PendingIntent.getBroadcast(this, 0, new Intent(ACTION_INSTALL_COMPLETE), 0)
+                .getIntentSender());
+    }
+
+    private void uninstallHelperPackage() {
+        getPackageManager().getPackageInstaller().uninstall(HELPER_APP_PKG,
+                PendingIntent.getBroadcast(this, 0, new Intent(ACTION_UNINSTALL_COMPLETE), 0)
+                        .getIntentSender());
+    }
+
     private void clearAllPolicies() throws Exception {
         clearProfileOwnerRelatedPolicies();
 
@@ -322,13 +374,20 @@
         mDpm.setKeyguardDisabled(mAdmin, false);
         mDpm.setAutoTimeRequired(mAdmin, false);
         mDpm.setStatusBarDisabled(mAdmin, false);
-        // STOPSHIP(b/33068581): Network logging will be un-hidden for O. Remove reflection when the
-        // un-hiding happens.
-        final Method setNetworkLoggingEnabledMethod = DevicePolicyManager.class.getDeclaredMethod(
-                "setNetworkLoggingEnabled", ComponentName.class, boolean.class);
-        setNetworkLoggingEnabledMethod.invoke(mDpm, mAdmin, false);
         mDpm.setOrganizationName(mAdmin, null);
+        mDpm.setNetworkLoggingEnabled(mAdmin, false);
+        mDpm.setPermissionGrantState(mAdmin, getPackageName(),
+                Manifest.permission.ACCESS_FINE_LOCATION,
+                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
+        mDpm.setPermissionGrantState(mAdmin, getPackageName(), Manifest.permission.RECORD_AUDIO,
+                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
+        mDpm.setPermissionGrantState(mAdmin, getPackageName(), Manifest.permission.CAMERA,
+                DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
+        mDpm.setAlwaysOnVpnPackage(mAdmin, null, false);
         mDpm.setRecommendedGlobalProxy(mAdmin, null);
+
+        uninstallHelperPackage();
+        removeManagedProfile();
     }
 
     private void clearProfileOwnerRelatedPolicies() {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerNegativeTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerNegativeTestActivity.java
index cee7307..078e9ce 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerNegativeTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerNegativeTestActivity.java
@@ -45,6 +45,8 @@
             = "ENTERPRISE_PRIVACY_QUICK_SETTINGS_NEGATIVE";
     private static final String ENTERPRISE_PRIVACY_KEYGUARD_NEGATIVE
             = "ENTERPRISE_PRIVACY_KEYGUARD_NEGATIVE";
+    private static final String ENTERPRISE_PRIVACY_ADD_ACCOUNT_NEGATIVE
+            = "ENTERPRISE_PRIVACY_ADD_ACCOUNT_NEGATIVE";
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -100,6 +102,10 @@
                 R.string.enterprise_privacy_keyguard_negative,
                 R.string.enterprise_privacy_keyguard_negative_info,
                 new ButtonInfo(R.string.go_button_text, new Intent(Settings.ACTION_SETTINGS))));
+        adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_ADD_ACCOUNT_NEGATIVE,
+                R.string.enterprise_privacy_add_account_negative,
+                R.string.enterprise_privacy_add_account_negative_info,
+                new ButtonInfo(R.string.go_button_text, new Intent(Settings.ACTION_ADD_ACCOUNT))));
     }
 
     /**
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
index 034e52e..54f1b79 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/EnterprisePrivacyTestListActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.verifier.managedprovisioning;
 
+import android.Manifest;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -43,6 +44,14 @@
     private static final String ENTERPRISE_PRIVACY_BUG_REPORT = "ENTERPRISE_PRIVACY_BUG_REPORT";
     private static final String ENTERPRISE_PRIVACY_SECURITY_LOGGING
             = "ENTERPRISE_PRIVACY_SECURITY_LOGGING";
+    private static final String ENTERPRISE_PRIVACY_ENTERPRISE_INSTALLED_APPS
+            = "ENTERPRISE_PRIVACY_ENTERPRISE_INSTALLED_APPS";
+    private static final String ENTERPRISE_PRIVACY_LOCATION_ACCESS
+            = "ENTERPRISE_PRIVACY_LOCATION_ACCESS";
+    private static final String ENTERPRISE_PRIVACY_MICROPHONE_ACCESS
+            = "ENTERPRISE_PRIVACY_MICROPHONE_ACCESS";
+    private static final String ENTERPRISE_PRIVACY_CAMERA_ACCESS
+            = "ENTERPRISE_PRIVACY_CAMERA_ACCESS";
     private static final String ENTERPRISE_PRIVACY_ALWAYS_ON_VPN
             = "ENTERPRISE_PRIVACY_ALWAYS_ON_VPN";
     private static final String ENTERPRISE_PRIVACY_COMP_ALWAYS_ON_VPN
@@ -52,6 +61,7 @@
     private static final String ENTERPRISE_PRIVACY_QUICK_SETTINGS
             = "ENTERPRISE_PRIVACY_QUICK_SETTINGS";
     private static final String ENTERPRISE_PRIVACY_KEYGUARD = "ENTERPRISE_PRIVACY_KEYGUARD";
+    private static final String ENTERPRISE_PRIVACY_ADD_ACCOUNT = "ENTERPRISE_PRIVACY_ADD_ACCOUNT";
 
     public static final String EXTRA_TEST_ID =
             "com.android.cts.verifier.managedprovisioning.extra.TEST_ID";
@@ -95,6 +105,24 @@
                                new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS))});
     }
 
+    private TestListItem buildAdminGrantedPermissionTest(String id, int titleRes, int infoRes,
+            String permission) {
+        return createInteractiveTestItem(this, id, titleRes, infoRes,
+                new ButtonInfo[] {
+                        new ButtonInfo(R.string.enterprise_privacy_reset, buildCommandIntent(
+                                CommandReceiverActivity.COMMAND_SET_PERMISSION_GRANT_STATE)
+                                .putExtra(CommandReceiverActivity.EXTRA_PERMISSION, permission)
+                                .putExtra(CommandReceiverActivity.EXTRA_GRANT_STATE,
+                                        DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT)),
+                        new ButtonInfo(R.string.enterprise_privacy_grant, buildCommandIntent(
+                                CommandReceiverActivity.COMMAND_SET_PERMISSION_GRANT_STATE)
+                                .putExtra(CommandReceiverActivity.EXTRA_PERMISSION, permission)
+                                .putExtra(CommandReceiverActivity.EXTRA_GRANT_STATE,
+                                        DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED)),
+                        new ButtonInfo(R.string.enterprise_privacy_open_settings,
+                                new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS))});
+    }
+
     private void addTestsToAdapter(final ArrayTestListAdapter adapter) {
         adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_PAGE,
                 R.string.enterprise_privacy_page,
@@ -115,6 +143,30 @@
                 R.string.enterprise_privacy_security_logging_info,
                 R.string.enterprise_privacy_retrieve_security_logs,
                 CommandReceiverActivity.COMMAND_RETRIEVE_SECURITY_LOGS));
+        adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_ENTERPRISE_INSTALLED_APPS,
+                R.string.enterprise_privacy_enterprise_installed_apps,
+                R.string.enterprise_privacy_enterprise_installed_apps_info,
+                new ButtonInfo[] {
+                        new ButtonInfo(R.string.enterprise_privacy_install,
+                                buildCommandIntent(
+                                        CommandReceiverActivity.COMMAND_INSTALL_HELPER_PACKAGE)),
+                        new ButtonInfo(R.string.enterprise_privacy_uninstall,
+                                buildCommandIntent(CommandReceiverActivity
+                                        .COMMAND_UNINSTALL_HELPER_PACKAGE)),
+                        new ButtonInfo(R.string.enterprise_privacy_open_settings,
+                                new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS))}));
+        adapter.add(buildAdminGrantedPermissionTest(ENTERPRISE_PRIVACY_LOCATION_ACCESS,
+                R.string.enterprise_privacy_admin_granted_location_access,
+                R.string.enterprise_privacy_admin_granted_location_access_info,
+                Manifest.permission.ACCESS_FINE_LOCATION));
+        adapter.add(buildAdminGrantedPermissionTest(ENTERPRISE_PRIVACY_MICROPHONE_ACCESS,
+                R.string.enterprise_privacy_admin_granted_microphone_access,
+                R.string.enterprise_privacy_admin_granted_microphone_access_info,
+                Manifest.permission.RECORD_AUDIO));
+        adapter.add(buildAdminGrantedPermissionTest(ENTERPRISE_PRIVACY_CAMERA_ACCESS,
+                R.string.enterprise_privacy_admin_granted_camera_access,
+                R.string.enterprise_privacy_admin_granted_camera_access_info,
+                Manifest.permission.CAMERA));
         adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_ALWAYS_ON_VPN,
                 R.string.enterprise_privacy_always_on_vpn,
                 R.string.enterprise_privacy_always_on_vpn_info,
@@ -179,6 +231,20 @@
                                         CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
                                         .putExtra(CommandReceiverActivity.EXTRA_ORGANIZATION_NAME,
                                                 "Foo, Inc."))}));
+        adapter.add(createInteractiveTestItem(this, ENTERPRISE_PRIVACY_ADD_ACCOUNT,
+                R.string.enterprise_privacy_add_account,
+                R.string.enterprise_privacy_add_account_info,
+                new ButtonInfo[] {
+                        new ButtonInfo(R.string.enterprise_privacy_open_settings,
+                                new Intent(Settings.ACTION_ADD_ACCOUNT)),
+                        new ButtonInfo(R.string.enterprise_privacy_clear_organization,
+                                buildCommandIntent(
+                                        CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)),
+                        new ButtonInfo(R.string.enterprise_privacy_set_organization,
+                                buildCommandIntent(
+                                        CommandReceiverActivity.COMMAND_SET_ORGANIZATION_NAME)
+                                        .putExtra(CommandReceiverActivity.EXTRA_ORGANIZATION_NAME,
+                                                "Foo, Inc."))}));
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/NfcTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/NfcTestActivity.java
index 2f7619c..e767f7f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/NfcTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/NfcTestActivity.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -52,6 +53,7 @@
     private static final String NFC_BEAM_ACTIVITY = "com.android.nfc.BeamShareActivity";
     private static final String SAMPLE_IMAGE_FILENAME = "image_to_share.jpg";
     private static final String SAMPLE_IMAGE_CONTENT = "sample image";
+    private static final String SAMPLE_TEXT = "sample text";
     private static final int MARGIN = 80;
     private static final int TEXT_SIZE = 200;
 
@@ -76,11 +78,28 @@
                     UserManager.DISALLOW_OUTGOING_BEAM);
         }
 
-        final Uri uri = createUriForImage(SAMPLE_IMAGE_FILENAME, SAMPLE_IMAGE_CONTENT);
-        Uri[] uris = new Uri[] { uri };
-
         mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
-        mNfcAdapter.setBeamPushUris(uris, this);
+
+        final Intent shareIntent = new Intent(Intent.ACTION_SEND);
+
+        // Sending a large amount of data requires hand-over to bluetooth, so determine here
+        // if supported by the device. If bluetooth is not supported, a simple text message
+        // will be transferred instead.
+        final boolean hasBluetooth =
+                getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+
+        if (hasBluetooth) {
+            final Uri uri = createUriForImage(SAMPLE_IMAGE_FILENAME, SAMPLE_IMAGE_CONTENT);
+            Uri[] uris = new Uri[]{uri};
+
+            mNfcAdapter.setBeamPushUris(uris, this);
+
+            shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
+            shareIntent.setType("image/jpg");
+            shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        } else {
+            shareIntent.putExtra(Intent.EXTRA_TEXT, SAMPLE_TEXT);
+        }
 
         findViewById(R.id.manual_beam_button).setOnClickListener(new OnClickListener() {
             @Override
@@ -91,10 +110,6 @@
         findViewById(R.id.intent_share_button).setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View view) {
-                Intent shareIntent = new Intent(Intent.ACTION_SEND);
-                shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
-                shareIntent.setType("image/jpg");
-                shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 // Specify the package name of NfcBeamActivity so that the tester don't need to
                 // select the activity manually.
                 shareIntent.setClassName(NFC_BEAM_PACKAGE, NFC_BEAM_ACTIVITY);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
index ad2ead6..1c92fd7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
@@ -510,10 +510,6 @@
         if (resultCode == SensorTestDetails.ResultCode.FAIL) {
             mTestLogger.logInstructions(R.string.snsr_test_complete_with_errors);
             enableTestResultButton(
-                    mPassButton,
-                    R.string.snsr_pass_on_error,
-                    testDetails.cloneAndChangeResultCode(SensorTestDetails.ResultCode.PASS));
-            enableTestResultButton(
                     mFailButton,
                     R.string.fail_button_text,
                     testDetails.cloneAndChangeResultCode(SensorTestDetails.ResultCode.FAIL));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/usb/accessory/UsbAccessoryTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/usb/accessory/UsbAccessoryTestActivity.java
index 8ac009b..936775e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/usb/accessory/UsbAccessoryTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/usb/accessory/UsbAccessoryTestActivity.java
@@ -27,6 +27,7 @@
 import android.hardware.usb.UsbManager;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.util.Log;
@@ -34,6 +35,8 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
@@ -54,6 +57,8 @@
     private static final String LOG_TAG = UsbAccessoryTestActivity.class.getSimpleName();
     private static final int MAX_BUFFER_SIZE = 16384;
 
+    private static final int TEST_DATA_SIZE_THRESHOLD = 100 * 1024 * 1024; // 100MB
+
     private TextView mStatus;
     private ProgressBar mProgress;
 
@@ -187,6 +192,26 @@
                     assertEquals(MAX_BUFFER_SIZE, numRead);
                     assertArrayEquals(origBufferMax, bufferMax);
 
+                    // Send two transfers in a row
+                    nextTest(is, os, "measure transfer speed");
+
+                    byte[] result = new byte[1];
+                    long bytesSent = 0;
+                    long timeStart = SystemClock.elapsedRealtime();
+                    while (bytesSent < TEST_DATA_SIZE_THRESHOLD) {
+                        os.write(origBufferMax);
+                        bytesSent += MAX_BUFFER_SIZE;
+                    }
+                    numRead = is.read(result);
+                    double speedKBPS = (bytesSent * 8 * 1000. / 1024.)
+                            / (SystemClock.elapsedRealtime() - timeStart);
+                    assertEquals(1, numRead);
+                    assertEquals(1, result[0]);
+                    // We don't mandate min speed for now, let's collect data on what it is.
+                    getReportLog().setSummary(
+                            "Speed", speedKBPS, ResultType.HIGHER_BETTER, ResultUnit.KBPS);
+                    Log.i(LOG_TAG, "Data transfer speed is " + speedKBPS + "KBPS");
+
                     nextTest(is, os, "done");
                 }
             }
diff --git a/apps/CtsVerifierUSBCompanion/src/com/android/cts/verifierusbcompanion/AccessoryTestCompanion.java b/apps/CtsVerifierUSBCompanion/src/com/android/cts/verifierusbcompanion/AccessoryTestCompanion.java
index dc5cc3d..5999d3a 100644
--- a/apps/CtsVerifierUSBCompanion/src/com/android/cts/verifierusbcompanion/AccessoryTestCompanion.java
+++ b/apps/CtsVerifierUSBCompanion/src/com/android/cts/verifierusbcompanion/AccessoryTestCompanion.java
@@ -39,6 +39,7 @@
  */
 class AccessoryTestCompanion extends TestCompanion {
     private static final int MAX_BUFFER_SIZE = 16384;
+    private static final int TEST_DATA_SIZE_THRESHOLD = 100 * 1024 * 1024; // 100MB
 
     private static final String ACTION_USB_PERMISSION =
             "com.android.cts.verifierusbcompanion.USB_PERMISSION";
@@ -163,13 +164,38 @@
                     }
                     break;
 
+                    case "measure transfer speed": {
+                        byte[] buffer = new byte[MAX_BUFFER_SIZE];
+
+                        long bytesRead = 0;
+                        while (bytesRead < TEST_DATA_SIZE_THRESHOLD) {
+                            int numTransferred = connection.bulkTransfer(
+                                    in, buffer, MAX_BUFFER_SIZE, 0);
+                            bytesRead += numTransferred;
+                        }
+
+                        // If the data length is a multple of the maxpacket size read zero packet.
+                        int numTransferred = connection.bulkTransfer(in, buffer, 1, 0);
+                        assertEquals(0, numTransferred);
+
+                        byte[] confirm = new byte[] {1};
+                        numTransferred = connection.bulkTransfer(out, confirm, 1, 0);
+                        assertEquals(1, numTransferred);
+                    }
+                    break;
+
                     case "echo max bytes": {
                         byte[] buffer = new byte[MAX_BUFFER_SIZE];
+                        byte[] empty = new byte[1];
 
                         int numTransferred = connection.bulkTransfer(in, buffer, MAX_BUFFER_SIZE,
                                 0);
                         assertEquals(MAX_BUFFER_SIZE, numTransferred);
 
+                        // If the data length is a multple of the maxpacket size read zero packet.
+                        numTransferred = connection.bulkTransfer(in, empty, 1, 0);
+                        assertEquals(0, numTransferred);
+
                         numTransferred = connection.bulkTransfer(out, buffer, MAX_BUFFER_SIZE, 0);
                         assertEquals(MAX_BUFFER_SIZE, numTransferred);
                     }
@@ -177,6 +203,7 @@
 
                     case "echo max*2 bytes": {
                         byte[] buffer = new byte[MAX_BUFFER_SIZE * 2];
+                        byte[] empty = new byte[1];
 
                         int numTransferred = connection.bulkTransfer(in, buffer, MAX_BUFFER_SIZE,
                                 0);
@@ -187,6 +214,10 @@
                                 MAX_BUFFER_SIZE, 0);
                         assertEquals(MAX_BUFFER_SIZE, numTransferred);
 
+                        // If the data length is a multple of the maxpacket size read zero packet.
+                        numTransferred = connection.bulkTransfer(in, empty, 1, 0);
+                        assertEquals(0, numTransferred);
+
                         numTransferred = connection.bulkTransfer(out, buffer, MAX_BUFFER_SIZE, 0);
                         assertEquals(MAX_BUFFER_SIZE, numTransferred);
 
diff --git a/common/device-side/device-info/Android.mk b/common/device-side/device-info/Android.mk
index 1fde079..bf6e122 100644
--- a/common/device-side/device-info/Android.mk
+++ b/common/device-side/device-info/Android.mk
@@ -20,7 +20,11 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    compatibility-device-util \
+    android-support-test \
+    junit \
+    legacy-android-test
 
 LOCAL_MODULE := compatibility-device-info
 
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GlesStubActivity.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GlesStubActivity.java
index 9e0d3c5..5edf531 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GlesStubActivity.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GlesStubActivity.java
@@ -24,6 +24,8 @@
 import android.os.Bundle;
 import android.view.Window;
 import android.view.WindowManager;
+import android.opengl.EGL14;
+import android.opengl.EGLDisplay;
 import android.opengl.GLES20;
 import android.opengl.GLES30;
 import android.opengl.GLSurfaceView;
@@ -32,6 +34,7 @@
 import java.lang.reflect.Field;
 import java.nio.FloatBuffer;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 import java.util.HashSet;
@@ -50,10 +53,11 @@
     private int mVersion = -1;
     private GraphicsDeviceInfo mGraphicsDeviceInfo;
     private CountDownLatch mDone = new CountDownLatch(1);
-    private HashSet<String> mOpenGlExtensions = new HashSet<String>();
-    private HashSet<String> mFormats = new HashSet<String>();
-    private HashMap<String, Object> mImplVariables = new HashMap<String, Object>();
-    private HashSet<String> mDynamicArrayVariables = new HashSet<String>();
+    private HashSet<String> mOpenGlExtensions = new HashSet<>();
+    private HashSet<String> mEglExtensions = new HashSet<>();
+    private HashSet<String> mFormats = new HashSet<>();
+    private HashMap<String, Object> mImplVariables = new HashMap<>();
+    private HashSet<String> mDynamicArrayVariables = new HashSet<>();
     private String mGraphicsVendor;
     private String mGraphicsRenderer;
 
@@ -126,6 +130,15 @@
         mOpenGlExtensions.add(openGlExtension);
     }
 
+    List<String> getEglExtensions() {
+        return new ArrayList<>(mEglExtensions);
+    }
+
+    void addEglExtensions(String[] eglExtensions) {
+        // NOTE: We may end up here multiple times, using set to avoid dupes.
+        mEglExtensions.addAll(Arrays.asList(eglExtensions));
+    }
+
     List<String> getCompressedTextureFormats() {
         return new ArrayList<>(mFormats);
     }
@@ -429,6 +442,8 @@
             }
             scanner.close();
 
+            collectEglExtensions(mParent);
+
             mDone.countDown();
         }
 
@@ -446,5 +461,22 @@
                 mParent.addImplementationVariable(name, value, dynamicArray);
             }
         }
+
+        private static void collectEglExtensions(GlesStubActivity collector) {
+            EGLDisplay display = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+            if (display == EGL14.EGL_NO_DISPLAY) {
+                Log.e(LOG_TAG, "Failed to init EGL default display: 0x" +
+                        Integer.toHexString(EGL14.eglGetError()));
+                return;
+            }
+            String extensions = EGL14.eglQueryString(display, EGL14.EGL_EXTENSIONS);
+            int error = EGL14.eglGetError();
+            if (error != EGL14.EGL_SUCCESS) {
+                Log.e(LOG_TAG, "Failed to query extension string: 0x" + Integer.toHexString(error));
+                return;
+            }
+            // Fingers crossed for no extra white space in the extension string.
+            collector.addEglExtensions(extensions.split(" "));
+        }
     }
 }
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GraphicsDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GraphicsDeviceInfo.java
index f1832b3..e1d0cef 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GraphicsDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GraphicsDeviceInfo.java
@@ -95,5 +95,7 @@
                 }
             }
         }
+
+        store.addListResult("egl_extension", stubActivity.getEglExtensions());
     }
 }
diff --git a/common/device-side/device-info/tests/Android.mk b/common/device-side/device-info/tests/Android.mk
index a8d9e038..d40614c 100644
--- a/common/device-side/device-info/tests/Android.mk
+++ b/common/device-side/device-info/tests/Android.mk
@@ -18,7 +18,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-info
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-info junit legacy-android-test
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java b/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
index 3944f70..1d872a8 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
@@ -72,7 +72,7 @@
         super.addValue(source, message, value, type, unit);
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -85,7 +85,7 @@
         super.addValue(message, value, type, unit);
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -99,7 +99,7 @@
         super.addValues(source, message, values, type, unit);
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -112,7 +112,7 @@
         super.addValues(message, values, type, unit);
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -124,7 +124,7 @@
     public void addValue(String message, int value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -136,7 +136,7 @@
     public void addValue(String message, long value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -148,7 +148,7 @@
     public void addValue(String message, float value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -160,7 +160,7 @@
     public void addValue(String message, boolean value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -172,7 +172,7 @@
     public void addValue(String message, String value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -184,7 +184,7 @@
     public void addValues(String message, int[] values, ResultType type, ResultUnit unit) {
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -196,7 +196,7 @@
     public void addValues(String message, long[] values, ResultType type, ResultUnit unit) {
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -208,7 +208,7 @@
     public void addValues(String message, float[] values, ResultType type, ResultUnit unit) {
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -220,7 +220,7 @@
     public void addValues(String message, boolean[] values, ResultType type, ResultUnit unit) {
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -232,7 +232,7 @@
     public void addValues(String message, List<String> values, ResultType type, ResultUnit unit) {
         try {
             store.addListResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -247,7 +247,7 @@
         super.setSummary(message, value, type, unit);
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             Log.e(TAG, "Could not log metric.", e);
         }
     }
@@ -256,15 +256,13 @@
      * Closes report file and submits report to instrumentation.
      */
     public void submit(Instrumentation instrumentation) {
-        Log.i(TAG, "Submit");
         try {
             store.close();
             Bundle output = new Bundle();
             output.putString(RESULT, serialize(this));
             instrumentation.sendStatus(INST_STATUS_IN_PROGRESS, output);
-        } catch (IllegalArgumentException | IllegalStateException | XmlPullParserException
-                | IOException e) {
-            Log.e(TAG, "Submit Failed", e);
+        } catch (Exception e) {
+            Log.e(TAG, "ReportLog Submit Failed", e);
             instrumentation.sendStatus(INST_STATUS_ERROR, null);
         }
     }
@@ -275,11 +273,10 @@
      * does not appear in the result XML.
      */
     public void submit() {
-        Log.i(TAG, "Submit");
         try {
             store.close();
-        } catch (IOException e) {
-            Log.e(TAG, "Submit Failed", e);
+        } catch (Exception e) {
+            Log.e(TAG, "ReportLog Submit Failed", e);
         }
     }
 }
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java b/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java
index 504a02d..538881d 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/ReportLogDeviceInfoStore.java
@@ -27,12 +27,11 @@
 public class ReportLogDeviceInfoStore extends DeviceInfoStore {
 
     private final String mStreamName;
-    private final File tempJsonFile;
+    private File tempJsonFile;
 
     public ReportLogDeviceInfoStore(File jsonFile, String streamName) throws Exception {
         mJsonFile = jsonFile;
         mStreamName = streamName;
-        tempJsonFile = File.createTempFile(streamName, "-temp-report-log");
     }
 
     /**
@@ -42,7 +41,7 @@
     public void open() throws IOException {
         // Write new metrics to a temp file to avoid invalid JSON files due to failed tests.
         BufferedWriter formatWriter;
-        tempJsonFile.createNewFile();
+        tempJsonFile = File.createTempFile(mStreamName, "-temp-report-log");
         formatWriter = new BufferedWriter(new FileWriter(tempJsonFile));
         if (mJsonFile.exists()) {
             BufferedReader jsonReader = new BufferedReader(new FileReader(mJsonFile));
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/WifiConfigCreator.java b/common/device-side/util/src/com/android/compatibility/common/util/WifiConfigCreator.java
index ac30fe1..19d843b 100755
--- a/common/device-side/util/src/com/android/compatibility/common/util/WifiConfigCreator.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/WifiConfigCreator.java
@@ -16,21 +16,23 @@
 
 package com.android.compatibility.common.util;
 
+import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.ProxyInfo;
+import android.net.Uri;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.List;
-
-import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE;
-import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
 
 /**
  * A simple activity to create and manage wifi configurations.
@@ -84,6 +86,49 @@
     }
 
     /**
+     * Adds a new wifiConfiguration with OPEN security type, and the given pacProxy
+     * verifies that the proxy is added by getting the configuration back, and checking it.
+     * @return returns the PAC proxy URL after adding the network and getting it from WifiManager
+     * @throws IllegalStateException if any of the WifiManager operations fail
+     */
+    public String addHttpProxyNetworkVerifyAndRemove(String ssid, String pacProxyUrl)
+            throws IllegalStateException {
+        String retrievedPacProxyUrl = null;
+        int netId = -1;
+        try {
+            WifiConfiguration conf = createConfig(ssid, false, SECURITY_TYPE_NONE, null);
+            if (pacProxyUrl != null) {
+                conf.setHttpProxy(ProxyInfo.buildPacProxy(Uri.parse(pacProxyUrl)));
+            }
+            netId = mWifiManager.addNetwork(conf);
+            if (netId == -1) {
+                throw new IllegalStateException("Failed to addNetwork: " + ssid);
+            }
+            for (final WifiConfiguration w : mWifiManager.getConfiguredNetworks()) {
+                if (w.SSID.equals(ssid)) {
+                    conf = w;
+                    break;
+                }
+            }
+            if (conf == null) {
+                throw new IllegalStateException("Failed to get WifiConfiguration for: " + ssid);
+            }
+            Uri pacProxyFileUri = null;
+            ProxyInfo httpProxy = conf.getHttpProxy();
+            if (httpProxy != null) pacProxyFileUri = httpProxy.getPacFileUrl();
+            if (pacProxyFileUri != null) {
+                retrievedPacProxyUrl = conf.getHttpProxy().getPacFileUrl().toString();
+            }
+            if (!mWifiManager.removeNetwork(netId)) {
+                throw new IllegalStateException("Failed to remove WifiConfiguration: " + ssid);
+            }
+        } finally {
+            mWifiManager.removeNetwork(netId);
+        }
+        return retrievedPacProxyUrl;
+    }
+
+    /**
      * Updates a new WiFi network.
      * @return network id (may differ from original) or -1 in case of error
      */
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/devicepolicy/provisioning/SilentProvisioningTestManager.java b/common/device-side/util/src/com/android/compatibility/common/util/devicepolicy/provisioning/SilentProvisioningTestManager.java
index 3b4b408..5b83357 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/devicepolicy/provisioning/SilentProvisioningTestManager.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/devicepolicy/provisioning/SilentProvisioningTestManager.java
@@ -15,9 +15,10 @@
  */
 package com.android.compatibility.common.util.devicepolicy.provisioning;
 
+import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED;
 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
+import static android.content.Intent.ACTION_MANAGED_PROFILE_ADDED;
 
-import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -50,11 +51,9 @@
     };
 
     private final Context mContext;
-    private final ManagedProfileAddedReceiver mManagedProfileAddedReceiver;
 
     public SilentProvisioningTestManager(Context context) {
         mContext = context.getApplicationContext();
-        mManagedProfileAddedReceiver = new ManagedProfileAddedReceiver(mContext);
     }
 
     public boolean startProvisioningAndWait(Intent provisioningIntent) throws InterruptedException {
@@ -70,6 +69,35 @@
     }
 
     private boolean waitDeviceOwnerProvisioning() throws InterruptedException {
+        return pollProvisioningResult();
+    }
+
+    private boolean waitManagedProfileProvisioning() throws InterruptedException {
+        BlockingReceiver managedProfileProvisionedReceiver = new BlockingReceiver(mContext,
+                ACTION_MANAGED_PROFILE_PROVISIONED);
+        managedProfileProvisionedReceiver.register();
+        BlockingReceiver managedProfileAddedReceiver = new BlockingReceiver(mContext,
+                ACTION_MANAGED_PROFILE_ADDED);
+        managedProfileAddedReceiver.register();
+
+        if (!pollProvisioningResult()) {
+            return false;
+        }
+
+        if (!managedProfileProvisionedReceiver.await()) {
+            Log.i(TAG, "mManagedProfileProvisionedReceiver.await(): false");
+            return false;
+        }
+
+        if (!managedProfileAddedReceiver.await()) {
+            Log.i(TAG, "mManagedProfileAddedReceiver.await(): false");
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean pollProvisioningResult() throws InterruptedException {
         Boolean result = mProvisioningResults.poll(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         if (result == null) {
             Log.i(TAG, "ManagedProvisioning doesn't return result within "
@@ -84,22 +112,6 @@
         return true;
     }
 
-    private boolean waitManagedProfileProvisioning() throws InterruptedException {
-        mManagedProfileAddedReceiver.register();
-        Boolean result = mProvisioningResults.poll(TIMEOUT_SECONDS, TimeUnit.SECONDS);
-        if (result == null) {
-            Log.i(TAG, "ManagedProvisioning doesn't return result within "
-                    + TIMEOUT_SECONDS + " seconds ");
-            return false;
-        }
-
-        if (!result) {
-            Log.i(TAG, "Failed to provision");
-            return false;
-        }
-        return mManagedProfileAddedReceiver.await();
-    }
-
     private Intent getStartIntent(Intent intent) {
         final Bundle bundle = new Bundle();
         bundle.putParcelable(Intent.EXTRA_INTENT, intent);
@@ -118,22 +130,23 @@
         }
     }
 
-    private static class ManagedProfileAddedReceiver extends BroadcastReceiver {
+    private static class BlockingReceiver extends BroadcastReceiver {
 
         private static final CountDownLatch mLatch = new CountDownLatch(1);
 
         private final Context mContext;
+        private final String mAction;
 
-        private ManagedProfileAddedReceiver(Context context) {
+        private BlockingReceiver(Context context, String action) {
             mContext = context;
+            mAction = action;
         }
 
-        private void register() {
-            mContext.registerReceiver(this, new IntentFilter(
-                    DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED));
+        public void register() {
+            mContext.registerReceiver(this, new IntentFilter(mAction));
         }
 
-        private boolean await() throws InterruptedException {
+        public boolean await() throws InterruptedException {
             return mLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         }
 
diff --git a/common/device-side/util/tests/Android.mk b/common/device-side/util/tests/Android.mk
index fa7424d..12baeb7 100644
--- a/common/device-side/util/tests/Android.mk
+++ b/common/device-side/util/tests/Android.mk
@@ -18,7 +18,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util junit
 
 LOCAL_MODULE_TAGS := optional
 
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
index c1087a1..16bf486 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
@@ -71,6 +71,10 @@
         }
     }
 
+    public String getRecentCommandLineArgs() {
+        return mBuildInfo.getBuildAttributes().get(COMMAND_LINE_ARGS);
+    }
+
     public String getSuiteBuild() {
         return mBuildInfo.getBuildAttributes().get(SUITE_BUILD);
     }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
index 08b7c17..ec41baf 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
@@ -18,6 +18,7 @@
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.compatibility.common.tradefed.result.InvocationFailureHandler;
 import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
+import com.android.compatibility.common.tradefed.testtype.CompatibilityTest.RetryType;
 import com.android.compatibility.common.util.ICaseResult;
 import com.android.compatibility.common.util.IInvocationResult;
 import com.android.compatibility.common.util.IModuleResult;
@@ -82,6 +83,13 @@
             importance = Importance.IF_UNSET)
     private Integer mRetrySessionId = null;
 
+    @Option(name = CompatibilityTest.RETRY_TYPE_OPTION,
+            description = "used with " + CompatibilityTest.RETRY_OPTION
+            + ", retry tests of a certain status. Possible values include \"failed\" and "
+            + "\"not_executed\".",
+            importance = Importance.IF_UNSET)
+    private RetryType mRetryType = null;
+
     @Option(name = "result-server", description = "Server to publish test results.")
     private String mResultServer;
 
@@ -116,6 +124,13 @@
     private int mCurrentTestNum;
     private int mTotalTestsInModule;
 
+
+    // Whether modules can be marked done for this invocation. Initialized in invocationStarted()
+    // Visible for unit testing
+    protected boolean mCanMarkDone;
+    // Whether the current module has previously been marked done
+    private boolean mModuleWasDone;
+
     // Nullable. If null, "this" is considered the master and must handle
     // result aggregation and reporting. When not null, it should forward events
     // to the master.
@@ -148,6 +163,7 @@
             if (mDeviceSerial == null && buildInfo.getDeviceSerial() != null) {
                 mDeviceSerial = buildInfo.getDeviceSerial();
             }
+            mCanMarkDone = canMarkDone(mBuildHelper.getRecentCommandLineArgs());
         }
 
         if (isShardResultReporter()) {
@@ -244,13 +260,14 @@
                 mTotalTestsInModule +=
                         Math.max(0, numTests - mCurrentModuleResult.getNotExecuted());
             }
-            mCurrentModuleResult.setDone(false);
         } else {
             mCurrentModuleResult = mResult.getOrCreateModule(id);
             mTotalTestsInModule = numTests;
             // Reset counters
             mCurrentTestNum = 0;
         }
+        mModuleWasDone = mCurrentModuleResult.isDone();
+        mCurrentModuleResult.setDone(false);
     }
 
     /**
@@ -335,8 +352,12 @@
     @Override
     public void testRunEnded(long elapsedTime, Map<String, String> metrics) {
         mCurrentModuleResult.addRuntime(elapsedTime);
-        // Expect them to be equal, but greater than to be safe.
-        mCurrentModuleResult.setDone(mCurrentTestNum >= mTotalTestsInModule);
+        if (mCanMarkDone || mModuleWasDone) {
+            // Only mark module done if status of the invocation allows it (mCanMarkDone) or module
+            // was previously marked done (mModuleWasDone) and all expected tests are collected.
+            // Expect mCurrentTestNum = mTotalTestsInModule, but use >= to be safe
+            mCurrentModuleResult.setDone(mCurrentTestNum >= mTotalTestsInModule);
+        }
         mCurrentModuleResult.setNotExecuted(Math.max(mTotalTestsInModule - mCurrentTestNum, 0));
         if (isShardResultReporter()) {
             // Forward module results to the master.
@@ -604,6 +625,28 @@
     }
 
     /**
+     * Returns whether it is safe to mark modules as "done", given the invocation command-line
+     * arguments. Returns true unless this is a retry and specific filtering techniques are applied
+     * on the command-line, such as:
+     *   --retry-type failed
+     *   --include-filter
+     *   --exclude-filter
+     *   -t/--test
+     *   --subplan
+     */
+    private boolean canMarkDone(String args) {
+        if (mRetrySessionId == null) {
+            return true; // always allow modules to be marked done if not retry
+        }
+        return !(RetryType.FAILED.equals(mRetryType)
+                || args.contains(CompatibilityTest.INCLUDE_FILTER_OPTION)
+                || args.contains(CompatibilityTest.EXCLUDE_FILTER_OPTION)
+                || args.contains(CompatibilityTest.SUBPLAN_OPTION)
+                || args.matches(String.format(".* (-%s|--%s) .*",
+                CompatibilityTest.TEST_OPTION_SHORT_NAME, CompatibilityTest.TEST_OPTION)));
+    }
+
+    /**
      * Copy the xml formatting files stored in this jar to the results directory
      *
      * @param resultsDir
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 70bdafd..50ee9d0 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
@@ -92,6 +92,7 @@
     public static final String PRECONDITION_ARG_OPTION = "precondition-arg";
     public static final String MODULE_ARG_OPTION = "module-arg";
     public static final String TEST_ARG_OPTION = "test-arg";
+    public static final char TEST_OPTION_SHORT_NAME = 't';
     public static final String RETRY_OPTION = "retry";
     public static final String RETRY_TYPE_OPTION = "retry-type";
     public static final String ABI_OPTION = "abi";
@@ -129,7 +130,7 @@
     private String mModuleName = null;
 
     @Option(name = TEST_OPTION,
-            shortName = 't',
+            shortName = TEST_OPTION_SHORT_NAME,
             description = "the test run.",
             importance = Importance.IF_UNSET)
     private String mTestName = null;
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
index 84f9faf..09885ed 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
@@ -288,6 +288,84 @@
                 finalTestResult2.getResultStatus());
     }
 
+    public void testRetryCanSetDone() throws Exception {
+        mReporter.invocationStarted(mBuildInfo);
+        // Set mCanMarkDone directly (otherwise we must build result directory, write XML, and
+        // perform actual retry)
+        mReporter.mCanMarkDone = true;
+        // Set up IInvocationResult with existing results from previous session
+        IInvocationResult invocationResult = mReporter.getResult();
+        IModuleResult moduleResult = invocationResult.getOrCreateModule(ID);
+        moduleResult.setDone(false);
+        ICaseResult caseResult = moduleResult.getOrCreateResult(CLASS);
+        ITestResult testResult1 = caseResult.getOrCreateResult(METHOD_1);
+        testResult1.setResultStatus(TestStatus.PASS);
+        testResult1.setRetry(true);
+        ITestResult testResult2 = caseResult.getOrCreateResult(METHOD_2);
+        testResult2.setResultStatus(TestStatus.FAIL);
+        testResult2.setStackTrace(STACK_TRACE);
+        testResult2.setRetry(true);
+
+        // Assume no additional filtering is applied to retry, and all tests for the module have
+        // been collected. Thus, module "done" value should switch.
+        mReporter.testRunStarted(ID, 1);
+
+        TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+        mReporter.testStarted(test2);
+        mReporter.testEnded(test2, new HashMap<String, String>());
+
+        mReporter.testRunEnded(10, new HashMap<String, String>());
+        mReporter.invocationEnded(10);
+
+        // Verification that results have been overwritten.
+        IInvocationResult result = mReporter.getResult();
+        assertEquals("Expected 2 pass", 2, result.countResults(TestStatus.PASS));
+        assertEquals("Expected 0 failures", 0, result.countResults(TestStatus.FAIL));
+        List<IModuleResult> modules = result.getModules();
+        assertEquals("Expected 1 module", 1, modules.size());
+        IModuleResult module = modules.get(0);
+        assertTrue("Module should be marked done", module.isDone());
+    }
+
+    public void testRetryCannotSetDone() throws Exception {
+        mReporter.invocationStarted(mBuildInfo);
+        // Set mCanMarkDone directly (otherwise we must build result directory, write XML, and
+        // perform actual retry)
+        mReporter.mCanMarkDone = false;
+        // Set up IInvocationResult with existing results from previous session
+        IInvocationResult invocationResult = mReporter.getResult();
+        IModuleResult moduleResult = invocationResult.getOrCreateModule(ID);
+        moduleResult.setDone(false);
+        ICaseResult caseResult = moduleResult.getOrCreateResult(CLASS);
+        ITestResult testResult1 = caseResult.getOrCreateResult(METHOD_1);
+        testResult1.setResultStatus(TestStatus.PASS);
+        testResult1.setRetry(true);
+        ITestResult testResult2 = caseResult.getOrCreateResult(METHOD_2);
+        testResult2.setResultStatus(TestStatus.FAIL);
+        testResult2.setStackTrace(STACK_TRACE);
+        testResult2.setRetry(true);
+
+        // Since using retry-type failed option, we only run previously failed test
+        // and don't run any non-executed tests, so module "done" value should not switch.
+        mReporter.testRunStarted(ID, 1);
+
+        TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+        mReporter.testStarted(test2);
+        mReporter.testEnded(test2, new HashMap<String, String>());
+
+        mReporter.testRunEnded(10, new HashMap<String, String>());
+        mReporter.invocationEnded(10);
+
+        // Verification that results have been overwritten.
+        IInvocationResult result = mReporter.getResult();
+        assertEquals("Expected 2 pass", 2, result.countResults(TestStatus.PASS));
+        assertEquals("Expected 0 failures", 0, result.countResults(TestStatus.FAIL));
+        List<IModuleResult> modules = result.getModules();
+        assertEquals("Expected 1 module", 1, modules.size());
+        IModuleResult module = modules.get(0);
+        assertFalse("Module should not be marked done", module.isDone());
+    }
+
     public void testResultReporting_moduleNotDone() throws Exception {
         mReporter.invocationStarted(mBuildInfo);
         mReporter.testRunStarted(ID, 2);
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/MetricsReportLog.java b/common/host-side/util/src/com/android/compatibility/common/util/MetricsReportLog.java
index b87b86c..5ea9928 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/MetricsReportLog.java
+++ b/common/host-side/util/src/com/android/compatibility/common/util/MetricsReportLog.java
@@ -20,7 +20,6 @@
 import com.android.tradefed.util.FileUtil;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.List;
 
 /**
@@ -69,7 +68,7 @@
         super.addValue(source, message, value, type, unit);
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -82,7 +81,7 @@
         super.addValue(message, value, type, unit);
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
 
@@ -97,7 +96,7 @@
         super.addValues(source, message, values, type, unit);
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -110,7 +109,7 @@
         super.addValues(message, values, type, unit);
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -122,7 +121,7 @@
     public void addValue(String message, int value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -134,7 +133,7 @@
     public void addValue(String message, long value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -146,7 +145,7 @@
     public void addValue(String message, float value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -158,7 +157,7 @@
     public void addValue(String message, boolean value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -170,7 +169,7 @@
     public void addValue(String message, String value, ResultType type, ResultUnit unit) {
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -182,7 +181,7 @@
     public void addValues(String message, int[] values, ResultType type, ResultUnit unit) {
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -194,7 +193,7 @@
     public void addValues(String message, long[] values, ResultType type, ResultUnit unit) {
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -206,7 +205,7 @@
     public void addValues(String message, float[] values, ResultType type, ResultUnit unit) {
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -218,7 +217,7 @@
     public void addValues(String message, boolean[] values, ResultType type, ResultUnit unit) {
         try {
             store.addArrayResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -230,7 +229,7 @@
     public void addValues(String message, List<String> values, ResultType type, ResultUnit unit) {
         try {
             store.addListResult(message, values);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -245,7 +244,7 @@
         super.setSummary(message, value, type, unit);
         try {
             store.addResult(message, value);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }
@@ -256,9 +255,9 @@
     public void submit() {
         try {
             store.close();
-        } catch (IOException e) {
+            MetricsStore.storeResult(mBuildInfo, mAbi, mClassMethodName, this);
+        } catch (Exception e) {
             e.printStackTrace();
         }
-        MetricsStore.storeResult(mBuildInfo, mAbi, mClassMethodName, this);
     }
 }
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/ReportLogHostInfoStore.java b/common/host-side/util/src/com/android/compatibility/common/util/ReportLogHostInfoStore.java
index 38b742b..f501010 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/ReportLogHostInfoStore.java
+++ b/common/host-side/util/src/com/android/compatibility/common/util/ReportLogHostInfoStore.java
@@ -27,12 +27,11 @@
 public class ReportLogHostInfoStore extends HostInfoStore {
 
     private final String mStreamName;
-    private final File tempJsonFile;
+    private File tempJsonFile;
 
     public ReportLogHostInfoStore(File jsonFile, String streamName) throws Exception {
         mJsonFile = jsonFile;
         mStreamName = streamName;
-        tempJsonFile = File.createTempFile(streamName, "-temp-report-log");
     }
 
     /**
@@ -42,7 +41,7 @@
     public void open() throws IOException {
         // Write new metrics to a temp file to avoid invalid JSON files due to failed tests.
         BufferedWriter formatWriter;
-        tempJsonFile.createNewFile();
+        tempJsonFile = File.createTempFile(mStreamName, "-temp-report-log");
         formatWriter = new BufferedWriter(new FileWriter(tempJsonFile));
         if (mJsonFile.exists()) {
             BufferedReader jsonReader = new BufferedReader(new FileReader(mJsonFile));
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
index a064287..7d8c884 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
@@ -85,4 +85,8 @@
     public void testCreateDocumentAtInitialLocation() throws Exception {
         runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateDocumentAtInitialLocation");
     }
+
+    public void testCreateWebLink() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateWebLink");
+    }
 }
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 7a6ad8e..0249509 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -107,6 +107,10 @@
         runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartEphemeral");
     }
 
+    public void testExposedSystemActivities() throws Exception {
+        runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testExposedSystemActivities");
+    }
+
     private void runDeviceTests(String packageName, String testClassName, String testMethodName)
             throws DeviceNotAvailableException {
         Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
index 1566066..bc8f904 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
@@ -16,10 +16,13 @@
 
 package com.android.cts.documentclient;
 
+import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Intent;
+import android.content.IntentSender;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.SystemClock;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
@@ -524,4 +527,54 @@
 
         assertTrue(findDocument("FILE1").exists());
     }
+
+    public void testCreateWebLink() throws Exception {
+        if (!supportedHardware()) return;
+
+        final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+        intent.setType("*/*");
+        mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+        // Pick a virtual file from the local root.
+        mDevice.waitForIdle();
+        findRoot("CtsLocal").click();
+
+        mDevice.waitForIdle();
+        findDocument("WEB_LINKABLE_FILE").click();
+
+        // Confirm that the returned file is actually the selected one.
+        final Result result = mActivity.getResult();
+        final Uri uri = result.data.getData();
+        assertEquals("doc:web-linkable-file", DocumentsContract.getDocumentId(uri));
+
+        final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
+        final String streamTypes[] = resolver.getStreamTypes(uri, "*/*");
+        assertEquals(1, streamTypes.length);
+        assertEquals("text/plain", streamTypes[0]);
+
+        Bundle bundle = new Bundle();
+        bundle.putString(Intent.EXTRA_EMAIL, "x@x.com");
+        final IntentSender intentSender = DocumentsContract.createWebLinkIntent(resolver,
+                uri, bundle);
+
+        final int WEB_LINK_REQUEST_CODE = 1;
+        mActivity.startIntentSenderForResult(intentSender, WEB_LINK_REQUEST_CODE,
+                null, 0, 0, 0);
+        mDevice.waitForIdle();
+
+        // Confirm the permissions dialog. The dialog is provided by the stub
+        // provider.
+        UiObject okButton = new UiObject(new UiSelector().text("OK").clickable(true));
+        assertNotNull(okButton);
+        assertTrue(okButton.waitForExists(TIMEOUT));
+        okButton.click();
+
+        final Result webLinkResult = mActivity.getResult();
+        assertEquals(WEB_LINK_REQUEST_CODE, webLinkResult.requestCode);
+        assertEquals(Activity.RESULT_OK, webLinkResult.resultCode);
+
+        final Uri webLinkUri = webLinkResult.data.getData();
+        assertEquals("http://www.foobar.com/shared/SW33TCH3RR13S", webLinkUri.toString());
+    }
+
 }
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml
index c0fc6cc..894eff1 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml
@@ -36,5 +36,8 @@
                 <data android:mimeType="image/*" />
             </intent-filter>
         </activity>
+
+        <activity android:name=".WebLinkActivity">
+        </activity>
     </application>
 </manifest>
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
index eabf4ba..afcaefe 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
@@ -16,6 +16,9 @@
 
 package com.android.cts.documentprovider;
 
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.IntentSender;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.database.MatrixCursor;
@@ -46,6 +49,8 @@
 public class MyDocumentsProvider extends DocumentsProvider {
     private static final String TAG = "TestDocumentsProvider";
 
+    private static final int WEB_LINK_REQUEST_CODE = 321;
+
     private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
             Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
             Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES,
@@ -141,6 +146,15 @@
             mCreateRoot.children.add(virtualFile);
         }
 
+        {
+            Doc webLinkableFile = buildDoc("doc:web-linkable-file", "WEB_LINKABLE_FILE",
+                    "application/icecream", new String[] { "text/plain" });
+            webLinkableFile.flags = Document.FLAG_VIRTUAL_DOCUMENT | Document.FLAG_WEB_LINKABLE;
+            webLinkableFile.contents = "Fake contents.".getBytes();
+            mLocalRoot.children.add(webLinkableFile);
+            mCreateRoot.children.add(webLinkableFile);
+        }
+
         Doc dir1 = buildDoc("doc:dir1", "DIR1", Document.MIME_TYPE_DIR, null);
         mLocalRoot.children.add(dir1);
 
@@ -428,6 +442,29 @@
         throw new UnsupportedOperationException("Unsupported MIME type filter for tests.");
     }
 
+    @Override
+    public IntentSender createWebLinkIntent(String documentId, Bundle options)
+            throws FileNotFoundException {
+        final Doc doc = mDocs.get(documentId);
+        if (doc == null) {
+            throw new FileNotFoundException();
+        }
+        if ((doc.flags & Document.FLAG_WEB_LINKABLE) == 0) {
+            throw new IllegalArgumentException("The file is not web linkable");
+        }
+
+        final Intent intent = new Intent(getContext(), WebLinkActivity.class);
+        intent.putExtra(WebLinkActivity.EXTRA_DOCUMENT_ID, documentId);
+        if (options != null) {
+            intent.putExtras(options);
+        }
+
+        final PendingIntent pendingIntent = PendingIntent.getActivity(
+                getContext(), WEB_LINK_REQUEST_CODE, intent,
+                PendingIntent.FLAG_ONE_SHOT);
+        return pendingIntent.getIntentSender();
+    }
+
     private static byte[] readFullyNoClose(InputStream in) throws IOException {
         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
         byte[] buffer = new byte[1024];
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/WebLinkActivity.java b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/WebLinkActivity.java
new file mode 100644
index 0000000..76deee3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/WebLinkActivity.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.documentprovider;
+
+import android.app.Activity;
+import android.app.AlertDialog.Builder;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class WebLinkActivity extends Activity {
+    public static final String EXTRA_DOCUMENT_ID =
+            "com.android.cts.documentprovider.EXTRA_DOCUMENT_ID";
+    private static final Uri FAKE_WEB_LINK = Uri.parse(
+            "http://www.foobar.com/shared/SW33TCH3RR13S");
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final String documentId = getIntent().getStringExtra(EXTRA_DOCUMENT_ID);
+        final String email = getIntent().getStringExtra(Intent.EXTRA_EMAIL);
+
+        new AlertDialog.Builder(this)
+            .setTitle("Grant permissions to this file to " + email + "?")
+            .setMessage(documentId)
+            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    final Intent intent = new Intent();
+                    intent.setData(FAKE_WEB_LINK);
+                    setResult(RESULT_OK, intent);
+                    finish();
+                }
+             })
+            .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    setResult(RESULT_CANCELED, null);
+                    finish();
+                }
+             })
+            .setIcon(android.R.drawable.ic_dialog_alert)
+            .show();
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
index 88501bf..c50dbd9 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
@@ -18,7 +18,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    legacy-android-test
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index 2b03efa..b480791 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -59,6 +59,22 @@
             "com.android.cts.ephemeraltest.QUERY";
     private static final String EXTRA_ACTIVITY_NAME =
             "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_NAME";
+    private static final String EXTRA_ACTIVITY_RESULT =
+            "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_RESULT";
+
+    /**
+     * Intents that we expect the system to expose activities to ephemeral apps to handle.
+     */
+    private static final Intent[] EXPECTED_EXPOSED_SYSTEM_INTENTS = new Intent[] {
+        makeIntent(Intent.ACTION_OPEN_DOCUMENT, Intent.CATEGORY_OPENABLE, "*/*"),
+        makeIntent(Intent.ACTION_OPEN_DOCUMENT, null, "*/*"),
+        makeIntent(Intent.ACTION_GET_CONTENT, Intent.CATEGORY_OPENABLE, "*/*"),
+        makeIntent(Intent.ACTION_GET_CONTENT, null, "*/*"),
+        makeIntent(Intent.ACTION_OPEN_DOCUMENT_TREE, null, null),
+        makeIntent(Intent.ACTION_CREATE_DOCUMENT, Intent.CATEGORY_OPENABLE, "text/plain"),
+        makeIntent(Intent.ACTION_CREATE_DOCUMENT, null, "text/plain"),
+
+    };
 
     private BroadcastReceiver mReceiver;
     private final SynchronousQueue<BroadcastResult> mResultQueue = new SynchronousQueue<>();
@@ -156,6 +172,8 @@
                     is("com.android.cts.normalapp"));
             assertThat(testResult.activityName,
                     is("ExposedActivity"));
+            assertThat(testResult.result,
+                    is("PASS"));
         }
 
         // start the exposed activity; directed package
@@ -169,6 +187,8 @@
                     is("com.android.cts.normalapp"));
             assertThat(testResult.activityName,
                     is("ExposedActivity"));
+            assertThat(testResult.result,
+                    is("PASS"));
         }
 
         // start the exposed activity; directed component
@@ -183,6 +203,8 @@
                     is("com.android.cts.normalapp"));
             assertThat(testResult.activityName,
                     is("ExposedActivity"));
+            assertThat(testResult.result,
+                    is("PASS"));
         }
     }
 
@@ -229,6 +251,21 @@
         }
     }
 
+    @Test
+    public void testExposedSystemActivities() throws Exception {
+        for (Intent queryIntent : EXPECTED_EXPOSED_SYSTEM_INTENTS) {
+            assertIntentHasExposedActivities(queryIntent);
+        }
+    }
+
+    private void assertIntentHasExposedActivities(Intent queryIntent) throws Exception {
+        final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+                .getContext().getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
+        if (resolveInfo == null || resolveInfo.size() == 0) {
+            fail("No activies found for Intent: " + queryIntent);
+        }
+    }
+
     private BroadcastResult getResult() {
         final BroadcastResult result;
         try {
@@ -242,17 +279,33 @@
         return result;
     }
 
+    private static Intent makeIntent(String action, String category, String mimeType) {
+        Intent intent = new Intent(action);
+        if (category != null) {
+            intent.addCategory(category);
+        }
+        if (mimeType != null) {
+            intent.setType(mimeType);
+        }
+        return intent;
+    }
+
     private static class BroadcastResult {
         final String packageName;
         final String activityName;
-        public BroadcastResult(String packageName, String activityName) {
+        final String result;
+
+        public BroadcastResult(String packageName, String activityName, String result) {
             this.packageName = packageName;
             this.activityName = activityName;
+            this.result = result;
         }
 
         @Override
         public String toString() {
-            return "[pkg=" + packageName + ", activity=" + activityName + "]";
+            return "[pkg=" + packageName
+                    + ", activity=" + activityName
+                    + ", result=" + result + "]";
         }
     }
 
@@ -268,7 +321,9 @@
                 mQueue.offer(
                         new BroadcastResult(
                                 intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME),
-                                intent.getStringExtra(EXTRA_ACTIVITY_NAME)),
+                                intent.getStringExtra(EXTRA_ACTIVITY_NAME),
+                                intent.getStringExtra(EXTRA_ACTIVITY_RESULT)
+                                ),
                         5, TimeUnit.SECONDS);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/Android.mk
index c2db091..945422e 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/Android.mk
@@ -18,7 +18,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    legacy-android-test
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
index c2e91c4..e38ab54 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
@@ -16,6 +16,8 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.cts.normalapp">
+    <uses-sdk
+        android:minSdkVersion="24" />
 
     <application
         android:label="@string/app_name">
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
index 8bd6a68..1f1c292 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
@@ -58,6 +58,8 @@
             "com.android.cts.ephemeraltest.QUERY";
     private static final String EXTRA_ACTIVITY_NAME =
             "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_NAME";
+    private static final String EXTRA_ACTIVITY_RESULT =
+            "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_RESULT";
 
     private BroadcastReceiver mReceiver;
     private final SynchronousQueue<BroadcastResult> mResultQueue = new SynchronousQueue<>();
@@ -129,6 +131,8 @@
                     is("com.android.cts.normalapp"));
             assertThat(testResult.activityName,
                     is("NormalActivity"));
+            assertThat(testResult.result,
+                    is("android.content.pm.PackageManager$NameNotFoundException"));
         }
 
         // start the normal activity; directed package
@@ -141,6 +145,8 @@
                     is("com.android.cts.normalapp"));
             assertThat(testResult.activityName,
                     is("NormalActivity"));
+            assertThat(testResult.result,
+                    is("android.content.pm.PackageManager$NameNotFoundException"));
         }
 
         // start the normal activity; directed component
@@ -154,6 +160,8 @@
                     is("com.android.cts.normalapp"));
             assertThat(testResult.activityName,
                     is("NormalActivity"));
+            assertThat(testResult.result,
+                    is("android.content.pm.PackageManager$NameNotFoundException"));
         }
     }
 
@@ -219,14 +227,19 @@
     private static class BroadcastResult {
         final String packageName;
         final String activityName;
-        public BroadcastResult(String packageName, String activityName) {
+        final String result;
+
+        public BroadcastResult(String packageName, String activityName, String result) {
             this.packageName = packageName;
             this.activityName = activityName;
+            this.result = result;
         }
 
         @Override
         public String toString() {
-            return "[pkg=" + packageName + ", activity=" + activityName + "]";
+            return "[pkg=" + packageName
+                    + ", activity=" + activityName
+                    + ", result=" + result + "]";
         }
     }
 
@@ -242,7 +255,9 @@
                 mQueue.offer(
                         new BroadcastResult(
                                 intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME),
-                                intent.getStringExtra(EXTRA_ACTIVITY_NAME)),
+                                intent.getStringExtra(EXTRA_ACTIVITY_NAME),
+                                intent.getStringExtra(EXTRA_ACTIVITY_RESULT)
+                                ),
                         5, TimeUnit.SECONDS);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedActivity.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedActivity.java
index 0295085..de597c8 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedActivity.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedActivity.java
@@ -19,10 +19,14 @@
 import android.app.Activity;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.List;
 
 public class ExposedActivity extends Activity {
@@ -30,6 +34,8 @@
             "com.android.cts.ephemeraltest.START_ACTIVITY";
     private static final String EXTRA_ACTIVITY_NAME =
             "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_NAME";
+    private static final String EXTRA_ACTIVITY_RESULT =
+            "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_RESULT";
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -39,8 +45,22 @@
         broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
         broadcastIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, "com.android.cts.normalapp");
         broadcastIntent.putExtra(EXTRA_ACTIVITY_NAME, "ExposedActivity");
+        String result = "FAIL";
+        try {
+            tryAccessingEphemeral();
+            result = "PASS";
+        } catch (Throwable t) {
+            result = t.getClass().getName();
+        }
+        broadcastIntent.putExtra(EXTRA_ACTIVITY_RESULT, result);
         sendBroadcast(broadcastIntent);
 
         finish();
     }
+
+    private void tryAccessingEphemeral() throws NameNotFoundException {
+        final PackageInfo info =
+                getPackageManager().getPackageInfo("com.android.cts.ephemeralapp1", 0 /*flags*/);
+        if (info == null) throw new IllegalStateException("No PackageInfo object found");
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalActivity.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalActivity.java
index d279506..1807971 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalActivity.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalActivity.java
@@ -18,11 +18,15 @@
 
 import android.app.Activity;
 import android.content.Intent;
+import android.content.pm.PackageInfo;
 import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.List;
 
 public class NormalActivity extends Activity {
@@ -30,6 +34,8 @@
             "com.android.cts.ephemeraltest.START_ACTIVITY";
     private static final String EXTRA_ACTIVITY_NAME =
             "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_NAME";
+    private static final String EXTRA_ACTIVITY_RESULT =
+            "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_RESULT";
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -39,8 +45,22 @@
         broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
         broadcastIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, "com.android.cts.normalapp");
         broadcastIntent.putExtra(EXTRA_ACTIVITY_NAME, "NormalActivity");
+        String result = "FAIL";
+        try {
+            tryAccessingEphemeral();
+            result = "PASS";
+        } catch (Throwable t) {
+            result = t.getClass().getName();
+        }
+        broadcastIntent.putExtra(EXTRA_ACTIVITY_RESULT, result);
         sendBroadcast(broadcastIntent);
 
         finish();
     }
+
+    private void tryAccessingEphemeral() throws NameNotFoundException {
+        final PackageInfo info =
+                getPackageManager().getPackageInfo("com.android.cts.ephemeralapp1", 0 /*flags*/);
+        if (info == null) throw new IllegalStateException("No PackageInfo object found");
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalWebActivity.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalWebActivity.java
index 3283cea..a1a50b9 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalWebActivity.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalWebActivity.java
@@ -18,11 +18,15 @@
 
 import android.app.Activity;
 import android.content.Intent;
+import android.content.pm.PackageInfo;
 import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.List;
 
 public class NormalWebActivity extends Activity {
@@ -30,6 +34,8 @@
             "com.android.cts.ephemeraltest.START_ACTIVITY";
     private static final String EXTRA_ACTIVITY_NAME =
             "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_NAME";
+    private static final String EXTRA_ACTIVITY_RESULT =
+            "com.android.cts.ephemeraltest.EXTRA_ACTIVITY_RESULT";
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -39,8 +45,22 @@
         broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
         broadcastIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, "com.android.cts.normalapp");
         broadcastIntent.putExtra(EXTRA_ACTIVITY_NAME, "NormalWebActivity");
+        String result = "FAIL";
+        try {
+            tryAccessingEphemeral();
+            result = "PASS";
+        } catch (Throwable t) {
+            result = t.getClass().getName();
+        }
+        broadcastIntent.putExtra(EXTRA_ACTIVITY_RESULT, result);
         sendBroadcast(broadcastIntent);
 
         finish();
     }
+
+    private void tryAccessingEphemeral() throws NameNotFoundException {
+        final PackageInfo info =
+                getPackageManager().getPackageInfo("com.android.cts.ephemeralapp1", 0 /*flags*/);
+        if (info == null) throw new IllegalStateException("No PackageInfo object found");
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk
index 34f4170..f8db5aa 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/Android.mk
@@ -19,7 +19,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-util ctstestrunner ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java \
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk
index e8aefb9..9e6ea3e 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/Android.mk
@@ -19,7 +19,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-util ctstestrunner ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
diff --git a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
index 3ab7d95..25c0b89 100644
--- a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
+++ b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
@@ -20,6 +20,7 @@
 import com.android.ddmlib.Log;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IBuildReceiver;
 
@@ -102,7 +103,7 @@
                         /*details*/ m.group(6));
                 return;
             }
-            System.err.println("line doesn't match: " + line);
+            CLog.i("line doesn't match: " + line);
         }
 
         private static void parse(Reader reader, FtraceEntryCallback callback) throws Exception {
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/AdminReceiver.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/AdminReceiver.java
index 957cbf5..bf18ebb 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/AdminReceiver.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/AdminReceiver.java
@@ -37,6 +37,7 @@
         super.onProfileProvisioningComplete(context, intent);
         Log.i(TAG, "onProfileProvisioningComplete");
         // Enabled profile
+        getManager(context).setProfileEnabled(getComponentName(context));
         getManager(context).setProfileName(getComponentName(context), "Corp owned Managed Profile");
     }
 }
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ManagementTest.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ManagementTest.java
index 1daa496..230859d 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ManagementTest.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ManagementTest.java
@@ -16,10 +16,11 @@
 package com.android.cts.comp;
 
 import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.os.UserHandle;
 import android.test.AndroidTestCase;
-
+import android.test.MoreAsserts;
 import java.util.List;
 
 public class ManagementTest extends AndroidTestCase {
@@ -84,4 +85,15 @@
         assertTrue(mDevicePolicyManager.removeUser(AdminReceiver.getComponentName(mContext),
                 profileUserHandle));
     }
+
+    public void testCreateSecondaryUser() throws Exception {
+        ComponentName admin = AdminReceiver.getComponentName(mContext);
+        assertNotNull(mDevicePolicyManager.createAndManageUser(admin, "secondary-user",
+                admin, null, DevicePolicyManager.SKIP_SETUP_WIZARD));
+    }
+
+    public void testNoBindDeviceAdminTargetUsers() {
+        MoreAsserts.assertEmpty(mDevicePolicyManager.getBindDeviceAdminTargetUsers(
+                AdminReceiver.getComponentName(mContext)));
+    }
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/WipeDataTest.java b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/WipeDataTest.java
new file mode 100644
index 0000000..ea010f4
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAdmin/src/com.android.cts.deviceadmin/WipeDataTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.deviceadmin;
+
+public class WipeDataTest extends BaseDeviceAdminTest {
+
+    // Caution: this test will wipe the device's data if it fails
+    public void testWipeDataThrowsSecurityException() {
+        try {
+            dpm.wipeData(0);
+            fail("wipeData didn't throw expected SecurityException. Managed to kick off factory"
+                    + " reset process");
+        } catch (SecurityException expected) {
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/ProfileGlobalRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/ProfileGlobalRestrictionsTest.java
new file mode 100644
index 0000000..d343401
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/ProfileGlobalRestrictionsTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.deviceandprofileowner.userrestrictions;
+
+import static android.os.UserManager.ENSURE_VERIFY_APPS;
+
+import com.android.cts.deviceandprofileowner.BaseDeviceAdminTest;
+
+public class ProfileGlobalRestrictionsTest extends BaseDeviceAdminTest {
+    private void assertRestriction(String restriction, boolean expected) {
+        assertEquals("Wrong restriction value",
+                expected, mUserManager.hasUserRestriction(restriction));
+    }
+
+    public void testSetProfileGlobalRestrictions() throws Exception {
+        mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT, ENSURE_VERIFY_APPS);
+    }
+
+    public void testClearProfileGlobalRestrictions() throws Exception  {
+        mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT, ENSURE_VERIFY_APPS);
+    }
+
+    public void testProfileGlobalRestrictionsEnforced() {
+        assertRestriction(ENSURE_VERIFY_APPS, true);
+    }
+
+    public void testProfileGlobalRestrictionsNotEnforced() {
+        assertRestriction(ENSURE_VERIFY_APPS, false);
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
index 9acb94e..51a8fd3 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
@@ -69,6 +69,15 @@
             android:taskAffinity="com.android.cts.deviceowner.LockTaskTest.IntentReceivingActivity"
             />
 
+        <activity
+            android:name=".SetPolicyActivity"
+            android:launchMode="singleTop">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+
         <activity android:name="com.android.compatibility.common.util.devicepolicy.provisioning.StartProvisioningActivity"/>
 
     </application>
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BackupServiceEnabledTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BackupServiceEnabledTest.java
new file mode 100644
index 0000000..fbf1ec7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BackupServiceEnabledTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.deviceowner;
+
+public class BackupServiceEnabledTest extends BaseDeviceOwnerTest {
+
+    /**
+     * Test: Test enabling backup service. This test should be executed after installing a device
+     * owner so that we check that backup service is not enabled by default.
+     * This test will keep backup service disabled after its execution.
+     */
+    public void testEnablingAndDisablingBackupService() {
+        assertFalse(mDevicePolicyManager.isBackupServiceEnabled(getWho()));
+        mDevicePolicyManager.setBackupServiceEnabled(getWho(), true);
+        assertTrue(mDevicePolicyManager.isBackupServiceEnabled(getWho()));
+        mDevicePolicyManager.setBackupServiceEnabled(getWho(), false);
+        assertFalse(mDevicePolicyManager.isBackupServiceEnabled(getWho()));
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java
new file mode 100644
index 0000000..028bf2ea
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java
@@ -0,0 +1,82 @@
+/*
+ * 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.deviceowner;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.Log;
+
+/**
+ * Simple activity that adds or clears a user restriction depending on the value of the extras.
+ */
+public class SetPolicyActivity extends Activity {
+
+    private static final String TAG = SetPolicyActivity.class.getName();
+
+    private static final String EXTRA_RESTRICTION_KEY = "extra-restriction-key";
+    private static final String EXTRA_COMMAND = "extra-command";
+
+    private static final String ADD_RESTRICTION_COMMAND = "add-restriction";
+    private static final String CLEAR_RESTRICTION_COMMAND = "clear-restriction";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        handleIntent(getIntent());
+    }
+
+    // Overriding this method in case another intent is sent to this activity before finish()
+    @Override
+    public void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        handleIntent(intent);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        // Calling finish() here because doing it in onCreate(), onStart() or onResume() makes
+        // "adb shell am start" timeout if using the -W option.
+        finish();
+    }
+
+    private void handleIntent(Intent intent) {
+        DevicePolicyManager dpm = (DevicePolicyManager)
+                getSystemService(Context.DEVICE_POLICY_SERVICE);
+        String command = intent.getStringExtra(EXTRA_COMMAND);
+        Log.i(TAG, "Command: \"" + command);
+        ComponentName admin = BaseDeviceOwnerTest.getWho();
+        if (ADD_RESTRICTION_COMMAND.equals(command)) {
+            String restrictionKey = intent.getStringExtra(EXTRA_RESTRICTION_KEY);
+            dpm.addUserRestriction(admin, restrictionKey);
+            Log.i(TAG, "Added user restriction " + restrictionKey
+                    + " for user " + Process.myUserHandle());
+        } else if (CLEAR_RESTRICTION_COMMAND.equals(command)) {
+            String restrictionKey = intent.getStringExtra(EXTRA_RESTRICTION_KEY);
+            dpm.clearUserRestriction(admin, restrictionKey);
+            Log.i(TAG, "Cleared user restriction " + restrictionKey
+                    + " for user " + Process.myUserHandle());
+        } else {
+            Log.e(TAG, "Invalid command: " + command);
+        }
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiSetHttpProxyTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiSetHttpProxyTest.java
new file mode 100644
index 0000000..bd651f2
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiSetHttpProxyTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.deviceowner;
+
+import android.content.pm.PackageManager;
+
+import com.android.compatibility.common.util.WifiConfigCreator;
+
+/**
+ * Tests that DeviceOwner can add WifiConfigurations containing a HttpProxy
+ */
+public class WifiSetHttpProxyTest extends BaseDeviceOwnerTest {
+
+    private static final String TAG = "WifiSetHttpProxyTest";
+    private static final String TEST_PAC_URL = "http://www.example.com/proxy.pac";
+    private static final String TEST_SSID = "SomeProxyApSsid";
+    private static final int FAILURE_NETWORK_ID = -1;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    /**
+     * Test WifiManager.addNetwork() succeeds for a DeviceOwner adding a WifiConfiguraiton
+     * containing a HttpProxy.
+     * 2. Creates a new WifiConfiguration with ssid TEST_SSID
+     * 3. Adds a PAC proxy file URL to the WifiConfiguraiton
+     * 4. Adds the WifiConfiguration via WifiManager.addNetwork(), expects success
+     * 5. Verifies the added WifiConfiguration has the same proxy
+     */
+    public void testSetHttpProxy() throws Exception {
+        PackageManager packageManager = getContext().getPackageManager();
+        if (!packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        WifiConfigCreator configCreator = new WifiConfigCreator(getContext());
+        String retreievedPacProxyUrl = configCreator.addHttpProxyNetworkVerifyAndRemove(
+                TEST_SSID, TEST_PAC_URL);
+        assertEquals(TEST_PAC_URL, retreievedPacProxyUrl);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java b/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java
index 35c16ea..e4af64c 100644
--- a/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java
+++ b/hostsidetests/devicepolicy/app/LauncherTests/src/com/android/cts/launchertests/LauncherAppsTests.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.LauncherApps;
 import android.content.ServiceConnection;
@@ -120,6 +121,12 @@
             assertTrue(activity.getUser().equals(mUser));
         }
         assertTrue(foundSimpleApp);
+
+        // Also make sure getApplicationInfo works too.
+        final ApplicationInfo ai =
+                mLauncherApps.getApplicationInfo(SIMPLE_APP_PACKAGE, /* flags= */ 0, mUser);
+        assertEquals(SIMPLE_APP_PACKAGE, ai.packageName);
+        assertEquals(mUser, UserHandle.getUserHandleForUid(ai.uid));
     }
 
     public void testPackageAddedCallbackForUser() throws Throwable {
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index e5786dd..90ed617 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -44,6 +44,15 @@
             </intent-filter>
         </receiver>
         <receiver
+                android:name="com.android.cts.managedprofile.ProvisioningTest$ProvisioningAdminReceiver"
+                android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                    android:resource="@xml/device_admin" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+        <receiver
             android:name="com.android.cts.managedprofile.PrimaryUserDeviceAdmin"
             android:permission="android.permission.BIND_DEVICE_ADMIN">
             <meta-data android:name="android.app.device_admin"
@@ -112,6 +121,7 @@
             <meta-data android:name="android.accounts.AccountAuthenticator"
                        android:resource="@xml/authenticator" />
         </service>
+        <activity android:name="com.android.compatibility.common.util.devicepolicy.provisioning.StartProvisioningActivity"/>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ProvisioningTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ProvisioningTest.java
new file mode 100644
index 0000000..b31851a
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ProvisioningTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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 android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_SKIP_ENCRYPTION;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.PersistableBundle;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.util.Log;
+
+import com.android.compatibility.common.util.devicepolicy.provisioning.SilentProvisioningTestManager;
+import org.junit.Before;
+import org.junit.Test;
+
+@SmallTest
+public class ProvisioningTest {
+    private static final String TAG = ProvisioningTest.class.getSimpleName();
+
+    private static final String ADMIN_EXTRAS_BUNDLE_FILENAME = "admin_extras_bundle.txt";
+    private static final PersistableBundle ADMIN_EXTRAS_BUNDLE = new PersistableBundle();
+    private static final String ADMIN_EXTRAS_BUNDLE_KEY_1 = "KEY_1";
+    private static final String ADMIN_EXTRAS_BUNDLE_VALUE_1 = "VALUE_1";
+    static {
+        ADMIN_EXTRAS_BUNDLE.putString(ADMIN_EXTRAS_BUNDLE_KEY_1, ADMIN_EXTRAS_BUNDLE_VALUE_1);
+    }
+
+    private static final ComponentName ADMIN_RECEIVER_COMPONENT = new ComponentName(
+            ProvisioningAdminReceiver.class.getPackage().getName(),
+            ProvisioningAdminReceiver.class.getName());
+
+    public static class ProvisioningAdminReceiver extends DeviceAdminReceiver {
+        @Override
+        public void onProfileProvisioningComplete(Context context, Intent intent) {
+            super.onProfileProvisioningComplete(context, intent);
+            // Enabled profile
+            getManager(context).setProfileName(ADMIN_RECEIVER_COMPONENT, "Managed Profile");
+            getManager(context).setProfileEnabled(ADMIN_RECEIVER_COMPONENT);
+            Log.i(TAG, "onProfileProvisioningComplete");
+
+            saveBundle(context, intent.getParcelableExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE));
+        }
+    }
+
+    private Context mContext;
+    private DevicePolicyManager mDpm;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mDpm = mContext.getSystemService(DevicePolicyManager.class);
+    }
+
+    @Test
+    public void testIsManagedProfile() {
+        assertTrue(mDpm.isManagedProfile(ADMIN_RECEIVER_COMPONENT));
+        Log.i(TAG, "managed profile app: " + ADMIN_RECEIVER_COMPONENT.getPackageName());
+    }
+
+    @Test
+    public void testProvisionManagedProfile() throws InterruptedException {
+        provisionManagedProfile();
+    }
+
+    @Test
+    public void testVerifyAdminExtraBundle() {
+        PersistableBundle bundle = loadBundle(mContext);
+        assertNotNull(bundle);
+        assertEquals(ADMIN_EXTRAS_BUNDLE_VALUE_1, bundle.getString(ADMIN_EXTRAS_BUNDLE_KEY_1));
+    }
+
+    private void provisionManagedProfile() throws InterruptedException {
+        Intent intent = new Intent(ACTION_PROVISION_MANAGED_PROFILE)
+                .putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, ADMIN_RECEIVER_COMPONENT)
+                .putExtra(EXTRA_PROVISIONING_SKIP_ENCRYPTION, true)
+                .putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, ADMIN_EXTRAS_BUNDLE);
+        SilentProvisioningTestManager provisioningManager =
+                new SilentProvisioningTestManager(mContext);
+        assertTrue(provisioningManager.startProvisioningAndWait(intent));
+        Log.i(TAG, "managed profile provisioning successful");
+    }
+
+    private static void saveBundle(Context context, PersistableBundle bundle) {
+        if (bundle == null) {
+            Log.e(TAG, "null saveBundle");
+            return;
+        }
+
+        getAdminExtraSharedPreferences(context).edit()
+                .putString(ADMIN_EXTRAS_BUNDLE_KEY_1, bundle.getString(ADMIN_EXTRAS_BUNDLE_KEY_1))
+                .commit();
+    }
+
+    private static PersistableBundle loadBundle(Context context) {
+        SharedPreferences pref = getAdminExtraSharedPreferences(context);
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putString(ADMIN_EXTRAS_BUNDLE_KEY_1,
+                pref.getString(ADMIN_EXTRAS_BUNDLE_KEY_1, null));
+        return bundle;
+    }
+
+    private static SharedPreferences getAdminExtraSharedPreferences(Context context) {
+        return context.getSharedPreferences(ADMIN_EXTRAS_BUNDLE_FILENAME, 0);
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/PackageInstaller/Android.mk b/hostsidetests/devicepolicy/app/PackageInstaller/Android.mk
index 5f2a64e..3c0a2a1 100644
--- a/hostsidetests/devicepolicy/app/PackageInstaller/Android.mk
+++ b/hostsidetests/devicepolicy/app/PackageInstaller/Android.mk
@@ -28,7 +28,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctstestrunner ub-uiautomator
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
 
 # tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/BasePackageInstallTest.java b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/BasePackageInstallTest.java
index f994e9e..33d4427 100644
--- a/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/BasePackageInstallTest.java
+++ b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/BasePackageInstallTest.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
+import android.os.Process;
 import android.support.test.uiautomator.UiDevice;
 import android.test.InstrumentationTestCase;
 
@@ -195,4 +196,8 @@
             return false;
         }
     }
+
+    protected int getInstallReason(String packageName) {
+        return mPackageManager.getInstallReason(packageName, Process.myUserHandle());
+    }
 }
diff --git a/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/InstallReasonTest.java b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/InstallReasonTest.java
new file mode 100644
index 0000000..d6cf39b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/InstallReasonTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.packageinstaller;
+
+import android.content.pm.PackageManager;
+
+/**
+ * This class tests that the install reason is correctly recorded for packages.
+ */
+public class InstallReasonTest extends BasePackageInstallTest {
+    public void testInstallReason() throws Exception {
+        // Verify that since the Device Owner was sideloaded, its install reason is unknown.
+        assertEquals(PackageManager.INSTALL_REASON_UNKNOWN, getInstallReason(PACKAGE_NAME));
+
+        // Verify that when the Device Owner installs another package, its install reason is
+        // recorded as enterprise policy.
+        assertInstallPackage();
+        assertEquals(PackageManager.INSTALL_REASON_POLICY, getInstallReason(TEST_APP_PKG));
+        tryUninstallPackage();
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminHostSideTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminHostSideTest.java
index c5e022b..591a5be 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminHostSideTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDeviceAdminHostSideTest.java
@@ -27,47 +27,24 @@
  */
 public abstract class BaseDeviceAdminHostSideTest extends BaseDevicePolicyTest {
 
-    private static final String ADMIN_RECEIVER_TEST_CLASS = "BaseDeviceAdminTest$AdminReceiver";
-
-    private static final String UNPROTECTED_ADMIN_RECEIVER_TEST_CLASS =
-            "DeviceAdminReceiverWithNoProtection";
-
     protected int mUserId;
 
-    /** returns "com.android.cts.deviceadmin" */
-    protected final String getDeviceAdminJavaPackage() {
-        return "com.android.cts.deviceadmin";
-    }
-
-    /** e.g. 23, 24, etc. */
     protected abstract int getTargetApiVersion();
 
-    /** e.g. CtsDeviceAdminApp24.apk */
     protected final String getDeviceAdminApkFileName() {
-        return "CtsDeviceAdminApp" + getTargetApiVersion() + ".apk";
+        return DeviceAdminHelper.getDeviceAdminApkFileName(getTargetApiVersion());
     }
 
-    /** e.g. "com.android.cts.deviceadmin24" */
     protected final String getDeviceAdminApkPackage() {
-        return getDeviceAdminJavaPackage() + getTargetApiVersion();
+        return DeviceAdminHelper.getDeviceAdminApkPackage(getTargetApiVersion());
     }
 
-    /**
-     * e.g.
-     * "com.android.cts.deviceadmin24/com.android.cts.deviceadmin.BaseDeviceAdminTest$AdminReceiver"
-     */
     protected final String getAdminReceiverComponent() {
-        return getDeviceAdminApkPackage() + "/" + getDeviceAdminJavaPackage() + "." +
-                ADMIN_RECEIVER_TEST_CLASS;
+        return DeviceAdminHelper.getAdminReceiverComponent(getTargetApiVersion());
     }
 
-    /**
-     * e.g.
-     * "com.android.cts.deviceadmin24/com.android.cts.deviceadmin.DeviceAdminReceiverWithNoProtection"
-     */
     protected final String getUnprotectedAdminReceiverComponent() {
-        return getDeviceAdminApkPackage() + "/" + getDeviceAdminJavaPackage() + "." +
-                UNPROTECTED_ADMIN_RECEIVER_TEST_CLASS;
+        return DeviceAdminHelper.getUnprotectedAdminReceiverComponent(getTargetApiVersion());
     }
 
     @Override
@@ -85,8 +62,7 @@
     @Override
     protected void tearDown() throws Exception {
         if (mHasFeature) {
-            assertTrue("Failed to remove admin",
-                    removeAdmin(getAdminReceiverComponent(), mUserId));
+            assertTrue("Failed to remove admin", removeAdmin(getAdminReceiverComponent(), mUserId));
             getDevice().uninstallPackage(getDeviceAdminApkPackage());
         }
 
@@ -96,7 +72,7 @@
     protected void runTests(@Nonnull String apk, @Nonnull String className,
             @Nullable String method) throws DeviceNotAvailableException {
         runDeviceTestsAsUser(apk,
-                getDeviceAdminJavaPackage() + "." + className, method, mUserId);
+                DeviceAdminHelper.getDeviceAdminJavaPackage() + "." + className, method, mUserId);
     }
 
     protected void runTests(@Nonnull String apk, @Nonnull String className)
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index d2b8d25..d9eb2e6 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -34,6 +34,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -228,13 +229,20 @@
     }
 
     protected void removeTestUsers() throws Exception {
-        for (int userId : listUsers()) {
-            if (!mFixedUsers.contains(userId)) {
-                removeUser(userId);
-            }
+        for (int userId : getUsersCreatedByTests()) {
+            removeUser(userId);
         }
     }
 
+    /**
+     * Returns the users that have been created since running this class' setUp() method.
+     */
+    protected List<Integer> getUsersCreatedByTests() throws Exception {
+        List<Integer> result = listUsers();
+        result.removeAll(mFixedUsers);
+        return result;
+    }
+
     /** Removes any packages that were installed during the test. */
     protected void removeTestPackages() throws Exception {
         for (String packageName : getDevice().getUninstallablePackageNames()) {
@@ -645,4 +653,71 @@
         }
         fail(failureMessage);
     }
+
+    /**
+     * Sets a user restriction via SetPolicyActivity.
+     * <p>IMPORTANT: The package that contains SetPolicyActivity must have been installed prior to
+     * calling this method.
+     * @param key user restriction key
+     * @param value true if we should set the restriction, false if we should clear it
+     * @param userId userId to set/clear the user restriction on
+     * @param packageName package where SetPolicyActivity is installed
+     * @return The output of the command
+     * @throws DeviceNotAvailableException
+     */
+    protected String changeUserRestriction(String key, boolean value, int userId,
+            String packageName) throws DeviceNotAvailableException {
+        return changePolicy(getUserRestrictionCommand(value),
+                " --es extra-restriction-key " + key, userId, packageName);
+    }
+
+    /**
+     * Same as {@link #changeUserRestriction(String, boolean, int, String)} but asserts that it
+     * succeeds.
+     */
+    protected void changeUserRestrictionOrFail(String key, boolean value, int userId,
+            String packageName) throws DeviceNotAvailableException {
+        changePolicyOrFail(getUserRestrictionCommand(value), " --es extra-restriction-key " + key,
+                userId, packageName);
+    }
+
+    /**
+     * Sets some policy via SetPolicyActivity.
+     * <p>IMPORTANT: The package that contains SetPolicyActivity must have been installed prior to
+     * calling this method.
+     * @param command command to pass to SetPolicyActivity
+     * @param extras extras to pass to SetPolicyActivity
+     * @param userId the userId where we invoke SetPolicyActivity
+     * @param packageName where SetPolicyActivity is installed
+     * @return The output of the command
+     * @throws DeviceNotAvailableException
+     */
+    protected String changePolicy(String command, String extras, int userId, String packageName)
+            throws DeviceNotAvailableException {
+        String adbCommand = "am start -W --user " + userId
+                + " -c android.intent.category.DEFAULT "
+                + " --es extra-command " + command
+                + " " + extras
+                + " " + packageName + "/.SetPolicyActivity";
+        String commandOutput = getDevice().executeShellCommand(adbCommand);
+        CLog.d("Output for command " + adbCommand + ": " + commandOutput);
+        return commandOutput;
+    }
+
+    /**
+     * Same as {@link #changePolicy(String, String, int, String)} but asserts that it succeeds.
+     */
+    protected void changePolicyOrFail(String command, String extras, int userId,
+            String packageName) throws DeviceNotAvailableException {
+        String commandOutput = changePolicy(command, extras, userId, packageName);
+        assertTrue("Command was expected to succeed " + commandOutput,
+                commandOutput.contains("Status: ok"));
+    }
+
+    private String getUserRestrictionCommand(boolean setRestriction) {
+        if (setRestriction) {
+            return "add-restriction";
+        }
+        return "clear-restriction";
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
index bb1811f..e690a41 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
@@ -170,4 +170,30 @@
             getDevice().uninstallPackage(DEVICE_OWNER_PKG);
         }
     }
+
+    public void testInstallReason() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+        final File apk = buildHelper.getTestFile(TEST_APP_APK);
+        try {
+            // Install the test and prepare the test apk.
+            installAppAsUser(PACKAGE_INSTALLER_APK, mPrimaryUserId);
+            assertTrue(setDeviceOwner(PACKAGE_INSTALLER_ADMIN_COMPONENT, mPrimaryUserId,
+                    /*expectFailure*/ false));
+
+            getDevice().uninstallPackage(TEST_APP_PKG);
+            assertTrue(getDevice().pushFile(apk, TEST_APP_LOCATION + apk.getName()));
+            runDeviceTestsAsUser(PACKAGE_INSTALLER_PKG,
+                    PACKAGE_INSTALLER_PKG + ".InstallReasonTest", mPrimaryUserId);
+        } finally {
+            assertTrue("Failed to remove device owner.",
+                    removeAdmin(PACKAGE_INSTALLER_ADMIN_COMPONENT, mPrimaryUserId));
+            final String command = "rm " + TEST_APP_LOCATION + apk.getName();
+            final String commandOutput = getDevice().executeShellCommand(command);
+            getDevice().uninstallPackage(TEST_APP_PKG);
+            getDevice().uninstallPackage(PACKAGE_INSTALLER_PKG);
+        }
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminHelper.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminHelper.java
new file mode 100644
index 0000000..4955c42
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAdminHelper.java
@@ -0,0 +1,57 @@
+/*
+ * 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.devicepolicy;
+
+public class DeviceAdminHelper {
+
+    private static final String ADMIN_RECEIVER_TEST_CLASS = "BaseDeviceAdminTest$AdminReceiver";
+
+    private static final String UNPROTECTED_ADMIN_RECEIVER_TEST_CLASS =
+            "DeviceAdminReceiverWithNoProtection";
+
+    /** returns "com.android.cts.deviceadmin" */
+    static String getDeviceAdminJavaPackage() {
+        return "com.android.cts.deviceadmin";
+    }
+
+    /** e.g. CtsDeviceAdminApp24.apk */
+    static String getDeviceAdminApkFileName(int targetApiVersion) {
+        return "CtsDeviceAdminApp" + targetApiVersion + ".apk";
+    }
+
+    /** e.g. "com.android.cts.deviceadmin24" */
+    static String getDeviceAdminApkPackage(int targetApiVersion) {
+        return getDeviceAdminJavaPackage() + targetApiVersion;
+    }
+
+    /**
+     * e.g.
+     * "com.android.cts.deviceadmin24/com.android.cts.deviceadmin.BaseDeviceAdminTest$AdminReceiver"
+     */
+    static String getAdminReceiverComponent(int targetApiVersion) {
+        return getDeviceAdminApkPackage(targetApiVersion) + "/" + getDeviceAdminJavaPackage() + "."
+                + ADMIN_RECEIVER_TEST_CLASS;
+    }
+
+    /**
+     * e.g.
+     * "com.android.cts.deviceadmin24/com.android.cts.deviceadmin.DeviceAdminReceiverWithNoProtection"
+     */
+     static String getUnprotectedAdminReceiverComponent(int targetApiVersion) {
+        return getDeviceAdminApkPackage(targetApiVersion) + "/" + getDeviceAdminJavaPackage()
+                + "." + UNPROTECTED_ADMIN_RECEIVER_TEST_CLASS;
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index a6e8e5f..c2ee3f7 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -83,8 +83,6 @@
     private static final String VPN_APP_PKG = "com.android.cts.vpnfirewall";
     private static final String VPN_APP_APK = "CtsVpnFirewallApp.apk";
 
-    private static final String COMMAND_ADD_USER_RESTRICTION = "add-restriction";
-    private static final String COMMAND_CLEAR_USER_RESTRICTION = "clear-restriction";
     private static final String COMMAND_BLOCK_ACCOUNT_TYPE = "block-accounttype";
     private static final String COMMAND_UNBLOCK_ACCOUNT_TYPE = "unblock-accounttype";
 
@@ -365,13 +363,11 @@
 
         installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
         try {
-            changeUserRestrictionForUser(DISALLOW_MODIFY_ACCOUNTS, COMMAND_ADD_USER_RESTRICTION,
-                    mUserId);
+            changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, true, mUserId);
             executeAccountTest("testAddAccount_blocked");
         } finally {
             // Ensure we clear the user restriction
-            changeUserRestrictionForUser(DISALLOW_MODIFY_ACCOUNTS, COMMAND_CLEAR_USER_RESTRICTION,
-                    mUserId);
+            changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, false, mUserId);
         }
         executeAccountTest("testAddAccount_allowed");
     }
@@ -383,13 +379,11 @@
 
         installAppAsUser(ACCOUNT_MANAGEMENT_APK, mUserId);
         try {
-            changeUserRestrictionForUser(DISALLOW_MODIFY_ACCOUNTS, COMMAND_ADD_USER_RESTRICTION,
-                    mUserId);
+            changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, true, mUserId);
             executeAccountTest("testRemoveAccount_blocked");
         } finally {
             // Ensure we clear the user restriction
-            changeUserRestrictionForUser(DISALLOW_MODIFY_ACCOUNTS, COMMAND_CLEAR_USER_RESTRICTION,
-                    mUserId);
+            changeUserRestrictionOrFail(DISALLOW_MODIFY_ACCOUNTS, false, mUserId);
         }
         executeAccountTest("testRemoveAccount_allowed");
     }
@@ -461,13 +455,11 @@
 
         installAppAsUser(CUSTOMIZATION_APP_APK, mUserId);
         try {
-            changeUserRestrictionForUser(DISALLOW_SET_WALLPAPER, COMMAND_ADD_USER_RESTRICTION,
-                    mUserId);
+            changeUserRestrictionOrFail(DISALLOW_SET_WALLPAPER, true, mUserId);
             runDeviceTestsAsUser(CUSTOMIZATION_APP_PKG, ".CustomizationTest",
                 "testSetWallpaper_disallowed", mUserId);
         } finally {
-            changeUserRestrictionForUser(DISALLOW_SET_WALLPAPER, COMMAND_CLEAR_USER_RESTRICTION,
-                    mUserId);
+            changeUserRestrictionOrFail(DISALLOW_SET_WALLPAPER, false, mUserId);
         }
     }
 
@@ -516,14 +508,12 @@
 
             // Add restrictions and test if we can install the apk.
             getDevice().uninstallPackage(TEST_APP_PKG);
-            changeUserRestrictionForUser(DISALLOW_INSTALL_UNKNOWN_SOURCES,
-                    COMMAND_ADD_USER_RESTRICTION, mUserId);
+            changeUserRestrictionOrFail(DISALLOW_INSTALL_UNKNOWN_SOURCES, true, mUserId);
             runDeviceTestsAsUser(PACKAGE_INSTALLER_PKG, ".ManualPackageInstallTest",
                     "testManualInstallBlocked", mUserId);
 
             // Clear restrictions and test if we can install the apk.
-            changeUserRestrictionForUser(DISALLOW_INSTALL_UNKNOWN_SOURCES,
-                    COMMAND_CLEAR_USER_RESTRICTION, mUserId);
+            changeUserRestrictionOrFail(DISALLOW_INSTALL_UNKNOWN_SOURCES, false, mUserId);
 
             // Enable Unknown sources in Settings.
             unknownSourceSetting =
@@ -605,12 +595,10 @@
         }
         final int userId = createUser();
         try {
-            changeUserRestrictionForUser(DISALLOW_REMOVE_USER, COMMAND_ADD_USER_RESTRICTION,
-                    mUserId);
+            changeUserRestrictionOrFail(DISALLOW_REMOVE_USER, true, mUserId);
             assertFalse(getDevice().removeUser(userId));
         } finally {
-            changeUserRestrictionForUser(DISALLOW_REMOVE_USER, COMMAND_CLEAR_USER_RESTRICTION,
-                    mUserId);
+            changeUserRestrictionOrFail(DISALLOW_REMOVE_USER, false, mUserId);
             assertTrue(getDevice().removeUser(userId));
         }
     }
@@ -672,34 +660,26 @@
                 ".ApplicationRestrictionsManagerTest", testName, mUserId);
     }
 
-    private void changeUserRestrictionForUser(String key, String command, int userId)
+    private void changeUserRestrictionOrFail(String key, boolean value, int userId)
             throws DeviceNotAvailableException {
-        changePolicy(command, "--es extra-restriction-key " + key, userId);
+        changeUserRestrictionOrFail(key, value, userId, DEVICE_ADMIN_PKG);
     }
 
     private void changeAccountManagement(String command, String accountType, int userId)
             throws DeviceNotAvailableException {
-        changePolicy(command, "--es extra-account-type " + accountType, userId);
+        changePolicyOrFail(command, "--es extra-account-type " + accountType, userId);
     }
 
     private void changeApplicationRestrictionsManagingPackage(String packageName)
             throws DeviceNotAvailableException {
         String packageNameExtra = (packageName != null)
                 ? "--es extra-package-name " + packageName : "";
-        changePolicy("set-app-restrictions-manager", packageNameExtra, mUserId);
+        changePolicyOrFail("set-app-restrictions-manager", packageNameExtra, mUserId);
     }
 
-    private void changePolicy(String command, String extras, int userId)
+    private void changePolicyOrFail(String command, String extras, int userId)
             throws DeviceNotAvailableException {
-        String adbCommand = "am start -W --user " + userId
-                + " -c android.intent.category.DEFAULT "
-                + " --es extra-command " + command
-                + " " + extras
-                + " " + DEVICE_ADMIN_PKG + "/.SetPolicyActivity";
-        String commandOutput = getDevice().executeShellCommand(adbCommand);
-        CLog.d("Output for command " + adbCommand + ": " + commandOutput);
-        assertTrue("Command was expected to succeed " + commandOutput,
-                commandOutput.contains("Status: ok"));
+        changePolicyOrFail(command, extras, userId, DEVICE_ADMIN_PKG);
     }
 
     /**
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerPlusManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerPlusManagedProfileTest.java
index 76c1f21..c37b2e2 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerPlusManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerPlusManagedProfileTest.java
@@ -16,6 +16,8 @@
 
 package com.android.cts.devicepolicy;
 
+import java.util.List;
+
 /**
  * Tests for having both device owner and profile owner. Device owner is setup for you in
  * {@link #setUp()} and it is always the {@link #COMP_DPC_PKG}. You are required to call
@@ -388,6 +390,45 @@
         assertUserGetsRemoved(mProfileUserId);
     }
 
+    public void testCannotBindToSecondaryUser() throws Exception {
+        if (!mHasFeature || !canCreateAdditionalUsers(1)) {
+            return;
+        }
+        runDeviceTestsAsUser(
+                COMP_DPC_PKG,
+                MANAGEMENT_TEST,
+                "testCreateSecondaryUser",
+                mPrimaryUserId);
+        List<Integer> newUsers = getUsersCreatedByTests();
+        assertEquals(1, newUsers.size());
+        int secondaryUserId = newUsers.get(0);
+        getDevice().startUser(secondaryUserId);
+
+        // Set the same affiliation ids on both users.
+        runDeviceTestsAsUser(
+                COMP_DPC_PKG,
+                AFFILIATION_TEST,
+                "testSetAffiliationId1",
+                mPrimaryUserId);
+        runDeviceTestsAsUser(
+                COMP_DPC_PKG,
+                AFFILIATION_TEST,
+                "testSetAffiliationId1",
+                secondaryUserId);
+
+        // But check that we still can't bind to the other user.
+        runDeviceTestsAsUser(
+                COMP_DPC_PKG,
+                MANAGEMENT_TEST,
+                "testNoBindDeviceAdminTargetUsers",
+                mPrimaryUserId);
+        runDeviceTestsAsUser(
+                COMP_DPC_PKG,
+                MANAGEMENT_TEST,
+                "testNoBindDeviceAdminTargetUsers",
+                secondaryUserId);
+    }
+
     protected void setupManagedProfile(String apkName, String packageName,
             String adminReceiverClassName) throws Exception {
         // Temporary disable the DISALLOW_ADD_MANAGED_PROFILE, so that we can create profile
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 8be8f38..676f455 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -16,7 +16,10 @@
 
 package com.android.cts.devicepolicy;
 
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -217,23 +220,11 @@
             return;
         }
 
-        ArrayList<Integer> originalUsers = listUsers();
         executeDeviceTestMethod(".CreateAndManageUserTest", "testCreateAndManageEphemeralUser");
 
-        ArrayList<Integer> newUsers = listUsers();
-
-        // Check that exactly one new user was created.
-        assertEquals(
-                "One user should have been created", originalUsers.size() + 1, newUsers.size());
-
-        // Get the id of the newly created user.
-        int newUserId = -1;
-        for (int userId : newUsers) {
-            if (!originalUsers.contains(userId)) {
-                newUserId = userId;
-                break;
-            }
-        }
+        List<Integer> newUsers = getUsersCreatedByTests();
+        assertEquals(1, newUsers.size());
+        int newUserId = newUsers.get(0);
 
         // Get the flags of the new user and check the user is ephemeral.
         int flags = getUserFlags(newUserId);
@@ -389,6 +380,16 @@
         }
     }
 
+    /**
+     * Execute WifiSetHttpProxyTest as device owner.
+     */
+    public void testWifiSetHttpProxyTest() throws Exception {
+        final boolean hasWifi = hasDeviceFeature("android.hardware.wifi");
+        if (hasWifi && mHasFeature) {
+            executeDeviceOwnerTest("WifiSetHttpProxyTest");
+        }
+    }
+
     public void testCannotSetDeviceOwnerAgain() throws Exception {
         if (!mHasFeature) {
             return;
@@ -463,6 +464,35 @@
         executeDeviceOwnerTest("DeviceOwnerProvisioningTest");
     }
 
+    public void testDisallowFactoryReset() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        int adminVersion = 24;
+        changeUserRestrictionOrFail("no_factory_reset", true, mPrimaryUserId,
+                DEVICE_OWNER_PKG);
+        try {
+            installAppAsUser(DeviceAdminHelper.getDeviceAdminApkFileName(adminVersion),
+                    mPrimaryUserId);
+            setDeviceAdmin(DeviceAdminHelper.getAdminReceiverComponent(adminVersion),
+                    mPrimaryUserId);
+            runDeviceTestsAsUser(
+                    DeviceAdminHelper.getDeviceAdminApkPackage(adminVersion),
+                    DeviceAdminHelper.getDeviceAdminJavaPackage() + ".WipeDataTest",
+                    "testWipeDataThrowsSecurityException", mPrimaryUserId);
+        } finally {
+            removeAdmin(DeviceAdminHelper.getAdminReceiverComponent(adminVersion), mPrimaryUserId);
+            getDevice().uninstallPackage(DeviceAdminHelper.getDeviceAdminApkPackage(adminVersion));
+        }
+    }
+
+    public void testBackupServiceEnabling() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        executeDeviceOwnerTest("BackupServiceEnabledTest");
+    }
+
     private void executeDeviceOwnerTest(String testClassName) throws Exception {
         if (!mHasFeature) {
             return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileProvisioningTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileProvisioningTest.java
new file mode 100644
index 0000000..08a35d6
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileProvisioningTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.devicepolicy;
+
+public class ManagedProfileProvisioningTest extends BaseDevicePolicyTest {
+    private static final String MANAGED_PROFILE_PKG = "com.android.cts.managedprofile";
+    private static final String MANAGED_PROFILE_APK = "CtsManagedProfileApp.apk";
+
+    private int mProfileUserId;
+    private int mParentUserId;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // We need multi user to be supported in order to create a profile of the user owner.
+        mHasFeature = mHasFeature && hasDeviceFeature(
+                "android.software.managed_users");
+
+        if (mHasFeature) {
+            removeTestUsers();
+            mParentUserId = mPrimaryUserId;
+            installAppAsUser(MANAGED_PROFILE_APK, mParentUserId);
+
+            runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ProvisioningTest",
+                    "testProvisionManagedProfile", mParentUserId);
+
+            mProfileUserId = getFirstManagedProfileUserId();
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHasFeature) {
+            removeUser(mProfileUserId);
+            getDevice().uninstallPackage(MANAGED_PROFILE_PKG);
+        }
+        super.tearDown();
+    }
+
+    public void testManagedProfileProvisioning() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ProvisioningTest",
+                "testIsManagedProfile", mProfileUserId);
+    }
+
+    public void testEXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+
+        runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ProvisioningTest",
+                "testVerifyAdminExtraBundle", mProfileUserId);
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 5f5b319..1ec9c0ab 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -71,7 +71,6 @@
     private static final String FEATURE_TELEPHONY = "android.hardware.telephony";
     private static final String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice";
 
-    private static final String ADD_RESTRICTION_COMMAND = "add-restriction";
 
     private static final long TIMEOUT_USER_LOCKED_MILLIS = TimeUnit.SECONDS.toMillis(15);
 
@@ -244,8 +243,7 @@
         // managed profile
         assertAppLinkResult("testTwoReceivers");
 
-        changeUserRestrictionForUser("allow_parent_profile_app_linking", ADD_RESTRICTION_COMMAND,
-                mProfileUserId);
+        changeUserRestrictionOrFail("allow_parent_profile_app_linking", true, mProfileUserId);
         // Now we should also have one receiver in the primary user, so three receivers in total.
         assertAppLinkResult("testThreeReceivers");
 
@@ -300,8 +298,7 @@
 
         // We now set allow_parent_profile_app_linking, and hence we should have the app handler
         // in parent user if it is enabled.
-        changeUserRestrictionForUser("allow_parent_profile_app_linking", ADD_RESTRICTION_COMMAND,
-                mProfileUserId);
+        changeUserRestrictionOrFail("allow_parent_profile_app_linking", true, mProfileUserId);
 
         disableComponentOrPackage(mParentUserId, APP_HANDLER_COMPONENT);
         disableComponentOrPackage(mProfileUserId, APP_HANDLER_COMPONENT);
@@ -431,15 +428,13 @@
         }
         String restriction = "no_debugging_features";  // UserManager.DISALLOW_DEBUGGING_FEATURES
 
-        String addRestrictionCommandOutput =
-                changeUserRestrictionForUser(restriction, ADD_RESTRICTION_COMMAND, mProfileUserId);
-        assertTrue("Command was expected to succeed " + addRestrictionCommandOutput,
-                addRestrictionCommandOutput.contains("Status: ok"));
+        changeUserRestrictionOrFail(restriction, true, mProfileUserId);
+
 
         // This should now fail, as the shell is not available to start activities under a different
         // user once the restriction is in place.
-        addRestrictionCommandOutput =
-                changeUserRestrictionForUser(restriction, ADD_RESTRICTION_COMMAND, mProfileUserId);
+        String addRestrictionCommandOutput =
+                changeUserRestriction(restriction, true, mProfileUserId);
         assertTrue(
                 "Expected SecurityException when starting the activity "
                         + addRestrictionCommandOutput,
@@ -640,13 +635,8 @@
         runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
                 "testNfcShareEnabled", mParentUserId);
 
-        String restriction = "no_outgoing_beam";  // UserManager.DISALLOW_OUTGOING_BEAM
-        String command = "add-restriction";
-
-        String addRestrictionCommandOutput =
-                changeUserRestrictionForUser(restriction, command, mProfileUserId);
-        assertTrue("Command was expected to succeed " + addRestrictionCommandOutput,
-                addRestrictionCommandOutput.contains("Status: ok"));
+        changeUserRestrictionOrFail("no_outgoing_beam" /* UserManager.DISALLOW_OUTGOING_BEAM */,
+                true, mProfileUserId);
 
         runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
                 "testNfcShareDisabled", mProfileUserId);
@@ -840,17 +830,14 @@
                 + getDevice().executeShellCommand(command));
     }
 
-    private String changeUserRestrictionForUser(String key, String command, int userId)
+    private void changeUserRestrictionOrFail(String key, boolean value, int userId)
             throws DeviceNotAvailableException {
-        String adbCommand = "am start -W --user " + userId
-                + " -c android.intent.category.DEFAULT "
-                + " --es extra-command " + command
-                + " --es extra-restriction-key " + key
-                + " " + MANAGED_PROFILE_PKG + "/.SetPolicyActivity";
-        // Don't log output because sometimes used expecting failures.
-        CLog.d("Running command " + adbCommand);
-        String commandOutput = getDevice().executeShellCommand(adbCommand);
-        return commandOutput;
+        changeUserRestrictionOrFail(key, value, userId, MANAGED_PROFILE_PKG);
+    }
+
+    private String changeUserRestriction(String key, boolean value, int userId)
+            throws DeviceNotAvailableException {
+        return changeUserRestriction(key, value, userId, MANAGED_PROFILE_PKG);
     }
 
     private String changeCrossProfileWidgetForUser(String packageName, String command, int userId)
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
index 0c2f575..e8c6c57 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
@@ -26,6 +26,17 @@
     private static final String ADMIN_RECEIVER_TEST_CLASS
             = ".BaseDeviceAdminTest$BasicAdminReceiver";
 
+    private static final String GLOBAL_RESTRICTIONS_TEST_CLASS =
+            "userrestrictions.ProfileGlobalRestrictionsTest";
+    private static final String SET_GLOBAL_RESTRICTIONS_TEST =
+            "testSetProfileGlobalRestrictions";
+    private static final String CLEAR_GLOBAL_RESTRICTIONS_TEST =
+            "testClearProfileGlobalRestrictions";
+    private static final String ENSURE_GLOBAL_RESTRICTIONS_TEST =
+            "testProfileGlobalRestrictionsEnforced";
+    private static final String ENSURE_NO_GLOBAL_RESTRICTIONS_TEST =
+            "testProfileGlobalRestrictionsNotEnforced";
+
     private boolean mRemoveOwnerInTearDown;
     private int mDeviceOwnerUserId;
 
@@ -69,11 +80,7 @@
         if (!mHasFeature) {
             return;
         }
-        installAppAsUser(DEVICE_ADMIN_APK, mDeviceOwnerUserId);
-        assertTrue("Failed to set device owner",
-                setDeviceOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
-                        mDeviceOwnerUserId, /*expectFailure*/ false));
-        mRemoveOwnerInTearDown = true;
+        setDo();
 
         runTests("userrestrictions.DeviceOwnerUserRestrictionsTest",
                 "testDefaultRestrictions", mDeviceOwnerUserId);
@@ -90,11 +97,7 @@
             return;
         }
 
-        installAppAsUser(DEVICE_ADMIN_APK, mDeviceOwnerUserId);
-        assertTrue("Failed to set profile owner",
-                setProfileOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
-                        mDeviceOwnerUserId, /* expectFailure */ false));
-        mRemoveOwnerInTearDown = true;
+        setPoAsUser(mDeviceOwnerUserId);
 
         runTests("userrestrictions.PrimaryProfileOwnerUserRestrictionsTest",
                 "testDefaultRestrictions", mDeviceOwnerUserId);
@@ -107,11 +110,7 @@
             return;
         }
         final int secondaryUserId = createUser();
-
-        installAppAsUser(DEVICE_ADMIN_APK, secondaryUserId);
-        assertTrue("Failed to set profile owner",
-                setProfileOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
-                        secondaryUserId, /* expectFailure */ false));
+        setPoAsUser(secondaryUserId);
 
         runTests("userrestrictions.SecondaryProfileOwnerUserRestrictionsTest",
                 "testDefaultRestrictions", secondaryUserId);
@@ -126,20 +125,11 @@
         if (!mHasFeature || !mSupportsMultiUser) {
             return;
         }
-        // Set DO
-        installAppAsUser(DEVICE_ADMIN_APK, mDeviceOwnerUserId);
-        assertTrue("Failed to set device owner",
-                setDeviceOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
-                        mDeviceOwnerUserId, /*expectFailure*/ false));
-        mRemoveOwnerInTearDown = true;
+        setDo();
 
         // Create another user and set PO.
         final int secondaryUserId = createUser();
-
-        installAppAsUser(DEVICE_ADMIN_APK, secondaryUserId);
-        assertTrue("Failed to set profile owner",
-                setProfileOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
-                        secondaryUserId, /* expectFailure */ false));
+        setPoAsUser(secondaryUserId);
 
         // Let DO set all restrictions.
         runTests("userrestrictions.DeviceOwnerUserRestrictionsTest",
@@ -177,20 +167,12 @@
             // Can't set PO on user-0 in this mode.
             return;
         }
-        // Set DO on user 0
-        installAppAsUser(DEVICE_ADMIN_APK, mDeviceOwnerUserId);
-        assertTrue("Failed to set profile owner",
-                setProfileOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
-                        mDeviceOwnerUserId, /* expectFailure */ false));
-        mRemoveOwnerInTearDown = true;
+        // Set PO on user 0
+        setPoAsUser(mDeviceOwnerUserId);
 
         // Create another user and set PO.
         final int secondaryUserId = createUser();
-
-        installAppAsUser(DEVICE_ADMIN_APK, secondaryUserId);
-        assertTrue("Failed to set profile owner",
-                setProfileOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
-                        secondaryUserId, /* expectFailure */ false));
+        setPoAsUser(secondaryUserId);
 
         // Let user-0 PO sets all restrictions.
         runTests("userrestrictions.PrimaryProfileOwnerUserRestrictionsTest",
@@ -200,4 +182,100 @@
         runTests("userrestrictions.SecondaryProfileOwnerUserRestrictionsTest",
                 "testDefaultRestrictionsOnly", secondaryUserId);
     }
+
+    /**
+     * DO sets profile global restrictions (only ENSURE_VERIFY_APPS), should affect all
+     * users (not a particularly special case but to be sure).
+     */
+    public void testUserRestrictions_profileGlobalRestrictionsAsDo() throws Exception {
+        if (!mHasFeature || !mSupportsMultiUser) {
+            return;
+        }
+        setDo();
+
+        // Create another user with PO.
+        final int secondaryUserId = createUser();
+        setPoAsUser(secondaryUserId);
+
+        final int[] usersToCheck = {mDeviceOwnerUserId, secondaryUserId};
+
+        // Do sets the restriction.
+        setAndCheckProfileGlobalRestriction(mDeviceOwnerUserId, usersToCheck);
+    }
+
+    /**
+     * Managed profile owner sets profile global restrictions (only ENSURE_VERIFY_APPS), should
+     * affect all users.
+     */
+    public void testUserRestrictions_ProfileGlobalRestrictionsAsPo() throws Exception {
+        if (!mHasFeature || !mSupportsMultiUser) {
+            return;
+        }
+        // Set PO on user 0
+        setPoAsUser(mDeviceOwnerUserId);
+
+        // Create another user with PO.
+        final int secondaryUserId = createManagedProfile(mDeviceOwnerUserId /* parentUserId */);
+        setPoAsUser(secondaryUserId);
+
+        final int[] usersToCheck = {mDeviceOwnerUserId, secondaryUserId};
+
+        // Check the case when primary user's PO sets the restriction.
+        setAndCheckProfileGlobalRestriction(mDeviceOwnerUserId, usersToCheck);
+
+        // Check the case when managed profile owner sets the restriction.
+        setAndCheckProfileGlobalRestriction(secondaryUserId, usersToCheck);
+    }
+
+    /** Installs admin package and makes it a profile owner for a given user. */
+    private void setPoAsUser(int userId) throws Exception {
+        installAppAsUser(DEVICE_ADMIN_APK, userId);
+        assertTrue("Failed to set profile owner",
+                setProfileOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
+                        userId, /* expectFailure */ false));
+        // If PO is not in primary user, it will be removed with the user.
+        if (userId == mDeviceOwnerUserId) {
+            mRemoveOwnerInTearDown = true;
+        }
+    }
+
+    /** Installs admin package and makes it a device owner. */
+    private void setDo() throws Exception {
+        installAppAsUser(DEVICE_ADMIN_APK, mDeviceOwnerUserId);
+        assertTrue("Failed to set device owner",
+                setDeviceOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
+                        mDeviceOwnerUserId, /*expectFailure*/ false));
+        mRemoveOwnerInTearDown = true;
+    }
+
+    /**
+     * Sets user restriction and checks that it applies to all users.
+     * @param enforcingUserId user who should set/clear the restriction, should be either
+     *        primary or secondary user id and should have device or profile owner active.
+     * @param usersToCheck users that should have this restriction enforced.
+     */
+    private void setAndCheckProfileGlobalRestriction(int enforcingUserId, int usersToCheck[])
+            throws Exception {
+        // Always try to clear the restriction to avoid undesirable side effects.
+        try {
+            // Set the restriction.
+            runGlobalRestrictionsTest(SET_GLOBAL_RESTRICTIONS_TEST, enforcingUserId);
+            // Check that the restriction is in power.
+            for (int userId : usersToCheck) {
+                runGlobalRestrictionsTest(ENSURE_GLOBAL_RESTRICTIONS_TEST, userId);
+            }
+        } finally {
+            // Clear the restriction.
+            runGlobalRestrictionsTest(CLEAR_GLOBAL_RESTRICTIONS_TEST, enforcingUserId);
+            // Check that the restriction is not in power anymore.
+            for (int userId : usersToCheck) {
+                runGlobalRestrictionsTest(ENSURE_NO_GLOBAL_RESTRICTIONS_TEST, userId);
+            }
+        }
+    }
+
+    /** Convenience method to run global user restrictions tests. */
+    private void runGlobalRestrictionsTest(String testMethodName, int userId) throws Exception {
+        runTests(GLOBAL_RESTRICTIONS_TEST_CLASS, testMethodName, userId);
+    }
 }
diff --git a/hostsidetests/incident/apps/Android.mk b/hostsidetests/incident/apps/Android.mk
new file mode 100644
index 0000000..4a74e80
--- /dev/null
+++ b/hostsidetests/incident/apps/Android.mk
@@ -0,0 +1,20 @@
+# 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)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/incident/apps/netstatsapp/Android.mk b/hostsidetests/incident/apps/netstatsapp/Android.mk
new file mode 100644
index 0000000..682ec73
--- /dev/null
+++ b/hostsidetests/incident/apps/netstatsapp/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsNetStatsApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner \
+    compatibility-device-util \
+    android-support-v4
+
+LOCAL_SDK_VERSION := test_current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/incident/apps/netstatsapp/AndroidManifest.xml b/hostsidetests/incident/apps/netstatsapp/AndroidManifest.xml
new file mode 100644
index 0000000..b9d4d17
--- /dev/null
+++ b/hostsidetests/incident/apps/netstatsapp/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.server.cts.netstats" >
+
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.server.cts.netstats" />
+</manifest>
diff --git a/hostsidetests/incident/apps/netstatsapp/src/com/android/server/cts/netstats/NetstatsDeviceTest.java b/hostsidetests/incident/apps/netstatsapp/src/com/android/server/cts/netstats/NetstatsDeviceTest.java
new file mode 100644
index 0000000..075a393
--- /dev/null
+++ b/hostsidetests/incident/apps/netstatsapp/src/com/android/server/cts/netstats/NetstatsDeviceTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.cts.netstats;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+/**
+ * Used by NetstatsIncidentTest.  Makes some network requests so "dumpsys netstats" will have
+ * something to show.
+ */
+@RunWith(AndroidJUnit4.class)
+public class NetstatsDeviceTest {
+    private static final String TAG = "NetstatsDeviceTest";
+
+    @Test
+    public void testDoNetwork() throws Exception {
+        Log.i(TAG, "Making network requests...");
+
+        final URL url = new URL("http://www.android.com/");
+        final HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+        try {
+            final int status = urlConnection.getResponseCode();
+
+            Log.i(TAG, "Response code from " + url + ": " + status);
+
+            // Doesn't matter what response code we got.  We touched the network, which is enough.
+        } finally {
+            urlConnection.disconnect();
+        }
+    }
+}
diff --git a/hostsidetests/incident/src/com/android/server/cts/DiskStatsProtoTest.java b/hostsidetests/incident/src/com/android/server/cts/DiskStatsProtoTest.java
new file mode 100644
index 0000000..19a6a89
--- /dev/null
+++ b/hostsidetests/incident/src/com/android/server/cts/DiskStatsProtoTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.server.cts;
+
+import android.service.diskstats.DiskStatsFreeSpaceProto;
+import android.service.diskstats.DiskStatsServiceDumpProto;
+
+/**
+ * Test proto dump of diskstats
+ */
+public class DiskStatsProtoTest extends ProtoDumpTestCase {
+    /**
+     * Test that diskstats dump is reasonable
+     *
+     * @throws Exception
+     */
+    public void testDump() throws Exception {
+        final DiskStatsServiceDumpProto dump = getDump(DiskStatsServiceDumpProto.parser(),
+                "dumpsys diskstats --proto");
+
+        // At least one partition listed
+        assertTrue(dump.getPartitionsFreeSpaceCount() > 0);
+        // Test latency
+        boolean testError = dump.getHasTestError();
+        if (testError) {
+            assertNotNull(dump.getErrorMessage());
+        } else {
+            assertTrue(dump.getWrite512BLatencyMillis() < 100); // Less than 100ms
+        }
+        DiskStatsServiceDumpProto.EncryptionType encryptionType = dump.getEncryption();
+        if ("file".equals(getDevice().getProperty("ro.crypto.type"))) {
+            assertEquals(DiskStatsServiceDumpProto.EncryptionType.ENCRYPTION_FILE_BASED,
+                    encryptionType);
+        }
+    }
+}
diff --git a/hostsidetests/incident/src/com/android/server/cts/NetstatsIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/NetstatsIncidentTest.java
new file mode 100644
index 0000000..7ca4a5a
--- /dev/null
+++ b/hostsidetests/incident/src/com/android/server/cts/NetstatsIncidentTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.server.cts;
+
+import android.service.NetworkStatsServiceDumpProto;
+
+/**
+ * Test for "dumpsys netstats --proto"
+ * Usage:
+
+  cts-tradefed run cts --skip-device-info --skip-preconditions \
+      --skip-system-status-check \
+       com.android.compatibility.common.tradefed.targetprep.NetworkConnectivityChecker \
+       -a armeabi-v7a -m CtsIncidentHostTestCases -t com.android.server.cts.NetstatsIncidentTest
+
+ */
+public class NetstatsIncidentTest extends ProtoDumpTestCase {
+    private static final String DEVICE_SIDE_TEST_APK = "CtsNetStatsApp.apk";
+    private static final String DEVICE_SIDE_TEST_PACKAGE = "com.android.server.cts.netstats";
+
+    @Override
+    protected void tearDown() throws Exception {
+        getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
+
+        super.tearDown();
+    }
+
+    /**
+     * Parse the output of "dumpsys netstats --proto" and make sure all the values are probable.
+     */
+    public void testSanityCheck() throws Exception {
+        installPackage(DEVICE_SIDE_TEST_APK, /* grantPermissions= */ true);
+
+        // Run the device side test which makes some network requests.
+        runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, null, null);
+
+        // Also does ping for more network activity.
+        getDevice().executeShellCommand("ping -c 8 -i 0 8.8.8.8");
+
+        // Force refresh the output.
+        getDevice().executeShellCommand("dumpsys netstats --poll");
+
+        final NetworkStatsServiceDumpProto dump = getDump(NetworkStatsServiceDumpProto.parser(),
+                "dumpsys netstats --proto");
+
+        // TODO Actually check the output.
+    }
+}
diff --git a/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java b/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java
index 4bd9c60..0ec59c2 100644
--- a/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java
+++ b/hostsidetests/incident/src/com/android/server/cts/ProtoDumpTestCase.java
@@ -16,17 +16,47 @@
 
 package com.android.server.cts;
 
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.CollectingByteOutputReceiver;
-import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.CollectingTestListener;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
 import com.google.protobuf.InvalidProtocolBufferException;
 import com.google.protobuf.Message;
 import com.google.protobuf.Parser;
 
-import java.util.Scanner;
+import java.io.FileNotFoundException;
+import java.util.Map;
 
-public class ProtoDumpTestCase extends DeviceTestCase {
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public class ProtoDumpTestCase extends DeviceTestCase implements IBuildReceiver {
+
+    protected IBuildInfo mCtsBuild;
+
+    private static final String TEST_RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertNotNull(mCtsBuild);
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = buildInfo;
+    }
 
     /**
      * Call onto the device with an adb shell command and get the results of
@@ -46,4 +76,69 @@
         getDevice().executeShellCommand(command, receiver);
         return parser.parseFrom(receiver.getOutput());
     }
+
+    /**
+     * Install a device side test package.
+     *
+     * @param appFileName Apk file name, such as "CtsNetStatsApp.apk".
+     * @param grantPermissions whether to give runtime permissions.
+     */
+    protected void installPackage(String appFileName, boolean grantPermissions)
+            throws FileNotFoundException, DeviceNotAvailableException {
+        CLog.d("Installing app " + appFileName);
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+        final String result = getDevice().installPackage(
+                buildHelper.getTestFile(appFileName), true, grantPermissions);
+        assertNull("Failed to install " + appFileName + ": " + result, result);
+    }
+
+    /**
+     * Run a device side test.
+     *
+     * @param pkgName Test package name, such as "com.android.server.cts.netstats".
+     * @param testClassName Test class name; either a fully qualified name, or "." + a class name.
+     * @param testMethodName Test method name.
+     * @throws DeviceNotAvailableException
+     */
+    protected void runDeviceTests(@Nonnull String pkgName,
+            @Nullable String testClassName, @Nullable String testMethodName)
+            throws DeviceNotAvailableException {
+        if (testClassName != null && testClassName.startsWith(".")) {
+            testClassName = pkgName + testClassName;
+        }
+
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
+                pkgName, TEST_RUNNER, getDevice().getIDevice());
+        if (testClassName != null && testMethodName != null) {
+            testRunner.setMethodName(testClassName, testMethodName);
+        } else if (testClassName != null) {
+            testRunner.setClassName(testClassName);
+        }
+
+        CollectingTestListener listener = new CollectingTestListener();
+        assertTrue(getDevice().runInstrumentationTests(testRunner, listener));
+
+        final TestRunResult result = listener.getCurrentRunResults();
+        if (result.isRunFailure()) {
+            throw new AssertionError("Failed to successfully run device tests for "
+                    + result.getName() + ": " + result.getRunFailureMessage());
+        }
+        if (result.getNumTests() == 0) {
+            throw new AssertionError("No tests were run on the device");
+        }
+
+        if (result.hasFailedTests()) {
+            // build a meaningful error message
+            StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
+            for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+                    result.getTestResults().entrySet()) {
+                if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+                    errorBuilder.append(resultEntry.getKey().toString());
+                    errorBuilder.append(":\n");
+                    errorBuilder.append(resultEntry.getValue().getStackTrace());
+                }
+            }
+            throw new AssertionError(errorBuilder.toString());
+        }
+    }
 }
diff --git a/hostsidetests/security/Android.mk b/hostsidetests/security/Android.mk
index 334ce7e..2704850 100644
--- a/hostsidetests/security/Android.mk
+++ b/hostsidetests/security/Android.mk
@@ -42,7 +42,7 @@
 
 selinux_general_property_contexts := $(call intermediates-dir-for,ETC,general_property_contexts)/general_property_contexts
 
-selinux_general_service_contexts := $(call intermediates-dir-for,ETC,general_service_contexts)/general_service_contexts
+selinux_plat_service_contexts := $(call intermediates-dir-for,ETC,plat_service_contexts)/plat_service_contexts
 
 LOCAL_JAVA_RESOURCE_FILES := \
     $(HOST_OUT_EXECUTABLES)/checkseapp \
@@ -51,7 +51,7 @@
     $(selinux_plat_seapp_neverallows) \
     $(selinux_general_file_contexts) \
     $(selinux_general_property_contexts) \
-    $(selinux_general_service_contexts)
+    $(selinux_plat_service_contexts)
 
 selinux_general_policy := $(call intermediates-dir-for,ETC,general_sepolicy.conf)/general_sepolicy.conf
 
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 7d386d2..b3f4ad7 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -367,12 +367,12 @@
         /* obtain service_contexts file from running device */
         deviceSvcFile = File.createTempFile("service_contexts", ".tmp");
         deviceSvcFile.deleteOnExit();
-        mDevice.pullFile("/service_contexts", deviceSvcFile);
+        mDevice.pullFile("/plat_service_contexts", deviceSvcFile);
 
         /* retrieve the AOSP service_contexts file from jar */
-        aospSvcFile = copyResourceToTempFile("/general_service_contexts");
+        aospSvcFile = copyResourceToTempFile("/plat_service_contexts");
 
-        assertFileStartsWith(aospSvcFile, deviceSvcFile);
+        assertFileEquals(aospSvcFile, deviceSvcFile);
     }
 
     /**
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
index a022625..d604daf 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
@@ -233,6 +233,33 @@
     }
 
     /**
+     * Test that move-task works when moving between displays.
+     */
+    public void testMoveTaskBetweenDisplays() throws Exception {
+        // Create new virtual display.
+        final DisplayState newDisplay = createVirtualDisplay(CUSTOM_DENSITY_DPI,
+                false /* launchInSplitScreen */);
+        mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
+        mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
+                VIRTUAL_DISPLAY_ACTIVITY);
+        mAmWmState.assertFocusedStack("Focus must remain on primary display",
+                FULLSCREEN_WORKSPACE_STACK_ID);
+
+        // Launch activity on new secondary display.
+        launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
+        mAmWmState.assertFocusedActivity("Focus must be on secondary display", TEST_ACTIVITY_NAME);
+        mAmWmState.assertNotFocusedStack("Focused stack must be on secondary display",
+                FULLSCREEN_WORKSPACE_STACK_ID);
+
+        // Launch other activity with different uid and check it is launched on primary display.
+        moveActivityToStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.waitForFocusedStack(mDevice, FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.assertFocusedActivity("Focus must be on moved activity", TEST_ACTIVITY_NAME);
+        mAmWmState.assertFocusedStack("Focus must return to primary display",
+                FULLSCREEN_WORKSPACE_STACK_ID);
+    }
+
+    /**
      * Tests launching activities on secondary display and then removing it to see if stack focus
      * is moved correctly.
      */
diff --git a/libs/deviceutillegacy/Android.mk b/libs/deviceutillegacy/Android.mk
index 3784394..f169ca8 100644
--- a/libs/deviceutillegacy/Android.mk
+++ b/libs/deviceutillegacy/Android.mk
@@ -16,7 +16,10 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    compatibility-device-util \
+    junit \
+    legacy-android-test
 
 LOCAL_SRC_FILES := \
     $(call all-java-files-under, src)
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
index a3aa96a..413ff7d 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
@@ -36,7 +36,7 @@
 public class AccessibilityNodeInfoTest extends AndroidTestCase {
 
     /** The number of properties of the {@link AccessibilityNodeInfo} class that are marshalled. */
-    private static final int NUM_MARSHALLED_PROPERTIES = 31;
+    private static final int NUM_MARSHALLED_PROPERTIES = 32;
 
     /** The number of properties that are purposely not marshalled */
     private static final int NUM_NONMARSHALLED_PROPERTIES = 1;
@@ -204,6 +204,7 @@
         info.setContentDescription("content description");
         info.setPackageName("foo.bar.baz");
         info.setText("text");
+        info.setHintText("hint");
         info.setCheckable(true);
         info.setChecked(true);
         info.setClickable(true);
@@ -250,6 +251,8 @@
         assertEquals("packageName has incorrect value", expectedInfo.getPackageName(),
                 receivedInfo.getPackageName());
         assertEquals("text has incorrect value", expectedInfo.getText(), receivedInfo.getText());
+        assertEquals("Hint text has incorrect value",
+                expectedInfo.getHintText(), receivedInfo.getHintText());
         assertSame("checkable has incorrect value", expectedInfo.isCheckable(),
                 receivedInfo.isCheckable());
         assertSame("checked has incorrect value", expectedInfo.isChecked(),
@@ -310,6 +313,7 @@
         assertNull("contentDescription not properly recycled", info.getContentDescription());
         assertNull("packageName not properly recycled", info.getPackageName());
         assertNull("text not properly recycled", info.getText());
+        assertNull("Hint text not properly recycled", info.getHintText());
         assertFalse("checkable not properly recycled", info.isCheckable());
         assertFalse("checked not properly recycled", info.isChecked());
         assertFalse("clickable not properly recycled", info.isClickable());
diff --git a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index 9697ce2..454a2ab 100644
--- a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -797,4 +797,29 @@
         }
     }
 
+    public void testSetBackupServiceEnabled_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetBackupServiceEnabled");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setBackupServiceEnabled(mComponent, false);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testIsBackupServiceEnabled_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testIsBackupServiceEnabled");
+            return;
+        }
+        try {
+            mDevicePolicyManager.isBackupServiceEnabled(mComponent);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
 }
diff --git a/tests/app/app/Android.mk b/tests/app/app/Android.mk
index 8463a56..2e4bdf0 100644
--- a/tests/app/app/Android.mk
+++ b/tests/app/app/Android.mk
@@ -25,7 +25,12 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common voip-common org.apache.http.legacy
 
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util ctstestrunner ctstestserver mockito-target-minus-junit4
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    compatibility-device-util \
+    ctstestrunner \
+    ctstestserver \
+    mockito-target-minus-junit4 \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
               src/android/app/stubs/ISecondary.aidl
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index a03edf4..086aff9 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -88,8 +88,14 @@
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:mimeType="vnd.android.cursor.dir/person" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.app.stubs.activity.INSTRUMENTATION_TEST"/>
+            </intent-filter>
         </activity>
 
+        <activity android:name="android.app.stubs.ActivityMonitorTestActivity"
+                  android:label="ActivityMonitorTestActivity" />
+
         <activity android:name="android.app.stubs.AliasActivityStub">
             <meta-data android:name="android.app.alias"
                 android:resource="@xml/alias" />
diff --git a/tests/app/app/src/android/app/stubs/ActivityMonitorTestActivity.java b/tests/app/app/src/android/app/stubs/ActivityMonitorTestActivity.java
new file mode 100644
index 0000000..a850b16
--- /dev/null
+++ b/tests/app/app/src/android/app/stubs/ActivityMonitorTestActivity.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.stubs;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+public class ActivityMonitorTestActivity extends Activity {
+    private OnActivityResultListener mListener;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (mListener != null) {
+            mListener.onActivityResult(requestCode, resultCode, data);
+        }
+    }
+
+    public void startInstrumentationTestActivity(boolean startExplicit) {
+        Intent intent;
+        if (startExplicit) {
+            intent = new Intent(this, InstrumentationTestActivity.class);
+        } else {
+            intent = new Intent(InstrumentationTestActivity.START_INTENT);
+        }
+        startActivityForResult(intent, 42);
+    }
+
+    public void setOnActivityResultListener(OnActivityResultListener listener) {
+        mListener = listener;
+    }
+
+    public interface OnActivityResultListener {
+        void onActivityResult(int requestCode, int resultCode, Intent data);
+    }
+}
\ No newline at end of file
diff --git a/tests/app/app/src/android/app/stubs/InstrumentationTestActivity.java b/tests/app/app/src/android/app/stubs/InstrumentationTestActivity.java
index 495bae2..82f7b71 100644
--- a/tests/app/app/src/android/app/stubs/InstrumentationTestActivity.java
+++ b/tests/app/app/src/android/app/stubs/InstrumentationTestActivity.java
@@ -33,6 +33,8 @@
 
 public class InstrumentationTestActivity extends Activity {
 
+    public static final String START_INTENT = "android.app.stubs.activity.INSTRUMENTATION_TEST";
+
     private boolean mOnCreateCalled;
     private boolean mOnDestroyCalled ;
     private boolean mOnNewIntentCalled;
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
index 8c04dad..07dc354 100644
--- a/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -452,6 +452,7 @@
     static final class ServiceConnectionHandler implements ServiceConnection {
         final Context mContext;
         final Intent mIntent;
+        boolean mMonitoring;
         boolean mBound;
         IBinder mService;
 
@@ -470,25 +471,21 @@
             mIntent = intent;
         }
 
-        public void bind(long timeout) {
+        public void startMonitoring() {
+            if (mMonitoring) {
+                throw new IllegalStateException("Already monitoring");
+            }
+            if (!mContext.bindService(mIntent, this, Context.BIND_WAIVE_PRIORITY)) {
+                throw new IllegalStateException("Failed to bind " + mIntent);
+            }
+            mMonitoring = true;
+            mService = null;
+        }
+
+        public void waitForConnect(long timeout) {
+            final long endTime = SystemClock.uptimeMillis() + timeout;
+
             synchronized (this) {
-                if (mBound) {
-                    throw new IllegalStateException("Already bound");
-                }
-                // Here's the trick: the first binding allows us to to see the service come
-                // up and go down but doesn't actually cause it to run or impact process management.
-                // The second binding actually brings it up.
-                if (!mContext.bindService(mIntent, this, Context.BIND_WAIVE_PRIORITY)) {
-                    throw new IllegalStateException("Failed to bind " + mIntent);
-                }
-                if (!mContext.bindService(mIntent, mMainBinding, Context.BIND_AUTO_CREATE)) {
-                    throw new IllegalStateException("Failed to bind " + mIntent);
-                }
-                mBound = true;
-                mService = null;
-
-                final long endTime = SystemClock.uptimeMillis() + timeout;
-
                 while (mService == null) {
                     final long now = SystemClock.uptimeMillis();
                     if (now >= endTime) {
@@ -502,6 +499,48 @@
             }
         }
 
+        public void waitForDisconnect(long timeout) {
+            final long endTime = SystemClock.uptimeMillis() + timeout;
+
+            synchronized (this) {
+                while (mService != null) {
+                    final long now = SystemClock.uptimeMillis();
+                    if (now >= endTime) {
+                        throw new IllegalStateException("Timed out unbinding from " + mIntent);
+                    }
+                    try {
+                        wait(endTime - now);
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+        }
+
+        public void stopMonitoring() {
+            if (!mMonitoring) {
+                throw new IllegalStateException("Not monitoring");
+            }
+            mContext.unbindService(this);
+            mMonitoring = false;
+        }
+
+        public void bind(long timeout) {
+            synchronized (this) {
+                if (mBound) {
+                    throw new IllegalStateException("Already bound");
+                }
+                // Here's the trick: the first binding allows us to to see the service come
+                // up and go down but doesn't actually cause it to run or impact process management.
+                // The second binding actually brings it up.
+                startMonitoring();
+                if (!mContext.bindService(mIntent, mMainBinding, Context.BIND_AUTO_CREATE)) {
+                    throw new IllegalStateException("Failed to bind " + mIntent);
+                }
+                mBound = true;
+                waitForConnect(timeout);
+            }
+        }
+
         public void unbind(long timeout) {
             synchronized (this) {
                 if (!mBound) {
@@ -513,20 +552,9 @@
                 mBound = false;
 
                 try {
-                    final long endTime = SystemClock.uptimeMillis() + timeout;
-
-                    while (mService != null) {
-                        final long now = SystemClock.uptimeMillis();
-                        if (now >= endTime) {
-                            throw new IllegalStateException("Timed out unbinding from " + mIntent);
-                        }
-                        try {
-                            wait(endTime - now);
-                        } catch (InterruptedException e) {
-                        }
-                    }
+                    waitForDisconnect(timeout);
                 } finally {
-                    mContext.unbindService(this);
+                    stopMonitoring();
                 }
             }
         }
@@ -642,6 +670,127 @@
         am.removeOnUidImportanceListener(uidGoneListener);
     }
 
+    public void testBackgroundCheckService() throws Exception {
+        Intent serviceIntent = new Intent();
+        Parcel data = Parcel.obtain();
+        serviceIntent.setClassName(SIMPLE_PACKAGE_NAME,
+                SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE);
+        ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, serviceIntent);
+
+        ActivityManager am = mContext.getSystemService(ActivityManager.class);
+
+        String cmd = "pm grant " + STUB_PACKAGE_NAME + " "
+                + Manifest.permission.PACKAGE_USAGE_STATS;
+        String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        /*
+        Log.d("XXXX", "Invoke: " + cmd);
+        Log.d("XXXX", "Result: " + result);
+        Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package "
+                + STUB_PACKAGE_NAME));
+        */
+
+        ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
+                SIMPLE_PACKAGE_NAME, 0);
+
+        UidImportanceListener uidForegroundListener = new UidImportanceListener(appInfo.uid);
+        am.addOnUidImportanceListener(uidForegroundListener,
+                RunningAppProcessInfo.IMPORTANCE_SERVICE);
+        UidImportanceListener uidGoneListener = new UidImportanceListener(appInfo.uid);
+        am.addOnUidImportanceListener(uidGoneListener,
+                RunningAppProcessInfo.IMPORTANCE_EMPTY);
+
+        // First kill the process to start out in a stable state.
+        conn.bind(WAIT_TIME);
+        try {
+            conn.mService.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
+        } catch (RemoteException e) {
+        }
+        conn.unbind(WAIT_TIME);
+
+        //cmd = "am kill " + STUB_PACKAGE_NAME;
+        //result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+
+        // Wait for uid's process to go away.
+        uidGoneListener.waitForValue(RunningAppProcessInfo.IMPORTANCE_GONE,
+                RunningAppProcessInfo.IMPORTANCE_GONE, WAIT_TIME);
+        assertEquals(RunningAppProcessInfo.IMPORTANCE_GONE,
+                am.getPackageImportance(SIMPLE_PACKAGE_NAME));
+
+        cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny";
+        result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+
+        // We will use this to monitor when the service is running.
+        conn.startMonitoring();
+
+        try {
+            // Try starting the service.  Should fail!
+            boolean failed = false;
+            try {
+                mContext.startService(serviceIntent);
+            } catch (IllegalStateException e) {
+                failed = true;
+            }
+            if (!failed) {
+                fail("Service was allowed to start while in the background");
+            }
+
+            // Put app on temporary whitelist to see if this allows the service start.
+            cmd = "cmd deviceidle tempwhitelist -d 2000 " + SIMPLE_PACKAGE_NAME;
+            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+
+            // Try starting the service now that the app is whitelisted...  should work!
+            mContext.startService(serviceIntent);
+            conn.waitForConnect(WAIT_TIME);
+
+            // Good, now stop the service and give enough time to get off the temp whitelist.
+            mContext.stopService(serviceIntent);
+            conn.waitForDisconnect(WAIT_TIME);
+            Thread.sleep(3000);
+
+            // We don't want to wait for the uid to actually go idle, we can force it now.
+            cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
+            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+
+            // Now that we should be off the temp whitelist, make sure we again can't start.
+            failed = false;
+            try {
+                mContext.startService(serviceIntent);
+            } catch (IllegalStateException e) {
+                failed = true;
+            }
+            if (!failed) {
+                fail("Service was allowed to start while in the background");
+            }
+
+            // Work around bug in the platform.
+            conn.stopMonitoring();
+            conn.startMonitoring();
+
+            // Now put app on whitelist, should allow service to run.
+            cmd = "cmd deviceidle whitelist +" + SIMPLE_PACKAGE_NAME;
+            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+
+            // Try starting the service now that the app is whitelisted...  should work!
+            mContext.startService(serviceIntent);
+            conn.waitForConnect(WAIT_TIME);
+
+            // Okay, bring down the service.
+            mContext.stopService(serviceIntent);
+            conn.waitForDisconnect(WAIT_TIME);
+
+        } finally {
+            conn.stopMonitoring();
+
+            cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND normal";
+            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+
+            am.removeOnUidImportanceListener(uidGoneListener);
+            am.removeOnUidImportanceListener(uidForegroundListener);
+
+            data.recycle();
+        }
+    }
+
     /**
      * Verify that the TimeTrackingAPI works properly when starting and ending an activity.
      */
diff --git a/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java b/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java
index 719f74b..8ffb136 100644
--- a/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java
+++ b/tests/app/src/android/app/cts/Instrumentation_ActivityMonitorTest.java
@@ -20,15 +20,22 @@
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
 import android.app.Instrumentation.ActivityResult;
+import android.app.stubs.ActivityMonitorTestActivity;
 import android.app.stubs.InstrumentationTestActivity;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 public class Instrumentation_ActivityMonitorTest extends InstrumentationTestCase {
+    private static final String TAG = "ActivityMonitorTest";
 
-    private static final long WAIT_TIMEOUT = 100;
+    private static final long TIMEOUT_FOR_ACTIVITY_LAUNCH_MS = 5000; // 5 sec
+    private static final long CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS = 100; // 0.1 sec
 
     /**
      * check points:
@@ -46,10 +53,9 @@
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         context.startActivity(intent);
         Activity lastActivity = am.getLastActivity();
-        final long TIMEOUT_MSEC = 5000;
-        long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
+        long timeout = System.currentTimeMillis() + TIMEOUT_FOR_ACTIVITY_LAUNCH_MS;
         while (lastActivity == null && System.currentTimeMillis() < timeout) {
-            Thread.sleep(WAIT_TIMEOUT);
+            Thread.sleep(CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS);
             lastActivity = am.getLastActivity();
         }
         Activity activity = am.waitForActivity();
@@ -59,11 +65,11 @@
         activity.finish();
         instrumentation.waitForIdleSync();
         context.startActivity(intent);
-        timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
+        timeout = System.currentTimeMillis() + TIMEOUT_FOR_ACTIVITY_LAUNCH_MS;
         activity = null;
         while (activity == null && System.currentTimeMillis() < timeout) {
-            Thread.sleep(WAIT_TIMEOUT);
-            activity = am.waitForActivityWithTimeout(WAIT_TIMEOUT);
+            Thread.sleep(CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS);
+            activity = am.waitForActivityWithTimeout(CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS);
         }
         assertNotNull(activity);
         activity.finish();
@@ -77,4 +83,232 @@
         assertSame(which, am.getFilter());
         assertFalse(am.isBlocking());
     }
+
+    /**
+     * Verifies that
+     *   - when ActivityMonitor.onMatchIntent returs non-null, then there is monitor hit.
+     *   - when ActivityMonitor.onMatchIntent returns null, then the activity start is not blocked.
+     */
+    public void testActivityMonitor_onMatchIntent() throws Exception {
+        final ActivityResult result = new ActivityResult(Activity.RESULT_OK, new Intent());
+        final Instrumentation instrumentation = getInstrumentation();
+        final Context context = instrumentation.getTargetContext();
+        final Intent intent = new Intent(context, InstrumentationTestActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        // Verify when ActivityMonitor.onMatchIntent returns non-null, then there is a monitor hit.
+        final CustomActivityMonitor cam1 = new CustomActivityMonitor(result);
+        instrumentation.addMonitor(cam1);
+        context.startActivity(intent);
+        final Activity activity1 = cam1.waitForActivityWithTimeout(
+                CHECK_INTERVAL_FOR_ACTIVITY_LAUNCH_MS * 2);
+        try {
+            assertNull("Activity should not have been started", activity1);
+            assertEquals("There should be 1 monitor hit", 1, cam1.getHits());
+        } finally {
+            instrumentation.removeMonitor(cam1);
+        }
+
+        // Verify when ActivityMonitor.onMatchIntent returns null, then activity start is not
+        // blocked and there is no monitor hit.
+        final CustomActivityMonitor cam2 = new CustomActivityMonitor(null);
+        instrumentation.addMonitor(cam2);
+        Activity activity2 = instrumentation.startActivitySync(intent);
+        try {
+            assertNotNull("Activity should not be null", activity2);
+            assertTrue("Activity returned should be of instance InstrumentationTestActivity",
+                    activity2 instanceof InstrumentationTestActivity);
+            assertTrue("InstrumentationTestActivity should have been started",
+                    ((InstrumentationTestActivity) activity2).isOnCreateCalled());
+            assertEquals("There should be no monitor hits", 0, cam2.getHits());
+        } finally {
+            activity2.finish();
+            instrumentation.removeMonitor(cam2);
+        }
+    }
+
+    /**
+     * Verifies that when ActivityMonitor.onMatchIntent returns non-null, activity start is blocked.
+     */
+    public void testActivityMonitor_onMatchIntentBlocks() throws Exception {
+        final Instrumentation instrumentation = getInstrumentation();
+        final Context context = instrumentation.getTargetContext();
+
+        // Start ActivityMonitorTestActivity
+        final Intent intent = new Intent(context, ActivityMonitorTestActivity.class);
+        ActivityMonitorTestActivity amTestActivity =
+                (ActivityMonitorTestActivity) instrumentation.startActivitySync(intent);
+
+        // Initialize and set activity monitor.
+        final int expectedResultCode = 1111;
+        final String expectedAction = "matched_using_onMatchIntent";
+        final CustomActivityMonitor cam = new CustomActivityMonitor(
+                new ActivityResult(expectedResultCode, new Intent(expectedAction)));
+        instrumentation.addMonitor(cam);
+
+        // Start InstrumentationTestActivity from ActivityMonitorTestActivity and verify
+        // it is intercepted using onMatchIntent as expected.
+        try {
+            final CountDownLatch latch = new CountDownLatch(1);
+            amTestActivity.setOnActivityResultListener(
+                    new ActivityMonitorTestActivity.OnActivityResultListener() {
+                        @Override
+                        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+                            assertEquals("Result code is not same as expected",
+                                    expectedResultCode, resultCode);
+                            assertNotNull("Data from activity result is null", data);
+                            assertEquals("Data action is not same as expected",
+                                    expectedAction, data.getAction());
+                            latch.countDown();
+                        }
+                    });
+            amTestActivity.startInstrumentationTestActivity(false);
+            if (!latch.await(TIMEOUT_FOR_ACTIVITY_LAUNCH_MS, TimeUnit.MILLISECONDS)) {
+                fail("Timed out waiting for the activity result from "
+                        + ActivityMonitorTestActivity.class.getName());
+            }
+            assertEquals("There should be 1 monitor hit", 1, cam.getHits());
+        } finally {
+            amTestActivity.finish();
+            instrumentation.removeMonitor(cam);
+        }
+    }
+
+    /**
+     * Verifies that when the activity monitor is created using by passing IntentFilter,
+     * then onMatchIntent return value is ignored.
+     */
+    public void testActivityMonitor_onMatchIntentAndIntentFilter() throws Exception {
+        final Instrumentation instrumentation = getInstrumentation();
+        final Context context = instrumentation.getTargetContext();
+
+        // Start ActivityMonitorTestActivity
+        final Intent intent = new Intent(context, ActivityMonitorTestActivity.class);
+        ActivityMonitorTestActivity amTestActivity =
+                (ActivityMonitorTestActivity) instrumentation.startActivitySync(intent);
+
+        // Initialize and set activity monitor.
+        final int expectedResultCode = 1122;
+        final String expectedAction = "matched_using_intent_filter";
+        final CustomActivityMonitor cam = new CustomActivityMonitor(
+                new IntentFilter(InstrumentationTestActivity.START_INTENT),
+                new ActivityResult(expectedResultCode, new Intent(expectedAction)),
+                true);
+        cam.setResultToReturn(new ActivityResult(1111, new Intent("matched_using_onMatchIntent")));
+        instrumentation.addMonitor(cam);
+
+        // Start explicit InstrumentationTestActivity from ActivityMonitorTestActivity and verify
+        // it is intercepted using the intentFilter as expected.
+        try {
+            final CountDownLatch latch = new CountDownLatch(1);
+            amTestActivity.setOnActivityResultListener(
+                    new ActivityMonitorTestActivity.OnActivityResultListener() {
+                        @Override
+                        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+                            assertEquals("Result code is not same as expected",
+                                    expectedResultCode, resultCode);
+                            assertNotNull("Data from activity result is null", data);
+                            assertEquals("Data action is not same as expected",
+                                    expectedAction, data.getAction());
+                            latch.countDown();
+                        }
+                    });
+            amTestActivity.startInstrumentationTestActivity(false);
+            if (!latch.await(TIMEOUT_FOR_ACTIVITY_LAUNCH_MS, TimeUnit.MILLISECONDS)) {
+                fail("Timed out waiting for the activity result from "
+                        + ActivityMonitorTestActivity.class.getName());
+            }
+            assertEquals("There should be 1 monitor hit", 1, cam.getHits());
+        } finally {
+            amTestActivity.finish();
+            instrumentation.removeMonitor(cam);
+        }
+    }
+
+    /**
+     * Verifies that when the activity monitor is created using by passing activity class,
+     * then onMatchIntent return value is ignored.
+     */
+    public void testActivityMonitor_onMatchIntentAndActivityClass() throws Exception {
+        final Instrumentation instrumentation = getInstrumentation();
+        final Context context = instrumentation.getTargetContext();
+
+        // Start ActivityMonitorTestActivity
+        final Intent intent = new Intent(context, ActivityMonitorTestActivity.class);
+        ActivityMonitorTestActivity amTestActivity =
+                (ActivityMonitorTestActivity) instrumentation.startActivitySync(intent);
+
+        // Initialize and set activity monitor.
+        final int expectedResultCode = 2244;
+        final String expectedAction = "matched_using_activity_class";
+        final CustomActivityMonitor cam = new CustomActivityMonitor(
+                InstrumentationTestActivity.class.getName(),
+                new ActivityResult(expectedResultCode, new Intent(expectedAction)),
+                true);
+        cam.setResultToReturn(new ActivityResult(2222, new Intent("matched_using_onMatchIntent")));
+        instrumentation.addMonitor(cam);
+
+        // Start implicit InstrumentationTestActivity from ActivityMonitorTestActivity and verify
+        // it is intercepted using the activity class as expected.
+        try {
+            final CountDownLatch latch = new CountDownLatch(1);
+            amTestActivity.setOnActivityResultListener(
+                    new ActivityMonitorTestActivity.OnActivityResultListener() {
+                        @Override
+                        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+                            assertEquals("Result code is not same as expected",
+                                    expectedResultCode, resultCode);
+                            assertNotNull("Data from activity result is null", data);
+                            assertEquals("Data action is not same as expected",
+                                    expectedAction, data.getAction());
+                            latch.countDown();
+                        }
+                    });
+            amTestActivity.startInstrumentationTestActivity(true);
+            if (!latch.await(TIMEOUT_FOR_ACTIVITY_LAUNCH_MS, TimeUnit.MILLISECONDS)) {
+                fail("Timed out waiting for the activity result from "
+                        + ActivityMonitorTestActivity.class.getName());
+            }
+            assertEquals("There should be 1 monitor hit", 1, cam.getHits());
+        } finally {
+            amTestActivity.finish();
+            instrumentation.removeMonitor(cam);
+        }
+    }
+
+    private class CustomActivityMonitor extends ActivityMonitor {
+        private ActivityResult mResultToReturn;
+
+        public CustomActivityMonitor(ActivityResult resultToReturn) {
+            super();
+            mResultToReturn = resultToReturn;
+        }
+
+        public CustomActivityMonitor(IntentFilter intentFilter, ActivityResult result,
+                boolean blocked) {
+            super(intentFilter, result, blocked);
+        }
+
+        public CustomActivityMonitor(String activityClass, ActivityResult result,
+                boolean blocked) {
+            super(activityClass, result, blocked);
+        }
+
+        public void setResultToReturn(ActivityResult resultToReturn) {
+            mResultToReturn = resultToReturn;
+        }
+
+        @Override
+        public ActivityResult onMatchIntent(Intent intent) {
+            final boolean implicitInstrumentationTestActivity = intent.getAction() != null &&
+                    InstrumentationTestActivity.START_INTENT.equals(intent.getAction());
+            final boolean explicitInstrumentationTestActivity = intent.getComponent() != null &&
+                    InstrumentationTestActivity.class.getName().equals(
+                            intent.getComponent().getClassName());
+            if (implicitInstrumentationTestActivity || explicitInstrumentationTestActivity) {
+                return mResultToReturn;
+            }
+            return null;
+        }
+    }
 }
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index f45e0c7..232abb8 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -28,7 +28,11 @@
 import android.service.notification.StatusBarNotification;
 import android.test.AndroidTestCase;
 import android.util.Log;
-import java.util.concurrent.CountDownLatch;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
 
 import java.util.Arrays;
 
@@ -37,10 +41,13 @@
     final boolean DEBUG = false;
 
     private NotificationManager mNotificationManager;
+    private String mId;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        // This will leave a set of channels on the device with each test run.
+        mId = UUID.randomUUID().toString();
         mNotificationManager = (NotificationManager) mContext.getSystemService(
                 Context.NOTIFICATION_SERVICE);
         // clear the deck so that our getActiveNotifications results are predictable
@@ -55,7 +62,7 @@
 
     public void testCreateChannel() throws InterruptedException {
         final NotificationChannel channel =
-                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+                new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_DEFAULT);
         channel.enableVibration(true);
         channel.setVibrationPattern(new long[] {5, 8, 2, 1});
         channel.setSound(new Uri.Builder().scheme("test").build());
@@ -77,14 +84,14 @@
 
     public void testCreateSameChannelDoesNotUpdate() throws InterruptedException {
         final NotificationChannel channel =
-                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+                new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_DEFAULT);
         try {
             mNotificationManager.createNotificationChannel(channel);
             final NotificationChannel channelDupe =
-                    new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
+                    new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_HIGH);
             mNotificationManager.createNotificationChannel(channelDupe);
             final NotificationChannel createdChannel =
-                    mNotificationManager.getNotificationChannel("id");
+                    mNotificationManager.getNotificationChannel(mId);
             compareChannels(channel, createdChannel);
         } finally {
             mNotificationManager.deleteNotificationChannel(channel.getId());
@@ -93,11 +100,11 @@
 
     public void testCreateChannelAlreadyExistsNoOp() {
         NotificationChannel channel =
-                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+                new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_DEFAULT);
         try {
             mNotificationManager.createNotificationChannel(channel);
             NotificationChannel channelDupe =
-                    new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
+                    new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_HIGH);
             mNotificationManager.createNotificationChannel(channelDupe);
             compareChannels(channel, mNotificationManager.getNotificationChannel(channel.getId()));
         } finally {
@@ -107,7 +114,7 @@
 
     public void testCreateChannelInvalidImportance() {
         NotificationChannel channel =
-                new NotificationChannel("id2", "name", NotificationManager.IMPORTANCE_UNSPECIFIED);
+                new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_UNSPECIFIED);
         try {
             mNotificationManager.createNotificationChannel(channel);
         } catch (IllegalArgumentException e) {
@@ -117,7 +124,7 @@
 
     public void testDeleteChannel() {
         NotificationChannel channel =
-                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_LOW);
         mNotificationManager.createNotificationChannel(channel);
         compareChannels(channel, mNotificationManager.getNotificationChannel(channel.getId()));
         mNotificationManager.deleteNotificationChannel(channel.getId());
@@ -135,13 +142,16 @@
 
     public void testGetChannel() {
         NotificationChannel channel1 =
-                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+                new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_DEFAULT);
         NotificationChannel channel2 =
-                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel(
+                        UUID.randomUUID().toString(), "name2", NotificationManager.IMPORTANCE_HIGH);
         NotificationChannel channel3 =
-                new NotificationChannel("id3", "name3", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel(
+                        UUID.randomUUID().toString(), "name3", NotificationManager.IMPORTANCE_LOW);
         NotificationChannel channel4 =
-                new NotificationChannel("id4", "name4", NotificationManager.IMPORTANCE_MIN);
+                new NotificationChannel(
+                        UUID.randomUUID().toString(), "name4", NotificationManager.IMPORTANCE_MIN);
         try {
             mNotificationManager.createNotificationChannel(channel1);
             mNotificationManager.createNotificationChannel(channel2);
@@ -164,6 +174,68 @@
         }
     }
 
+    public void testGetChannels() {
+        NotificationChannel channel1 =
+                new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_DEFAULT);
+        NotificationChannel channel2 =
+                new NotificationChannel(
+                        UUID.randomUUID().toString(), "name2", NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel3 =
+                new NotificationChannel(
+                        UUID.randomUUID().toString(), "name3", NotificationManager.IMPORTANCE_LOW);
+        NotificationChannel channel4 =
+                new NotificationChannel(
+                        UUID.randomUUID().toString(), "name4", NotificationManager.IMPORTANCE_MIN);
+
+        Map<String, NotificationChannel> channelMap = new HashMap<>();
+        channelMap.put(channel1.getId(), channel1);
+        channelMap.put(channel2.getId(), channel2);
+        channelMap.put(channel3.getId(), channel3);
+        channelMap.put(channel4.getId(), channel4);
+        try {
+            mNotificationManager.createNotificationChannel(channel1);
+            mNotificationManager.createNotificationChannel(channel2);
+            mNotificationManager.createNotificationChannel(channel3);
+            mNotificationManager.createNotificationChannel(channel4);
+
+            mNotificationManager.deleteNotificationChannel(channel3.getId());
+
+            List<NotificationChannel> channels = mNotificationManager.getNotificationChannels();
+            for (NotificationChannel nc : channels) {
+                if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
+                    continue;
+                }
+                assertFalse(channel3.getId().equals(nc.getId()));
+                compareChannels(channelMap.get(nc.getId()), nc);
+            }
+        } finally {
+            mNotificationManager.deleteNotificationChannel(channel1.getId());
+            mNotificationManager.deleteNotificationChannel(channel2.getId());
+            mNotificationManager.deleteNotificationChannel(channel3.getId());
+            mNotificationManager.deleteNotificationChannel(channel4.getId());
+        }
+    }
+
+    public void testRecreateDeletedChannel() {
+        NotificationChannel channel =
+                new NotificationChannel(mId, "name", NotificationManager.IMPORTANCE_DEFAULT);
+        channel.setShowBadge(true);
+        NotificationChannel newChannel = new NotificationChannel(
+                channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
+        try {
+            mNotificationManager.createNotificationChannel(channel);
+            mNotificationManager.deleteNotificationChannel(channel.getId());
+
+            mNotificationManager.createNotificationChannel(newChannel);
+
+            compareChannels(channel,
+                    mNotificationManager.getNotificationChannel(newChannel.getId()));
+
+        } finally {
+            mNotificationManager.deleteNotificationChannel(channel.getId());
+        }
+    }
+
     public void testNotify() {
         mNotificationManager.cancelAll();
 
diff --git a/tests/autofillservice/Android.mk b/tests/autofillservice/Android.mk
new file mode 100644
index 0000000..5ccc277
--- /dev/null
+++ b/tests/autofillservice/Android.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+# TODO(b/30946317): remove guava (currently needed by truth-prebuilt)
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    compatibility-device-util \
+    ctstestrunner \
+    guava \
+    truth-prebuilt \
+    ub-uiautomator
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsAutoFillServiceTestCases
+
+LOCAL_SDK_VERSION := test_current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
new file mode 100644
index 0000000..bd283c1
--- /dev/null
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.autofillservice.cts" >
+
+    <application>
+        <activity
+            android:name=".LoginActivity"
+            android:label="LoginActivity" />
+        <service
+            android:name=".InstrumentedAutoFillService"
+            android:label="InstrumentedAutoFillService"
+            android:permission="android.permission.BIND_AUTO_FILL" >
+            <intent-filter>
+                <action android:name="android.service.autofill.AutoFillService" />
+            </intent-filter>
+        </service>
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:label="CTS tests for the AutoFill Framework APIs."
+        android:targetPackage="android.autofillservice.cts" >
+    </instrumentation>
+
+</manifest>
\ No newline at end of file
diff --git a/tests/autofillservice/AndroidTest.xml b/tests/autofillservice/AndroidTest.xml
new file mode 100644
index 0000000..885537f9
--- /dev/null
+++ b/tests/autofillservice/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for AutoFill Framework CTS tests.">
+
+  <target_preparer
+    class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+    <option name="cleanup-apks" value="true" />
+    <option name="test-file-name" value="CtsAutoFillServiceTestCases.apk" />
+  </target_preparer>
+
+  <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+    <option name="package" value="android.autofillservice.cts" />
+  </test>
+
+</configuration>
diff --git a/tests/autofillservice/res/layout/login_activity.xml b/tests/autofillservice/res/layout/login_activity.xml
new file mode 100644
index 0000000..6a8957da
--- /dev/null
+++ b/tests/autofillservice/res/layout/login_activity.xml
@@ -0,0 +1,80 @@
+<?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"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Username" />
+
+        <EditText
+            android:id="@+id/username"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Password" />
+
+        <EditText
+            android:id="@+id/password"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="textPassword" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <Button
+            android:id="@+id/clear"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Clear" />
+
+        <Button
+            android:id="@+id/login"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Login" />
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/output"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
new file mode 100644
index 0000000..0b6f235
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.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 android.autofillservice.cts;
+
+import static android.autofillservice.cts.Helper.UI_TIMEOUT_SEC;
+import static android.autofillservice.cts.Helper.runShellCommand;
+import static android.provider.Settings.Secure.AUTO_FILL_SERVICE;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+
+/**
+ * Base class for all other tests.
+ */
+@RunWith(AndroidJUnit4.class)
+abstract class AutoFillServiceTestCase {
+
+    private static final String SERVICE_NAME =
+            InstrumentedAutoFillService.class.getPackage().getName()
+            + "/." + InstrumentedAutoFillService.class.getSimpleName();
+
+    protected static UiBot sUiBot;
+
+    @BeforeClass
+    public static void setUiBot() {
+        sUiBot = new UiBot(InstrumentationRegistry.getInstrumentation(), UI_TIMEOUT_SEC);
+    }
+
+    @AfterClass
+    public static void disableService() {
+        runShellCommand("settings delete secure %s", AUTO_FILL_SERVICE);
+        assertServiceDisabled();
+    }
+
+    /**
+     * Enables the {@link InstrumentedAutoFillService} for auto-fill for the default user.
+     */
+    protected void enableService() {
+        runShellCommand(
+                "settings put secure %s %s default", AUTO_FILL_SERVICE, SERVICE_NAME);
+        assertServiceEnabled();
+    }
+
+    /**
+     * Asserts that the {@link InstrumentedAutoFillService} is enabled for the default user.
+     */
+    protected static void assertServiceEnabled() {
+        assertServiceStatus(true);
+    }
+
+    /**
+     * Asserts that the {@link InstrumentedAutoFillService} is disabled for the default user.
+     */
+    protected static void assertServiceDisabled() {
+        assertServiceStatus(false);
+    }
+
+    private static void assertServiceStatus(boolean enabled) {
+        final String actual = runShellCommand("settings get secure %s", AUTO_FILL_SERVICE);
+        final String expected = enabled ? SERVICE_NAME : "null";
+        assertWithMessage("Invalid value for secure setting %s", AUTO_FILL_SERVICE)
+                .that(actual).isEqualTo(expected);
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
new file mode 100644
index 0000000..14ab6a3
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.autofillservice.cts;
+
+import android.app.assist.AssistStructure;
+import android.view.autofill.AutoFillValue;
+import android.view.autofill.Dataset;
+import android.view.autofill.FillResponse;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper class used to produce a {@link FillResponse} based on expected fields that should be
+ * present in the {@link AssistStructure}.
+ *
+ * <p>Typical usage:
+ *
+ * <pre class="prettyprint">
+ * InstrumentedAutoFillService.setFillResponse(new CannedFillResponse.Builder()
+ *               .addDataset(new CannedDataset.Builder("dataset_name")
+ *                   .setField("resource_id1", AutoFillValue.forText("value1"))
+ *                   .setField("resource_id2", AutoFillValue.forText("value2"))
+ *                   .build())
+ *               .build());
+ * </pre class="prettyprint">
+ */
+final class CannedFillResponse {
+
+    final List<CannedDataset> datasets;
+
+    private CannedFillResponse(Builder builder) {
+        datasets = builder.mDatasets;
+    }
+
+    @Override
+    public String toString() {
+        return "CannedFillResponse: [datasets=" + datasets + "]";
+    }
+
+    static class Builder {
+        private final List<CannedDataset> mDatasets = new ArrayList<>();
+
+        public Builder addDataset(CannedDataset dataset) {
+            mDatasets.add(dataset);
+            return this;
+        }
+
+        public CannedFillResponse build() {
+            return new CannedFillResponse(this);
+        }
+    }
+
+    /**
+     * Helper class used to produce a {@link Dataset} based on expected fields that should be
+     * present in the {@link AssistStructure}.
+     *
+     * <p>Typical usage:
+     *
+     * <pre class="prettyprint">
+     * InstrumentedAutoFillService.setFillResponse(new CannedFillResponse.Builder()
+     *               .addDataset(new CannedDataset.Builder("dataset_name")
+     *                   .setField("resource_id1", AutoFillValue.forText("value1"))
+     *                   .setField("resource_id2", AutoFillValue.forText("value2"))
+     *                   .build())
+     *               .build());
+     * </pre class="prettyprint">
+     */
+    static class CannedDataset {
+
+        final Map<String, AutoFillValue> fields;
+        final String name;
+
+        private CannedDataset(Builder builder) {
+            fields = builder.mFields;
+            name = builder.mName;
+        }
+
+        @Override
+        public String toString() {
+            return "CannedDataset: [name=" + name + ", fields=" + fields + "]";
+        }
+
+        static class Builder {
+            private final Map<String, AutoFillValue> mFields = new HashMap<>();
+            private final String mName;
+
+            public Builder(String name) {
+                mName = name;
+            }
+
+            /**
+             * Sets the canned value of a field based on its {@code resourceId}.
+             */
+            public Builder setField(String resourceId, AutoFillValue value) {
+                mFields.put(resourceId, value);
+                return this;
+            }
+
+            public CannedDataset build() {
+                return new CannedDataset(this);
+            }
+        }
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
new file mode 100644
index 0000000..341a921
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts;
+
+import android.support.test.InstrumentationRegistry;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+/**
+ * Helper for common funcionalities.
+ */
+final class Helper {
+
+    private static final String TAG = "AutoFillCtsHelper";
+
+    /**
+     * Timeout (in milliseconds) for expected auto-fill requests.
+     */
+    static final long FILL_TIMEOUT_MS = 2000;
+
+    /**
+     * Timeout (in seconds) for UI operations. Typically used by {@link UiBot}.
+     */
+    static final int UI_TIMEOUT_SEC = 2;
+
+    /**
+     * Runs a Shell command, returning a trimmed response.
+     */
+    static String runShellCommand(String template, Object...args) {
+        final String command = String.format(template, args);
+        Log.d(TAG, "runShellCommand(): " + command);
+        try {
+            final String result = SystemUtil
+                    .runShellCommand(InstrumentationRegistry.getInstrumentation(), command);
+            return TextUtils.isEmpty(result) ? "" : result.trim();
+        } catch (Exception e) {
+            throw new RuntimeException("Command '" + command + "' failed: ", e);
+        }
+    }
+
+    private Helper() {
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
new file mode 100644
index 0000000..2237002
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.autofillservice.cts;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.app.assist.AssistStructure;
+import android.app.assist.AssistStructure.ViewNode;
+import android.app.assist.AssistStructure.WindowNode;
+import android.autofillservice.cts.CannedFillResponse.CannedDataset;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.service.autofill.AutoFillService;
+import android.service.autofill.FillCallback;
+import android.service.autofill.SaveCallback;
+import android.util.Log;
+import android.view.autofill.AutoFillId;
+import android.view.autofill.AutoFillValue;
+import android.view.autofill.Dataset;
+import android.view.autofill.FillResponse;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Implementation of {@link AutoFillService} used in the tests.
+ */
+public class InstrumentedAutoFillService extends AutoFillService {
+
+    private static final String TAG = "InstrumentedAutoFillService";
+
+    private static final AtomicReference<CannedFillResponse> sCannedFillResponse =
+            new AtomicReference<>();
+
+    // TODO(b/33197203, b/33802548): add tests for onConnected() / onDisconnected() and/or remove
+    // overriden methods below that are only logging their calls.
+
+    @Override
+    public void onConnected() {
+        Log.v(TAG, "onConnected()");
+    }
+
+    @Override
+    public void onDisconnected() {
+        Log.v(TAG, "onDisconnected()");
+    }
+
+    @Override
+    public void onFillRequest(AssistStructure structure, Bundle data,
+            CancellationSignal cancellationSignal, FillCallback callback) {
+        final CannedFillResponse cannedResponse = sCannedFillResponse.getAndSet(null);
+        Log.v(TAG, "onFillRequest(): cannedResponse = " + cannedResponse);
+
+        if (cannedResponse == null) {
+            callback.onSuccess(null);
+            return;
+        }
+        final FillResponse.Builder responseBuilder = new FillResponse.Builder();
+        final List<CannedDataset> datasets = cannedResponse.datasets;
+
+        if (datasets.isEmpty()) {
+            callback.onSuccess(responseBuilder.build());
+            return;
+        }
+
+        assertWithMessage("multiple datasets not supported yet").that(datasets).hasSize(1);
+
+        final CannedDataset dataset = datasets.get(0);
+
+        final Map<String, AutoFillValue> fields = dataset.fields;
+        if (fields.isEmpty()) {
+            callback.onSuccess(responseBuilder.build());
+            return;
+        }
+
+        final Dataset.Builder datasetBuilder = new Dataset.Builder(dataset.name);
+
+        Log.v(TAG, "Parsing request for activity " + structure.getActivityComponent());
+        final int nodes = structure.getWindowNodeCount();
+        for (int i = 0; i < nodes; i++) {
+            final WindowNode node = structure.getWindowNodeAt(i);
+            final ViewNode view = node.getRootViewNode();
+            fill(datasetBuilder, fields, view);
+        }
+
+        final FillResponse fillResponse =
+                responseBuilder.addDataset(datasetBuilder.build()).build();
+        Log.v(TAG, "onFillRequest(): fillResponse = " + fillResponse);
+        callback.onSuccess(fillResponse);
+    }
+
+    @Override
+    public void onSaveRequest(AssistStructure structure, Bundle data,
+            CancellationSignal cancellationSignal, SaveCallback callback) {
+        Log.v(TAG, "onSaveRequest()");
+    }
+
+    /**
+     * Sets the response returned by the service in the next
+     * {@link #onFillRequest(AssistStructure, Bundle, CancellationSignal, FillCallback)} call.
+     */
+    static void setFillResponse(CannedFillResponse response) {
+        final boolean ok = sCannedFillResponse.compareAndSet(null, response);
+        if (!ok) {
+            throw new IllegalStateException("already set: " + sCannedFillResponse.get());
+        }
+    }
+
+    private void fill(Dataset.Builder builder, Map<String, AutoFillValue> fields,
+            ViewNode view) {
+        final String resourceId = view.getIdEntry();
+
+        final AutoFillValue value = fields.get(resourceId);
+        if (value != null) {
+            final AutoFillId id = view.getAutoFillId();
+            Log.d(TAG, "setting '" + resourceId + "' (" + id + ") to " + value);
+            builder.setValue(id, value);
+        }
+
+        final int childrenSize = view.getChildCount();
+        if (childrenSize > 0) {
+            for (int i = 0; i < childrenSize; i++) {
+                fill(builder, fields, view.getChildAt(i));
+            }
+        }
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivity.java
new file mode 100644
index 0000000..86a38b7
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivity.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.autofillservice.cts;
+
+import static android.autofillservice.cts.Helper.FILL_TIMEOUT_MS;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.app.Activity;
+import android.autofillservice.cts.CannedFillResponse.CannedDataset;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.autofill.AutoFillValue;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * Activity that has the following fields:
+ *
+ * <ul>
+ *   <li>Username EditText (id: username, no input-type)
+ *   <li>Password EditText (id: "username", input-type textPassword)
+ *   <li>Clear Button
+ *   <li>Login Button
+ * </ul>
+ */
+public class LoginActivity extends Activity {
+
+    private static final String TAG = "LoginActivity";
+
+    private EditText mUsernameEditText;
+    private EditText mPasswordEditText;
+    private TextView mOutput;
+    private Button mLoginButton;
+    private Button mClearButton;
+    private AutoFillExpectation mAutoFillExpectation;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.login_activity);
+
+        mLoginButton = (Button) findViewById(R.id.login);
+        mClearButton = (Button) findViewById(R.id.clear);
+        mUsernameEditText = (EditText) findViewById(R.id.username);
+        mPasswordEditText = (EditText) findViewById(R.id.password);
+        mOutput = (TextView) findViewById(R.id.output);
+
+        // TODO(b/33197203): remove login / clear button if not used by the tests (currently,
+        // they're only used for debugging)
+        mLoginButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                login();
+            }
+        });
+        mClearButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                resetFields();
+            }
+        });
+    }
+
+    /**
+     * Resets the values of the input fields.
+     */
+    private void resetFields() {
+        mUsernameEditText.setText("");
+        mPasswordEditText.setText("");
+        mOutput.setText("");
+    }
+
+    /**
+     * Emulates a login action.
+     */
+    // TODO(b/33197203): check if username / password matches and either show error message
+    // or redirect to a welcome 'user' page
+    private void login() {
+        final StringBuilder buffer = new StringBuilder();
+        buffer.append("Username:").append(mUsernameEditText.getText()).append(":\n");
+        buffer.append("Password:").append(mPasswordEditText.getText()).append(":\n");
+        final String output = buffer.toString();
+        Log.d(TAG, "login(): " + output);
+        mOutput.setText(output);
+    }
+
+    /**
+     * Sets the expectation for an auto-fill request, so it can be asserted through
+     * {@link #assertAutoFilled()} later.
+     *
+     * <p>It fills the {@code builder} dataset with the proper fields for {@code} username and
+     * {@code password}, so caller can use it to set a {@link CannedFillResponse}.
+     */
+    void expectAutoFill(CannedDataset.Builder builder, String username, String password) {
+        builder
+                .setField("username", AutoFillValue.forText(username))
+                .setField("password", AutoFillValue.forText(password));
+        mAutoFillExpectation = new AutoFillExpectation(username, password);
+        mUsernameEditText
+                .addTextChangedListener(new MyTextWatcher(mAutoFillExpectation.usernameLatch));
+        mPasswordEditText
+                .addTextChangedListener(new MyTextWatcher(mAutoFillExpectation.passwordLatch));
+    }
+
+    /**
+     * Asserts the activity was auto-filled with the values passed to
+     * {@link #expectAutoFill(android.autofillservice.cts.CannedFillResponse.CannedDataset.Builder,
+     * String, String)}.
+     */
+    void assertAutoFilled() throws Exception {
+        assertWithMessage("expectAutoFill() not called").that(mAutoFillExpectation).isNotNull();
+        assertField("username", mUsernameEditText,
+                mAutoFillExpectation.usernameLatch, mAutoFillExpectation.expectedUsername);
+        assertField("password", mPasswordEditText,
+                mAutoFillExpectation.passwordLatch, mAutoFillExpectation.expectedPassword);
+    }
+
+    /**
+     * Asserts the value of an input field, using a latch to make sure it was set.
+     */
+    private void assertField(String name, EditText field, CountDownLatch latch,
+            String expectedValue) throws Exception {
+        final boolean set = latch.await(FILL_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        assertWithMessage("Timeout (%s ms) for auto-fill of field %s", FILL_TIMEOUT_MS, name)
+                .that(set).isTrue();
+        final String actualValue = field.getText().toString();
+        assertWithMessage("Wrong auto-fill value for field %s", name).that(actualValue)
+                .isEqualTo(expectedValue);
+    }
+
+    /**
+     * Holder for the expected auto-fill values.
+     */
+    private final class AutoFillExpectation {
+        private final CountDownLatch usernameLatch = new CountDownLatch(1);
+        private final CountDownLatch passwordLatch = new CountDownLatch(1);
+        private final String expectedUsername;
+        private final String expectedPassword;
+
+        private AutoFillExpectation(String username, String password) {
+            expectedUsername = username;
+            expectedPassword = password;
+        }
+    }
+
+    private class MyTextWatcher implements TextWatcher {
+        private final CountDownLatch latch;
+
+        private MyTextWatcher(CountDownLatch latch) {
+            this.latch = latch;
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+            Log.d(TAG, "onTextChanged(): " + s);
+            latch.countDown();
+        }
+
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+        }
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
new file mode 100644
index 0000000..43ed714
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.autofillservice.cts;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import android.autofillservice.cts.CannedFillResponse.CannedDataset;
+
+@SmallTest
+public class LoginActivityTest extends AutoFillServiceTestCase {
+
+    @Rule
+    public final ActivityTestRule<LoginActivity> mActivityRule =
+        new ActivityTestRule<LoginActivity>(LoginActivity.class);
+
+    private LoginActivity mLoginActivity;
+
+    @Before
+    public void setActivity() {
+        mLoginActivity = mActivityRule.getActivity();
+    }
+
+    @Test
+    public void testAutoFillOneDataset() throws Exception {
+        enableService();
+
+        final CannedDataset.Builder dataset = new CannedDataset.Builder("The Dude");
+        mLoginActivity.expectAutoFill(dataset, "dude", "sweet");
+
+        InstrumentedAutoFillService.setFillResponse(new CannedFillResponse.Builder()
+                .addDataset(dataset.build())
+                .build());
+
+        sUiBot.triggerFillRequest();
+        sUiBot.selectDataset("The Dude");
+
+        mLoginActivity.assertAutoFilled();
+    }
+
+    /*
+     * TODO(b/33197203, b/33802548): test other scenarios
+     *
+     *  - no dataset
+     *  - multiple datasets
+     *  - response-level authentication (custom and fingerprint)
+     *  - dataset-level authentication (custom and fingerprint)
+     *
+     *  Other assertions:
+     *  - illegal state thrown on callback calls
+     *  - system server state after calls (for example, no pending callback)
+     */
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
new file mode 100644
index 0000000..9900e19
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.app.Instrumentation;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+import android.util.Log;
+
+/**
+ * Helper for UI-related needs.
+ */
+final class UiBot {
+
+    private static final String TAG = "AutoFillCtsUiBot";
+
+    private final UiDevice mDevice;
+    private final int mTimeout;
+
+    UiBot(Instrumentation instrumentation, int timeout) {
+        mDevice = UiDevice.getInstance(instrumentation);
+        mTimeout = timeout;
+    }
+
+    /**
+     * Selects an auto-fill dataset whose name should be visible in the UI.
+     */
+    void selectDataset(String name) {
+        // TODO(b/33197203): use id string when using real auto-fill bar
+        Log.v(TAG, "selectDataset(): " + name);
+
+        clickOnNotification(name.toUpperCase());
+    }
+
+    /**
+     * Triggers the auto-fill affordance UI.
+     */
+    void triggerFillRequest() {
+        Log.v(TAG, "triggerFillRequest()");
+
+        // TODO(b/33197203): use id string when using real auto-fill bar
+        clickOnNotification("AutoFill IME Emulation");
+    }
+
+    /////////////////////////////////////////////////////////////////////////////////
+    // TODO(b/33197203): temporary code using a notification to request auto-fill. //
+    // Will be removed once UX decide the right way to present it to the user.     //
+    /////////////////////////////////////////////////////////////////////////////////
+    private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
+
+    /**
+     * Clicks on a UI element.
+     *
+     * @param uiObject UI element to be clicked.
+     * @param description Elements's description used on logging statements.
+     */
+    private void click(UiObject uiObject, String description) {
+        try {
+            boolean clicked = uiObject.click();
+            // TODO: assertion below fails sometimes, even though the click succeeded,
+            // (specially when clicking the "Just Once" button), so it's currently just logged.
+            // assertTrue("could not click on object '" + description + "'", clicked);
+
+            Log.v(TAG, "onClick for " + description + ": " + clicked);
+        } catch (UiObjectNotFoundException e) {
+            throw new IllegalStateException("exception when clicking on object '" + description
+                    + "'", e);
+        }
+    }
+
+    /**
+     * Opens the system notification and clicks a given notification.
+     *
+     * @param text Notificaton's text as displayed by the UI.
+     */
+    private void clickOnNotification(String text) {
+        final UiObject notification = getNotification(text);
+        click(notification, "notification '" + text+ "'");
+    }
+
+    private UiObject getNotification(String text) {
+        final boolean opened = mDevice.openNotification();
+        Log.v(TAG, "openNotification(): " + opened);
+        final boolean gotIt = mDevice.wait(Until.hasObject(By.pkg(SYSTEMUI_PACKAGE)), mTimeout);
+        assertWithMessage("could not get system ui (%s)", SYSTEMUI_PACKAGE).that(gotIt).isTrue();
+
+        return getObject(text);
+    }
+    /**
+     * Gets an object that might not yet be available in current UI.
+     *
+     * @param text Object's text as displayed by the UI.
+     */
+    private UiObject getObject(String text) {
+        final boolean gotIt = mDevice.wait(Until.hasObject(By.text(text)), mTimeout);
+        assertWithMessage("object with text '%s') not visible yet", text).that(gotIt).isTrue();
+        return getVisibleObject(text);
+    }
+
+    /**
+     * Gets an object which is guaranteed to be present in the current UI.
+     *
+     * @param text Object's text as displayed by the UI.
+     */
+    private UiObject getVisibleObject(String text) {
+        final UiObject uiObject = mDevice.findObject(new UiSelector().text(text));
+        assertWithMessage("could not find object with '%s'", text).that(uiObject.exists()).isTrue();
+        return uiObject;
+    }
+    /////////////////////////////////////////
+    // End of temporary notification code. //
+    /////////////////////////////////////////
+}
diff --git a/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index df89297..07e810f 100644
--- a/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -714,7 +714,7 @@
      */
     public int[] getAvailableToneMapModesChecked() {
         Key<int[]> key = CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES;
-        int[] modes = getValueFromKeyNonNull(key);
+        int[] modes = mCharacteristics.get(key);
 
         if (modes == null) {
             return new int[0];
diff --git a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
index f0dac9a..b5e9cad 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
@@ -15,34 +15,27 @@
  */
 package android.fragment.cts;
 
-import static junit.framework.Assert.*;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.app.Fragment;
 import android.app.FragmentController;
 import android.app.FragmentManager;
 import android.app.FragmentManagerNonConfig;
 import android.app.Instrumentation;
-import android.os.Debug;
 import android.os.Parcelable;
-import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.Pair;
 import android.view.View;
-import android.view.ViewGroup;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -298,6 +291,7 @@
         assertPostponed(fragment2, 0);
         assertNotNull(fragment1.getView());
         assertEquals(View.VISIBLE, fragment1.getView().getVisibility());
+        assertTrue(FragmentTestUtil.isVisible(fragment1));
         assertTrue(fragment1.getView().isAttachedToWindow());
 
         fragment2.startPostponedEnterTransition();
@@ -335,7 +329,7 @@
         FragmentTestUtil.popBackStackImmediate(mActivityRule);
 
         assertNotNull(fragment1.getView());
-        assertEquals(View.VISIBLE, fragment1.getView().getVisibility());
+        assertTrue(FragmentTestUtil.isVisible(fragment1));
         assertTrue(fragment1.getView().isAttachedToWindow());
         assertTrue(fragment1.isAdded());
 
@@ -447,7 +441,8 @@
     private void assertPostponed(AnimatorFragment fragment, int expectedAnimators)
             throws InterruptedException {
         assertTrue(fragment.mOnCreateViewCalled);
-        assertEquals(View.INVISIBLE, fragment.getView().getVisibility());
+        assertEquals(View.VISIBLE, fragment.getView().getVisibility());
+        assertFalse(FragmentTestUtil.isVisible(fragment));
         assertEquals(expectedAnimators, fragment.numAnimators);
     }
 
diff --git a/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java b/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java
index b4407a0..3a69b44 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java
@@ -17,17 +17,17 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentController;
 import android.app.FragmentManagerNonConfig;
 import android.app.Instrumentation;
-import android.os.Handler;
 import android.os.Parcelable;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.util.Pair;
+import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 public class FragmentTestUtil {
     public static void waitForExecution(final ActivityTestRule<FragmentTestActivity> rule) {
@@ -160,4 +160,12 @@
         });
         return result[0];
     }
+
+    public static boolean isVisible(Fragment fragment) {
+        View view = fragment.getView();
+        AccessibilityNodeInfo accessibilityNodeInfo = view.createAccessibilityNodeInfo();
+        boolean isVisible = accessibilityNodeInfo.isVisibleToUser();
+        accessibilityNodeInfo.recycle();
+        return isVisible;
+    }
 }
diff --git a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
index 82890df..c12fb30 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
@@ -30,6 +30,7 @@
 import android.support.test.filters.MediumTest;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -899,6 +900,105 @@
         assertEquals(View.GONE, fragment2.getView().getVisibility());
     }
 
+    // Test to ensure that popping and adding a fragment properly track the fragments added
+    // and removed.
+    @Test
+    public void popAdd() throws Throwable {
+        FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
+        ViewGroup container = (ViewGroup)
+                mActivityRule.getActivity().findViewById(R.id.fragmentContainer);
+        final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
+
+        // One fragment with a view
+        final StrictViewFragment fragment1 = new StrictViewFragment();
+        fm.beginTransaction().add(R.id.fragmentContainer, fragment1).addToBackStack(null).commit();
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        FragmentTestUtil.assertChildren(container, fragment1);
+
+        final StrictViewFragment fragment2 = new StrictViewFragment();
+        final StrictViewFragment fragment3 = new StrictViewFragment();
+        mInstrumentation.runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                fm.popBackStack();
+                fm.beginTransaction()
+                        .replace(R.id.fragmentContainer, fragment2)
+                        .addToBackStack(null)
+                        .commit();
+                fm.executePendingTransactions();
+                fm.popBackStack();
+                fm.beginTransaction()
+                        .replace(R.id.fragmentContainer, fragment3)
+                        .addToBackStack(null)
+                        .commit();
+                fm.executePendingTransactions();
+            }
+        });
+        FragmentTestUtil.assertChildren(container, fragment3);
+    }
+
+    // Ensure that non-optimized transactions are executed individually rather than together.
+    // This forces references from one fragment to another that should be executed earlier
+    // to work.
+    @Test
+    public void nonOptimizeTogether() throws Throwable {
+        FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
+        ViewGroup container = (ViewGroup)
+                mActivityRule.getActivity().findViewById(R.id.fragmentContainer);
+        final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
+
+        final StrictViewFragment fragment1 = new StrictViewFragment();
+        fragment1.setLayoutId(R.layout.scene1);
+        final StrictViewFragment fragment2 = new StrictViewFragment();
+        fragment2.setLayoutId(R.layout.text_a);
+
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                fm.beginTransaction()
+                        .add(R.id.fragmentContainer, fragment1)
+                        .setAllowOptimization(false)
+                        .addToBackStack(null)
+                        .commit();
+                fm.beginTransaction()
+                        .add(R.id.squareContainer, fragment2)
+                        .setAllowOptimization(false)
+                        .addToBackStack(null)
+                        .commit();
+                fm.executePendingTransactions();
+            }
+        });
+        FragmentTestUtil.assertChildren(container, fragment1);
+        assertNotNull(findViewById(R.id.textA));
+    }
+
+    // Ensure that there is no problem if the child fragment manager is used before
+    // the View has been added.
+    @Test
+    public void childFragmentManager() throws Throwable {
+        FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
+        ViewGroup container = (ViewGroup)
+                mActivityRule.getActivity().findViewById(R.id.fragmentContainer);
+        final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
+
+        final StrictViewFragment fragment1 = new ParentFragment();
+        fragment1.setLayoutId(R.layout.double_container);
+
+        fm.beginTransaction()
+                .add(R.id.fragmentContainer, fragment1)
+                .addToBackStack(null)
+                .commit();
+
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+
+        FragmentTestUtil.assertChildren(container, fragment1);
+        ViewGroup innerContainer = (ViewGroup)
+                fragment1.getView().findViewById(R.id.fragmentContainer1);
+
+        Fragment fragment2 = fragment1.getChildFragmentManager().findFragmentByTag("inner");
+        FragmentTestUtil.assertChildren(innerContainer, fragment2);
+    }
+
     private View findViewById(int viewId) {
         return mActivityRule.getActivity().findViewById(viewId);
     }
@@ -921,4 +1021,26 @@
             view.setVisibility(visibility);
             super.onViewCreated(view, savedInstanceState);
         }
-    }}
+    }
+
+    public static class ParentFragment extends StrictViewFragment {
+        public ParentFragment() {
+            setLayoutId(R.layout.double_container);
+        }
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View view = super.onCreateView(inflater, container, savedInstanceState);
+            final StrictViewFragment fragment2 = new StrictViewFragment();
+            fragment2.setLayoutId(R.layout.text_a);
+
+            getChildFragmentManager().beginTransaction()
+                    .add(R.id.fragmentContainer1, fragment2, "inner")
+                    .addToBackStack(null)
+                    .commit();
+            getChildFragmentManager().executePendingTransactions();
+            return view;
+        }
+    }
+}
diff --git a/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java b/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java
index 29a723b..e94cb5a 100644
--- a/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java
+++ b/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java
@@ -27,7 +27,6 @@
 import android.app.FragmentManagerNonConfig;
 import android.app.Instrumentation;
 import android.os.Bundle;
-import android.os.Debug;
 import android.os.Parcelable;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
@@ -629,7 +628,7 @@
         assertFalse(fragment.isAdded());
         assertNull(fragment.getView());
         assertNotNull(mBeginningFragment.getView());
-        assertEquals(View.VISIBLE, mBeginningFragment.getView().getVisibility());
+        assertTrue(FragmentTestUtil.isVisible(mBeginningFragment));
         assertTrue(mBeginningFragment.getView().isAttachedToWindow());
     }
 
@@ -687,7 +686,9 @@
         assertTrue(fromFragment.getView().isAttachedToWindow());
         assertTrue(toFragment.getView().isAttachedToWindow());
         assertEquals(View.VISIBLE, fromFragment.getView().getVisibility());
-        assertEquals(View.INVISIBLE, toFragment.getView().getVisibility());
+        assertTrue(FragmentTestUtil.isVisible(fromFragment));
+        assertEquals(View.VISIBLE, toFragment.getView().getVisibility());
+        assertFalse(FragmentTestUtil.isVisible(toFragment));
         assureNoTransition(fromFragment);
         assureNoTransition(toFragment);
         assertTrue(fromFragment.isResumed());
diff --git a/tests/jank/Android.mk b/tests/jank/Android.mk
index fe3644a..0d4f533 100644
--- a/tests/jank/Android.mk
+++ b/tests/jank/Android.mk
@@ -27,6 +27,12 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util ctstestrunner ub-uiautomator ub-janktesthelper
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    ub-janktesthelper \
+    junit \
+    legacy-android-test
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/jdwp/runner/device-side/Android.mk b/tests/jdwp/runner/device-side/Android.mk
index c30cf88..871fc39 100644
--- a/tests/jdwp/runner/device-side/Android.mk
+++ b/tests/jdwp/runner/device-side/Android.mk
@@ -24,7 +24,7 @@
 
 LOCAL_PROGUARD_ENABLED := disabled
 
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util junit
 
 # don't include these packages in any target
 LOCAL_MODULE_TAGS := optional
diff --git a/tests/leanbackjank/Android.mk b/tests/leanbackjank/Android.mk
index b24b1da..25fd9a0 100644
--- a/tests/leanbackjank/Android.mk
+++ b/tests/leanbackjank/Android.mk
@@ -35,7 +35,8 @@
     ub-janktesthelper \
     android-support-v17-leanback \
     android-support-v7-recyclerview \
-    android-support-v4
+    android-support-v4 \
+    legacy-android-test
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/libcore/luni/Android.mk b/tests/libcore/luni/Android.mk
index f722f5fe..2d65cd3 100644
--- a/tests/libcore/luni/Android.mk
+++ b/tests/libcore/luni/Android.mk
@@ -47,8 +47,6 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_JAVA_RESOURCE_DIRS := resources
-
 LOCAL_JAVA_RESOURCE_FILES := \
     libcore/expectations/brokentests.txt \
     libcore/expectations/icebox.txt \
diff --git a/tests/netlegacy22.api/Android.mk b/tests/netlegacy22.api/Android.mk
index 93f848b..3fca098 100644
--- a/tests/netlegacy22.api/Android.mk
+++ b/tests/netlegacy22.api/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_SDK_VERSION := 22
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner legacy-android-test
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/netlegacy22.permission/Android.mk b/tests/netlegacy22.permission/Android.mk
index 8f6f12e..d21cd676 100644
--- a/tests/netlegacy22.permission/Android.mk
+++ b/tests/netlegacy22.permission/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_SDK_VERSION := 22
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner legacy-android-test
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/tests/app.usage/Android.mk b/tests/tests/app.usage/Android.mk
index 0303dbd..f8bab5b 100644
--- a/tests/tests/app.usage/Android.mk
+++ b/tests/tests/app.usage/Android.mk
@@ -26,7 +26,11 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner \
+    android-support-test \
+    junit \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/app/Android.mk b/tests/tests/app/Android.mk
index cf76aa0b..d710ce8 100644
--- a/tests/tests/app/Android.mk
+++ b/tests/tests/app/Android.mk
@@ -26,7 +26,11 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner \
+    android-support-test \
+    junit \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/appwidget/Android.mk b/tests/tests/appwidget/Android.mk
index d97d7d7..077461d 100644
--- a/tests/tests/appwidget/Android.mk
+++ b/tests/tests/appwidget/Android.mk
@@ -20,13 +20,20 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+    $(call all-java-files-under, common/src)
 
 LOCAL_PACKAGE_NAME := CtsAppWidgetTestCases
 
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target-minus-junit4 ctstestrunner hamcrest
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    mockito-target-minus-junit4 \
+    ctstestrunner \
+    junit \
+    legacy-android-test
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
 include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/appwidget/AndroidTest.xml b/tests/tests/appwidget/AndroidTest.xml
index 9a8bad2..6e4ee66 100644
--- a/tests/tests/appwidget/AndroidTest.xml
+++ b/tests/tests/appwidget/AndroidTest.xml
@@ -15,6 +15,8 @@
 <configuration description="Config for CTS App Widget test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsAppWidgetLauncher1.apk" />
+        <option name="test-file-name" value="CtsAppWidgetLauncher2.apk" />
         <option name="test-file-name" value="CtsAppWidgetTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/appwidget/common/src/android/appwidget/cts/common/Constants.java b/tests/tests/appwidget/common/src/android/appwidget/cts/common/Constants.java
new file mode 100644
index 0000000..954a81b
--- /dev/null
+++ b/tests/tests/appwidget/common/src/android/appwidget/cts/common/Constants.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.appwidget.cts.common;
+
+public class Constants {
+
+    public static final String ACTION_CONFIRM_PIN =
+            "android.appwidget.cts.packages.AppWidgetConfirmPin";
+
+    public static final String ACTION_SETUP_REPLY =
+            "android.appwidget.cts.SETUP_REPLY";
+
+    public static final String EXTRA_SUCCESS = "SUCCESS";
+    public static final String EXTRA_PACKAGE = "PACKAGE_NAME";
+    public static final String EXTRA_REQUEST = "REQUEST";
+
+}
diff --git a/tests/tests/appwidget/packages/Android.mk b/tests/tests/appwidget/packages/Android.mk
new file mode 100644
index 0000000..cddf11e
--- /dev/null
+++ b/tests/tests/appwidget/packages/Android.mk
@@ -0,0 +1,17 @@
+# 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 $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/appwidget/packages/launchermanifest/Android.mk b/tests/tests/appwidget/packages/launchermanifest/Android.mk
new file mode 100644
index 0000000..dc9ce04
--- /dev/null
+++ b/tests/tests/appwidget/packages/launchermanifest/Android.mk
@@ -0,0 +1,57 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+#-----------------------------------------------------------
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsAppWidgetLauncher1
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.appwidget.cts.packages.launcher1
+
+include $(BUILD_CTS_PACKAGE)
+
+#-----------------------------------------------------------
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsAppWidgetLauncher2
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_AAPT_FLAGS += --rename-manifest-package android.appwidget.cts.packages.launcher2
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/appwidget/packages/launchermanifest/AndroidManifest.xml b/tests/tests/appwidget/packages/launchermanifest/AndroidManifest.xml
new file mode 100644
index 0000000..ad82a7d
--- /dev/null
+++ b/tests/tests/appwidget/packages/launchermanifest/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.appwidget.cts.packages">
+
+    <application>
+        <activity android:name="Launcher">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.HOME" />
+            </intent-filter>
+        </activity>
+        <activity android:name="AppWidgetConfirmPin">
+            <intent-filter>
+                <action android:name="android.content.pm.action.CONFIRM_PIN_ITEM" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/AppWidgetConfirmPin.java b/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/AppWidgetConfirmPin.java
new file mode 100644
index 0000000..4b50c80
--- /dev/null
+++ b/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/AppWidgetConfirmPin.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 android.appwidget.cts.packages;
+
+import android.app.Activity;
+import android.appwidget.cts.common.Constants;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.PinItemRequest;
+import android.os.Bundle;
+
+public class AppWidgetConfirmPin extends Activity {
+
+    private PinItemRequest mRequest;
+
+    private BroadcastReceiver mReceiver;
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        try {
+            final LauncherApps launcherApps = getSystemService(LauncherApps.class);
+            mRequest = launcherApps.getPinItemRequest(getIntent());
+
+            if (mRequest == null) {
+                throw new IllegalArgumentException("Null request");
+            }
+
+            if (mRequest.getRequestType() != PinItemRequest.REQUEST_TYPE_APPWIDGET ||
+                    mRequest.getAppWidgetProviderInfo(this) == null) {
+                throw new IllegalArgumentException("Wrong request");
+            }
+
+            mReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    onCommandReceive(intent);
+                }
+            };
+            registerReceiver(mReceiver, new IntentFilter(Constants.ACTION_CONFIRM_PIN));
+            sendSetupReply(true);
+        } catch (Exception e) {
+            sendSetupReply(false);
+            finish();
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mReceiver != null) {
+            unregisterReceiver(mReceiver);
+            mReceiver = null;
+        }
+    }
+
+    private void sendSetupReply(boolean success) {
+        sendBroadcast(new Intent(Constants.ACTION_SETUP_REPLY)
+                .putExtra(Constants.EXTRA_SUCCESS, success)
+                .putExtra(Constants.EXTRA_PACKAGE, getPackageName())
+                .putExtra(Constants.EXTRA_REQUEST, mRequest));
+    }
+
+    private void onCommandReceive(Intent intent) {
+        mRequest.accept(intent.getExtras());
+        finish();
+    }
+}
diff --git a/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/Launcher.java b/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/Launcher.java
new file mode 100644
index 0000000..661bd55
--- /dev/null
+++ b/tests/tests/appwidget/packages/src/android/appwidget/cts/packages/Launcher.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.appwidget.cts.packages;
+
+import android.app.Activity;
+
+public class Launcher extends Activity {
+}
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
index 313f009..6348c6a 100644
--- a/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
+++ b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
@@ -40,45 +40,33 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.appwidget.cts.R;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.test.InstrumentationTestCase;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.widget.RemoteViews;
 import android.widget.RemoteViewsService.RemoteViewsFactory;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
+
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.mockito.InOrder;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-import java.io.FileInputStream;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
-public class AppWidgetTest extends InstrumentationTestCase {
+public class AppWidgetTest extends AppWidgetTestCase {
 
     private static final long OPERATION_TIMEOUT = 20 * 1000; // 20 sec
 
-    private static final String FIRST_APP_WIDGET_CONFIGURE_ACTIVITY =
-            "android.appwidget.cts.provider.FirstAppWidgetConfigureActivity";
-
-    private static final String SECOND_APP_WIDGET_CONFIGURE_ACTIVITY =
-            "android.appwidget.cts.provider.SecondAppWidgetConfigureActivity";
-
     private final Object mLock = new Object();
 
     @Override
@@ -96,11 +84,6 @@
             "appwidget revokebind --package android.appwidget.cts --user 0";
 
 
-    private boolean hasAppWidgets() {
-        return getInstrumentation().getTargetContext().getPackageManager()
-            .hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS);
-    }
-
     public void testGetAppInstalledProvidersForCurrentUserLegacy() throws Exception {
         if (!hasAppWidgets()) {
             return;
@@ -1313,117 +1296,25 @@
 
     @SuppressWarnings("deprecation")
     private void assertExpectedInstalledProviders(List<AppWidgetProviderInfo> providers) {
-        boolean firstProviderVerified = false;
-        boolean secondProviderVerified = false;
-
-        ComponentName firstComponentName = new ComponentName(
-                getInstrumentation().getTargetContext().getPackageName(),
-                FirstAppWidgetProvider.class.getName());
-
-        ComponentName secondComponentName = new ComponentName(
-                getInstrumentation().getTargetContext().getPackageName(),
-                SecondAppWidgetProvider.class.getName());
-
-        final int providerCount = providers.size();
-        for (int i = 0; i < providerCount; i++) {
-            AppWidgetProviderInfo provider = providers.get(i);
-
-            if (firstComponentName.equals(provider.provider)
-                    && android.os.Process.myUserHandle().equals(provider.getProfile())) {
-                assertEquals(getNormalizedDimensionResource(R.dimen.first_min_appwidget_size),
-                        provider.minWidth);
-                assertEquals(getNormalizedDimensionResource(R.dimen.first_min_appwidget_size),
-                        provider.minHeight);
-                assertEquals(getNormalizedDimensionResource(
-                        R.dimen.first_min_resize_appwidget_size), provider.minResizeWidth);
-                assertEquals(getNormalizedDimensionResource(
-                        R.dimen.first_min_resize_appwidget_size), provider.minResizeHeight);
-                assertEquals(getIntResource(R.integer.first_update_period_millis),
-                        provider.updatePeriodMillis);
-                assertEquals(getInstrumentation().getTargetContext().getPackageName(),
-                        provider.configure.getPackageName());
-                assertEquals(FIRST_APP_WIDGET_CONFIGURE_ACTIVITY,
-                        provider.configure.getClassName());
-                assertEquals(getIntResource(R.integer.first_resize_mode),
-                        provider.resizeMode);
-                assertEquals(getIntResource(R.integer.first_widget_category),
-                        provider.widgetCategory);
-                assertEquals(R.layout.first_initial_layout,
-                        provider.initialLayout);
-                assertEquals(R.layout.first_initial_keyguard_layout,
-                        provider.initialKeyguardLayout);
-                assertEquals(R.drawable.first_android_icon,
-                        provider.previewImage);
-                assertEquals(R.id.first_auto_advance_view_id,
-                        provider.autoAdvanceViewId);
-                firstProviderVerified = true;
-            } else if (secondComponentName.equals(provider.provider)
-                    && android.os.Process.myUserHandle().equals(provider.getProfile())) {
-                assertEquals(getNormalizedDimensionResource(R.dimen.second_min_appwidget_size),
-                        provider.minWidth);
-                assertEquals(getNormalizedDimensionResource(R.dimen.second_min_appwidget_size),
-                        provider.minHeight);
-                assertEquals(getNormalizedDimensionResource(
-                        R.dimen.second_min_resize_appwidget_size), provider.minResizeWidth);
-                assertEquals(getNormalizedDimensionResource(
-                        R.dimen.second_min_resize_appwidget_size), provider.minResizeHeight);
-                assertEquals(getIntResource(R.integer.second_update_period_millis),
-                        provider.updatePeriodMillis);
-                assertEquals(getInstrumentation().getTargetContext().getPackageName(),
-                        provider.configure.getPackageName());
-                assertEquals(SECOND_APP_WIDGET_CONFIGURE_ACTIVITY,
-                        provider.configure.getClassName());
-                assertEquals(getIntResource(R.integer.second_resize_mode),
-                        provider.resizeMode);
-                assertEquals(getIntResource(R.integer.second_widget_category),
-                        provider.widgetCategory);
-                assertEquals(R.layout.second_initial_layout,
-                        provider.initialLayout);
-                assertEquals(R.layout.second_initial_keyguard_layout,
-                        provider.initialKeyguardLayout);
-                assertEquals(R.drawable.second_android_icon,
-                        provider.previewImage);
-                assertEquals(R.id.second_auto_advance_view_id,
-                        provider.autoAdvanceViewId);
-                secondProviderVerified = true;
-            }
-        }
-
-        assertTrue(firstProviderVerified && secondProviderVerified);
+        boolean[] verifiedWidgets = verifyInstalledProviders(providers);
+        assertTrue(verifiedWidgets[0]);
+        assertTrue(verifiedWidgets[1]);
     }
 
-    private void grantBindAppWidgetPermission() {
-        executeShellCommandIgnoreOutput(GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND);
+    private void grantBindAppWidgetPermission() throws Exception {
+        runShellCommand(GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND);
     }
 
-    private void revokeBindAppWidgetPermission() {
-        executeShellCommandIgnoreOutput(REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND);
-    }
-
-    private void executeShellCommandIgnoreOutput(String command) {
-        ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
-                .executeShellCommand(command);
-        try {
-            Streams.readFully(new FileInputStream(pfd.getFileDescriptor()));
-        } catch (IOException ioe) {
-            IoUtils.closeQuietly(pfd);
-        }
+    private void revokeBindAppWidgetPermission() throws Exception {
+        runShellCommand(REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND);
     }
 
     private AppWidgetProviderInfo getFirstAppWidgetProviderInfo() {
-        ComponentName firstComponentName = new ComponentName(
-                getInstrumentation().getTargetContext().getPackageName(),
-                FirstAppWidgetProvider.class.getName());
-
-        return getProviderInfo(firstComponentName);
+        return getProviderInfo(getFirstWidgetComponent());
     }
 
     private AppWidgetProviderInfo getSecondAppWidgetProviderInfo() {
-        ComponentName secondComponentName = new ComponentName(
-                getInstrumentation().getTargetContext().getPackageName(),
-                SecondAppWidgetProvider.class.getName());
-
-        return getProviderInfo(secondComponentName);
+        return getProviderInfo(getSecondWidgetComponent());
     }
 
     private AppWidgetProviderInfo getProviderInfo(ComponentName componentName) {
@@ -1442,15 +1333,6 @@
         return null;
     }
 
-    private int getNormalizedDimensionResource(int resId) {
-        return getInstrumentation().getTargetContext().getResources()
-                .getDimensionPixelSize(resId);
-    }
-
-    private int getIntResource(int resId) {
-        return getInstrumentation().getTargetContext().getResources().getInteger(resId);
-    }
-
     private AppWidgetManager getAppWidgetManager() {
         return (AppWidgetManager) getInstrumentation().getTargetContext()
                 .getSystemService(Context.APPWIDGET_SERVICE);
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTestCase.java b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTestCase.java
new file mode 100644
index 0000000..fb0dbd1
--- /dev/null
+++ b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTestCase.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appwidget.cts;
+
+import android.appwidget.AppWidgetProviderInfo;
+import android.appwidget.cts.provider.FirstAppWidgetProvider;
+import android.appwidget.cts.provider.SecondAppWidgetProvider;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.os.ParcelFileDescriptor;
+import android.test.InstrumentationTestCase;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class AppWidgetTestCase extends InstrumentationTestCase {
+    private static final String FIRST_APP_WIDGET_CONFIGURE_ACTIVITY =
+            "android.appwidget.cts.provider.FirstAppWidgetConfigureActivity";
+
+    private static final String SECOND_APP_WIDGET_CONFIGURE_ACTIVITY =
+            "android.appwidget.cts.provider.SecondAppWidgetConfigureActivity";
+
+    public boolean hasAppWidgets() {
+        return getInstrumentation().getTargetContext().getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS);
+    }
+
+    public boolean[] verifyInstalledProviders(List<AppWidgetProviderInfo> providers) {
+        boolean firstProviderVerified = false;
+        boolean secondProviderVerified = false;
+
+        ComponentName firstComponentName = getFirstWidgetComponent();
+        ComponentName secondComponentName = getSecondWidgetComponent();
+
+        final int providerCount = providers.size();
+        for (int i = 0; i < providerCount; i++) {
+            AppWidgetProviderInfo provider = providers.get(i);
+
+            if (firstComponentName.equals(provider.provider)
+                    && android.os.Process.myUserHandle().equals(provider.getProfile())) {
+                assertEquals(getNormalizedDimensionResource(android.appwidget.cts.R.dimen.first_min_appwidget_size),
+                        provider.minWidth);
+                assertEquals(getNormalizedDimensionResource(android.appwidget.cts.R.dimen.first_min_appwidget_size),
+                        provider.minHeight);
+                assertEquals(getNormalizedDimensionResource(
+                        android.appwidget.cts.R.dimen.first_min_resize_appwidget_size), provider.minResizeWidth);
+                assertEquals(getNormalizedDimensionResource(
+                        android.appwidget.cts.R.dimen.first_min_resize_appwidget_size), provider.minResizeHeight);
+                assertEquals(getIntResource(android.appwidget.cts.R.integer.first_update_period_millis),
+                        provider.updatePeriodMillis);
+                assertEquals(getInstrumentation().getTargetContext().getPackageName(),
+                        provider.configure.getPackageName());
+                assertEquals(FIRST_APP_WIDGET_CONFIGURE_ACTIVITY,
+                        provider.configure.getClassName());
+                assertEquals(getIntResource(android.appwidget.cts.R.integer.first_resize_mode),
+                        provider.resizeMode);
+                assertEquals(getIntResource(android.appwidget.cts.R.integer.first_widget_category),
+                        provider.widgetCategory);
+                assertEquals(android.appwidget.cts.R.layout.first_initial_layout,
+                        provider.initialLayout);
+                assertEquals(android.appwidget.cts.R.layout.first_initial_keyguard_layout,
+                        provider.initialKeyguardLayout);
+                assertEquals(android.appwidget.cts.R.drawable.first_android_icon,
+                        provider.previewImage);
+                assertEquals(android.appwidget.cts.R.id.first_auto_advance_view_id,
+                        provider.autoAdvanceViewId);
+                firstProviderVerified = true;
+            } else if (secondComponentName.equals(provider.provider)
+                    && android.os.Process.myUserHandle().equals(provider.getProfile())) {
+                assertEquals(getNormalizedDimensionResource(android.appwidget.cts.R.dimen.second_min_appwidget_size),
+                        provider.minWidth);
+                assertEquals(getNormalizedDimensionResource(android.appwidget.cts.R.dimen.second_min_appwidget_size),
+                        provider.minHeight);
+                assertEquals(getNormalizedDimensionResource(
+                        android.appwidget.cts.R.dimen.second_min_resize_appwidget_size), provider.minResizeWidth);
+                assertEquals(getNormalizedDimensionResource(
+                        android.appwidget.cts.R.dimen.second_min_resize_appwidget_size), provider.minResizeHeight);
+                assertEquals(getIntResource(android.appwidget.cts.R.integer.second_update_period_millis),
+                        provider.updatePeriodMillis);
+                assertEquals(getInstrumentation().getTargetContext().getPackageName(),
+                        provider.configure.getPackageName());
+                assertEquals(SECOND_APP_WIDGET_CONFIGURE_ACTIVITY,
+                        provider.configure.getClassName());
+                assertEquals(getIntResource(android.appwidget.cts.R.integer.second_resize_mode),
+                        provider.resizeMode);
+                assertEquals(getIntResource(android.appwidget.cts.R.integer.second_widget_category),
+                        provider.widgetCategory);
+                assertEquals(android.appwidget.cts.R.layout.second_initial_layout,
+                        provider.initialLayout);
+                assertEquals(android.appwidget.cts.R.layout.second_initial_keyguard_layout,
+                        provider.initialKeyguardLayout);
+                assertEquals(android.appwidget.cts.R.drawable.second_android_icon,
+                        provider.previewImage);
+                assertEquals(android.appwidget.cts.R.id.second_auto_advance_view_id,
+                        provider.autoAdvanceViewId);
+                secondProviderVerified = true;
+            }
+        }
+
+        return new boolean[]{firstProviderVerified, secondProviderVerified};
+    }
+
+    private int getNormalizedDimensionResource(int resId) {
+        return getInstrumentation().getTargetContext().getResources()
+                .getDimensionPixelSize(resId);
+    }
+
+    private int getIntResource(int resId) {
+        return getInstrumentation().getTargetContext().getResources().getInteger(resId);
+    }
+
+    public ComponentName getFirstWidgetComponent() {
+        return new ComponentName(
+                getInstrumentation().getTargetContext().getPackageName(),
+                FirstAppWidgetProvider.class.getName());
+    }
+
+    public ComponentName getSecondWidgetComponent() {
+        return new ComponentName(
+                getInstrumentation().getTargetContext().getPackageName(),
+                SecondAppWidgetProvider.class.getName());
+    }
+
+    public ArrayList<String> runShellCommand(String command) throws Exception {
+        ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
+                .executeShellCommand(command);
+
+        ArrayList<String> ret = new ArrayList<>();
+        // Read the input stream fully.
+        try (BufferedReader r = new BufferedReader(
+                new InputStreamReader(new ParcelFileDescriptor.AutoCloseInputStream(pfd)))) {
+            String line;
+            while ((line = r.readLine()) != null) {
+                ret.add(line);
+            }
+        }
+        return ret;
+    }
+}
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java b/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java
new file mode 100644
index 0000000..a337143
--- /dev/null
+++ b/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.appwidget.cts;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.cts.common.Constants;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.LauncherApps;
+import android.os.Handler;
+
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class RequestPinAppWidgetTest extends AppWidgetTestCase {
+
+    private static final String LAUNCHER_CLASS = "android.appwidget.cts.packages.Launcher";
+    private static final String ACTION_PIN_RESULT = "android.appwidget.cts.ACTION_PIN_RESULT";
+
+    private String mDefaultLauncher;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDefaultLauncher = getDefaultLauncher();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        // Set the launcher back
+        setLauncher(mDefaultLauncher);
+    }
+
+    private void runPinWidgetTest(final String launcherPkg) throws Exception {
+        if (!hasAppWidgets()) {
+            return;
+        }
+        setLauncher(launcherPkg + "/" + LAUNCHER_CLASS);
+
+        Context context = getInstrumentation().getContext();
+
+        // Request to pin widget
+        BlockingReceiver setupReceiver = new BlockingReceiver()
+                .register(Constants.ACTION_SETUP_REPLY);
+
+        PendingIntent pinResult = PendingIntent.getBroadcast(context, 0,
+                new Intent(ACTION_PIN_RESULT), PendingIntent.FLAG_ONE_SHOT);
+        AppWidgetManager.getInstance(context).requestPinAppWidget(
+                getFirstWidgetComponent(), pinResult);
+
+        setupReceiver.await();
+        // Verify that the confirmation dialog was opened
+        assertTrue(setupReceiver.mResult.getBooleanExtra(Constants.EXTRA_SUCCESS, false));
+        assertEquals(launcherPkg, setupReceiver.mResult.getStringExtra(Constants.EXTRA_PACKAGE));
+        setupReceiver.unregister();
+
+        LauncherApps.PinItemRequest req =
+                setupReceiver.mResult.getParcelableExtra(Constants.EXTRA_REQUEST);
+        assertNotNull(req);
+        // Verify that multiple calls to getAppWidgetProviderInfo have proper dimension.
+        boolean[] providerInfo = verifyInstalledProviders(Arrays.asList(
+                req.getAppWidgetProviderInfo(context), req.getAppWidgetProviderInfo(context)));
+        assertTrue(providerInfo[0]);
+
+        // Accept the request
+        BlockingReceiver resultReceiver = new BlockingReceiver().register(ACTION_PIN_RESULT);
+        context.sendBroadcast(new Intent(Constants.ACTION_CONFIRM_PIN)
+                .setPackage(launcherPkg)
+                .putExtra("dummy", "dummy-2"));
+        resultReceiver.await();
+
+        // Verify that the result contain the extras
+        assertEquals("dummy-2", resultReceiver.mResult.getStringExtra("dummy"));
+        resultReceiver.unregister();
+    }
+
+    public void testPinWidget_launcher1() throws Exception {
+        runPinWidgetTest("android.appwidget.cts.packages.launcher1");
+    }
+
+    public void testPinWidget_launcher2() throws Exception {
+        runPinWidgetTest("android.appwidget.cts.packages.launcher2");
+    }
+
+    private String getDefaultLauncher() throws Exception {
+        final String PREFIX = "Launcher: ComponentInfo{";
+        final String POSTFIX = "}";
+        for (String s : runShellCommand("cmd shortcut get-default-launcher")) {
+            if (s.startsWith(PREFIX) && s.endsWith(POSTFIX)) {
+                return s.substring(PREFIX.length(), s.length() - POSTFIX.length());
+            }
+        }
+        throw new Exception("Default launcher not found");
+    }
+
+    private void setLauncher(String component) throws Exception {
+        runShellCommand("cmd package set-home-activity --user "
+                + getInstrumentation().getContext().getUserId() + " " + component);
+    }
+
+    private class BlockingReceiver extends BroadcastReceiver {
+        private final CountDownLatch notifier = new CountDownLatch(1);
+
+        private Intent mResult;
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mResult = new Intent(intent);
+            notifier.countDown();
+        }
+
+        public BlockingReceiver register(String action) {
+            Context context = getInstrumentation().getContext();
+            context.registerReceiver(this, new IntentFilter(action),
+                    null, new Handler(context.getMainLooper()));
+            return this;
+        }
+
+        public void await() throws Exception {
+            assertTrue(notifier.await(20, TimeUnit.SECONDS));
+        }
+
+        public void unregister() {
+            getInstrumentation().getContext().unregisterReceiver(this);
+        }
+    }
+}
diff --git a/tests/tests/carrierapi/Android.mk b/tests/tests/carrierapi/Android.mk
index 4cb2c38..298c6ab 100644
--- a/tests/tests/carrierapi/Android.mk
+++ b/tests/tests/carrierapi/Android.mk
@@ -22,7 +22,11 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner \
+    compatibility-device-util \
+    junit \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/contactsproviderwipe/Android.mk b/tests/tests/contactsproviderwipe/Android.mk
new file mode 100644
index 0000000..b7bd687
--- /dev/null
+++ b/tests/tests/contactsproviderwipe/Android.mk
@@ -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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-support-v4 \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+    $(call all-java-files-under, common/src)
+
+LOCAL_PACKAGE_NAME := CtsContactsProviderWipe
+
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_SDK_VERSION := test_current
+
+include $(BUILD_CTS_PACKAGE)
+#include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/contactsproviderwipe/AndroidManifest.xml b/tests/tests/contactsproviderwipe/AndroidManifest.xml
new file mode 100644
index 0000000..9ac9ad0
--- /dev/null
+++ b/tests/tests/contactsproviderwipe/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.provider.cts.contactsproviderwipe">
+
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+
+    <application>
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.provider.cts.contactsproviderwipe">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+</manifest>
+
diff --git a/tests/tests/contactsproviderwipe/AndroidTest.xml b/tests/tests/contactsproviderwipe/AndroidTest.xml
new file mode 100644
index 0000000..e20faa6
--- /dev/null
+++ b/tests/tests/contactsproviderwipe/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS Provider test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsContactsProviderWipe.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.provider.cts.contactsproviderwipe" />
+        <option name="runtime-hint" value="3m" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/contactsproviderwipe/src/android/provider/cts/contactsproviderwipe/ContactsContract_Wipe.java b/tests/tests/contactsproviderwipe/src/android/provider/cts/contactsproviderwipe/ContactsContract_Wipe.java
new file mode 100644
index 0000000..2bea43f
--- /dev/null
+++ b/tests/tests/contactsproviderwipe/src/android/provider/cts/contactsproviderwipe/ContactsContract_Wipe.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider.cts.contactsproviderwipe;
+
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.ProviderStatus;
+import android.support.test.InstrumentationRegistry;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * CTS tests for CP2 regarding data wipe.
+ *
+ * <p>We can't use CtsProviderTestCases for this test because CtsProviderTestCases creates
+ * a stable connection to the contacts provider, which would cause the test process to be killed
+ * when the CP2 process gets killed (for "pm clear").
+ */
+public class ContactsContract_Wipe extends AndroidTestCase {
+    public static final String TAG = "ContactsContract_PS";
+
+    /** 1 hour in milliseconds. */
+    private static final long ONE_HOUR_IN_MILLIS = 1000L * 60 * 60;
+
+    private long getDatabaseCreationTimestamp() {
+        try (Cursor cursor = getContext().getContentResolver().query(
+                ProviderStatus.CONTENT_URI, null, null, null, null)) {
+            assertTrue(cursor.moveToFirst());
+
+            final Long timestamp = cursor.getLong(
+                    cursor.getColumnIndexOrThrow(ProviderStatus.DATABASE_CREATION_TIMESTAMP));
+            assertNotNull(timestamp);
+
+            return timestamp;
+        }
+    }
+
+    private void assertBigger(long bigger, long smaller) {
+        assertTrue("Expecting " + bigger + " > " + smaller, bigger > smaller);
+    }
+
+    private String getContactsProviderPackageName() {
+        final List<ProviderInfo> list = getContext().getPackageManager().queryContentProviders(
+                null, 0, PackageManager.MATCH_ALL);
+        assertNotNull(list);
+        for (ProviderInfo pi : list) {
+            if (TextUtils.isEmpty(pi.authority)) {
+                continue;
+            }
+            for (String authority : pi.authority.split(";")) {
+                Log.i(TAG, "Found " + authority);
+                if (ContactsContract.AUTHORITY.equals(authority)) {
+                    return pi.packageName;
+                }
+            }
+        }
+        fail("Contacts provider package not found.");
+        return null;
+    }
+
+    static List<String> readAll(ParcelFileDescriptor pfd) {
+        try {
+            try {
+                final ArrayList<String> ret = new ArrayList<>();
+                try (BufferedReader r = new BufferedReader(
+                        new FileReader(pfd.getFileDescriptor()))) {
+                    String line;
+                    while ((line = r.readLine()) != null) {
+                        ret.add(line);
+                    }
+                    r.readLine();
+                }
+                return ret;
+            } finally {
+                pfd.close();
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static String concatResult(List<String> result) {
+        final StringBuilder sb = new StringBuilder();
+        for (String s : result) {
+            sb.append(s);
+            sb.append("\n");
+        }
+        return sb.toString().trim();
+    }
+
+    private void wipeContactsProvider() {
+        final String providerPackage = getContactsProviderPackageName();
+
+        Log.i(TAG, "Wiping "  + providerPackage + "...");
+
+        final String result = concatResult(readAll(
+                InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(
+                        "pm clear " + providerPackage)));
+        Log.i(TAG, "Result:" + result);
+
+        assertEquals("Success", result);
+    }
+
+    public void testCreationTimestamp() throws Exception {
+        final long originalTimestamp = getDatabaseCreationTimestamp();
+
+        Thread.sleep(1);
+
+        final long start = System.currentTimeMillis();
+
+        Log.i(TAG, "start="  + start);
+        Log.i(TAG, "originalTimestamp="  + originalTimestamp);
+
+        // Check: the (old) creation time should be smaller than the start time (=now).
+        // Add 1 hour to compensate for possible day light saving.
+        assertBigger(start + ONE_HOUR_IN_MILLIS, originalTimestamp);
+
+        Thread.sleep(1);
+
+        wipeContactsProvider();
+
+        // Check: the creation time should be bigger than the start time.
+        final long newTimestamp = getDatabaseCreationTimestamp();
+        Log.i(TAG, "newTimestamp="  + newTimestamp);
+
+        assertBigger(newTimestamp, start);
+    }
+
+    private void checkDatabaseWipeNotification(Uri notificationUri) throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        final AtomicReference<Uri> notifiedUri = new AtomicReference<>();
+
+        getContext().getContentResolver().registerContentObserver(notificationUri,
+                /* notifyForDescendants=*/ false,
+                new ContentObserver(new Handler(Looper.getMainLooper())) {
+            @Override
+            public void onChange(boolean selfChange, Uri uri) {
+                Log.i(TAG, "Received notification on " + uri);
+                notifiedUri.set(uri);
+                latch.countDown();
+            }
+        });
+
+        wipeContactsProvider();
+
+        assertTrue("Didn't receive content change notification",
+                latch.await(60, TimeUnit.SECONDS));
+
+        assertEquals(notificationUri, notifiedUri.get());
+    }
+
+    public void testDatabaseWipeNotification() throws Exception {
+        checkDatabaseWipeNotification(ProviderStatus.CONTENT_URI);
+        checkDatabaseWipeNotification(ProviderStatus.STATUS_CHANGE_NOTIFICATION_CONTENT_URI);
+    }
+}
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index 67fc3fa..684e665 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -27,7 +27,9 @@
                                 android-support-multidex \
                                 compatibility-device-util \
                                 ctstestrunner \
-                                services.core
+                                services.core \
+                                junit \
+                                legacy-android-test
 
 # Use multi-dex as the compatibility-common-util-devicesidelib dependency
 # on compatibility-device-util pushes us beyond 64k methods.
diff --git a/tests/tests/database/Android.mk b/tests/tests/database/Android.mk
index 36ca51b..1be93c6 100644
--- a/tests/tests/database/Android.mk
+++ b/tests/tests/database/Android.mk
@@ -21,7 +21,12 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES += android-common ctstestrunner ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-common \
+    ctstestrunner \
+    ctstestrunner \
+    junit \
+    legacy-android-test
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
diff --git a/tests/tests/debug/libdebugtest/android_debug_cts.cpp b/tests/tests/debug/libdebugtest/android_debug_cts.cpp
index 70cb41c..2c7c967 100644
--- a/tests/tests/debug/libdebugtest/android_debug_cts.cpp
+++ b/tests/tests/debug/libdebugtest/android_debug_cts.cpp
@@ -19,9 +19,13 @@
 
 #include <sys/ptrace.h>
 #include <sys/types.h>
+#include <sys/uio.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <functional>
+#include <vector>
+
 #define LOG_TAG "Cts-DebugTest"
 
 #define assert_or_exit(x)                                                                         \
@@ -48,8 +52,19 @@
     return true;
 }
 
-static bool child(pid_t parent) __attribute__((noreturn));
-static bool child(pid_t parent) {
+static bool run_test(const std::function<void(pid_t)> &test) {
+    pid_t pid = fork();
+    assert_or_return(pid >= 0);
+    if (pid != 0)
+        return parent(pid);
+    else {
+        // child
+        test(getppid());
+        _exit(0);
+    }
+}
+
+static void ptraceAttach(pid_t parent) {
     assert_or_exit(ptrace(PTRACE_ATTACH, parent, nullptr, nullptr) == 0);
     int status;
     assert_or_exit(waitpid(parent, &status, __WALL) == parent);
@@ -57,15 +72,52 @@
     assert_or_exit(WSTOPSIG(status) == SIGSTOP);
 
     assert_or_exit(ptrace(PTRACE_DETACH, parent, nullptr, nullptr) == 0);
-    _exit(0);
 }
 
 // public static native boolean ptraceAttach();
 extern "C" jboolean Java_android_debug_cts_DebugTest_ptraceAttach(JNIEnv *, jclass) {
-    pid_t pid = fork();
-    assert_or_return(pid >= 0);
-    if (pid != 0)
-        return parent(pid);
-    else
-        child(getppid());
+    return run_test(ptraceAttach);
+}
+
+
+static void processVmReadv(pid_t parent, const std::vector<long *> &addresses) {
+    long destination;
+    iovec local = { &destination, sizeof destination };
+
+    for (long *address : addresses) {
+        // Since we are forked, the address will be valid in the remote process as well.
+        iovec remote = { address, sizeof *address };
+        __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "%s About to read %p\n", __func__,
+                            address);
+        assert_or_exit(process_vm_readv(parent, &local, 1, &remote, 1, 0) == sizeof destination);
+
+        // Compare the data with the contents of our memory.
+        assert_or_exit(destination == *address);
+    }
+}
+
+static long global_variable = 0x47474747;
+// public static native boolean processVmReadv();
+extern "C" jboolean Java_android_debug_cts_DebugTest_processVmReadv(JNIEnv *, jclass) {
+    long stack_variable = 0x42424242;
+    // This runs the test with a selection of different kinds of addresses and
+    // makes sure the child process (simulating a debugger) can read them.
+    return run_test([&](pid_t parent) {
+        processVmReadv(parent, std::vector<long *>{
+                                   &global_variable, &stack_variable,
+                                   reinterpret_cast<long *>(&processVmReadv)});
+    });
+}
+
+// public static native boolean processVmReadvNullptr();
+extern "C" jboolean Java_android_debug_cts_DebugTest_processVmReadvNullptr(JNIEnv *, jclass) {
+    // Make sure reading unallocated memory behaves reasonably.
+    return run_test([](pid_t parent) {
+        long destination;
+        iovec local = {&destination, sizeof destination};
+        iovec remote = {nullptr, sizeof(long)};
+
+        assert_or_exit(process_vm_readv(parent, &local, 1, &remote, 1, 0) == -1);
+        assert_or_exit(errno == EFAULT);
+    });
 }
diff --git a/tests/tests/debug/src/android/debug/cts/DebugTest.java b/tests/tests/debug/src/android/debug/cts/DebugTest.java
index 9fae539..ca55d9c 100644
--- a/tests/tests/debug/src/android/debug/cts/DebugTest.java
+++ b/tests/tests/debug/src/android/debug/cts/DebugTest.java
@@ -25,8 +25,17 @@
     }
 
     public static native boolean ptraceAttach();
-
     public void test_ptraceAttach() {
         assertEquals(true, ptraceAttach());
     }
+
+    public static native boolean processVmReadv();
+    public void test_processVmReadv() {
+        assertEquals(true, processVmReadv());
+    }
+
+    public static native boolean processVmReadvNullptr();
+    public void test_processVmReadvNullptr() {
+        assertEquals(true, processVmReadvNullptr());
+    }
 }
diff --git a/tests/tests/dpi/Android.mk b/tests/tests/dpi/Android.mk
index 0c158121..963db7a 100644
--- a/tests/tests/dpi/Android.mk
+++ b/tests/tests/dpi/Android.mk
@@ -17,7 +17,7 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner junit legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
@@ -41,6 +41,8 @@
 # CTS tests, so drop it into a library that other tests can use.
 include $(CLEAR_VARS)
 
+LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+
 LOCAL_SRC_FILES := src/android/dpi/cts/DefaultManifestAttributesTest.java
 
 LOCAL_MODULE_TAGS := optional
diff --git a/tests/tests/dpi2/Android.mk b/tests/tests/dpi2/Android.mk
index 2919ef8..6e7c649 100644
--- a/tests/tests/dpi2/Android.mk
+++ b/tests/tests/dpi2/Android.mk
@@ -18,7 +18,7 @@
 include $(CLEAR_VARS)
 
 # We use the DefaultManifestAttributesTest from the android.cts.dpi package.
-LOCAL_STATIC_JAVA_LIBRARIES := android.cts.dpi ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := android.cts.dpi ctstestrunner junit
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/dreams/Android.mk b/tests/tests/dreams/Android.mk
index b268e37..eb46897 100644
--- a/tests/tests/dreams/Android.mk
+++ b/tests/tests/dreams/Android.mk
@@ -24,7 +24,7 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner junit legacy-android-test
 
 LOCAL_JAVA_LIBRARIES :=  android.test.runner
 
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index ee3b453..3059d71 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -27,7 +27,9 @@
     mockito-target-minus-junit4 \
     compatibility-device-util \
     ctstestrunner \
-    android-support-annotations
+    android-support-annotations \
+    junit \
+    legacy-android-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsgraphics_jni
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index a5fa1ab..a4b57bd 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -24,10 +24,12 @@
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.BitmapFactory;
+import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.Canvas.EdgeType;
 import android.graphics.Canvas.VertexMode;
 import android.graphics.Color;
+import android.graphics.ComposeShader;
 import android.graphics.DrawFilter;
 import android.graphics.Matrix;
 import android.graphics.Paint;
@@ -35,10 +37,12 @@
 import android.graphics.Path.Direction;
 import android.graphics.Picture;
 import android.graphics.PorterDuff.Mode;
+import android.graphics.RadialGradient;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.graphics.Region.Op;
+import android.graphics.Shader;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -1949,6 +1953,38 @@
         assertEquals(DisplayMetrics.DENSITY_HIGH, mCanvas.getDensity());
     }
 
+    @Test(expected = IllegalStateException.class)
+    public void testDrawHwBitmapInSwCanvas() {
+        Bitmap hwBitmap = mImmutableBitmap.copy(Config.HARDWARE, false);
+        mCanvas.drawBitmap(hwBitmap, 0, 0, null);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testHwBitmapShaderInSwCanvas1() {
+        Bitmap hwBitmap = mImmutableBitmap.copy(Config.HARDWARE, false);
+        BitmapShader bitmapShader = new BitmapShader(hwBitmap, Shader.TileMode.REPEAT,
+                Shader.TileMode.REPEAT);
+        RadialGradient gradientShader = new RadialGradient(10, 10, 30, Color.BLACK, Color.CYAN,
+                Shader.TileMode.REPEAT);
+        Shader shader = new ComposeShader(gradientShader, bitmapShader, Mode.OVERLAY);
+        Paint p = new Paint();
+        p.setShader(shader);
+        mCanvas.drawRect(0, 0, 10, 10, p);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testHwBitmapShaderInSwCanvas2() {
+        Bitmap hwBitmap = mImmutableBitmap.copy(Config.HARDWARE, false);
+        BitmapShader bitmapShader = new BitmapShader(hwBitmap, Shader.TileMode.REPEAT,
+                Shader.TileMode.REPEAT);
+        RadialGradient gradientShader = new RadialGradient(10, 10, 30, Color.BLACK, Color.CYAN,
+                Shader.TileMode.REPEAT);
+        Shader shader = new ComposeShader(bitmapShader, gradientShader, Mode.OVERLAY);
+        Paint p = new Paint();
+        p.setShader(shader);
+        mCanvas.drawRect(0, 0, 10, 10, p);
+    }
+
     private void preCompare() {
         final float[] values = new float[FLOAT_ARRAY_LEN];
         mCanvas.getMatrix().getValues(values);
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
index 4494656..cd3d2e0 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
@@ -109,7 +109,6 @@
         DoubleUnaryOperator op = Math::sqrt;
         ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", new float[6], new float[2],
                 op, sIdentity, 0.0f, 1.0f);
-        assertEquals(op, cs.getOetf());
         assertEquals(0.5, cs.getOetf().applyAsDouble(0.25), 1e-5);
     }
 
@@ -123,7 +122,6 @@
         DoubleUnaryOperator op = x -> x * x;
         ColorSpace.Rgb cs = new ColorSpace.Rgb("Test", new float[6], new float[2],
                 sIdentity, op, 0.0f, 1.0f);
-        assertEquals(op, cs.getEotf());
         assertEquals(0.0625, cs.getEotf().applyAsDouble(0.25), 1e-5);
     }
 
@@ -672,7 +670,7 @@
         // These cannot change
         assertEquals(0, ColorSpace.get(ColorSpace.Named.SRGB).getId());
         assertEquals(-1, ColorSpace.MIN_ID);
-        assertEquals(64, ColorSpace.MAX_ID);
+        assertEquals(63, ColorSpace.MAX_ID);
     }
 
     @Test
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorTest.java
index 7df4360..4801a1a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorTest.java
@@ -37,6 +37,8 @@
     public void testArgb() {
         assertEquals(Color.RED, Color.argb(0xff, 0xff, 0x00, 0x00));
         assertEquals(Color.YELLOW, Color.argb(0xff, 0xff, 0xff, 0x00));
+        assertEquals(Color.RED, Color.argb(1.0f, 1.0f, 0.0f, 0.0f));
+        assertEquals(Color.YELLOW, Color.argb(1.0f, 1.0f, 1.0f, 0.0f));
     }
 
     @Test
@@ -112,6 +114,8 @@
     public void testRgb() {
         assertEquals(Color.RED, Color.rgb(0xff, 0x00, 0x00));
         assertEquals(Color.YELLOW, Color.rgb(0xff, 0xff, 0x00));
+        assertEquals(Color.RED, Color.rgb(1.0f, 0.0f, 0.0f));
+        assertEquals(Color.YELLOW, Color.rgb(1.0f, 1.0f, 0.0f));
     }
 
     @Test(expected=RuntimeException.class)
diff --git a/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java b/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java
new file mode 100644
index 0000000..a124dbc
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.graphics.cts;
+
+import android.graphics.Color;
+import android.graphics.ColorSpace;
+import android.graphics.ColorSpace.Named;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.graphics.Color.alpha;
+import static android.graphics.Color.blue;
+import static android.graphics.Color.colorSpace;
+import static android.graphics.Color.convert;
+import static android.graphics.Color.green;
+import static android.graphics.Color.luminance;
+import static android.graphics.Color.pack;
+import static android.graphics.Color.red;
+import static android.graphics.Color.toArgb;
+import static android.graphics.Color.valueOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class Color_ColorLongTest {
+    @Test
+    public void testRed() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+
+        assertEquals(0.5f, red(pack(0.5f, 0.0f, 1.0f)), 0.01f);
+        assertEquals(0.5f, red(pack(0.5f, 0.0f, 1.0f, 1.0f, p3)), 0.01f);
+    }
+
+    @Test
+    public void testGreen() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+
+        assertEquals(0.7f, green(pack(0.5f, 0.7f, 1.0f)), 0.01f);
+        assertEquals(0.7f, green(pack(0.5f, 0.7f, 1.0f, 1.0f, p3)), 0.01f);
+    }
+
+    @Test
+    public void testBlue() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+
+        assertEquals(1.0f, blue(pack(0.5f, 0.7f, 1.0f)), 0.01f);
+        assertEquals(1.0f, blue(pack(0.5f, 0.7f, 1.0f, 1.0f, p3)), 0.01f);
+    }
+
+    @Test
+    public void testAlpha() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+
+        assertEquals(0.25f, alpha(pack(0.5f, 0.7f, 1.0f, 0.25f)), 0.01f);
+        assertEquals(0.25f, alpha(pack(0.5f, 0.7f, 1.0f, 0.25f, p3)), 0.01f);
+    }
+
+    @Test
+    public void testColorSpace() {
+        ColorSpace srgb = ColorSpace.get(Named.SRGB);
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+
+        assertEquals(srgb, colorSpace(pack(0.5f, 0.7f, 1.0f)));
+        assertEquals(p3, colorSpace(pack(0.5f, 0.7f, 1.0f, 1.0f, p3)));
+    }
+
+    @Test
+    public void testIsSrgb() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+
+        assertTrue(Color.isSrgb(pack(0.5f, 0.7f, 1.0f)));
+        assertFalse(Color.isSrgb(pack(0.5f, 0.7f, 1.0f, 1.0f, p3)));
+
+        assertTrue(Color.valueOf(0.5f, 0.7f, 1.0f).isSrgb());
+        assertFalse(Color.valueOf(0.5f, 0.7f, 1.0f, 1.0f, p3).isSrgb());
+    }
+
+    @Test
+    public void testIsWideGamut() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+
+        assertFalse(Color.isWideGamut(pack(0.5f, 0.7f, 1.0f)));
+        assertTrue(Color.isWideGamut(pack(0.5f, 0.7f, 1.0f, 1.0f, p3)));
+
+        assertFalse(Color.valueOf(0.5f, 0.7f, 1.0f).isWideGamut());
+        assertTrue(Color.valueOf(0.5f, 0.7f, 1.0f, 1.0f, p3).isWideGamut());
+    }
+
+    @Test
+    public void testIsInColorSpace() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+
+        assertFalse(Color.isInColorSpace(pack(0.5f, 0.7f, 1.0f), p3));
+        assertTrue(Color.isInColorSpace(pack(0.5f, 0.7f, 1.0f, 1.0f, p3), p3));
+    }
+
+    @Test
+    public void testValueOf() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+
+        Color color1 = valueOf(0x7fff00ff);
+        assertEquals(1.0f, color1.red(), 0.01f);
+        assertEquals(0.0f, color1.green(), 0.01f);
+        assertEquals(1.0f, color1.blue(), 0.01f);
+        assertEquals(0.5f, color1.alpha(), 0.01f);
+        assertTrue(color1.getColorSpace().isSrgb());
+
+        Color color2 = valueOf(0.5f, 0.7f, 1.0f);
+        assertEquals(0.5f, color2.red(), 0.01f);
+        assertEquals(0.7f, color2.green(), 0.01f);
+        assertEquals(1.0f, color2.blue(), 0.01f);
+        assertEquals(1.0f, color2.alpha(), 0.01f);
+        assertTrue(color2.getColorSpace().isSrgb());
+
+        Color color3 = valueOf(0.5f, 0.5f, 1.0f, 0.25f);
+        assertEquals(0.5f, color3.red(), 0.01f);
+        assertEquals(0.5f, color3.green(), 0.01f);
+        assertEquals(1.0f, color3.blue(), 0.01f);
+        assertEquals(0.25f, color3.alpha(), 0.01f);
+        assertTrue(color3.getColorSpace().isSrgb());
+
+        Color color4 = valueOf(0.5f, 0.5f, 1.0f, 0.25f, p3);
+        assertEquals(0.5f, color4.red(), 0.01f);
+        assertEquals(0.5f, color4.green(), 0.01f);
+        assertEquals(1.0f, color4.blue(), 0.01f);
+        assertEquals(0.25f, color4.alpha(), 0.01f);
+        assertFalse(color4.getColorSpace().isSrgb());
+        assertEquals(p3, color4.getColorSpace());
+
+        Color color5 = valueOf(pack(0.5f, 0.5f, 1.0f, 0.25f, p3));
+        assertEquals(0.5f, color5.red(), 0.01f);
+        assertEquals(0.5f, color5.green(), 0.01f);
+        assertEquals(1.0f, color5.blue(), 0.01f);
+        assertEquals(0.25f, color5.alpha(), 0.01f);
+        assertFalse(color5.getColorSpace().isSrgb());
+        assertEquals(p3, color5.getColorSpace());
+
+        Color color6 = valueOf(pack(0.5f, 0.5f, 1.0f, 0.25f));
+        assertEquals(0.5f, color6.red(), 0.01f);
+        assertEquals(0.5f, color6.green(), 0.01f);
+        assertEquals(1.0f, color6.blue(), 0.01f);
+        assertEquals(0.25f, color6.alpha(), 0.01f);
+        assertTrue(color6.getColorSpace().isSrgb());
+
+        Color color7 = valueOf(new float[] { 0.5f, 0.5f, 1.0f, 0.25f }, ColorSpace.get(Named.SRGB));
+        assertEquals(0.5f, color7.red(), 0.01f);
+        assertEquals(0.5f, color7.green(), 0.01f);
+        assertEquals(1.0f, color7.blue(), 0.01f);
+        assertEquals(0.25f, color7.alpha(), 0.01f);
+        assertTrue(color7.getColorSpace().isSrgb());
+
+        float[] components = { 0.5f, 0.5f, 1.0f, 0.25f, 0.5f, 0.8f };
+        Color color8 = valueOf(components, ColorSpace.get(Named.SRGB));
+        assertEquals(0.5f, color8.red(), 0.01f);
+        assertEquals(0.5f, color8.green(), 0.01f);
+        assertEquals(1.0f, color8.blue(), 0.01f);
+        assertEquals(0.25f, color8.alpha(), 0.01f);
+        assertTrue(color8.getColorSpace().isSrgb());
+        // Make sure we received a copy
+        components[0] = 127.0f;
+        assertNotEquals(color8.red(), components[0]);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testValueOfFailure() {
+        valueOf(new float[] { 0.5f, 0.5f, 1.0f }, ColorSpace.get(Named.SRGB));
+    }
+
+    @Test
+    public void testModel() {
+        Color c = valueOf(new float[] { 0.5f, 0.5f, 1.0f, 1.0f }, ColorSpace.get(Named.CIE_XYZ));
+        assertEquals(ColorSpace.Model.XYZ, c.getModel());
+    }
+
+    @Test
+    public void testComponents() {
+        Color c = valueOf(0.1f, 0.2f, 0.3f, 0.4f);
+
+        assertEquals(4, c.getComponentCount());
+        assertEquals(c.red(), c.getComponent(0), 0.0f);
+        assertEquals(c.green(), c.getComponent(1), 0.0f);
+        assertEquals(c.blue(), c.getComponent(2), 0.0f);
+        assertEquals(c.alpha(), c.getComponent(3), 0.0f);
+
+        float[] components = c.getComponents();
+        assertEquals(c.getComponentCount(), components.length);
+        assertEquals(c.red(), components[0], 0.0f);
+        assertEquals(c.green(), components[1], 0.0f);
+        assertEquals(c.blue(), components[2], 0.0f);
+        assertEquals(c.alpha(), components[3], 0.0f);
+
+        // Make sure we received a copy
+        components[0] = 127.0f;
+        assertNotEquals(c.red(), components[0]);
+    }
+
+    @Test(expected = ArrayIndexOutOfBoundsException.class)
+    public void testComponentOutOfBounds() {
+        valueOf(0.1f, 0.2f, 0.3f, 0.4f).getComponent(4);
+    }
+
+    @Test
+    public void testToArgb() {
+        assertEquals(0xff8000ff, toArgb(pack(0.5f, 0.0f, 1.0f)));
+
+        long color = pack(0.8912f, 0.4962f, 0.1164f, 1.0f, ColorSpace.get(Named.ADOBE_RGB));
+        // Red if 0x7f instead of 0x80 because the rounding error caused by the
+        // intermediate fp16 representation
+        assertEquals(0xffff7f00, toArgb(color));
+
+        assertEquals(0xff8000ff, valueOf(0.5f, 0.0f, 1.0f).toArgb());
+        assertEquals(0xffff7f00,
+                valueOf(0.8912f, 0.4962f, 0.1164f, 1.0f, ColorSpace.get(Named.ADOBE_RGB)).toArgb());
+    }
+
+    @Test
+    public void testPackSrgb() {
+        ColorSpace srgb = ColorSpace.get(Named.SRGB);
+
+        long color1 = pack(0.5f, 0.0f, 1.0f);
+        long color2 = pack(0.5f, 0.0f, 1.0f, 1.0f);
+        long color3 = pack(0.5f, 0.0f, 1.0f, 1.0f, srgb);
+
+        assertEquals(color1, color2);
+        assertEquals(color1, color3);
+
+        assertEquals(0xff8000ff, (int) (color1 >>> 32));
+
+        long color4 = pack(0.5f, 0.0f, 1.0f);
+
+        assertEquals(0.5f, red(color4), 0.01f);
+        assertEquals(0.0f, green(color4), 0.01f);
+        assertEquals(1.0f, blue(color4), 0.01f);
+        assertEquals(1.0f, alpha(color4), 0.01f);
+
+        long color5 = pack(0xff8000ff);
+
+        assertEquals(color1, color5);
+        assertEquals(0xff8000ff, (int) (color5 >>> 32));
+
+        assertEquals(color1, valueOf(0.5f, 0.0f, 1.0f).pack());
+    }
+
+    @Test
+    public void testPack() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+        long color = pack(0.5f, 0.0f, 1.0f, 0.25f, p3);
+
+        assertEquals(0.5f, red(color), 0.01f);
+        assertEquals(0.0f, green(color), 0.01f);
+        assertEquals(1.0f, blue(color), 0.01f);
+        assertEquals(0.25f, alpha(color), 0.01f);
+
+        assertEquals(color, valueOf(0.5f, 0.0f, 1.0f, 0.25f, p3).pack());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testPackFailure() {
+        ColorSpace colorSpace = new ColorSpace.Rgb("Fake",
+                new float[] { 0.7347f, 0.2653f, 0.1596f, 0.8404f, 0.0366f, 0.0001f },
+                new float[] { 0.34567f, 0.35850f }, x -> x * 2.0f, x -> x / 2.0f, 0.0f, 1.0f);
+        pack(0.5f, 0.0f, 1.0f, 0.25f, colorSpace);
+    }
+
+    @Test
+    public void testLuminanceSrgb() {
+        assertEquals(0.0722f, luminance(pack(0.0f, 0.0f, 1.0f)), 0.000001f);
+        assertEquals(0.2126f, luminance(pack(1.0f, 0.0f, 0.0f)), 0.000001f);
+        assertEquals(0.7152f, luminance(pack(0.0f, 1.0f, 0.0f)), 0.000001f);
+        assertEquals(1.0f,    luminance(pack(1.0f, 1.0f, 1.0f)), 0.0f);
+        assertEquals(0.0f,    luminance(pack(0.0f, 0.0f, 0.0f)), 0.0f);
+
+        assertEquals(0.0722f, valueOf(0.0f, 0.0f, 1.0f).luminance(), 0.000001f);
+        assertEquals(0.2126f, valueOf(1.0f, 0.0f, 0.0f).luminance(), 0.000001f);
+        assertEquals(0.7152f, valueOf(0.0f, 1.0f, 0.0f).luminance(), 0.000001f);
+        assertEquals(1.0f,    valueOf(1.0f, 1.0f, 1.0f).luminance(), 0.0f);
+        assertEquals(0.0f,    valueOf(0.0f, 0.0f, 0.0f).luminance(), 0.0f);
+    }
+
+    @Test
+    public void testLuminance() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+        assertEquals(0.0722f, luminance(pack(0.0f, 0.0f, 1.0f, 1.0f, p3)), 0.000001f);
+        assertEquals(0.2126f, luminance(pack(1.0f, 0.0f, 0.0f, 1.0f, p3)), 0.000001f);
+        assertEquals(0.7152f, luminance(pack(0.0f, 1.0f, 0.0f, 1.0f, p3)), 0.000001f);
+        assertEquals(1.0f,    luminance(pack(1.0f, 1.0f, 1.0f, 1.0f, p3)), 0.0f);
+        assertEquals(0.0f,    luminance(pack(0.0f, 0.0f, 0.0f, 1.0f, p3)), 0.0f);
+
+        assertEquals(0.0722f, valueOf(0.0f, 0.0f, 1.0f, 1.0f, p3).luminance(), 0.000001f);
+        assertEquals(0.2126f, valueOf(1.0f, 0.0f, 0.0f, 1.0f, p3).luminance(), 0.000001f);
+        assertEquals(0.7152f, valueOf(0.0f, 1.0f, 0.0f, 1.0f, p3).luminance(), 0.000001f);
+        assertEquals(1.0f,    valueOf(1.0f, 1.0f, 1.0f, 1.0f, p3).luminance(), 0.0f);
+        assertEquals(0.0f,    valueOf(0.0f, 0.0f, 0.0f, 1.0f, p3).luminance(), 0.0f);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testLuminanceFunctionFailure() {
+        luminance(pack(1.0f, 1.0f, 1.0f, 1.0f, ColorSpace.get(Named.CIE_LAB)));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testLuminanceMethodFailure() {
+        valueOf(1.0f, 1.0f, 1.0f, 1.0f, ColorSpace.get(Named.CIE_LAB)).luminance();
+    }
+
+    @Test
+    public void testConvertMethod() {
+        Color sRgb = Color.valueOf(1.0f, 0.5f, 0.0f);
+        Color adobeRgb = sRgb.convert(ColorSpace.get(Named.ADOBE_RGB));
+
+        assertEquals(ColorSpace.get(Named.ADOBE_RGB), adobeRgb.getColorSpace());
+        assertEquals(0.8912f, adobeRgb.red(), 0.001f);
+        assertEquals(0.4962f, adobeRgb.green(), 0.001f);
+        assertEquals(0.1164f, adobeRgb.blue(), 0.001f);
+    }
+
+    @Test
+    public void testConvertColorInt() {
+        long color = convert(0xffff8000, ColorSpace.get(Named.ADOBE_RGB));
+
+        assertEquals(ColorSpace.get(Named.ADOBE_RGB), colorSpace(color));
+        assertEquals(0.8912f, red(color), 0.01f);
+        assertEquals(0.4962f, green(color), 0.01f);
+        assertEquals(0.1164f, blue(color), 0.01f);
+    }
+
+    @Test
+    public void testConvertColorLong() {
+        long color = convert(pack(1.0f, 0.5f, 0.0f, 1.0f, ColorSpace.get(Named.DISPLAY_P3)),
+                ColorSpace.get(Named.ADOBE_RGB));
+
+        assertEquals(0.9499f, red(color), 0.01f);
+        assertEquals(0.4597f, green(color), 0.01f);
+        assertEquals(0.0000f, blue(color), 0.01f);
+    }
+
+    @Test
+    public void testConvertConnector() {
+        ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
+        ColorSpace.Connector connector = ColorSpace.connect(p3, ColorSpace.get(Named.ADOBE_RGB));
+        long color = convert(pack(1.0f, 0.5f, 0.0f, 1.0f, p3), connector);
+
+        assertEquals(0.9499f, red(color), 0.01f);
+        assertEquals(0.4597f, green(color), 0.01f);
+        assertEquals(0.0000f, blue(color), 0.01f);
+
+        color = convert(1.0f, 0.5f, 0.0f, 1.0f, connector);
+
+        assertEquals(0.9499f, red(color), 0.01f);
+        assertEquals(0.4597f, green(color), 0.01f);
+        assertEquals(0.0000f, blue(color), 0.01f);
+    }
+
+    @Test
+    public void testConvert() {
+        long color = convert(1.0f, 0.5f, 0.0f, 1.0f,
+                ColorSpace.get(Named.DISPLAY_P3), ColorSpace.get(Named.ADOBE_RGB));
+
+        assertEquals(0.9499f, red(color), 0.01f);
+        assertEquals(0.4597f, green(color), 0.01f);
+        assertEquals(0.0000f, blue(color), 0.01f);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 15a3a43..4916ffa 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -900,21 +900,6 @@
     }
 
     @Test
-    public void testSetGetFontVariationSettings() {
-        Paint p = new Paint();
-
-        // The default variation settings should be null.
-        assertNull(p.getFontVariationSettings());
-
-        final String settings = "'wdth' 1.0";
-        p.setFontVariationSettings(settings);
-        assertEquals(settings, p.getFontVariationSettings());
-
-        p.setFontVariationSettings("");
-        assertNull(p.getFontVariationSettings());
-    }
-
-    @Test
     public void testGetTextBounds() {
         Paint p = new Paint();
         p.setTextSize(10);
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index 68828ac..ae1b804 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -30,7 +30,9 @@
         core-tests-support \
         compatibility-device-util \
         ctstestrunner \
-        guava
+        guava \
+        junit \
+        legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/keystore/src/android/keystore/cts/AuthorizationList.java b/tests/tests/keystore/src/android/keystore/cts/AuthorizationList.java
index d488b26..f3ee3e4 100644
--- a/tests/tests/keystore/src/android/keystore/cts/AuthorizationList.java
+++ b/tests/tests/keystore/src/android/keystore/cts/AuthorizationList.java
@@ -79,6 +79,8 @@
     public static final int KM_PURPOSE_DECRYPT = 1;
     public static final int KM_PURPOSE_SIGN = 2;
     public static final int KM_PURPOSE_VERIFY = 3;
+    public static final int KM_PURPOSE_DERIVE_KEY = 4;
+    public static final int KM_PURPOSE_WRAP_KEY = 5;
 
     // User authenticators.
     public static final int HW_AUTH_PASSWORD = 1 << 0;
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 4c27d0e..98f85e7 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -29,6 +29,7 @@
 import static android.keystore.cts.AuthorizationList.KM_PURPOSE_ENCRYPT;
 import static android.keystore.cts.AuthorizationList.KM_PURPOSE_SIGN;
 import static android.keystore.cts.AuthorizationList.KM_PURPOSE_VERIFY;
+import static android.keystore.cts.AuthorizationList.KM_PURPOSE_WRAP_KEY;
 import static android.keystore.cts.RootOfTrust.KM_VERIFIED_BOOT_VERIFIED;
 import static android.security.keystore.KeyProperties.DIGEST_NONE;
 import static android.security.keystore.KeyProperties.DIGEST_SHA256;
@@ -42,6 +43,7 @@
 import static android.security.keystore.KeyProperties.PURPOSE_ENCRYPT;
 import static android.security.keystore.KeyProperties.PURPOSE_SIGN;
 import static android.security.keystore.KeyProperties.PURPOSE_VERIFY;
+import static android.security.keystore.KeyProperties.PURPOSE_WRAP_KEY;
 import static android.security.keystore.KeyProperties.SIGNATURE_PADDING_RSA_PKCS1;
 import static android.security.keystore.KeyProperties.SIGNATURE_PADDING_RSA_PSS;
 import static org.hamcrest.CoreMatchers.is;
@@ -220,6 +222,7 @@
         int[] purposes = {
                 PURPOSE_SIGN | PURPOSE_VERIFY,
                 PURPOSE_ENCRYPT | PURPOSE_DECRYPT,
+                PURPOSE_WRAP_KEY,
         };
         String[][] encryptionPaddingModes = {
                 {
@@ -249,13 +252,18 @@
                 },
         };
 
+        // We don't allow the caller to specify padding mode for wrapping.
+        String[][] wrapKeyPaddingModes = {};
+
         for (int keySize : keySizes) {
             for (byte[] challenge : challenges) {
                 for (int purpose : purposes) {
                     if (isEncryptionPurpose(purpose)) {
                         testRsaAttestations(keySize, challenge, purpose, encryptionPaddingModes);
-                    } else {
+                    } else if (isSignaturePurpose(purpose)){
                         testRsaAttestations(keySize, challenge, purpose, signaturePaddingModes);
+                    } else {
+                        testRsaAttestations(keySize, challenge, purpose, wrapKeyPaddingModes);
                     }
                 }
             }
@@ -378,6 +386,7 @@
             // Because we sometimes set "no padding", allow non-randomized encryption.
             builder.setRandomizedEncryptionRequired(false);
         }
+
         if (isSignaturePurpose(purposes)) {
             builder.setSignaturePaddings(paddingModes);
         }
@@ -413,6 +422,10 @@
             expectedKeyUsage[KEY_USAGE_KEY_ENCIPHERMENT_BIT_OFFSET] = true;
             expectedKeyUsage[KEY_USAGE_DATA_ENCIPHERMENT_BIT_OFFSET] = true;
         }
+        if (isWrapPurpose(purposes)) {
+            expectedKeyUsage[KEY_USAGE_KEY_ENCIPHERMENT_BIT_OFFSET] = true;
+            expectedKeyUsage[KEY_USAGE_DATA_ENCIPHERMENT_BIT_OFFSET] = false;
+        }
         assertThat(attestationCert.getKeyUsage(), is(expectedKeyUsage));
     }
 
@@ -803,6 +816,10 @@
         return (purposes & PURPOSE_SIGN) != 0 || (purposes & PURPOSE_VERIFY) != 0;
     }
 
+    private boolean isWrapPurpose(int purposes) {
+        return (purposes & PURPOSE_WRAP_KEY) != 0;
+    }
+
     private ImmutableSet<Integer> buildPurposeSet(int purposes) {
         ImmutableSet.Builder<Integer> builder = ImmutableSet.builder();
         if ((purposes & PURPOSE_SIGN) != 0)
@@ -813,6 +830,8 @@
             builder.add(KM_PURPOSE_ENCRYPT);
         if ((purposes & PURPOSE_DECRYPT) != 0)
             builder.add(KM_PURPOSE_DECRYPT);
+        if ((purposes & PURPOSE_WRAP_KEY) != 0)
+            builder.add(KM_PURPOSE_WRAP_KEY);
         return builder.build();
     }
 
diff --git a/tests/tests/libcorefileio/Android.mk b/tests/tests/libcorefileio/Android.mk
index 29226bf..d329c9d 100644
--- a/tests/tests/libcorefileio/Android.mk
+++ b/tests/tests/libcorefileio/Android.mk
@@ -21,7 +21,7 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner junit legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/location/src/android/location/cts/LocationManagerTest.java b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
index f829bf3..3af213e 100644
--- a/tests/tests/location/src/android/location/cts/LocationManagerTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
@@ -994,16 +994,24 @@
     }
 
     /**
-     * Test case for bug 33091107.
+     * Test case for bug 33091107, where a malicious app used to be able to fool a real provider
+     * into providing a mock location that isn't marked as being mock.
      */
     public void testLocationShouldStillBeMarkedMockWhenProvidersDoNotMatch()
-        throws InterruptedException {
+            throws InterruptedException {
         double latitude = 20;
         double longitude = 40;
 
-        // Register a listener for the location we are about to set.
-        updateLocationAndWait(
-                TEST_MOCK_PROVIDER_NAME, LocationManager.GPS_PROVIDER, latitude, longitude);
+        List<String> providers = mManager.getAllProviders();
+        if (providers.isEmpty()) {
+            // Device doesn't have any providers. Can't perform this test, and no need to do so:
+            // no providers that malicious app could fool
+            return;
+        }
+        String realProviderToFool = providers.get(0);
+
+        // Register for location updates, then set a mock location and ensure it is marked "mock"
+        updateLocationAndWait(TEST_MOCK_PROVIDER_NAME, realProviderToFool, latitude, longitude);
     }
 
     @UiThreadTest
diff --git a/tests/tests/location2/Android.mk b/tests/tests/location2/Android.mk
index 4273444..a081213 100644
--- a/tests/tests/location2/Android.mk
+++ b/tests/tests/location2/Android.mk
@@ -24,7 +24,7 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner junit legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 1886093..92f4755 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -44,7 +44,14 @@
 # include both the 32 and 64 bit versions
 LOCAL_MULTILIB := both
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctsmediautil compatibility-device-util ctstestserver ctstestrunner ndkaudio android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctsmediautil \
+    compatibility-device-util \
+    ctstestserver \
+    ctstestrunner \
+    ndkaudio \
+    junit \
+    legacy-android-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni libaudio_jni libnativehelper_compat_libc++ libndkaudioLib
 
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index 700ecfd..2801dd0 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -30,8 +30,9 @@
 import android.media.MediaRecorder.OnErrorListener;
 import android.media.MediaRecorder.OnInfoListener;
 import android.media.MediaMetadataRetriever;
-import android.os.Environment;
 import android.os.ConditionVariable;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
 import android.support.test.filters.SmallTest;
 import android.platform.test.annotations.RequiresDevice;
 import android.test.ActivityInstrumentationTestCase2;
@@ -45,8 +46,11 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
 import java.lang.InterruptedException;
 import java.lang.Runnable;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -90,10 +94,14 @@
     private File mOutFile2;
     private Camera mCamera;
     private MediaStubActivity mActivity = null;
+    private int mFileIndex;
 
     private MediaRecorder mMediaRecorder;
     private ConditionVariable mMaxDurationCond;
     private ConditionVariable mMaxFileSizeCond;
+    private ConditionVariable mMaxFileSizeApproachingCond;
+    private ConditionVariable mNextOutputFileStartedCond;
+    private boolean mExpectMaxFileCond;
 
     public MediaRecorderTest() {
         super("android.media.cts", MediaStubActivity.class);
@@ -129,9 +137,13 @@
                 mMediaRecorder = new MediaRecorder();
                 mOutFile = new File(OUTPUT_PATH);
                 mOutFile2 = new File(OUTPUT_PATH2);
+                mFileIndex = 0;
 
                 mMaxDurationCond = new ConditionVariable();
                 mMaxFileSizeCond = new ConditionVariable();
+                mMaxFileSizeApproachingCond = new ConditionVariable();
+                mNextOutputFileStartedCond = new ConditionVariable();
+                mExpectMaxFileCond = true;
 
                 mMediaRecorder.setOutputFile(OUTPUT_PATH);
                 mMediaRecorder.setOnInfoListener(new OnInfoListener() {
@@ -178,6 +190,10 @@
         mMaxDurationCond = null;
         mMaxFileSizeCond.close();
         mMaxFileSizeCond = null;
+        mMaxFileSizeApproachingCond.close();
+        mMaxFileSizeApproachingCond = null;
+        mNextOutputFileStartedCond.close();
+        mNextOutputFileStartedCond = null;
         mActivity = null;
         super.tearDown();
     }
@@ -593,10 +609,163 @@
         checkOutputFileSize(OUTPUT_PATH, fileSize, tolerance);
     }
 
+    public void testRecordExceedFileSizeLimit() throws Exception {
+        if (!hasMicrophone() || !hasCamera() || !hasAmrNb() || !hasH264()) {
+            MediaUtils.skipTest("no microphone, camera, or codecs");
+            return;
+        }
+        long fileSize = 128 * 1024;
+        long tolerance = 50 * 1024;
+        List<String> recordFileList = new ArrayList<String>();
+        mFileIndex = 0;
+
+        // Override the handler in setup for test.
+        mMediaRecorder.setOnInfoListener(new OnInfoListener() {
+            public void onInfo(MediaRecorder mr, int what, int extra) {
+                mOnInfoCalled = true;
+                if (what ==
+                    MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
+                    Log.v(TAG, "max duration reached");
+                    mMaxDurationCond.open();
+                } else if (what ==
+                    MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
+                    if (!mExpectMaxFileCond) {
+                        fail("Do not expect MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED");
+                    } else {
+                        Log.v(TAG, "max file size reached");
+                        mMaxFileSizeCond.open();
+                    }
+                } else if (what ==
+                    MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING) {
+                    Log.v(TAG, "max file size is approaching");
+                    mMaxFileSizeApproachingCond.open();
+
+                    // Test passing a read-only FileDescriptor and expect IOException.
+                    if (mFileIndex == 1) {
+                        RandomAccessFile file = null;
+                        try {
+                            String path = OUTPUT_PATH + '0';
+                            file = new RandomAccessFile(path, "r");
+                            mMediaRecorder.setNextOutputFile(file.getFD());
+                            fail("Expect IOException.");
+                        } catch (IOException e) {
+                            // Expected.
+                        } finally {
+                            try {
+                                file.close();
+                            } catch (IOException e) {
+                                fail("Fail to close file");
+                            }
+                        }
+                    }
+
+                    // Test passing a read-only FileDescriptor and expect IOException.
+                    if (mFileIndex == 2) {
+                        ParcelFileDescriptor out = null;
+                        String path = null;
+                        try {
+                            path = OUTPUT_PATH + '0';
+                            out = ParcelFileDescriptor.open(new File(path),
+                                    ParcelFileDescriptor.MODE_READ_ONLY | ParcelFileDescriptor.MODE_CREATE);
+                            mMediaRecorder.setNextOutputFile(out.getFileDescriptor());
+                            fail("Expect IOException.");
+                        } catch (IOException e) {
+                            // Expected.
+                        } finally {
+                            try {
+                                out.close();
+                            } catch (IOException e) {
+                                fail("Fail to close file");
+                            }
+                        }
+                    }
+
+                    // Test passing a write-only FileDescriptor and expect IOException.
+                    if (mFileIndex == 3) {
+                        ParcelFileDescriptor out = null;
+                        String path = null;
+                        try {
+                            path = OUTPUT_PATH + '9';
+                            out = ParcelFileDescriptor.open(new File(path),
+                                    ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_CREATE);
+                            mMediaRecorder.setNextOutputFile(out.getFileDescriptor());
+                            fail("Expect IOException.");
+                        } catch (IOException e) {
+                            // Expected.
+                        } finally {
+                            try {
+                                out.close();
+                                new File(path).delete();
+                            } catch (IOException e) {
+                                fail("Fail to close file");
+                            }
+                        }
+                    }
+
+                    // only record 5 files.
+                    if (mFileIndex < 6) {
+                        try {
+                            String path = OUTPUT_PATH + mFileIndex;
+                            mMediaRecorder.setNextOutputFile(path);
+                            recordFileList.add(path);
+                            mFileIndex++;
+                        } catch (IOException e) {
+                            fail("Fail to set next output file error: " + e);
+                        }
+                    }
+                } else if (what ==
+                    MediaRecorder.MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED) {
+                    Log.v(TAG, "Next output file started");
+                    mNextOutputFileStartedCond.open();
+                }
+            }
+        });
+        mExpectMaxFileCond = false;
+        mMediaRecorder.setOutputFile(OUTPUT_PATH + mFileIndex);
+        recordFileList.add(OUTPUT_PATH + mFileIndex);
+        mFileIndex++;
+        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
+        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
+        mMediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);
+        mMediaRecorder.setVideoEncodingBitRate(256000);
+        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
+        mMediaRecorder.setMaxFileSize(fileSize);
+        mMediaRecorder.prepare();
+        mMediaRecorder.start();
+
+        // Record total 5 files including previous one.
+        int fileCount = 0;
+        while (fileCount < 5) {
+            if (!mMaxFileSizeApproachingCond.block(MAX_FILE_SIZE_TIMEOUT_MS)) {
+                fail("timed out waiting for MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING");
+            }
+            if (!mNextOutputFileStartedCond.block(MAX_FILE_SIZE_TIMEOUT_MS)) {
+                fail("timed out waiting for MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED");
+            }
+            fileCount++;
+            mMaxFileSizeApproachingCond.close();
+            mNextOutputFileStartedCond.close();
+        }
+
+        mExpectMaxFileCond = true;
+        if (!mMaxFileSizeCond.block(MAX_FILE_SIZE_TIMEOUT_MS)) {
+            fail("timed out waiting for MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED");
+        }
+        mMediaRecorder.stop();
+
+        for (String filePath : recordFileList) {
+            checkOutputFileSize(filePath, fileSize, tolerance);
+        }
+    }
+
     private void checkOutputFileSize(final String fileName, long fileSize, long tolerance) {
-        assertTrue(mOutFile.exists());
-        assertEquals(fileSize, mOutFile.length(), tolerance);
-        assertTrue(mOutFile.delete());
+        File file = new File(fileName);
+        assertTrue(file.exists());
+        assertEquals(fileSize, file.length(), tolerance);
+        assertTrue(file.delete());
     }
 
     public void testOnErrorListener() throws Exception {
diff --git a/tests/tests/net/Android.mk b/tests/tests/net/Android.mk
index 4a77640..98cde9b 100644
--- a/tests/tests/net/Android.mk
+++ b/tests/tests/net/Android.mk
@@ -34,8 +34,14 @@
 
 LOCAL_PACKAGE_NAME := CtsNetTestCases
 
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support  compatibility-device-util \
-                               ctstestrunner ctstestserver mockwebserver
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    core-tests-support \
+    compatibility-device-util \
+    ctstestrunner \
+    ctstestserver \
+    mockwebserver \
+    junit \
+    legacy-android-test
 
 # uncomment when b/13249961 is fixed
 #LOCAL_SDK_VERSION := current
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index 897e5cf..dcedb18 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -22,7 +22,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.location.LocationManager;
 import android.net.NetworkInfo;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
@@ -35,6 +34,8 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import com.android.compatibility.common.util.WifiConfigCreator;
+
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.util.HashSet;
@@ -68,6 +69,8 @@
     private static final String TAG = "WifiManagerTest";
     private static final String SSID1 = "\"WifiManagerTest\"";
     private static final String SSID2 = "\"WifiManagerTestModified\"";
+    private static final String PROXY_TEST_SSID = "SomeProxyAp";
+    private static final String ADD_NETWORK_EXCEPTION_SUBSTR = "addNetwork";
     private static final int TIMEOUT_MSEC = 6000;
     private static final int WAIT_MSEC = 60;
     private static final int DURATION = 10000;
@@ -75,6 +78,8 @@
     private static final int WIFI_SCAN_TEST_CACHE_DELAY_MILLIS = 3 * 60 * 1000;
     private static final int WIFI_SCAN_TEST_ITERATIONS = 5;
 
+    private static final String TEST_PAC_URL = "http://www.example.com/proxy.pac";
+
     private IntentFilter mIntentFilter;
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -405,6 +410,31 @@
         }
     }
 
+    /**
+     * Verifies that addNetwork() fails for WifiConfigurations containing a non-null http proxy when
+     * the caller doesn't have OVERRIDE_WIFI_CONFIG permission, DeviceOwner or ProfileOwner device
+     * management policies
+     */
+    public void testSetHttpProxy_PermissionFail() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        WifiConfigCreator configCreator = new WifiConfigCreator(getContext());
+        boolean exceptionThrown = false;
+        try {
+            configCreator.addHttpProxyNetworkVerifyAndRemove(
+                    PROXY_TEST_SSID, TEST_PAC_URL);
+        } catch (IllegalStateException e) {
+            // addHttpProxyNetworkVerifyAndRemove throws three IllegalStateException,
+            // expect it to throw for the addNetwork operation
+            if (e.getMessage().contains(ADD_NETWORK_EXCEPTION_SUBSTR)) {
+                exceptionThrown = true;
+            }
+        }
+        assertTrue(exceptionThrown);
+    }
+
     private Set<String> getEnabledNetworks(List<WifiConfiguration> configuredNetworks) {
         Set<String> ssids = new HashSet<String>();
         for (WifiConfiguration wifiConfig : configuredNetworks) {
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index 7effcab..c99e236 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -25,7 +25,12 @@
 LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test compatibility-device-util ctstestrunner guava platform-test-annotations
+    android-support-test \
+    compatibility-device-util \
+    ctstestrunner \
+    guava \
+    junit \
+    legacy-android-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/os/jni/Android.mk b/tests/tests/os/jni/Android.mk
index 1e4eb25..bcb9d6f 100644
--- a/tests/tests/os/jni/Android.mk
+++ b/tests/tests/os/jni/Android.mk
@@ -30,6 +30,15 @@
 		android_os_cts_NoExecutePermissionTest.cpp \
 		android_os_cts_SeccompTest.cpp
 
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libnativehelper_compat_libc++ liblog libdl
+LOCAL_CXX_STL := none
+
+LOCAL_SRC_FILES += android_os_cts_CpuFeatures.cpp
+LOCAL_C_INCLUDES += ndk/sources/cpufeatures
+LOCAL_STATIC_LIBRARIES := cpufeatures libc++_static libminijail
+
 # Select the architectures on which seccomp-bpf are supported. This is used to
 # include extra test files that will not compile on architectures where it is
 # not supported.
@@ -42,19 +51,10 @@
 endif
 
 ifeq ($(ARCH_SUPPORTS_SECCOMP),1)
-	LOCAL_SRC_FILES += seccomp-tests/tests/seccomp_bpf_tests.c
+	LOCAL_STATIC_LIBRARIES += external_seccomp_tests
 
 	# This define controls the behavior of OSFeatures.needsSeccompSupport().
 	LOCAL_CFLAGS += -DARCH_SUPPORTS_SECCOMP
 endif
 
-LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
-
-LOCAL_SHARED_LIBRARIES := libnativehelper_compat_libc++ liblog libdl
-LOCAL_CXX_STL := none
-
-LOCAL_SRC_FILES += android_os_cts_CpuFeatures.cpp
-LOCAL_C_INCLUDES += ndk/sources/cpufeatures
-LOCAL_STATIC_LIBRARIES := cpufeatures libc++_static libminijail
-
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/os/jni/android_os_cts_SeccompTest.cpp b/tests/tests/os/jni/android_os_cts_SeccompTest.cpp
index 44cfc7e..b853c96 100644
--- a/tests/tests/os/jni/android_os_cts_SeccompTest.cpp
+++ b/tests/tests/os/jni/android_os_cts_SeccompTest.cpp
@@ -21,15 +21,9 @@
 
 #if defined(ARCH_SUPPORTS_SECCOMP)
 #include <libminijail.h>
+#include <seccomp_bpf_tests.h>
 #endif
 
-#include "seccomp-tests/tests/test_harness.h"
-
-// Forward declare from seccomp_bpf_tests.c.
-extern "C" {
-struct __test_metadata* get_seccomp_test_list();
-}
-
 static const char TAG[] = "SeccompBpfTest-Native";
 
 jboolean android_security_cts_SeccompBpfTest_runKernelUnitTest(
@@ -57,6 +51,7 @@
     return false;
 #else
     minijail* j = minijail_new();
+    minijail_no_new_privs(j);
     minijail_use_seccomp_filter(j);
     minijail_set_seccomp_filter_tsync(j);
     minijail_parse_seccomp_filters_from_fd(j, policyFd);
diff --git a/tests/tests/os/jni/seccomp-tests/LICENSE b/tests/tests/os/jni/seccomp-tests/LICENSE
deleted file mode 100644
index b9e779f..0000000
--- a/tests/tests/os/jni/seccomp-tests/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2014 The Chromium OS Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tests/tests/os/jni/seccomp-tests/README b/tests/tests/os/jni/seccomp-tests/README
deleted file mode 100644
index c8cd2ad..0000000
--- a/tests/tests/os/jni/seccomp-tests/README
+++ /dev/null
@@ -1,4 +0,0 @@
-seccomp
--------
-
-Landing place for code relating to seccomp_filter work for the Linux kernel.
diff --git a/tests/tests/os/jni/seccomp-tests/README.android b/tests/tests/os/jni/seccomp-tests/README.android
deleted file mode 100644
index cad678a..0000000
--- a/tests/tests/os/jni/seccomp-tests/README.android
+++ /dev/null
@@ -1,22 +0,0 @@
-This is the kernel unittest for seccomp-bpf sandboxing.
-
-URL: https://github.com/redpig/seccomp
-Revision: e65c79a14dc2bbb6d8dbf12ebf71905e2253a4b2
-License: BSD
-
-Local modifications:
-- Remove usage of pthread_cancel()
-- Use __android_log_print() instead of fprintf()
-- Rename main() to seccomp_test_main()
-- Add get_seccomp_test_list()
-- Backport TEST(syscall_restart) from upstream
-- Add parentheses in macro IS_SECCOMP_EVENT(status),
-  __TEST_IMPL, __TEST_F_IMPL, __EXPECT_STR, and _CONSTRUCTOR_ORDER_BACKWARD.
-
-The diff of modifications can be found in local-modifications-android.diff
-and local-modifications-android-2.diff. Note, the TEST(syscall_restart)
-backport is the only change in local-modifications-android-2.diff
-
-Additional modification is to backport fixes for Android Native Bridge:
-https://patchwork.kernel.org/patch/7537891/. This is not found in the above
-diff file. The patch is located in local-modifications-strict-args-fd88d16.diff.
diff --git a/tests/tests/os/jni/seccomp-tests/local-modifications-android-2.diff b/tests/tests/os/jni/seccomp-tests/local-modifications-android-2.diff
deleted file mode 100644
index b56fc359..0000000
--- a/tests/tests/os/jni/seccomp-tests/local-modifications-android-2.diff
+++ /dev/null
@@ -1,153 +0,0 @@
-diff --git a/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c b/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
-index 3c238e6..7481dd2 100644
---- a/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
-+++ b/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
-@@ -19,7 +19,6 @@
- #include <linux/prctl.h>
- #include <linux/ptrace.h>
- #include <linux/seccomp.h>
--#include <poll.h>
- #include <pthread.h>
- #include <semaphore.h>
- #include <signal.h>
-@@ -28,6 +27,7 @@
- #include <string.h>
- #include <linux/elf.h>
- #include <sys/uio.h>
-+#include <sys/utsname.h>
- #include <fcntl.h>  // ANDROID
- #include <sys/mman.h>
- #include <sys/times.h>
-@@ -1798,7 +1798,8 @@ TEST_F(TSYNC, two_siblings_not_under_filter) {
- }
- 
- /* Make sure restarted syscalls are seen directly as "restart_syscall". */
--TEST(syscall_restart) {
-+TEST(syscall_restart)
-+{
- 	long ret;
- 	unsigned long msg;
- 	pid_t child_pid;
-@@ -1815,20 +1816,25 @@ TEST(syscall_restart) {
- 		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 5, 0),
- 		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_exit, 4, 0),
- 		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_rt_sigreturn, 3, 0),
--		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_poll, 4, 0),
-+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_nanosleep, 4, 0),
- 		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_restart_syscall, 4, 0),
- 
- 		/* Allow __NR_write for easy logging. */
- 		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_write, 0, 1),
- 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
- 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
--		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x100), /* poll */
--		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x200), /* restart */
-+		/* The nanosleep jump target. */
-+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x100),
-+		/* The restart_syscall jump target. */
-+		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x200),
- 	};
- 	struct sock_fprog prog = {
--		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-+		.len = (unsigned short) (sizeof(filter)/sizeof(filter[0])),
- 		.filter = filter,
- 	};
-+#if defined(__arm__)
-+	struct utsname utsbuf;
-+#endif
- 
- 	ASSERT_EQ(0, pipe(pipefd));
- 
-@@ -1837,10 +1843,7 @@ TEST(syscall_restart) {
- 	if (child_pid == 0) {
- 		/* Child uses EXPECT not ASSERT to deliver status correctly. */
- 		char buf = ' ';
--		struct pollfd fds = {
--			.fd = pipefd[0],
--			.events = POLLIN,
--		};
-+		struct timespec timeout = { };
- 
- 		/* Attach parent as tracer and stop. */
- 		EXPECT_EQ(0, ptrace(PTRACE_TRACEME));
-@@ -1864,10 +1867,11 @@ TEST(syscall_restart) {
- 			TH_LOG("Failed to get sync data from read()");
- 		}
- 
--		/* Start poll to be interrupted. */
-+		/* Start nanosleep to be interrupted. */
-+		timeout.tv_sec = 1;
- 		errno = 0;
--		EXPECT_EQ(1, poll(&fds, 1, -1)) {
--			TH_LOG("Call to poll() failed (errno %d)", errno);
-+		EXPECT_EQ(0, nanosleep(&timeout, NULL)) {
-+			TH_LOG("Call to nanosleep() failed (errno %d)", errno);
- 		}
- 
- 		/* Read final sync from parent. */
-@@ -1892,14 +1896,14 @@ TEST(syscall_restart) {
- 	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
- 	ASSERT_EQ(1, write(pipefd[1], ".", 1));
- 
--	/* Wait for poll() to start. */
-+	/* Wait for nanosleep() to start. */
- 	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
- 	ASSERT_EQ(true, WIFSTOPPED(status));
- 	ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
- 	ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
- 	ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
- 	ASSERT_EQ(0x100, msg);
--	EXPECT_EQ(__NR_poll, get_syscall(_metadata, child_pid));
-+	EXPECT_EQ(__NR_nanosleep, get_syscall(_metadata, child_pid));
- 
- 	/* Might as well check siginfo for sanity while we're here. */
- 	ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
-@@ -1910,7 +1914,7 @@ TEST(syscall_restart) {
- 	/* Verify signal delivery came from child (seccomp-triggered). */
- 	EXPECT_EQ(child_pid, info.si_pid);
- 
--	/* Interrupt poll with SIGSTOP (which we'll need to handle). */
-+	/* Interrupt nanosleep with SIGSTOP (which we'll need to handle). */
- 	ASSERT_EQ(0, kill(child_pid, SIGSTOP));
- 	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
- 	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
-@@ -1920,7 +1924,7 @@ TEST(syscall_restart) {
- 	ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
- 	EXPECT_EQ(getpid(), info.si_pid);
- 
--	/* Restart poll with SIGCONT, which triggers restart_syscall. */
-+	/* Restart nanosleep with SIGCONT, which triggers restart_syscall. */
- 	ASSERT_EQ(0, kill(child_pid, SIGCONT));
- 	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
- 	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
-@@ -1934,16 +1938,25 @@ TEST(syscall_restart) {
- 	ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
- 	ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
- 	ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
-+
- 	ASSERT_EQ(0x200, msg);
- 	ret = get_syscall(_metadata, child_pid);
- #if defined(__arm__)
--	/* FIXME: ARM does not expose true syscall in registers. */
--	EXPECT_EQ(__NR_poll, ret);
--#else
--	EXPECT_EQ(__NR_restart_syscall, ret);
-+	/*
-+	 * FIXME:
-+	 * - native ARM registers do NOT expose true syscall.
-+	 * - compat ARM registers on ARM64 DO expose true syscall.
-+	 */
-+	ASSERT_EQ(0, uname(&utsbuf));
-+	if (strncmp(utsbuf.machine, "arm", 3) == 0) {
-+		EXPECT_EQ(__NR_nanosleep, ret);
-+	} else
- #endif
-+	{
-+		EXPECT_EQ(__NR_restart_syscall, ret);
-+	}
- 
--	/* Write again to end poll. */
-+	/* Write again to end test. */
- 	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
- 	ASSERT_EQ(1, write(pipefd[1], "!", 1));
- 	EXPECT_EQ(0, close(pipefd[1]));
diff --git a/tests/tests/os/jni/seccomp-tests/local-modifications-android.diff b/tests/tests/os/jni/seccomp-tests/local-modifications-android.diff
deleted file mode 100644
index 288261a..0000000
--- a/tests/tests/os/jni/seccomp-tests/local-modifications-android.diff
+++ /dev/null
@@ -1,59 +0,0 @@
-diff --git a/tests/seccomp_bpf_tests.c b/tests/seccomp_bpf_tests.c
-index deb78d1..98b0231 100644
---- a/tests/seccomp_bpf_tests.c
-+++ b/tests/seccomp_bpf_tests.c
-@@ -1457,7 +1457,7 @@ FIXTURE_TEARDOWN(TSYNC) {
- 		if (!s->tid)
- 			continue;
- 		if (pthread_kill(s->tid, 0)) {
--			pthread_cancel(s->tid);
-+			//pthread_cancel(s->tid);  // ANDROID
- 			pthread_join(s->tid, &status);
- 		}
- 	}
-@@ -1940,4 +1940,10 @@ TEST(syscall_restart) {
-  * - ...
-  */
- 
-+// ANDROID:begin
-+struct __test_metadata* get_seccomp_test_list() {
-+  return __test_list;
-+}
-+// ANDROID:end
-+
- TEST_HARNESS_MAIN
-diff --git a/tests/test_harness.h b/tests/test_harness.h
-index 47ee027..597e40c 100644
---- a/tests/test_harness.h
-+++ b/tests/test_harness.h
-@@ -49,6 +49,8 @@
- #include <sys/wait.h>
- #include <unistd.h>
- 
-+#include <android/log.h>  // ANDROID
-+
- /* All exported functionality should be declared through this macro. */
- #define TEST_API(x) _##x
- 
-@@ -206,9 +208,11 @@
- } while (0)
- 
- /* Unconditional logger for internal use. */
-+// ANDROID:begin
- #define __TH_LOG(fmt, ...) \
--    fprintf(TH_LOG_STREAM, "%s:%d:%s:" fmt "\n", \
-+    __android_log_print(ANDROID_LOG_ERROR, "SeccompBpfTest-KernelUnit", "%s:%d:%s:" fmt "\n", \
-             __FILE__, __LINE__, _metadata->name, ##__VA_ARGS__)
-+// ANDROID:end
- 
- /* Defines the test function and creates the registration stub. */
- #define _TEST(test_name) __TEST_IMPL(test_name, -1)
-@@ -292,7 +296,7 @@
-     if (!__constructor_order) \
-       __constructor_order = _CONSTRUCTOR_ORDER_BACKWARD; \
-   } \
--  int main(int argc, char **argv) { return test_harness_run(argc, argv); }
-+  int seccomp_test_main(int argc, char **argv) { return test_harness_run(argc, argv); }  // ANDROID
- 
- #define _ASSERT_EQ(_expected, _seen) \
-   __EXPECT(_expected, _seen, ==, 1)
diff --git a/tests/tests/os/jni/seccomp-tests/local-modifications-strict-args-fd88d16.diff b/tests/tests/os/jni/seccomp-tests/local-modifications-strict-args-fd88d16.diff
deleted file mode 100644
index a289147..0000000
--- a/tests/tests/os/jni/seccomp-tests/local-modifications-strict-args-fd88d16.diff
+++ /dev/null
@@ -1,102 +0,0 @@
-diff --git a/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c b/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
-index 98b0231..3c238e6 100644
---- a/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
-+++ b/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
-@@ -28,6 +28,9 @@
- #include <string.h>
- #include <linux/elf.h>
- #include <sys/uio.h>
-+#include <fcntl.h>  // ANDROID
-+#include <sys/mman.h>
-+#include <sys/times.h>
- 
- #define _GNU_SOURCE
- #include <unistd.h>
-@@ -386,14 +389,16 @@ TEST_SIGNAL(KILL_one, SIGSYS) {
- }
- 
- TEST_SIGNAL(KILL_one_arg_one, SIGSYS) {
-+	void *fatal_address;
- 	struct sock_filter filter[] = {
- 		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
- 			offsetof(struct seccomp_data, nr)),
--		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
-+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_times, 1, 0),
- 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
- 		/* Only both with lower 32-bit for now. */
- 		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(0)),
--		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0C0FFEE, 0, 1),
-+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K,
-+			(unsigned long)&fatal_address, 0, 1),
- 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
- 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
- 	};
-@@ -403,23 +408,29 @@ TEST_SIGNAL(KILL_one_arg_one, SIGSYS) {
- 	};
- 	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
- 	pid_t parent = getppid();
--	pid_t pid = getpid();
-+	struct tms timebuf;
-+	clock_t clock = times(&timebuf);
- 	ASSERT_EQ(0, ret);
- 
- 	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
- 	ASSERT_EQ(0, ret);
- 
- 	EXPECT_EQ(parent, syscall(__NR_getppid));
--	EXPECT_EQ(pid, syscall(__NR_getpid));
--	/* getpid() should never return. */
--	EXPECT_EQ(0, syscall(__NR_getpid, 0x0C0FFEE));
-+	EXPECT_LE(clock, syscall(__NR_times, &timebuf));
-+	/* times() should never return. */
-+	EXPECT_EQ(0, syscall(__NR_times, &fatal_address));
- }
- 
- TEST_SIGNAL(KILL_one_arg_six, SIGSYS) {
-+#ifndef __NR_mmap2
-+	int sysno = __NR_mmap;
-+#else
-+	int sysno = __NR_mmap2;
-+#endif
- 	struct sock_filter filter[] = {
- 		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
- 			offsetof(struct seccomp_data, nr)),
--		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
-+		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, sysno, 1, 0),
- 		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
- 		/* Only both with lower 32-bit for now. */
- 		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(5)),
-@@ -433,16 +444,29 @@ TEST_SIGNAL(KILL_one_arg_six, SIGSYS) {
- 	};
- 	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
- 	pid_t parent = getppid();
--	pid_t pid = getpid();
-+	int fd;
-+	void *map1, *map2;
- 	ASSERT_EQ(0, ret);
- 
- 	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
- 	ASSERT_EQ(0, ret);
- 
-+	fd = open("/dev/zero", O_RDONLY);
-+	ASSERT_NE(-1, fd);
-+
- 	EXPECT_EQ(parent, syscall(__NR_getppid));
--	EXPECT_EQ(pid, syscall(__NR_getpid));
--	/* getpid() should never return. */
--	EXPECT_EQ(0, syscall(__NR_getpid, 1, 2, 3, 4, 5, 0x0C0FFEE));
-+	map1 = (void *)syscall(sysno,
-+		NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, PAGE_SIZE);
-+	EXPECT_NE(MAP_FAILED, map1);
-+	/* mmap2() should never return. */
-+	map2 = (void *)syscall(sysno,
-+		 NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0x0C0FFEE);
-+	EXPECT_EQ(MAP_FAILED, map2);
-+
-+	/* The test failed, so clean up the resources. */
-+	munmap(map1, PAGE_SIZE);
-+	munmap(map2, PAGE_SIZE);
-+	close(fd);
- }
- 
- /* TODO(wad) add 64-bit versus 32-bit arg tests. */
diff --git a/tests/tests/os/jni/seccomp-tests/tests/.gitignore b/tests/tests/os/jni/seccomp-tests/tests/.gitignore
deleted file mode 100644
index cdfc7c6..0000000
--- a/tests/tests/os/jni/seccomp-tests/tests/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-sigsegv
-resumption
-seccomp_bpf_tests
diff --git a/tests/tests/os/jni/seccomp-tests/tests/Makefile b/tests/tests/os/jni/seccomp-tests/tests/Makefile
deleted file mode 100644
index 88994b3..0000000
--- a/tests/tests/os/jni/seccomp-tests/tests/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-CFLAGS += -Wall
-EXEC=resumption seccomp_bpf_tests sigsegv
-
-all: $(EXEC)
-
-clean:
-	rm -f $(EXEC)
-
-seccomp_bpf_tests: seccomp_bpf_tests.c test_harness.h
-	$(CC) seccomp_bpf_tests.c -o seccomp_bpf_tests $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -pthread
-
-resumption: resumption.c test_harness.h
-	$(CC) $^ -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -ggdb3
-
-sigsegv: sigsegv.c test_harness.h
-	$(CC) $^ -o $@ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -ggdb3
-
-run_tests: $(EXEC)
-	./seccomp_bpf_tests
-	./resumption
-	./sigsegv
-
-.PHONY: clean run_tests
diff --git a/tests/tests/os/jni/seccomp-tests/tests/resumption.c b/tests/tests/os/jni/seccomp-tests/tests/resumption.c
deleted file mode 100644
index 41795c0..0000000
--- a/tests/tests/os/jni/seccomp-tests/tests/resumption.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/* seccomp_bpf_tests.c
- * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Test code for seccomp bpf.
- */
-
-#include <asm/siginfo.h>
-#define __have_siginfo_t 1
-#define __have_sigval_t 1
-#define __have_sigevent_t 1
-
-#include <linux/filter.h>
-#include <sys/prctl.h>
-#include <linux/prctl.h>
-#include <linux/seccomp.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <string.h>
-#include <syscall.h>
-#define __USE_GNU 1
-#include <sys/ucontext.h>
-#include <sys/mman.h>
-
-#include "test_harness.h"
-
-#ifndef PR_SET_NO_NEW_PRIVS
-#define PR_SET_NO_NEW_PRIVS 38
-#define PR_GET_NO_NEW_PRIVS 39
-#endif
-
-#if defined(__i386__)
-#define REG_IP	REG_EIP
-#define REG_SP	REG_ESP
-#define REG_RESULT	REG_EAX
-#define REG_SYSCALL	REG_EAX
-#define REG_ARG0	REG_EBX
-#define REG_ARG1	REG_ECX
-#define REG_ARG2	REG_EDX
-#define REG_ARG3	REG_ESI
-#define REG_ARG4	REG_EDI
-#define REG_ARG5	REG_EBP
-#elif defined(__x86_64__)
-#define REG_IP	REG_RIP
-#define REG_SP	REG_RSP
-#define REG_RESULT	REG_RAX
-#define REG_SYSCALL	REG_RAX
-#define REG_ARG0	REG_RDI
-#define REG_ARG1	REG_RSI
-#define REG_ARG2	REG_RDX
-#define REG_ARG3	REG_R10
-#define REG_ARG4	REG_R8
-#define REG_ARG5	REG_R9
-#endif
-
-FIXTURE_DATA(TRAP) {
-	struct sock_fprog prog;
-};
-
-/* XXX: will need one per arch, etc.
- *      thankfully _arch can tell us the calling convention!
- */
-extern void *thunk_ip;	/* label for the instruction _after_ syscall */
-static void syscall_thunk(void)
-{
-	asm("syscall; thunk_ip:");
-}
-
-static time_t vsyscall_time(time_t *p)
-{
-	register time_t t asm ("rax");
-	__attribute__((unused)) register time_t *p1 asm ("rdi") = p;
-	__asm__("call 0xffffffffff600400 \n");
-	return t;
-}
-
-
-#if 0
-/* For instance, we could jump here instead. */
-static void compat_thunk(void)
-{
-	asm("int 0x80");
-}
-#endif
-
-FIXTURE_SETUP(TRAP) {
-	/* instruction after the syscall. Will be arch specific, of course. */
-	unsigned long thunk_addr = (unsigned long)&thunk_ip;
-	TH_LOG("Thunk: 0x%lX\n", thunk_addr);
-	{
-		struct sock_filter filter[] = {
-			BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
-				offsetof(struct seccomp_data, nr)),
-			/* Whitelist anything you might need in the sigaction */
-#ifdef __NR_sigreturn
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 3, 0),
-#endif
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 2, 0),
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 1, 0),
-			/* Allow __NR_write so easy logging. */
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 0, 1),
-			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
-			/* Check if we're within the thunk. */
-			BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
-				offsetof(struct seccomp_data, instruction_pointer)),
-			/* XXX: make this 32-bit friendly. */
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ((__u32*)&thunk_addr)[0], 0, 3),
-			BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
-				offsetof(struct seccomp_data, instruction_pointer)+sizeof(int)),
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ((__u32*)&thunk_addr)[1], 0, 1),
-			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
-			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
-		};
-		memset(&self->prog, 0, sizeof(self->prog));
-		self->prog.filter = malloc(sizeof(filter));
-		ASSERT_NE(NULL, self->prog.filter);
-		memcpy(self->prog.filter, filter, sizeof(filter));
-		self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
-	}
-}
-
-FIXTURE_TEARDOWN(TRAP) {
-	if (self->prog.filter)
-		free(self->prog.filter);
-};
-
-struct arch_sigsys {
-		void *_call_addr; /* calling user insn */
-		int _syscall;	/* triggering system call number */
-		unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
-};
-
-static void TRAP_action(int nr, siginfo_t *info, void *void_context)
-{
-	ucontext_t *ctx = (ucontext_t *)void_context;
-	char buf[256];
-	int len;
-	int do_ret = 1;
-	struct arch_sigsys *sys = (struct arch_sigsys *)
-#ifdef si_syscall
-		&(info->si_call_addr);
-#else
-		&(info->si_pid);
-#endif
-
-	if (info->si_code != SYS_SECCOMP)
-		return;
-	if (!ctx)
-		return;
-	len = snprintf(buf, sizeof(buf),
-			"@0x%lX:%X:%d:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX\n",
-			(unsigned long)sys->_call_addr,
-			sys->_arch,
-			sys->_syscall,
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG0],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG1],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG2],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG3],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG4],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG5]);
-	/* Send the soft-fail to our "listener" */
-	syscall(__NR_write, STDOUT_FILENO, buf, len);
-	if (ctx->uc_mcontext.gregs[REG_IP] >= 0xffffffffff600000ULL &&
-	    ctx->uc_mcontext.gregs[REG_IP] < 0xffffffffff601000ULL)
-		do_ret = 0;
-	if (do_ret) {
-		/* push [REG_IP] */
-		ctx->uc_mcontext.gregs[REG_SP] -= sizeof(unsigned long);
-		*((unsigned long *)ctx->uc_mcontext.gregs[REG_SP]) =
-		    ctx->uc_mcontext.gregs[REG_IP];
-	}
-	/* jmp syscall_thunk */
-	ctx->uc_mcontext.gregs[REG_IP] = (unsigned long)syscall_thunk;
-	return;
-}
-
-TEST_F(TRAP, handler) {
-	int ret;
-	struct sigaction act;
-	pid_t pid;
-	sigset_t mask;
-	memset(&act, 0, sizeof(act));
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGSYS);
-
-	act.sa_sigaction = &TRAP_action;
-	act.sa_flags = SA_SIGINFO;
-	ret = sigaction(SIGSYS, &act, NULL);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("sigaction failed");
-	}
-	ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("sigprocmask failed");
-	}
-
-	/* Get the pid to compare against. */
-	pid = getpid();
-
-	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
-	ASSERT_EQ(0, ret);
-
-	/* Call anything! */
-	ret = syscall(__NR_getpid);
-	ASSERT_EQ(pid, ret);
-	ret = syscall(__NR_close, 0);
-	ASSERT_EQ(0, ret);
-	ret = syscall(__NR_close, 0);
-	ASSERT_EQ(-1, ret);
-	printf("The time is %ld\n", vsyscall_time(NULL));
-	ASSERT_LT(0, vsyscall_time(NULL));
-}
-
-TEST_HARNESS_MAIN
diff --git a/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c b/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
deleted file mode 100644
index a813361..0000000
--- a/tests/tests/os/jni/seccomp-tests/tests/seccomp_bpf_tests.c
+++ /dev/null
@@ -1,1986 +0,0 @@
-/* seccomp_bpf_tests.c
- * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Test code for seccomp bpf.
- */
-
-#include <asm/siginfo.h>
-#define __have_siginfo_t 1
-#define __have_sigval_t 1
-#define __have_sigevent_t 1
-
-#include <errno.h>
-#include <linux/filter.h>
-#include <sys/prctl.h>
-#include <sys/ptrace.h>
-#include <sys/user.h>
-#include <linux/prctl.h>
-#include <linux/ptrace.h>
-#include <linux/seccomp.h>
-#include <pthread.h>
-#include <semaphore.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <string.h>
-#include <linux/elf.h>
-#include <sys/uio.h>
-#include <sys/utsname.h>
-#include <fcntl.h>  // ANDROID
-#include <sys/mman.h>
-#include <sys/times.h>
-
-#define _GNU_SOURCE
-#include <unistd.h>
-#include <sys/syscall.h>
-
-#include "test_harness.h"
-
-#ifndef PR_SET_PTRACER
-# define PR_SET_PTRACER 0x59616d61
-#endif
-
-#ifndef PR_SET_NO_NEW_PRIVS
-#define PR_SET_NO_NEW_PRIVS 38
-#define PR_GET_NO_NEW_PRIVS 39
-#endif
-
-#ifndef PR_SECCOMP_EXT
-#define PR_SECCOMP_EXT 43
-#endif
-
-#ifndef SECCOMP_EXT_ACT
-#define SECCOMP_EXT_ACT 1
-#endif
-
-#ifndef SECCOMP_EXT_ACT_TSYNC
-#define SECCOMP_EXT_ACT_TSYNC 1
-#endif
-
-#ifndef SECCOMP_MODE_STRICT
-#define SECCOMP_MODE_STRICT 1
-#endif
-
-#ifndef SECCOMP_MODE_FILTER
-#define SECCOMP_MODE_FILTER 2
-#endif
-
-#ifndef SECCOMP_RET_KILL
-#define SECCOMP_RET_KILL        0x00000000U // kill the task immediately
-#define SECCOMP_RET_TRAP        0x00030000U // disallow and force a SIGSYS
-#define SECCOMP_RET_ERRNO       0x00050000U // returns an errno
-#define SECCOMP_RET_TRACE       0x7ff00000U // pass to a tracer or disallow
-#define SECCOMP_RET_ALLOW       0x7fff0000U // allow
-
-/* Masks for the return value sections. */
-#define SECCOMP_RET_ACTION      0x7fff0000U
-#define SECCOMP_RET_DATA        0x0000ffffU
-
-struct seccomp_data {
-	int nr;
-	__u32 arch;
-	__u64 instruction_pointer;
-	__u64 args[6];
-};
-#endif
-
-#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
-
-#define SIBLING_EXIT_UNKILLED	0xbadbeef
-#define SIBLING_EXIT_FAILURE	0xbadface
-#define SIBLING_EXIT_NEWPRIVS	0xbadfeed
-
-TEST(mode_strict_support) {
-	long ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, NULL, NULL);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Kernel does not support CONFIG_SECCOMP");
-	}
-	syscall(__NR_exit, 1);
-}
-
-TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL) {
-	long ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, NULL, NULL);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Kernel does not support CONFIG_SECCOMP");
-	}
-	syscall(__NR_prctl, PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, NULL, NULL);
-	EXPECT_FALSE(true) {
-		TH_LOG("Unreachable!");
-	}
-}
-
-/* Note! This doesn't test no new privs behavior */
-TEST(no_new_privs_support) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	EXPECT_EQ(0, ret) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-}
-
-/* Tests kernel support by checking for a copy_from_user() fault on * NULL. */
-TEST(mode_filter_support) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, NULL, NULL);
-	EXPECT_EQ(-1, ret);
-	EXPECT_EQ(EFAULT, errno) {
-		TH_LOG("Kernel does not support CONFIG_SECCOMP_FILTER!");
-	}
-}
-
-TEST(mode_filter_without_nnp) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_GET_NO_NEW_PRIVS, 0, NULL, 0, 0);
-	ASSERT_LE(0, ret) {
-		TH_LOG("Expected 0 or unsupported for NO_NEW_PRIVS");
-	}
-	errno = 0;
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-	/* Succeeds with CAP_SYS_ADMIN, fails without */
-	/* TODO(wad) check caps not euid */
-	if (geteuid()) {
-		EXPECT_EQ(-1, ret);
-		EXPECT_EQ(EACCES, errno);
-	} else {
-		EXPECT_EQ(0, ret);
-	}
-}
-
-#define MAX_INSNS_PER_PATH 32768
-
-TEST(filter_size_limits) {
-	int i;
-	int count = BPF_MAXINSNS + 1;
-	struct sock_filter allow[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_filter *filter;
-	struct sock_fprog prog = { };
-
-	filter = calloc(count, sizeof(*filter));
-	ASSERT_NE(NULL, filter);
-
-	for (i = 0; i < count; i++) {
-		filter[i] = allow[0];
-	}
-
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	prog.filter = filter;
-	prog.len = count;
-
-	/* Too many filter instructions in a single filter. */
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-	ASSERT_NE(0, ret) {
-		TH_LOG("Installing %d insn filter was allowed", prog.len);
-	}
-
-	/* One less is okay, though. */
-	prog.len -= 1;
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Installing %d insn filter wasn't allowed", prog.len);
-	}
-}
-
-TEST(filter_chain_limits) {
-	int i;
-	int count = BPF_MAXINSNS;
-	struct sock_filter allow[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_filter *filter;
-	struct sock_fprog prog = { };
-
-	filter = calloc(count, sizeof(*filter));
-	ASSERT_NE(NULL, filter);
-
-	for (i = 0; i < count; i++) {
-		filter[i] = allow[0];
-	}
-
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	prog.filter = filter;
-	prog.len = 1;
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	prog.len = count;
-
-	/* Too many total filter instructions. */
-	for (i = 0; i < MAX_INSNS_PER_PATH; i++) {
-		ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-		if (ret != 0)
-			break;
-	}
-	ASSERT_NE(0, ret) {
-		TH_LOG("Allowed %d %d-insn filters (total with penalties:%d)",
-		       i, count, i * (count + 4));
-	}
-}
-
-TEST(mode_filter_cannot_move_to_strict) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, NULL, 0, 0);
-	EXPECT_EQ(-1, ret);
-	EXPECT_EQ(EINVAL, errno);
-}
-
-
-TEST(mode_filter_get_seccomp) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
-	EXPECT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
-	EXPECT_EQ(2, ret);
-}
-
-
-TEST(ALLOW_all) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	ASSERT_EQ(0, ret);
-}
-
-TEST(empty_prog) {
-	struct sock_filter filter[] = {
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	EXPECT_EQ(-1, ret);
-	EXPECT_EQ(EINVAL, errno);
-}
-
-TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, 0x10000000U),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	ASSERT_EQ(0, ret);
-	EXPECT_EQ(0, syscall(__NR_getpid)) {
-		TH_LOG("getpid() shouldn't ever return");
-	}
-}
-
-/* return code >= 0x80000000 is unused. */
-TEST_SIGNAL(unknown_ret_is_kill_above_allow, SIGSYS) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, 0x90000000U),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	ASSERT_EQ(0, ret);
-	EXPECT_EQ(0, syscall(__NR_getpid)) {
-		TH_LOG("getpid() shouldn't ever return");
-	}
-}
-
-TEST_SIGNAL(KILL_all, SIGSYS) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	ASSERT_EQ(0, ret);
-}
-
-TEST_SIGNAL(KILL_one, SIGSYS) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	ASSERT_EQ(0, ret);
-
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	/* getpid() should never return. */
-	EXPECT_EQ(0, syscall(__NR_getpid));
-}
-
-TEST_SIGNAL(KILL_one_arg_one, SIGSYS) {
-	void *fatal_address;
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_times, 1, 0),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-		/* Only both with lower 32-bit for now. */
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(0)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K,
-			(unsigned long)&fatal_address, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	struct tms timebuf;
-	clock_t clock = times(&timebuf);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	ASSERT_EQ(0, ret);
-
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	EXPECT_LE(clock, syscall(__NR_times, &timebuf));
-	/* times() should never return. */
-	EXPECT_EQ(0, syscall(__NR_times, &fatal_address));
-}
-
-TEST_SIGNAL(KILL_one_arg_six, SIGSYS) {
-#ifndef __NR_mmap2
-	int sysno = __NR_mmap;
-#else
-	int sysno = __NR_mmap2;
-#endif
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, sysno, 1, 0),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-		/* Only both with lower 32-bit for now. */
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(5)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0C0FFEE, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	int fd;
-	void *map1, *map2;
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	ASSERT_EQ(0, ret);
-
-	fd = open("/dev/zero", O_RDONLY);
-	ASSERT_NE(-1, fd);
-
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	map1 = (void *)syscall(sysno,
-		NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, PAGE_SIZE);
-	EXPECT_NE(MAP_FAILED, map1);
-	/* mmap2() should never return. */
-	map2 = (void *)syscall(sysno,
-		 NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0x0C0FFEE);
-	EXPECT_EQ(MAP_FAILED, map2);
-
-	/* The test failed, so clean up the resources. */
-	munmap(map1, PAGE_SIZE);
-	munmap(map2, PAGE_SIZE);
-	close(fd);
-}
-
-/* TODO(wad) add 64-bit versus 32-bit arg tests. */
-
-TEST(arg_out_of_range) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_arg(6)),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	EXPECT_EQ(-1, ret);
-	EXPECT_EQ(EINVAL, errno);
-}
-
-TEST(ERRNO_one) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | E2BIG),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	ASSERT_EQ(0, ret);
-
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	EXPECT_EQ(-1, read(0, NULL, 0));
-	EXPECT_EQ(E2BIG, errno);
-}
-
-TEST(ERRNO_one_ok) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 0),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
-	ASSERT_EQ(0, ret);
-
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	/* "errno" of 0 is ok. */
-	EXPECT_EQ(0, read(0, NULL, 0));
-}
-
-FIXTURE_DATA(TRAP) {
-	struct sock_fprog prog;
-};
-
-FIXTURE_SETUP(TRAP) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	memset(&self->prog, 0, sizeof(self->prog));
-	self->prog.filter = malloc(sizeof(filter));
-	ASSERT_NE(NULL, self->prog.filter);
-	memcpy(self->prog.filter, filter, sizeof(filter));
-	self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
-}
-
-FIXTURE_TEARDOWN(TRAP) {
-	if (self->prog.filter)
-		free(self->prog.filter);
-};
-
-TEST_F_SIGNAL(TRAP, dfl, SIGSYS) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
-	ASSERT_EQ(0, ret);
-	syscall(__NR_getpid);
-}
-
-/* Ensure that SIGSYS overrides SIG_IGN */
-TEST_F_SIGNAL(TRAP, ign, SIGSYS) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	signal(SIGSYS, SIG_IGN);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
-	ASSERT_EQ(0, ret);
-	syscall(__NR_getpid);
-}
-
-static struct siginfo TRAP_info;
-static volatile int TRAP_nr;
-static void TRAP_action(int nr, siginfo_t *info, void *void_context)
-{
-	memcpy(&TRAP_info, info, sizeof(TRAP_info));
-	TRAP_nr = nr;
-	return;
-}
-
-TEST_F(TRAP, handler) {
-	int ret, test;
-	struct sigaction act;
-	sigset_t mask;
-	memset(&act, 0, sizeof(act));
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGSYS);
-
-	act.sa_sigaction = &TRAP_action;
-	act.sa_flags = SA_SIGINFO;
-	ret = sigaction(SIGSYS, &act, NULL);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("sigaction failed");
-	}
-	ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("sigprocmask failed");
-	}
-
-	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
-	ASSERT_EQ(0, ret);
-	TRAP_nr = 0;
-	memset(&TRAP_info, 0, sizeof(TRAP_info));
-	/* Expect the registers to be rolled back. (nr = error) may vary
-	 * based on arch. */
-	ret = syscall(__NR_getpid);
-	/* Silence gcc warning about volatile. */
-	test = TRAP_nr;
-	EXPECT_EQ(SIGSYS, test);
-	struct local_sigsys {
-			void *_call_addr; /* calling user insn */
-			int _syscall;	/* triggering system call number */
-			unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
-	} *sigsys = (struct local_sigsys *)
-#ifdef si_syscall
-		&(TRAP_info.si_call_addr);
-#else
-		&TRAP_info.si_pid;
-#endif
-	EXPECT_EQ(__NR_getpid, sigsys->_syscall);
-	/* Make sure arch is non-zero. */
-	EXPECT_NE(0, sigsys->_arch);
-	EXPECT_NE(0, (unsigned long)sigsys->_call_addr);
-}
-
-FIXTURE_DATA(precedence) {
-	struct sock_fprog allow;
-	struct sock_fprog trace;
-	struct sock_fprog error;
-	struct sock_fprog trap;
-	struct sock_fprog kill;
-};
-
-FIXTURE_SETUP(precedence) {
-	struct sock_filter allow_insns[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_filter trace_insns[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE),
-	};
-	struct sock_filter error_insns[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO),
-	};
-	struct sock_filter trap_insns[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP),
-	};
-	struct sock_filter kill_insns[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
-	};
-	memset(self, 0, sizeof(*self));
-#define FILTER_ALLOC(_x) \
-	self->_x.filter = malloc(sizeof(_x##_insns)); \
-	ASSERT_NE(NULL, self->_x.filter); \
-	memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
-	self->_x.len = (unsigned short)(sizeof(_x##_insns)/sizeof(_x##_insns[0]))
-	FILTER_ALLOC(allow);
-	FILTER_ALLOC(trace);
-	FILTER_ALLOC(error);
-	FILTER_ALLOC(trap);
-	FILTER_ALLOC(kill);
-}
-
-FIXTURE_TEARDOWN(precedence) {
-#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
-	FILTER_FREE(allow);
-	FILTER_FREE(trace);
-	FILTER_FREE(error);
-	FILTER_FREE(trap);
-	FILTER_FREE(kill);
-}
-
-TEST_F(precedence, allow_ok) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	pid_t res = 0;
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
-	ASSERT_EQ(0, ret);
-	/* Should work just fine. */
-	res = syscall(__NR_getppid);
-	EXPECT_EQ(parent, res);
-}
-
-TEST_F_SIGNAL(precedence, kill_is_highest, SIGSYS) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	pid_t res = 0;
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
-	ASSERT_EQ(0, ret);
-	/* Should work just fine. */
-	res = syscall(__NR_getppid);
-	EXPECT_EQ(parent, res);
-	/* getpid() should never return. */
-	res = syscall(__NR_getpid);
-	EXPECT_EQ(0, res);
-}
-
-TEST_F_SIGNAL(precedence, kill_is_highest_in_any_order, SIGSYS) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->kill);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
-	ASSERT_EQ(0, ret);
-	/* Should work just fine. */
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	/* getpid() should never return. */
-	EXPECT_EQ(0, syscall(__NR_getpid));
-}
-
-TEST_F_SIGNAL(precedence, trap_is_second, SIGSYS) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
-	ASSERT_EQ(0, ret);
-	/* Should work just fine. */
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	/* getpid() should never return. */
-	EXPECT_EQ(0, syscall(__NR_getpid));
-}
-
-TEST_F_SIGNAL(precedence, trap_is_second_in_any_order, SIGSYS) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
-	ASSERT_EQ(0, ret);
-	/* Should work just fine. */
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	/* getpid() should never return. */
-	EXPECT_EQ(0, syscall(__NR_getpid));
-}
-
-TEST_F(precedence, errno_is_third) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
-	ASSERT_EQ(0, ret);
-	/* Should work just fine. */
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	EXPECT_EQ(0, syscall(__NR_getpid));
-}
-
-TEST_F(precedence, errno_is_third_in_any_order) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
-	ASSERT_EQ(0, ret);
-	/* Should work just fine. */
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	EXPECT_EQ(0, syscall(__NR_getpid));
-}
-
-TEST_F(precedence, trace_is_fourth) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
-	ASSERT_EQ(0, ret);
-	/* Should work just fine. */
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	/* No ptracer */
-	EXPECT_EQ(-1, syscall(__NR_getpid));
-}
-
-TEST_F(precedence, trace_is_fourth_in_any_order) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	pid_t parent = getppid();
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
-	ASSERT_EQ(0, ret);
-	/* Should work just fine. */
-	EXPECT_EQ(parent, syscall(__NR_getppid));
-	/* No ptracer */
-	EXPECT_EQ(-1, syscall(__NR_getpid));
-}
-
-#ifndef PTRACE_O_TRACESECCOMP
-#define PTRACE_O_TRACESECCOMP	0x00000080
-#endif
-
-/* Catch the Ubuntu 12.04 value error. */
-#if PTRACE_EVENT_SECCOMP != 7
-#undef PTRACE_EVENT_SECCOMP
-#endif
-
-#ifndef PTRACE_EVENT_SECCOMP
-#define PTRACE_EVENT_SECCOMP 7
-#endif
-
-#define IS_SECCOMP_EVENT(status) (((status) >> 16) == PTRACE_EVENT_SECCOMP)
-bool tracer_running;
-void tracer_stop(int sig)
-{
-	tracer_running = false;
-}
-
-typedef void tracer_func_t(struct __test_metadata *_metadata,
-			   pid_t tracee, int status, void *args);
-
-void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee,
-	    tracer_func_t tracer_func, void *args) {
-	int ret = -1;
-	struct sigaction action = {
-		.sa_handler = tracer_stop,
-	};
-
-	/* Allow external shutdown. */
-	tracer_running = true;
-	ASSERT_EQ(0, sigaction(SIGUSR1, &action, NULL));
-
-	errno = 0;
-	while (ret == -1 && errno != EINVAL) {
-		ret = ptrace(PTRACE_ATTACH, tracee, NULL, 0);
-	}
-	ASSERT_EQ(0, ret) {
-		kill(tracee, SIGKILL);
-	}
-	/* Wait for attach stop */
-	wait(NULL);
-
-	ret = ptrace(PTRACE_SETOPTIONS, tracee, NULL, PTRACE_O_TRACESECCOMP);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Failed to set PTRACE_O_TRACESECCOMP");
-		kill(tracee, SIGKILL);
-	}
-	ptrace(PTRACE_CONT, tracee, NULL, 0);
-
-	/* Unblock the tracee */
-	ASSERT_EQ(1, write(fd, "A", 1));
-	ASSERT_EQ(0, close(fd));
-
-	/* Run until we're shut down. Must assert to stop execution. */
-	while (tracer_running) {
-		int status;
-		if (wait(&status) != tracee)
-			continue;
-		if (WIFSIGNALED(status) || WIFEXITED(status))
-			/* Child is dead. Time to go. */
-			return;
-
-		/* Make sure this is a seccomp event. */
-		ASSERT_EQ(true, IS_SECCOMP_EVENT(status));
-
-		tracer_func(_metadata, tracee, status, args);
-
-		ret = ptrace(PTRACE_CONT, tracee, NULL, NULL);
-		ASSERT_EQ(0, ret);
-	}
-	/* Directly report the status of our test harness results. */
-	syscall(__NR_exit, _metadata->passed ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-
-/* Common tracer setup/teardown functions. */
-void cont_handler(int num) {
-}
-pid_t setup_trace_fixture(struct __test_metadata *_metadata,
-			  tracer_func_t func, void *args) {
-	char sync;
-	int pipefd[2];
-	pid_t tracer_pid;
-	pid_t tracee = getpid();
-
-	/* Setup a pipe for clean synchronization. */
-	ASSERT_EQ(0, pipe(pipefd));
-
-	/* Fork a child which we'll promote to tracer */
-	tracer_pid = fork();
-	ASSERT_LE(0, tracer_pid);
-	signal(SIGALRM, cont_handler);
-	if (tracer_pid == 0) {
-		close(pipefd[0]);
-		tracer(_metadata, pipefd[1], tracee, func, args);
-		syscall(__NR_exit, 0);
-	}
-	close(pipefd[1]);
-	prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
-	read(pipefd[0], &sync, 1);
-	close(pipefd[0]);
-
-	return tracer_pid;
-}
-void teardown_trace_fixture(struct __test_metadata *_metadata,
-			    pid_t tracer) {
-	if (tracer) {
-		int status;
-		/*
-		 * Extract the exit code from the other process and
-		 * adopt it for ourselves in case its asserts failed.
-		 */
-		ASSERT_EQ(0, kill(tracer, SIGUSR1));
-		ASSERT_EQ(tracer, waitpid(tracer, &status, 0));
-		if (WEXITSTATUS(status))
-			_metadata->passed = 0;
-	}
-}
-
-/* "poke" tracer arguments and function. */
-struct tracer_args_poke_t {
-	unsigned long poke_addr;
-};
-
-void tracer_poke(struct __test_metadata *_metadata, pid_t tracee, int status,
-		 void *args) {
-	int ret;
-	unsigned long msg;
-	struct tracer_args_poke_t *info = (struct tracer_args_poke_t *)args;
-
-	ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
-	EXPECT_EQ(0, ret);
-	/* If this fails, don't try to recover. */
-	ASSERT_EQ(0x1001, msg) {
-		kill(tracee, SIGKILL);
-	}
-	/*
-	 * Poke in the message.
-	 * Registers are not touched to try to keep this relatively arch
-	 * agnostic.
-	 */
-	ret = ptrace(PTRACE_POKEDATA, tracee, info->poke_addr, 0x1001);
-	EXPECT_EQ(0, ret);
-}
-
-FIXTURE_DATA(TRACE_poke) {
-	struct sock_fprog prog;
-	pid_t tracer;
-	long poked;
-	struct tracer_args_poke_t tracer_args;
-};
-
-FIXTURE_SETUP(TRACE_poke) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1001),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-
-	self->poked = 0;
-	memset(&self->prog, 0, sizeof(self->prog));
-	self->prog.filter = malloc(sizeof(filter));
-	ASSERT_NE(NULL, self->prog.filter);
-	memcpy(self->prog.filter, filter, sizeof(filter));
-	self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
-
-	/* Set up tracer args. */
-	self->tracer_args.poke_addr = (unsigned long)&self->poked;
-
-	/* Launch tracer. */
-	self->tracer = setup_trace_fixture(_metadata, tracer_poke,
-					   &self->tracer_args);
-}
-
-FIXTURE_TEARDOWN(TRACE_poke) {
-	teardown_trace_fixture(_metadata, self->tracer);
-	if (self->prog.filter)
-		free(self->prog.filter);
-};
-
-TEST_F(TRACE_poke, read_has_side_effects) {
-	ssize_t ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	EXPECT_EQ(0, self->poked);
-	ret = read(-1, NULL, 0);
-	EXPECT_EQ(-1, ret);
-	EXPECT_EQ(0x1001, self->poked);
-}
-
-TEST_F(TRACE_poke, getpid_runs_normally) {
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	EXPECT_EQ(0, self->poked);
-	EXPECT_NE(0, syscall(__NR_getpid));
-	EXPECT_EQ(0, self->poked);
-}
-
-#if defined(__x86_64__)
-# define ARCH_REGS	struct user_regs_struct
-# define SYSCALL_NUM	orig_rax
-# define SYSCALL_RET	rax
-#elif defined(__i386__)
-# define ARCH_REGS	struct user_regs_struct
-# define SYSCALL_NUM	orig_eax
-# define SYSCALL_RET	eax
-#elif defined(__arm__)
-# define ARCH_REGS	struct pt_regs
-# define SYSCALL_NUM	ARM_r7
-# define SYSCALL_RET	ARM_r0
-#elif defined(__aarch64__)
-# define ARCH_REGS	struct user_pt_regs
-# define SYSCALL_NUM	regs[8]
-# define SYSCALL_RET	regs[0]
-#else
-# error "Do not know how to find your architecture's registers and syscalls"
-#endif
-
-/* Architecture-specific syscall fetching routine. */
-int get_syscall(struct __test_metadata *_metadata, pid_t tracee) {
-	struct iovec iov;
-	ARCH_REGS regs;
-
-	iov.iov_base = &regs;
-	iov.iov_len = sizeof(regs);
-	EXPECT_EQ(0, ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &iov)) {
-		TH_LOG("PTRACE_GETREGSET failed");
-		return -1;
-	}
-
-	return regs.SYSCALL_NUM;
-}
-
-/* Architecture-specific syscall changing routine. */
-void change_syscall(struct __test_metadata *_metadata,
-		    pid_t tracee, int syscall) {
-	struct iovec iov;
-	int ret;
-	ARCH_REGS regs;
-
-	iov.iov_base = &regs;
-	iov.iov_len = sizeof(regs);
-	ret = ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &iov);
-	EXPECT_EQ(0, ret);
-
-#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__)
-	{
-		regs.SYSCALL_NUM = syscall;
-	}
-
-#elif defined(__arm__)
-# ifndef PTRACE_SET_SYSCALL
-#  define PTRACE_SET_SYSCALL   23
-# endif
-	{
-		ret = ptrace(PTRACE_SET_SYSCALL, tracee, NULL, syscall);
-		EXPECT_EQ(0, ret);
-	}
-
-#else
-	ASSERT_EQ(1, 0) {
-		TH_LOG("How is the syscall changed on this architecture?");
-	}
-#endif
-
-	/* If syscall is skipped, change return value. */
-	if (syscall == -1)
-		regs.SYSCALL_RET = 1;
-
-	ret = ptrace(PTRACE_SETREGSET, tracee, NT_PRSTATUS, &iov);
-	EXPECT_EQ(0, ret);
-}
-
-void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
-		    int status, void *args) {
-	int ret;
-	unsigned long msg;
-
-	/* Make sure we got the right message. */
-	ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
-	EXPECT_EQ(0, ret);
-
-	switch (msg) {
-	case 0x1002:
-		/* change getpid to getppid. */
-		change_syscall(_metadata, tracee, __NR_getppid);
-		break;
-	case 0x1003:
-		/* skip gettid. */
-		change_syscall(_metadata, tracee, -1);
-		break;
-	case 0x1004:
-		/* do nothing (allow getppid) */
-		break;
-	default:
-		EXPECT_EQ(0, msg) {
-			TH_LOG("Unknown PTRACE_GETEVENTMSG: 0x%lx", msg);
-			kill(tracee, SIGKILL);
-		}
-	}
-
-}
-
-FIXTURE_DATA(TRACE_syscall) {
-	struct sock_fprog prog;
-	pid_t tracer, mytid, mypid, parent;
-};
-
-FIXTURE_SETUP(TRACE_syscall) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1002),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_gettid, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1003),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1004),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-
-	memset(&self->prog, 0, sizeof(self->prog));
-	self->prog.filter = malloc(sizeof(filter));
-	ASSERT_NE(NULL, self->prog.filter);
-	memcpy(self->prog.filter, filter, sizeof(filter));
-	self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
-
-	/* Prepare some testable syscall results. */
-	self->mytid = syscall(__NR_gettid);
-	ASSERT_GT(self->mytid, 0);
-	ASSERT_NE(self->mytid, 1) {
-		TH_LOG("Running this test as init is not supported. :)");
-	}
-
-	self->mypid = getpid();
-	ASSERT_GT(self->mypid, 0);
-	ASSERT_EQ(self->mytid, self->mypid);
-
-	self->parent = getppid();
-	ASSERT_GT(self->parent, 0);
-	ASSERT_NE(self->parent, self->mypid);
-
-	/* Launch tracer. */
-	self->tracer = setup_trace_fixture(_metadata, tracer_syscall, NULL);
-}
-
-FIXTURE_TEARDOWN(TRACE_syscall) {
-	teardown_trace_fixture(_metadata, self->tracer);
-	if (self->prog.filter)
-		free(self->prog.filter);
-};
-
-TEST_F(TRACE_syscall, syscall_allowed) {
-	long ret;
-
-	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	/* getppid works as expected (no changes). */
-	EXPECT_EQ(self->parent, syscall(__NR_getppid));
-	EXPECT_NE(self->mypid, syscall(__NR_getppid));
-}
-
-TEST_F(TRACE_syscall, syscall_redirected) {
-	long ret;
-
-	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	/* getpid has been redirected to getppid as expected. */
-	EXPECT_EQ(self->parent, syscall(__NR_getpid));
-	EXPECT_NE(self->mypid, syscall(__NR_getpid));
-}
-
-TEST_F(TRACE_syscall, syscall_dropped) {
-	long ret;
-
-	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
-	ASSERT_EQ(0, ret);
-
-	/* gettid has been skipped and an altered return value stored. */
-	EXPECT_EQ(1, syscall(__NR_gettid));
-	EXPECT_NE(self->mytid, syscall(__NR_gettid));
-}
-
-#ifndef __NR_seccomp
-# if defined(__i386__)
-#  define __NR_seccomp 354
-# elif defined(__x86_64__)
-#  define __NR_seccomp 317
-# elif defined(__arm__)
-#  define __NR_seccomp 383
-# elif defined(__aarch64__)
-#  define __NR_seccomp 277
-# else
-#  warning "seccomp syscall number unknown for this architecture"
-#  define __NR_seccomp 0xffff
-# endif
-#endif
-
-#ifndef SECCOMP_SET_MODE_STRICT
-#define SECCOMP_SET_MODE_STRICT 0
-#endif
-
-#ifndef SECCOMP_SET_MODE_FILTER
-#define SECCOMP_SET_MODE_FILTER 1
-#endif
-
-#ifndef SECCOMP_FLAG_FILTER_TSYNC
-#define SECCOMP_FLAG_FILTER_TSYNC 1
-#endif
-
-#ifndef seccomp
-int seccomp(unsigned int op, unsigned int flags, struct sock_fprog *filter)
-{
-	errno = 0;
-	return syscall(__NR_seccomp, op, flags, filter);
-}
-#endif
-
-TEST(seccomp_syscall) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-
-	/* Reject insane operation. */
-	ret = seccomp(-1, 0, &prog);
-	EXPECT_EQ(EINVAL, errno) {
-		TH_LOG("Did not reject crazy op value!");
-	}
-
-	/* Reject strict with flags or pointer. */
-	ret = seccomp(SECCOMP_SET_MODE_STRICT, -1, NULL);
-	EXPECT_EQ(EINVAL, errno) {
-		TH_LOG("Did not reject mode strict with flags!");
-	}
-	ret = seccomp(SECCOMP_SET_MODE_STRICT, 0, &prog);
-	EXPECT_EQ(EINVAL, errno) {
-		TH_LOG("Did not reject mode strict with uargs!");
-	}
-
-	/* Reject insane args for filter. */
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, -1, &prog);
-	EXPECT_EQ(EINVAL, errno) {
-		TH_LOG("Did not reject crazy filter flags!");
-	}
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, NULL);
-	EXPECT_EQ(EFAULT, errno) {
-		TH_LOG("Did not reject NULL filter!");
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
-	EXPECT_EQ(0, errno) {
-		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER: %s",
-			strerror(errno));
-	}
-}
-
-TEST(seccomp_syscall_mode_lock) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
-	EXPECT_EQ(0, ret) {
-		TH_LOG("Could not install filter!");
-	}
-
-	/* Make sure neither entry point will switch to strict. */
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT, 0, 0, 0);
-	EXPECT_EQ(EINVAL, errno) {
-		TH_LOG("Switched to mode strict!");
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_STRICT, 0, NULL);
-	EXPECT_EQ(EINVAL, errno) {
-		TH_LOG("Switched to mode strict!");
-	}
-}
-
-TEST(TSYNC_first) {
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-	long ret = prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
-		      &prog);
-	EXPECT_EQ(0, ret) {
-		TH_LOG("Could not install initial filter with TSYNC!");
-	}
-}
-
-#define TSYNC_SIBLINGS 2
-struct tsync_sibling {
-	pthread_t tid;
-	pid_t system_tid;
-	sem_t *started;
-	pthread_cond_t *cond;
-	pthread_mutex_t *mutex;
-	int diverge;
-	int num_waits;
-	struct sock_fprog *prog;
-	struct __test_metadata *metadata;
-};
-
-FIXTURE_DATA(TSYNC) {
-	struct sock_fprog root_prog, apply_prog;
-	struct tsync_sibling sibling[TSYNC_SIBLINGS];
-	sem_t started;
-	pthread_cond_t cond;
-	pthread_mutex_t mutex;
-	int sibling_count;
-};
-
-FIXTURE_SETUP(TSYNC) {
-	struct sock_filter root_filter[] = {
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_filter apply_filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	memset(&self->root_prog, 0, sizeof(self->root_prog));
-	memset(&self->apply_prog, 0, sizeof(self->apply_prog));
-	memset(&self->sibling, 0, sizeof(self->sibling));
-	self->root_prog.filter = malloc(sizeof(root_filter));
-	ASSERT_NE(NULL, self->root_prog.filter);
-	memcpy(self->root_prog.filter, &root_filter, sizeof(root_filter));
-	self->root_prog.len = (unsigned short)(sizeof(root_filter)/sizeof(root_filter[0]));
-
-	self->apply_prog.filter = malloc(sizeof(apply_filter));
-	ASSERT_NE(NULL, self->apply_prog.filter);
-	memcpy(self->apply_prog.filter, &apply_filter, sizeof(apply_filter));
-	self->apply_prog.len = (unsigned short)(sizeof(apply_filter)/sizeof(apply_filter[0]));
-
-	self->sibling_count = 0;
-	pthread_mutex_init(&self->mutex, NULL);
-	pthread_cond_init(&self->cond, NULL);
-	sem_init(&self->started, 0, 0);
-	self->sibling[0].tid = 0;
-	self->sibling[0].cond = &self->cond;
-	self->sibling[0].started = &self->started;
-	self->sibling[0].mutex = &self->mutex;
-	self->sibling[0].diverge = 0;
-	self->sibling[0].num_waits = 1;
-	self->sibling[0].prog = &self->root_prog;
-	self->sibling[0].metadata = _metadata;
-	self->sibling[1].tid = 0;
-	self->sibling[1].cond = &self->cond;
-	self->sibling[1].started = &self->started;
-	self->sibling[1].mutex = &self->mutex;
-	self->sibling[1].diverge = 0;
-	self->sibling[1].prog = &self->root_prog;
-	self->sibling[1].num_waits = 1;
-	self->sibling[1].metadata = _metadata;
-}
-
-FIXTURE_TEARDOWN(TSYNC) {
-	int sib = 0;
-	if (self->root_prog.filter)
-		free(self->root_prog.filter);
-	if (self->apply_prog.filter)
-		free(self->apply_prog.filter);
-
-	for ( ; sib < self->sibling_count; ++sib) {
-		struct tsync_sibling *s = &self->sibling[sib];
-		void *status;
-		if (!s->tid)
-			continue;
-		if (pthread_kill(s->tid, 0)) {
-			//pthread_cancel(s->tid);  // ANDROID
-			pthread_join(s->tid, &status);
-		}
-	}
-	pthread_mutex_destroy(&self->mutex);
-	pthread_cond_destroy(&self->cond);
-	sem_destroy(&self->started);
-};
-
-void *tsync_sibling(void *data)
-{
-	long ret = 0;
-	struct tsync_sibling *me = data;
-	me->system_tid = syscall(__NR_gettid);
-
-	pthread_mutex_lock(me->mutex);
-	if (me->diverge) {
-		/* Just re-apply the root prog to fork the tree */
-		ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER,
-				me->prog, 0, 0);
-	}
-	sem_post(me->started);
-	/* Return outside of started so parent notices failures. */
-	if (ret) {
-		pthread_mutex_unlock(me->mutex);
-		return (void *)SIBLING_EXIT_FAILURE;
-	}
-	do {
-		pthread_cond_wait(me->cond, me->mutex);
-		me->num_waits = me->num_waits - 1;
-	}
-	while (me->num_waits);
-	pthread_mutex_unlock(me->mutex);
-	long nnp = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
-	if (!nnp)
-		return (void*)SIBLING_EXIT_NEWPRIVS;
-	read(0, NULL, 0);
-	return (void *)SIBLING_EXIT_UNKILLED;
-}
-
-void tsync_start_sibling(struct tsync_sibling *sibling)
-{
-	pthread_create(&sibling->tid, NULL, tsync_sibling, (void *)sibling);
-}
-
-TEST_F(TSYNC, siblings_fail_prctl) {
-	long ret;
-	void *status;
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			offsetof(struct seccomp_data, nr)),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EINVAL),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-
-	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-
-	/* Check prctl failure detection by requesting sib 0 diverge. */
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("setting filter failed");
-	}
-
-	self->sibling[0].diverge = 1;
-	tsync_start_sibling(&self->sibling[0]);
-	tsync_start_sibling(&self->sibling[1]);
-
-	while (self->sibling_count < TSYNC_SIBLINGS) {
-		sem_wait(&self->started);
-		self->sibling_count++;
-	}
-
-	/* Signal the threads to clean up*/
-	pthread_mutex_lock(&self->mutex);
-	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
-		TH_LOG("cond broadcast non-zero");
-	}
-	pthread_mutex_unlock(&self->mutex);
-
-	/* Ensure diverging sibling failed to call prctl. */
-	pthread_join(self->sibling[0].tid, &status);
-	EXPECT_EQ(SIBLING_EXIT_FAILURE, (long)status);
-	pthread_join(self->sibling[1].tid, &status);
-	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
-}
-
-TEST_F(TSYNC, two_siblings_with_ancestor) {
-	long ret;
-	void *status;
-
-	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
-	}
-	tsync_start_sibling(&self->sibling[0]);
-	tsync_start_sibling(&self->sibling[1]);
-
-	while (self->sibling_count < TSYNC_SIBLINGS) {
-		sem_wait(&self->started);
-		self->sibling_count++;
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
-		      &self->apply_prog);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Could install filter on all threads!");
-	}
-	/* Tell the siblings to test the policy */
-	pthread_mutex_lock(&self->mutex);
-	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
-		TH_LOG("cond broadcast non-zero");
-	}
-	pthread_mutex_unlock(&self->mutex);
-	/* Ensure they are both killed and don't exit cleanly. */
-	pthread_join(self->sibling[0].tid, &status);
-	EXPECT_EQ(0x0, (long)status);
-	pthread_join(self->sibling[1].tid, &status);
-	EXPECT_EQ(0x0, (long)status);
-}
-
-TEST_F(TSYNC, two_sibling_want_nnp) {
-	void *status;
-
-	/* start siblings before any prctl() operations */
-	tsync_start_sibling(&self->sibling[0]);
-	tsync_start_sibling(&self->sibling[1]);
-	while (self->sibling_count < TSYNC_SIBLINGS) {
-		sem_wait(&self->started);
-		self->sibling_count++;
-	}
-
-	/* Tell the siblings to test no policy */
-	pthread_mutex_lock(&self->mutex);
-	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
-		TH_LOG("cond broadcast non-zero");
-	}
-	pthread_mutex_unlock(&self->mutex);
-
-	/* Ensure they are both upset about lacking nnp. */
-	pthread_join(self->sibling[0].tid, &status);
-	EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
-	pthread_join(self->sibling[1].tid, &status);
-	EXPECT_EQ(SIBLING_EXIT_NEWPRIVS, (long)status);
-}
-
-TEST_F(TSYNC, two_siblings_with_no_filter) {
-	long ret;
-	void *status;
-
-	/* start siblings before any prctl() operations */
-	tsync_start_sibling(&self->sibling[0]);
-	tsync_start_sibling(&self->sibling[1]);
-	while (self->sibling_count < TSYNC_SIBLINGS) {
-		sem_wait(&self->started);
-		self->sibling_count++;
-	}
-
-	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
-		      &self->apply_prog);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Could install filter on all threads!");
-	}
-
-	/* Tell the siblings to test the policy */
-	pthread_mutex_lock(&self->mutex);
-	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
-		TH_LOG("cond broadcast non-zero");
-	}
-	pthread_mutex_unlock(&self->mutex);
-
-	/* Ensure they are both killed and don't exit cleanly. */
-	pthread_join(self->sibling[0].tid, &status);
-	EXPECT_EQ(0x0, (long)status);
-	pthread_join(self->sibling[1].tid, &status);
-	EXPECT_EQ(0x0, (long)status);
-}
-
-TEST_F(TSYNC, two_siblings_with_one_divergence) {
-	long ret;
-	void *status;
-
-	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
-	}
-	self->sibling[0].diverge = 1;
-	tsync_start_sibling(&self->sibling[0]);
-	tsync_start_sibling(&self->sibling[1]);
-
-	while (self->sibling_count < TSYNC_SIBLINGS) {
-		sem_wait(&self->started);
-		self->sibling_count++;
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
-		      &self->apply_prog);
-	ASSERT_EQ(self->sibling[0].system_tid, ret) {
-		TH_LOG("Did not fail on diverged sibling.");
-	}
-
-	/* Wake the threads */
-	pthread_mutex_lock(&self->mutex);
-	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
-		TH_LOG("cond broadcast non-zero");
-	}
-	pthread_mutex_unlock(&self->mutex);
-
-	/* Ensure they are both unkilled. */
-	pthread_join(self->sibling[0].tid, &status);
-	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
-	pthread_join(self->sibling[1].tid, &status);
-	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
-}
-
-TEST_F(TSYNC, two_siblings_not_under_filter) {
-	long ret, sib;
-	void *status;
-
-	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
-		TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-	}
-
-	/*
-	 * Sibling 0 will have its own seccomp policy
-	 * and Sibling 1 will not be under seccomp at
-	 * all. Sibling 1 will enter seccomp and 0
-	 * will cause failure.
-	 */
-	self->sibling[0].diverge = 1;
-	tsync_start_sibling(&self->sibling[0]);
-	tsync_start_sibling(&self->sibling[1]);
-
-	while (self->sibling_count < TSYNC_SIBLINGS) {
-		sem_wait(&self->started);
-		self->sibling_count++;
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
-	}
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
-		      &self->apply_prog);
-	ASSERT_EQ(ret, self->sibling[0].system_tid) {
-		TH_LOG("Did not fail on diverged sibling.");
-	}
-	sib = 1;
-	if (ret == self->sibling[0].system_tid)
-		sib = 0;
-
-	pthread_mutex_lock(&self->mutex);
-
-	/* Increment the other siblings num_waits so we can clean up
-	 * the one we just saw.
-	 */
-	self->sibling[!sib].num_waits += 1;
-
-	/* Signal the thread to clean up*/
-	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
-		TH_LOG("cond broadcast non-zero");
-	}
-	pthread_mutex_unlock(&self->mutex);
-	pthread_join(self->sibling[sib].tid, &status);
-	EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status);
-	/* Poll for actual task death. pthread_join doesn't guarantee it. */
-	while (!kill(self->sibling[sib].system_tid, 0)) sleep(0.1);
-	/* Switch to the remaining sibling */
-	sib = !sib;
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
-		      &self->apply_prog);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("Expected the remaining sibling to sync");
-	};
-
-	pthread_mutex_lock(&self->mutex);
-
-	/* If remaining sibling didn't have a chance to wake up during
-	 * the first broadcast, manually reduce the num_waits now.
-	 */
-	if (self->sibling[sib].num_waits > 1)
-		self->sibling[sib].num_waits = 1;
-	ASSERT_EQ(0, pthread_cond_broadcast(&self->cond)) {
-		TH_LOG("cond broadcast non-zero");
-	}
-	pthread_mutex_unlock(&self->mutex);
-	pthread_join(self->sibling[sib].tid, &status);
-	EXPECT_EQ(0, (long)status);
-	/* Poll for actual task death. pthread_join doesn't guarantee it. */
-	while (!kill(self->sibling[sib].system_tid, 0)) sleep(0.1);
-
-	ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
-		      &self->apply_prog);
-	ASSERT_EQ(0, ret);  /* just us chickens */
-}
-
-/* Make sure restarted syscalls are seen directly as "restart_syscall". */
-TEST(syscall_restart)
-{
-	long ret;
-	unsigned long msg;
-	pid_t child_pid;
-	int pipefd[2];
-	int status;
-	siginfo_t info = { };
-	struct sock_filter filter[] = {
-		BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
-			 offsetof(struct seccomp_data, nr)),
-
-#ifdef __NR_sigreturn
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_sigreturn, 6, 0),
-#endif
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 5, 0),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_exit, 4, 0),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_rt_sigreturn, 3, 0),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_nanosleep, 4, 0),
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_restart_syscall, 4, 0),
-
-		/* Allow __NR_write for easy logging. */
-		BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_write, 0, 1),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
-		/* The nanosleep jump target. */
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x100),
-		/* The restart_syscall jump target. */
-		BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE|0x200),
-	};
-	struct sock_fprog prog = {
-		.len = (unsigned short) (sizeof(filter)/sizeof(filter[0])),
-		.filter = filter,
-	};
-#if defined(__arm__)
-	struct utsname utsbuf;
-#endif
-
-	ASSERT_EQ(0, pipe(pipefd));
-
-	child_pid = fork();
-	ASSERT_LE(0, child_pid);
-	if (child_pid == 0) {
-		/* Child uses EXPECT not ASSERT to deliver status correctly. */
-		char buf = ' ';
-		struct timespec timeout = { };
-
-		/* Attach parent as tracer and stop. */
-		EXPECT_EQ(0, ptrace(PTRACE_TRACEME));
-		EXPECT_EQ(0, raise(SIGSTOP));
-
-		EXPECT_EQ(0, close(pipefd[1]));
-
-		EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
-			TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
-		}
-
-		ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
-		EXPECT_EQ(0, ret) {
-			TH_LOG("Failed to install filter!");
-		}
-
-		EXPECT_EQ(1, read(pipefd[0], &buf, 1)) {
-			TH_LOG("Failed to read() sync from parent");
-		}
-		EXPECT_EQ('.', buf) {
-			TH_LOG("Failed to get sync data from read()");
-		}
-
-		/* Start nanosleep to be interrupted. */
-		timeout.tv_sec = 1;
-		errno = 0;
-		EXPECT_EQ(0, nanosleep(&timeout, NULL)) {
-			TH_LOG("Call to nanosleep() failed (errno %d)", errno);
-		}
-
-		/* Read final sync from parent. */
-		EXPECT_EQ(1, read(pipefd[0], &buf, 1)) {
-			TH_LOG("Failed final read() from parent");
-		}
-		EXPECT_EQ('!', buf) {
-			TH_LOG("Failed to get final data from read()");
-		}
-
-		/* Directly report the status of our test harness results. */
-		syscall(__NR_exit, _metadata->passed ? EXIT_SUCCESS
-						     : EXIT_FAILURE);
-	}
-	EXPECT_EQ(0, close(pipefd[0]));
-
-	/* Attach to child, setup options, and release. */
-	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
-	ASSERT_EQ(true, WIFSTOPPED(status));
-	ASSERT_EQ(0, ptrace(PTRACE_SETOPTIONS, child_pid, NULL,
-			    PTRACE_O_TRACESECCOMP));
-	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
-	ASSERT_EQ(1, write(pipefd[1], ".", 1));
-
-	/* Wait for nanosleep() to start. */
-	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
-	ASSERT_EQ(true, WIFSTOPPED(status));
-	ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
-	ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
-	ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
-	ASSERT_EQ(0x100, msg);
-	EXPECT_EQ(__NR_nanosleep, get_syscall(_metadata, child_pid));
-
-	/* Might as well check siginfo for sanity while we're here. */
-	ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
-	ASSERT_EQ(SIGTRAP, info.si_signo);
-	ASSERT_EQ(SIGTRAP | (PTRACE_EVENT_SECCOMP << 8), info.si_code);
-	EXPECT_EQ(0, info.si_errno);
-	EXPECT_EQ(getuid(), info.si_uid);
-	/* Verify signal delivery came from child (seccomp-triggered). */
-	EXPECT_EQ(child_pid, info.si_pid);
-
-	/* Interrupt nanosleep with SIGSTOP (which we'll need to handle). */
-	ASSERT_EQ(0, kill(child_pid, SIGSTOP));
-	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
-	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
-	ASSERT_EQ(true, WIFSTOPPED(status));
-	ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
-	/* Verify signal delivery came from parent now. */
-	ASSERT_EQ(0, ptrace(PTRACE_GETSIGINFO, child_pid, NULL, &info));
-	EXPECT_EQ(getpid(), info.si_pid);
-
-	/* Restart nanosleep with SIGCONT, which triggers restart_syscall. */
-	ASSERT_EQ(0, kill(child_pid, SIGCONT));
-	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
-	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
-	ASSERT_EQ(true, WIFSTOPPED(status));
-	ASSERT_EQ(SIGCONT, WSTOPSIG(status));
-	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
-
-	/* Wait for restart_syscall() to start. */
-	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
-	ASSERT_EQ(true, WIFSTOPPED(status));
-	ASSERT_EQ(SIGTRAP, WSTOPSIG(status));
-	ASSERT_EQ(PTRACE_EVENT_SECCOMP, (status >> 16));
-	ASSERT_EQ(0, ptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &msg));
-
-	ASSERT_EQ(0x200, msg);
-	ret = get_syscall(_metadata, child_pid);
-#if defined(__arm__)
-	/*
-	 * FIXME:
-	 * - native ARM registers do NOT expose true syscall.
-	 * - compat ARM registers on ARM64 DO expose true syscall.
-	 */
-	ASSERT_EQ(0, uname(&utsbuf));
-	if (strncmp(utsbuf.machine, "arm", 3) == 0) {
-		EXPECT_EQ(__NR_nanosleep, ret);
-	} else
-#endif
-	{
-		EXPECT_EQ(__NR_restart_syscall, ret);
-	}
-
-	/* Write again to end test. */
-	ASSERT_EQ(0, ptrace(PTRACE_CONT, child_pid, NULL, 0));
-	ASSERT_EQ(1, write(pipefd[1], "!", 1));
-	EXPECT_EQ(0, close(pipefd[1]));
-
-	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
-	if (WIFSIGNALED(status) || WEXITSTATUS(status))
-		_metadata->passed = 0;
-}
-
-/*
- * TODO:
- * - add microbenchmarks
- * - expand NNP testing
- * - better arch-specific TRACE and TRAP handlers.
- * - endianness checking when appropriate
- * - 64-bit arg prodding
- * - arch value testing (x86 modes especially)
- * - ...
- */
-
-// ANDROID:begin
-struct __test_metadata* get_seccomp_test_list() {
-  return __test_list;
-}
-// ANDROID:end
-
-TEST_HARNESS_MAIN
diff --git a/tests/tests/os/jni/seccomp-tests/tests/sigsegv.c b/tests/tests/os/jni/seccomp-tests/tests/sigsegv.c
deleted file mode 100644
index a0d06e7..0000000
--- a/tests/tests/os/jni/seccomp-tests/tests/sigsegv.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* sigsegv.c
- * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Forces a denied system call to trigger a SIGSEGV at the instruction after
- * the call using a SIGSYS handler.. This can be useful when debugging
- * frameworks have trouble tracing through the SIGSYS handler.
- * Proof of concept using amd64 registers and 'syscall'.
- */
-
-#include <asm/siginfo.h>
-#define __have_siginfo_t 1
-#define __have_sigval_t 1
-#define __have_sigevent_t 1
-
-#include <linux/filter.h>
-#include <sys/prctl.h>
-#include <linux/prctl.h>
-#include <linux/seccomp.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include <string.h>
-#include <syscall.h>
-#define __USE_GNU 1
-#include <sys/ucontext.h>
-#include <sys/mman.h>
-
-#include "test_harness.h"
-
-#ifndef PR_SET_NO_NEW_PRIVS
-#define PR_SET_NO_NEW_PRIVS 38
-#define PR_GET_NO_NEW_PRIVS 39
-#endif
-
-#if defined(__i386__)
-#define REG_IP	REG_EIP
-#define REG_SP	REG_ESP
-#define REG_RESULT	REG_EAX
-#define REG_SYSCALL	REG_EAX
-#define REG_ARG0	REG_EBX
-#define REG_ARG1	REG_ECX
-#define REG_ARG2	REG_EDX
-#define REG_ARG3	REG_ESI
-#define REG_ARG4	REG_EDI
-#define REG_ARG5	REG_EBP
-#elif defined(__x86_64__)
-#define REG_IP	REG_RIP
-#define REG_SP	REG_RSP
-#define REG_RESULT	REG_RAX
-#define REG_SYSCALL	REG_RAX
-#define REG_ARG0	REG_RDI
-#define REG_ARG1	REG_RSI
-#define REG_ARG2	REG_RDX
-#define REG_ARG3	REG_R10
-#define REG_ARG4	REG_R8
-#define REG_ARG5	REG_R9
-#endif
-
-FIXTURE_DATA(TRAP) {
-	struct sock_fprog prog;
-};
-
-FIXTURE_SETUP(TRAP) {
-	/* instruction after the syscall. Will be arch specific, of course. */
-	{
-		struct sock_filter filter[] = {
-			BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
-				offsetof(struct seccomp_data, nr)),
-			/* Whitelist anything you might need in the sigaction */
-#ifdef __NR_sigreturn
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 4, 0),
-#endif
-			/* TODO: only allow PROT_NONE */
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_mprotect, 3, 0),
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 2, 0),
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 1, 0),
-			/* Allow __NR_write so easy logging. */
-			BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 0, 1),
-			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
-			BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
-		};
-		memset(&self->prog, 0, sizeof(self->prog));
-		self->prog.filter = malloc(sizeof(filter));
-		ASSERT_NE(NULL, self->prog.filter);
-		memcpy(self->prog.filter, filter, sizeof(filter));
-		self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0]));
-	}
-}
-
-FIXTURE_TEARDOWN(TRAP) {
-	if (self->prog.filter)
-		free(self->prog.filter);
-};
-
-struct arch_sigsys {
-		void *_call_addr; /* calling user insn */
-		int _syscall;	/* triggering system call number */
-		unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
-};
-
-#define _ALIGN(x,sz) (((x + ((sz)-1)) & ~((sz)-1)) - (sz))
-#define ALIGN(x,sz) ((typeof(x))_ALIGN((unsigned long)(x),(unsigned long)(sz)))
-static long local_mprotect(void *target, unsigned long sz)
-{
-	register unsigned long res asm ("rax") = __NR_mprotect;
-	__attribute__((unused)) register void *addr asm ("rdi") = ALIGN(target, sz);
-	__attribute__((unused)) register long len asm ("rsi") = sz;
-	__attribute__((unused)) register long num asm ("rdx") = PROT_NONE;
-	__asm__("syscall\n");
-	return res;
-}
-
-static void TRAP_action(int nr, siginfo_t *info, void *void_context)
-{
-	ucontext_t *ctx = (ucontext_t *)void_context;
-	char buf[256];
-	int len;
-	struct arch_sigsys *sys = (struct arch_sigsys *)
-#ifdef si_syscall
-		&(info->si_call_addr);
-#else
-		&(info->si_pid);
-#endif
-
-	if (info->si_code != SYS_SECCOMP)
-		return;
-	if (!ctx)
-		return;
-	len = snprintf(buf, sizeof(buf),
-			"@0x%lX:%X:%d:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX [0x%lX]\n",
-			(unsigned long)sys->_call_addr,
-			sys->_arch,
-			sys->_syscall,
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG0],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG1],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG2],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG3],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG4],
-			(unsigned long)ctx->uc_mcontext.gregs[REG_ARG5],
-			(unsigned long)ALIGN(ctx->uc_mcontext.gregs[REG_IP],
-			4096));
-	/* Emit some useful logs or whatever. */
-	syscall(__NR_write, STDOUT_FILENO, buf, len);
-	/* Make the calling page non-exec */
-	/* Careful on how it is called since it may make the syscall() instructions non-exec. */
-	local_mprotect((void *)ctx->uc_mcontext.gregs[REG_IP], sysconf(_SC_PAGE_SIZE));
-}
-
-TEST_F_SIGNAL(TRAP, sigsegv, SIGSEGV) {
-	int ret;
-	struct sigaction act;
-	sigset_t mask;
-	memset(&act, 0, sizeof(act));
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGSYS);
-
-	act.sa_sigaction = &TRAP_action;
-	act.sa_flags = SA_SIGINFO;
-	ret = sigaction(SIGSYS, &act, NULL);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("sigaction failed");
-	}
-	ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
-	ASSERT_EQ(0, ret) {
-		TH_LOG("sigprocmask failed");
-	}
-
-	ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-	ASSERT_EQ(0, ret);
-	ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog);
-	ASSERT_EQ(0, ret);
-
-	/* Call anything! */
-	ret = syscall(__NR_getpid);
-}
-
-TEST_HARNESS_MAIN
diff --git a/tests/tests/os/jni/seccomp-tests/tests/test_harness.h b/tests/tests/os/jni/seccomp-tests/tests/test_harness.h
deleted file mode 100644
index b7d44f1..0000000
--- a/tests/tests/os/jni/seccomp-tests/tests/test_harness.h
+++ /dev/null
@@ -1,521 +0,0 @@
-/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * test_harness.h: simple C unit test helper.
- *
- * Usage:
- *   #include "test_harness.h"
- *   TEST(standalone_test) {
- *     do_some_stuff;
- *     EXPECT_GT(10, stuff) {
- *        stuff_state_t state;
- *        enumerate_stuff_state(&state);
- *        TH_LOG("expectation failed with state: %s", state.msg);
- *     }
- *     more_stuff;
- *     ASSERT_NE(some_stuff, NULL) TH_LOG("how did it happen?!");
- *     last_stuff;
- *     EXPECT_EQ(0, last_stuff);
- *   }
- *
- *   FIXTURE(my_fixture) {
- *     mytype_t *data;
- *     int awesomeness_level;
- *   };
- *   FIXTURE_SETUP(my_fixture) {
- *     self->data = mytype_new();
- *     ASSERT_NE(NULL, self->data);
- *   }
- *   FIXTURE_TEARDOWN(my_fixture) {
- *     mytype_free(self->data);
- *   }
- *   TEST_F(my_fixture, data_is_good) {
- *     EXPECT_EQ(1, is_my_data_good(self->data));
- *   }
- *
- *   TEST_HARNESS_MAIN
- *
- * API inspired by code.google.com/p/googletest
- */
-#ifndef TEST_HARNESS_H_
-#define TEST_HARNESS_H_
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <android/log.h>  // ANDROID
-
-/* All exported functionality should be declared through this macro. */
-#define TEST_API(x) _##x
-
-/*
- * Exported APIs
- */
-
-/* TEST(name) { implementation }
- * Defines a test by name.
- * Names must be unique and tests must not be run in parallel.  The
- * implementation containing block is a function and scoping should be treated
- * as such.  Returning early may be performed with a bare "return;" statement.
- *
- * EXPECT_* and ASSERT_* are valid in a TEST() { } context.
- */
-#define TEST TEST_API(TEST)
-
-/* TEST_SIGNAL(name, signal) { implementation }
- * Defines a test by name and the expected term signal.
- * Names must be unique and tests must not be run in parallel.  The
- * implementation containing block is a function and scoping should be treated
- * as such.  Returning early may be performed with a bare "return;" statement.
- *
- * EXPECT_* and ASSERT_* are valid in a TEST() { } context.
- */
-#define TEST_SIGNAL TEST_API(TEST_SIGNAL)
-
-/* FIXTURE(datatype name) {
- *   type property1;
- *   ...
- * };
- * Defines the data provided to TEST_F()-defined tests as |self|.  It should be
- * populated and cleaned up using FIXTURE_SETUP and FIXTURE_TEARDOWN.
- */
-#define FIXTURE TEST_API(FIXTURE)
-
-/* FIXTURE_DATA(datatype name)
- * This call may be used when the type of the fixture data
- * is needed.  In general, this should not be needed unless
- * the |self| is being passed to a helper directly.
- */
-#define FIXTURE_DATA TEST_API(FIXTURE_DATA)
-
-/* FIXTURE_SETUP(fixture name) { implementation }
- * Populates the required "setup" function for a fixture.  An instance of the
- * datatype defined with _FIXTURE_DATA will be exposed as |self| for the
- * implementation.
- *
- * ASSERT_* are valid for use in this context and will prempt the execution
- * of any dependent fixture tests.
- *
- * A bare "return;" statement may be used to return early.
- */
-#define FIXTURE_SETUP TEST_API(FIXTURE_SETUP)
-
-/* FIXTURE_TEARDOWN(fixture name) { implementation }
- * Populates the required "teardown" function for a fixture.  An instance of the
- * datatype defined with _FIXTURE_DATA will be exposed as |self| for the
- * implementation to clean up.
- *
- * A bare "return;" statement may be used to return early.
- */
-#define FIXTURE_TEARDOWN TEST_API(FIXTURE_TEARDOWN)
-
-/* TEST_F(fixture, name) { implementation }
- * Defines a test that depends on a fixture (e.g., is part of a test case).
- * Very similar to TEST() except that |self| is the setup instance of fixture's
- * datatype exposed for use by the implementation.
- */
-#define TEST_F TEST_API(TEST_F)
-
-#define TEST_F_SIGNAL TEST_API(TEST_F_SIGNAL)
-
-/* Use once to append a main() to the test file. E.g.,
- *   TEST_HARNESS_MAIN
- */
-#define TEST_HARNESS_MAIN TEST_API(TEST_HARNESS_MAIN)
-
-/*
- * Operators for use in TEST and TEST_F.
- * ASSERT_* calls will stop test execution immediately.
- * EXPECT_* calls will emit a failure warning, note it, and continue.
- */
-
-/* ASSERT_EQ(expected, measured): expected == measured */
-#define ASSERT_EQ TEST_API(ASSERT_EQ)
-/* ASSERT_NE(expected, measured): expected != measured */
-#define ASSERT_NE TEST_API(ASSERT_NE)
-/* ASSERT_LT(expected, measured): expected < measured */
-#define ASSERT_LT TEST_API(ASSERT_LT)
-/* ASSERT_LE(expected, measured): expected <= measured */
-#define ASSERT_LE TEST_API(ASSERT_LE)
-/* ASSERT_GT(expected, measured): expected > measured */
-#define ASSERT_GT TEST_API(ASSERT_GT)
-/* ASSERT_GE(expected, measured): expected >= measured */
-#define ASSERT_GE TEST_API(ASSERT_GE)
-/* ASSERT_NULL(measured): NULL == measured */
-#define ASSERT_NULL TEST_API(ASSERT_NULL)
-/* ASSERT_TRUE(measured): measured != 0 */
-#define ASSERT_TRUE TEST_API(ASSERT_TRUE)
-/* ASSERT_FALSE(measured): measured == 0 */
-#define ASSERT_FALSE TEST_API(ASSERT_FALSE)
-/* ASSERT_STREQ(expected, measured): !strcmp(expected, measured) */
-#define ASSERT_STREQ TEST_API(ASSERT_STREQ)
-/* ASSERT_STRNE(expected, measured): strcmp(expected, measured) */
-#define ASSERT_STRNE TEST_API(ASSERT_STRNE)
-/* EXPECT_EQ(expected, measured): expected == measured */
-#define EXPECT_EQ TEST_API(EXPECT_EQ)
-/* EXPECT_NE(expected, measured): expected != measured */
-#define EXPECT_NE TEST_API(EXPECT_NE)
-/* EXPECT_LT(expected, measured): expected < measured */
-#define EXPECT_LT TEST_API(EXPECT_LT)
-/* EXPECT_LE(expected, measured): expected <= measured */
-#define EXPECT_LE TEST_API(EXPECT_LE)
-/* EXPECT_GT(expected, measured): expected > measured */
-#define EXPECT_GT TEST_API(EXPECT_GT)
-/* EXPECT_GE(expected, measured): expected >= measured */
-#define EXPECT_GE TEST_API(EXPECT_GE)
-/* EXPECT_NULL(measured): NULL == measured */
-#define EXPECT_NULL TEST_API(EXPECT_NULL)
-/* EXPECT_TRUE(measured): 0 != measured */
-#define EXPECT_TRUE TEST_API(EXPECT_TRUE)
-/* EXPECT_FALSE(measured): 0 == measured */
-#define EXPECT_FALSE TEST_API(EXPECT_FALSE)
-/* EXPECT_STREQ(expected, measured): !strcmp(expected, measured) */
-#define EXPECT_STREQ TEST_API(EXPECT_STREQ)
-/* EXPECT_STRNE(expected, measured): strcmp(expected, measured) */
-#define EXPECT_STRNE TEST_API(EXPECT_STRNE)
-
-/* TH_LOG(format, ...)
- * Optional debug logging function available for use in tests.
- * Logging may be enabled or disabled by defining TH_LOG_ENABLED.
- * E.g., #define TH_LOG_ENABLED 1
- * If no definition is provided, logging is enabled by default.
- */
-#define TH_LOG  TEST_API(TH_LOG)
-
-/*
- * Internal implementation.
- *
- */
-
-/* Utilities exposed to the test definitions */
-#ifndef TH_LOG_STREAM
-#  define TH_LOG_STREAM stderr
-#endif
-
-#ifndef TH_LOG_ENABLED
-#  define TH_LOG_ENABLED 1
-#endif
-
-#define _TH_LOG(fmt, ...) do { \
-  if (TH_LOG_ENABLED) \
-    __TH_LOG(fmt, ##__VA_ARGS__); \
-} while (0)
-
-/* Unconditional logger for internal use. */
-// ANDROID:begin
-#define __TH_LOG(fmt, ...) \
-    __android_log_print(ANDROID_LOG_ERROR, "SeccompBpfTest-KernelUnit", "%s:%d:%s:" fmt "\n", \
-            __FILE__, __LINE__, _metadata->name, ##__VA_ARGS__)
-// ANDROID:end
-
-/* Defines the test function and creates the registration stub. */
-#define _TEST(test_name) __TEST_IMPL(test_name, -1)
-
-#define _TEST_SIGNAL(test_name, signal) __TEST_IMPL(test_name, signal)
-
-#define __TEST_IMPL(test_name, _signal) \
-  static void test_name(struct __test_metadata *_metadata); \
-  static struct __test_metadata _##test_name##_object = \
-    { name: "global." #test_name, fn: &(test_name), termsig: (_signal) }; \
-  static void __attribute__((constructor)) _register_##test_name(void) { \
-    __register_test(&_##test_name##_object); \
-  } \
-  static void test_name( \
-    struct __test_metadata __attribute__((unused)) *_metadata)
-
-/* Wraps the struct name so we have one less argument to pass around. */
-#define _FIXTURE_DATA(fixture_name) struct _test_data_##fixture_name
-
-/* Called once per fixture to setup the data and register. */
-#define _FIXTURE(fixture_name) \
-  static void __attribute__((constructor)) \
-      _register_##fixture_name##_data(void) { \
-    __fixture_count++; \
-  } \
-  _FIXTURE_DATA(fixture_name)
-
-/* Prepares the setup function for the fixture.  |_metadata| is included
- * so that ASSERT_* work as a convenience.
- */
-#define _FIXTURE_SETUP(fixture_name) \
-  void fixture_name##_setup( \
-    struct __test_metadata __attribute__((unused)) *_metadata, \
-    _FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
-#define _FIXTURE_TEARDOWN(fixture_name) \
-  void fixture_name##_teardown( \
-    struct __test_metadata __attribute__((unused)) *_metadata, \
-    _FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
-
-/* Emits test registration and helpers for fixture-based test
- * cases.
- * TODO(wad) register fixtures on dedicated test lists.
- */
-#define _TEST_F(fixture_name, test_name) \
-  __TEST_F_IMPL(fixture_name, test_name, -1)
-
-#define _TEST_F_SIGNAL(fixture_name, test_name, signal) \
-  __TEST_F_IMPL(fixture_name, test_name, signal)
-
-#define __TEST_F_IMPL(fixture_name, test_name, signal) \
-  static void fixture_name##_##test_name( \
-    struct __test_metadata *_metadata, \
-    _FIXTURE_DATA(fixture_name) *self); \
-  static inline void wrapper_##fixture_name##_##test_name( \
-    struct __test_metadata *_metadata) { \
-    /* fixture data is allocated, setup, and torn down per call. */ \
-    _FIXTURE_DATA(fixture_name) self; \
-    memset(&self, 0, sizeof(_FIXTURE_DATA(fixture_name))); \
-    fixture_name##_setup(_metadata, &self); \
-    /* Let setup failure terminate early. */ \
-    if (!_metadata->passed) return; \
-    fixture_name##_##test_name(_metadata, &self); \
-    fixture_name##_teardown(_metadata, &self); \
-  } \
-  static struct __test_metadata _##fixture_name##_##test_name##_object = { \
-    name: #fixture_name "." #test_name, \
-    fn: &wrapper_##fixture_name##_##test_name, \
-    termsig: (signal), \
-   }; \
-  static void __attribute__((constructor)) \
-      _register_##fixture_name##_##test_name(void) { \
-    __register_test(&_##fixture_name##_##test_name##_object); \
-  } \
-  static void fixture_name##_##test_name( \
-    struct __test_metadata __attribute__((unused)) *_metadata, \
-    _FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
-
-/* Exports a simple wrapper to run the test harness. */
-#define _TEST_HARNESS_MAIN \
-  static void __attribute__((constructor)) __constructor_order_last(void) { \
-    if (!__constructor_order) \
-      __constructor_order = _CONSTRUCTOR_ORDER_BACKWARD; \
-  } \
-  int seccomp_test_main(int argc, char **argv) { return test_harness_run(argc, argv); }  // ANDROID
-
-#define _ASSERT_EQ(_expected, _seen) \
-  __EXPECT(_expected, _seen, ==, 1)
-#define _ASSERT_NE(_expected, _seen) \
-  __EXPECT(_expected, _seen, !=, 1)
-#define _ASSERT_LT(_expected, _seen) \
-  __EXPECT(_expected, _seen, <, 1)
-#define _ASSERT_LE(_expected, _seen) \
-  __EXPECT(_expected, _seen, <=, 1)
-#define _ASSERT_GT(_expected, _seen) \
-  __EXPECT(_expected, _seen, >, 1)
-#define _ASSERT_GE(_expected, _seen) \
-  __EXPECT(_expected, _seen, >=, 1)
-#define _ASSERT_NULL(_seen) \
-  __EXPECT(NULL, _seen, ==, 1)
-
-#define _ASSERT_TRUE(_seen) \
-  _ASSERT_NE(0, _seen)
-#define _ASSERT_FALSE(_seen) \
-  _ASSERT_EQ(0, _seen)
-#define _ASSERT_STREQ(_expected, _seen) \
-  __EXPECT_STR(_expected, _seen, ==, 1)
-#define _ASSERT_STRNE(_expected, _seen) \
-  __EXPECT_STR(_expected, _seen, !=, 1)
-
-#define _EXPECT_EQ(_expected, _seen) \
-  __EXPECT(_expected, _seen, ==, 0)
-#define _EXPECT_NE(_expected, _seen) \
-  __EXPECT(_expected, _seen, !=, 0)
-#define _EXPECT_LT(_expected, _seen) \
-  __EXPECT(_expected, _seen, <, 0)
-#define _EXPECT_LE(_expected, _seen) \
-  __EXPECT(_expected, _seen, <=, 0)
-#define _EXPECT_GT(_expected, _seen) \
-  __EXPECT(_expected, _seen, >, 0)
-#define _EXPECT_GE(_expected, _seen) \
-  __EXPECT(_expected, _seen, >=, 0)
-
-#define _EXPECT_NULL(_seen) \
-  __EXPECT(NULL, _seen, ==, 0)
-#define _EXPECT_TRUE(_seen) \
-  _EXPECT_NE(0, _seen)
-#define _EXPECT_FALSE(_seen) \
-  _EXPECT_EQ(0, _seen)
-
-#define _EXPECT_STREQ(_expected, _seen) \
-  __EXPECT_STR(_expected, _seen, ==, 0)
-#define _EXPECT_STRNE(_expected, _seen) \
-  __EXPECT_STR(_expected, _seen, !=, 0)
-
-/* Support an optional handler after and ASSERT_* or EXPECT_*.  The approach is
- * not thread-safe, but it should be fine in most sane test scenarios.
- *
- * Using __bail(), which optionally abort()s, is the easiest way to early
- * return while still providing an optional block to the API consumer.
- */
-#define OPTIONAL_HANDLER(_assert) \
-  for (; _metadata->trigger;  _metadata->trigger = __bail(_assert))
-
-#define __EXPECT(_expected, _seen, _t, _assert) do { \
-  /* Avoid multiple evaluation of the cases */ \
-  __typeof__(_expected) __exp = (_expected); \
-  __typeof__(_seen) __seen = (_seen); \
-  if (!(__exp _t __seen)) { \
-    unsigned long long __exp_print = 0; \
-    unsigned long long __seen_print = 0; \
-    /* Avoid casting complaints the scariest way we can. */ \
-    memcpy(&__exp_print, &__exp, sizeof(__exp)); \
-    memcpy(&__seen_print, &__seen, sizeof(__seen)); \
-    __TH_LOG("Expected %s (%llu) %s %s (%llu)", \
-            #_expected, __exp_print, #_t, \
-            #_seen, __seen_print); \
-    _metadata->passed = 0; \
-    /* Ensure the optional handler is triggered */ \
-    _metadata->trigger = 1; \
-  } \
-} while (0); OPTIONAL_HANDLER(_assert)
-
-#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \
-  const char *__exp = (_expected); \
-  const char *__seen = (_seen); \
-  if (!(strcmp(__exp, __seen) _t (0)))  { \
-    __TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \
-    _metadata->passed = 0; \
-    _metadata->trigger = 1; \
-  } \
-} while (0); OPTIONAL_HANDLER(_assert)
-
-/* Contains all the information for test execution and status checking. */
-struct __test_metadata {
-  const char *name;
-  void (*fn)(struct __test_metadata *);
-  int termsig;
-  int passed;
-  int trigger; /* extra handler after the evaluation */
-  struct __test_metadata *prev, *next;
-};
-
-/* Storage for the (global) tests to be run. */
-static struct __test_metadata *__test_list = NULL;
-static unsigned int __test_count = 0;
-static unsigned int __fixture_count = 0;
-static int __constructor_order = 0;
-
-#define _CONSTRUCTOR_ORDER_FORWARD   1
-#define _CONSTRUCTOR_ORDER_BACKWARD (-1)
-
-/*
- * Since constructors are called in reverse order, reverse the test
- * list so tests are run in source declaration order.
- * https://gcc.gnu.org/onlinedocs/gccint/Initialization.html
- * However, it seems not all toolchains do this correctly, so use
- * __constructor_order to detect which direction is called first
- * and adjust list building logic to get things running in the right
- * direction.
- */
-static inline void __register_test(struct __test_metadata *t) {
-  __test_count++;
-  /* Circular linked list where only prev is circular. */
-  if (__test_list == NULL) {
-    __test_list = t;
-    t->next = NULL;
-    t->prev = t;
-    return;
-  }
-  if (__constructor_order == _CONSTRUCTOR_ORDER_FORWARD) {
-    t->next = NULL;
-    t->prev = __test_list->prev;
-    t->prev->next = t;
-    __test_list->prev = t;
-  } else {
-    t->next = __test_list;
-    t->next->prev = t;
-    t->prev = t;
-    __test_list = t;
-  }
-}
-
-static inline int __bail(int for_realz) {
-  if (for_realz)
-    abort();
-  return 0;
-}
-
-void __run_test(struct __test_metadata *t) {
-  pid_t child_pid;
-  int status;
-  t->passed = 1;
-  t->trigger = 0;
-  printf("[ RUN      ] %s\n", t->name);
-  child_pid = fork();
-  if (child_pid < 0) {
-    printf("ERROR SPAWNING TEST CHILD\n");
-    t->passed = 0;
-  } else if (child_pid == 0) {
-    t->fn(t);
-    _exit(t->passed);
-  } else {
-    /* TODO(wad) add timeout support. */
-    waitpid(child_pid, &status, 0);
-    if (WIFEXITED(status)) {
-      t->passed = t->termsig == -1 ? WEXITSTATUS(status) : 0;
-      if (t->termsig != -1) {
-       fprintf(TH_LOG_STREAM,
-                "%s: Test exited normally instead of by signal (code: %d)\n",
-               t->name,
-               WEXITSTATUS(status));
-      }
-    } else if (WIFSIGNALED(status)) {
-      t->passed = 0;
-      if (WTERMSIG(status) == SIGABRT) {
-        fprintf(TH_LOG_STREAM,
-                "%s: Test terminated by assertion\n",
-               t->name);
-      } else if (WTERMSIG(status) == t->termsig) {
-        t->passed = 1;
-      } else {
-        fprintf(TH_LOG_STREAM,
-                "%s: Test terminated unexpectedly by signal %d\n",
-               t->name,
-               WTERMSIG(status));
-      }
-    } else {
-        fprintf(TH_LOG_STREAM,
-                "%s: Test ended in some other way [%u]\n",
-               t->name,
-               status);
-    }
-  }
-  printf("[     %4s ] %s\n", (t->passed ? "OK" : "FAIL"), t->name);
-}
-
-static int test_harness_run(int __attribute__((unused)) argc,
-                            char __attribute__((unused)) **argv) {
-  struct __test_metadata *t;
-  int ret = 0;
-  unsigned int count = 0;
-  unsigned int pass_count = 0;
-
-  /* TODO(wad) add optional arguments similar to gtest. */
-  printf("[==========] Running %u tests from %u test cases.\n",
-          __test_count, __fixture_count + 1);
-  for (t = __test_list; t; t = t->next) {
-    count++;
-    __run_test(t);
-    if (t->passed)
-      pass_count++;
-    else
-      ret = 1;
-  }
-  /* TODO(wad) organize by fixtures since ordering is not guaranteed now. */
-  printf("[==========] %u / %u tests passed.\n", pass_count, count);
-  printf("[  %s  ]\n", (ret ? "FAILED" : "PASSED"));
-  return ret;
-}
-
-static void __attribute__((constructor)) __constructor_order_first(void) {
-  if (!__constructor_order)
-    __constructor_order = _CONSTRUCTOR_ORDER_FORWARD;
-}
-
-#endif  /* TEST_HARNESS_H_ */
diff --git a/tests/tests/os/src/android/os/cts/SeccompTest.java b/tests/tests/os/src/android/os/cts/SeccompTest.java
index d70a647..a58ed0d 100644
--- a/tests/tests/os/src/android/os/cts/SeccompTest.java
+++ b/tests/tests/os/src/android/os/cts/SeccompTest.java
@@ -98,8 +98,9 @@
             "global.KILL_one_arg_one",
             "global.KILL_one_arg_six",
             "global.arg_out_of_range",
-            "global.ERRNO_one",
-            "global.ERRNO_one_ok",
+            "global.ERRNO_valid",
+            "global.ERRNO_zero",
+            /* "global.ERRNO_capped", // presently fails */
         };
         runKernelUnitTestSuite(tests);
     }
@@ -180,9 +181,9 @@
     private void runKernelUnitTestSuite(final String[] tests) {
         for (final String test : tests) {
             // TODO: Replace the URL with the documentation when it's finished.
-            assertTrue(test + " failed. This test requires kernel functionality to pass. "
-                       + "Please go to http://XXXXX for instructions on how to enable or "
-                       + "backport the required functionality.",
+            assertTrue(test + " failed. This test requires kernel functionality to pass. Please go to "
+                       + "http://source.android.com/devices/tech/config/kernel.html#Seccomp-BPF-TSYNC"
+                       + " for instructions on how to enable or backport the required functionality.",
                        runKernelUnitTest(test));
         }
     }
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
index 13df2a9..4500969 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
@@ -22,10 +22,15 @@
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.os.Environment;
+import android.os.ProxyFileDescriptorCallback;
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.os.storage.OnObbStateChangeListener;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
 import android.test.AndroidTestCase;
 import android.test.ComparisonFailure;
 import android.util.Log;
@@ -36,7 +41,9 @@
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.InputStream;
+import java.io.SyncFailedException;
 import java.io.IOException;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
@@ -44,6 +51,8 @@
 import java.util.Arrays;
 import java.util.List;
 
+import junit.framework.AssertionFailedError;
+
 public class StorageManagerTest extends AndroidTestCase {
 
     private static final String TAG = StorageManager.class.getSimpleName();
@@ -243,6 +252,262 @@
         assertStorageVolumesEquals(primary, childVolume);
     }
 
+    private static class TestProxyFileDescriptorCallback extends ProxyFileDescriptorCallback {
+        final byte[] bytes;
+        int fsyncCount;
+        int releaseCount;
+        ErrnoException onGetSizeError = null;
+        ErrnoException onReadError = null;
+        ErrnoException onWriteError = null;
+        ErrnoException onFsyncError = null;
+
+        TestProxyFileDescriptorCallback(int size, String seed) {
+            final byte[] seedBytes = seed.getBytes();
+            bytes = new byte[size];
+            for (int i = 0; i < size; i++) {
+                bytes[i] = seedBytes[i % seedBytes.length];
+            }
+        }
+
+        @Override
+        public int onWrite(long offset, int size, byte[] data) throws ErrnoException {
+            if (onWriteError != null) {
+                throw onWriteError;
+            }
+            for (int i = 0; i < size; i++) {
+                bytes[(int)(i + offset)] = data[i];
+            }
+            return size;
+        }
+
+        @Override
+        public int onRead(long offset, int size, byte[] data) throws ErrnoException {
+            if (onReadError != null) {
+                throw onReadError;
+            }
+            final int len = (int)(Math.min(size, data.length - offset));
+            for (int i = 0; i < len; i++) {
+                data[i] = bytes[(int)(i + offset)];
+            }
+            return len;
+        }
+
+        @Override
+        public long onGetSize() throws ErrnoException {
+            if (onGetSizeError != null) {
+                throw onGetSizeError;
+            }
+            return bytes.length;
+        }
+
+        @Override
+        public void onFsync() throws ErrnoException {
+            if (onFsyncError != null) {
+                throw onFsyncError;
+            }
+            fsyncCount++;
+        }
+
+        @Override
+        public void onRelease() {
+            releaseCount++;
+        }
+    }
+
+    public void testOpenProxyFileDescriptor() throws Exception {
+        final TestProxyFileDescriptorCallback appleCallback =
+                new TestProxyFileDescriptorCallback(1024 * 1024, "Apple");
+        final TestProxyFileDescriptorCallback orangeCallback =
+                new TestProxyFileDescriptorCallback(1024 * 128, "Orange");
+        final TestProxyFileDescriptorCallback cherryCallback =
+                new TestProxyFileDescriptorCallback(1024 * 1024, "Cherry");
+        try (final ParcelFileDescriptor appleFd = mStorageManager.openProxyFileDescriptor(
+                     ParcelFileDescriptor.MODE_READ_ONLY, appleCallback);
+             final ParcelFileDescriptor orangeFd = mStorageManager.openProxyFileDescriptor(
+                     ParcelFileDescriptor.MODE_WRITE_ONLY, orangeCallback);
+             final ParcelFileDescriptor cherryFd = mStorageManager.openProxyFileDescriptor(
+                     ParcelFileDescriptor.MODE_READ_WRITE, cherryCallback)) {
+            // Stat
+            assertEquals(appleCallback.onGetSize(), appleFd.getStatSize());
+            assertEquals(orangeCallback.onGetSize(), orangeFd.getStatSize());
+            assertEquals(cherryCallback.onGetSize(), cherryFd.getStatSize());
+
+            final byte[] bytes = new byte[100];
+
+            // Read
+            for (int i = 0; i < 2; i++) {
+                Os.read(appleFd.getFileDescriptor(), bytes, 0, 100);
+                for (int j = 0; j < 100; j++) {
+                    assertEquals(appleCallback.bytes[i * 100 + j], bytes[j]);
+                }
+            }
+            try {
+                Os.read(orangeFd.getFileDescriptor(), bytes, 0, 100);
+                fail();
+            } catch (ErrnoException exp) {
+                assertEquals(OsConstants.EBADF, exp.errno);
+            }
+            for (int i = 0; i < 2; i++) {
+                Os.read(cherryFd.getFileDescriptor(), bytes, 0, 100);
+                for (int j = 0; j < 100; j++) {
+                    assertEquals(cherryCallback.bytes[i * 100 + j], bytes[j]);
+                }
+            }
+
+            // Pread
+            Os.pread(appleFd.getFileDescriptor(), bytes, 0, 100, 500);
+            for (int j = 0; j < 100; j++) {
+                assertEquals(appleCallback.bytes[500 + j], bytes[j]);
+            }
+            try {
+                Os.pread(orangeFd.getFileDescriptor(), bytes, 0, 100, 500);
+                fail();
+            } catch (ErrnoException exp) {
+                assertEquals(OsConstants.EBADF, exp.errno);
+            }
+            Os.pread(cherryFd.getFileDescriptor(), bytes, 0, 100, 500);
+            for (int j = 0; j < 100; j++) {
+                assertEquals(cherryCallback.bytes[500 + j], bytes[j]);
+            }
+
+            // Write
+            final byte[] writeSeed = "Strawberry".getBytes();
+            for (int i = 0; i < bytes.length; i++) {
+                bytes[i] = writeSeed[i % writeSeed.length];
+            }
+            try {
+                Os.write(appleFd.getFileDescriptor(), bytes, 0, 100);
+                fail();
+            } catch (ErrnoException exp) {
+                assertEquals(OsConstants.EBADF, exp.errno);
+            }
+            for (int i = 0; i < 2; i++) {
+                Os.write(orangeFd.getFileDescriptor(), bytes, 0, 100);
+                for (int j = 0; j < 100; j++) {
+                    assertEquals(bytes[j], orangeCallback.bytes[i * 100 + j]);
+                }
+            }
+            Os.lseek(cherryFd.getFileDescriptor(), 0, OsConstants.SEEK_SET);
+            for (int i = 0; i < 2; i++) {
+                Os.write(cherryFd.getFileDescriptor(), bytes, 0, 100);
+                for (int j = 0; j < 100; j++) {
+                    assertEquals(bytes[j], cherryCallback.bytes[i * 100 + j]);
+                }
+            }
+
+            // Pwrite
+            try {
+                Os.pwrite(appleFd.getFileDescriptor(), bytes, 0, 100, 500);
+                fail();
+            } catch (ErrnoException exp) {
+                assertEquals(OsConstants.EBADF, exp.errno);
+            }
+            Os.pwrite(orangeFd.getFileDescriptor(), bytes, 0, 100, 500);
+            for (int j = 0; j < 100; j++) {
+                assertEquals(bytes[j], orangeCallback.bytes[500 + j]);
+            }
+            Os.pwrite(cherryFd.getFileDescriptor(), bytes, 0, 100, 500);
+            for (int j = 0; j < 100; j++) {
+                assertEquals(bytes[j], cherryCallback.bytes[500 + j]);
+            }
+
+            // Flush
+            assertEquals(0, appleCallback.fsyncCount);
+            assertEquals(0, orangeCallback.fsyncCount);
+            assertEquals(0, cherryCallback.fsyncCount);
+            appleFd.getFileDescriptor().sync();
+            orangeFd.getFileDescriptor().sync();
+            cherryFd.getFileDescriptor().sync();
+            assertEquals(1, appleCallback.fsyncCount);
+            assertEquals(1, orangeCallback.fsyncCount);
+            assertEquals(1, cherryCallback.fsyncCount);
+
+            // Before release
+            assertEquals(0, appleCallback.releaseCount);
+            assertEquals(0, orangeCallback.releaseCount);
+            assertEquals(0, cherryCallback.releaseCount);
+        }
+
+        // Release
+        int retry = 3;
+        while (true) {
+            try {
+                assertEquals(1, appleCallback.releaseCount);
+                assertEquals(1, orangeCallback.releaseCount);
+                assertEquals(1, cherryCallback.releaseCount);
+                break;
+            } catch (AssertionFailedError error) {
+                if (retry-- > 0) {
+                   Thread.sleep(500);
+                   continue;
+                } else {
+                    throw error;
+                }
+            }
+        }
+    }
+
+    public void testOpenProxyFileDescriptor_error() throws Exception {
+        final TestProxyFileDescriptorCallback callback =
+                new TestProxyFileDescriptorCallback(1024 * 1024, "Error");
+        final byte[] bytes = new byte[128];
+        callback.onGetSizeError = new ErrnoException("onGetSize", OsConstants.ENOENT);
+        try {
+            try (final ParcelFileDescriptor fd = mStorageManager.openProxyFileDescriptor(
+                    ParcelFileDescriptor.MODE_READ_WRITE, callback)) {}
+            fail();
+        } catch (IOException exp) {}
+        callback.onGetSizeError = null;
+
+        try (final ParcelFileDescriptor fd = mStorageManager.openProxyFileDescriptor(
+                ParcelFileDescriptor.MODE_READ_WRITE, callback)) {
+            callback.onReadError = new ErrnoException("onRead", OsConstants.EIO);
+            try {
+                Os.read(fd.getFileDescriptor(), bytes, 0, bytes.length);
+                fail();
+            } catch (ErrnoException error) {}
+
+            callback.onReadError = new ErrnoException("onRead", OsConstants.ENOSYS);
+            try {
+                Os.read(fd.getFileDescriptor(), bytes, 0, bytes.length);
+                fail();
+            } catch (ErrnoException error) {}
+
+            callback.onReadError = null;
+            Os.read(fd.getFileDescriptor(), bytes, 0, bytes.length);
+
+            callback.onWriteError = new ErrnoException("onWrite", OsConstants.EIO);
+            try {
+                Os.write(fd.getFileDescriptor(), bytes, 0, bytes.length);
+                fail();
+            } catch (ErrnoException error) {}
+
+            callback.onWriteError = new ErrnoException("onWrite", OsConstants.ENOSYS);
+            try {
+                Os.write(fd.getFileDescriptor(), bytes, 0, bytes.length);
+                fail();
+            } catch (ErrnoException error) {}
+
+            callback.onWriteError = null;
+            Os.write(fd.getFileDescriptor(), bytes, 0, bytes.length);
+
+            callback.onFsyncError = new ErrnoException("onFsync", OsConstants.EIO);
+            try {
+                fd.getFileDescriptor().sync();
+                fail();
+            } catch (SyncFailedException error) {}
+
+            callback.onFsyncError = new ErrnoException("onFsync", OsConstants.ENOSYS);
+            try {
+                fd.getFileDescriptor().sync();
+                fail();
+            } catch (SyncFailedException error) {}
+
+            callback.onFsyncError = null;
+            fd.getFileDescriptor().sync();
+        }
+    }
+
     private void assertStorageVolumesEquals(StorageVolume volume, StorageVolume clone)
             throws Exception {
         // Asserts equals() method.
diff --git a/tests/tests/permission/Android.mk b/tests/tests/permission/Android.mk
index af0f8c4..68fa193 100644
--- a/tests/tests/permission/Android.mk
+++ b/tests/tests/permission/Android.mk
@@ -30,7 +30,10 @@
 LOCAL_JAVA_LIBRARIES := telephony-common
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    ctstestrunner guava android-ex-camera2
+    ctstestrunner \
+    guava \
+    android-ex-camera2 \
+    legacy-android-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libctspermission_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
index 2a4b6da..e2112aa 100644
--- a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
@@ -244,6 +244,32 @@
 
     }
 
+    /**
+     * Verify that TelephonyManager.getImei requires Permission.
+     * <p>
+     * Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE}.
+     */
+    @Test
+    public void testGetImei() {
+        if (!mHasTelephony) {
+            return;
+        }
+
+        try {
+            String imei = mTelephonyManager.getImei();
+            fail("Got IMEI: " + imei);
+        } catch (SecurityException e) {
+            // expected
+        }
+        try {
+            String imei = mTelephonyManager.getImei(0);
+            fail("Got IMEI: " + imei);
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
     private static Context getContext() {
         return InstrumentationRegistry.getContext();
     }
diff --git a/tests/tests/permission2/src/android/permission2/cts/PrivappPermissionsTest.java b/tests/tests/permission2/src/android/permission2/cts/PrivappPermissionsTest.java
index e1505f7..11dfb99 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PrivappPermissionsTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PrivappPermissionsTest.java
@@ -105,8 +105,11 @@
                 assertTrue("Not whitelisted permissions are granted for package "
                                 + pkg.packageName + ": " + grantedNotInWhitelist,
                         grantedNotInWhitelist.isEmpty());
-            }
 
+                assertTrue("Requested permissions not granted for package "
+                                + pkg.packageName + ": " + notGranted,
+                        notGranted.isEmpty());
+            }
         }
     }
 
diff --git a/tests/tests/provider/Android.mk b/tests/tests/provider/Android.mk
index 6a7d871..ce0a890 100644
--- a/tests/tests/provider/Android.mk
+++ b/tests/tests/provider/Android.mk
@@ -31,7 +31,11 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    compatibility-device-util ctstestrunner ub-uiautomator
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    junit \
+    legacy-android-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index b335065..ddd78f1 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -21,7 +21,15 @@
 # Include both the 32 and 64 bit versions
 LOCAL_MULTILIB := both
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestserver ctstestrunner compatibility-device-util guava
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-common \
+    ctstestserver \
+    ctstestrunner \
+    compatibility-device-util \
+    guava \
+    platform-test-annotations \
+    legacy-android-test
 
 LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy
 
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 757d719..6e67855 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -50,6 +50,14 @@
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
             </intent-filter>
         </activity>
+        <activity
+            android:name="android.security.cts.MotionEventTestActivity"
+            android:label="Test MotionEvent">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+            </intent-filter>
+        </activity>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/security/res/raw/bug_33137046.mp4 b/tests/tests/security/res/raw/bug_33137046.mp4
new file mode 100644
index 0000000..01f49b2
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_33137046.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_33300701.tiff b/tests/tests/security/res/raw/bug_33300701.tiff
new file mode 100644
index 0000000..ea7a477
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_33300701.tiff
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/AudioSecurityTest.java b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
new file mode 100644
index 0000000..ecad5dc
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/AudioSecurityTest.java
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.security.cts;
+
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.media.audiofx.AudioEffect;
+import android.util.Log;
+
+import com.android.compatibility.common.util.CtsAndroidTestCase;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.UUID;
+
+public class AudioSecurityTest extends CtsAndroidTestCase {
+    private static final String TAG = "AudioSecurityTest";
+
+    private static final int ERROR_DEAD_OBJECT = -7; // AudioEffect.ERROR_DEAD_OBJECT
+
+    // should match audio_effect.h (native)
+    private static final int EFFECT_CMD_SET_PARAM = 5;
+    private static final int EFFECT_CMD_GET_PARAM = 8;
+    private static final int EFFECT_CMD_OFFLOAD   = 20;
+    private static final int SIZEOF_EFFECT_PARAM_T = 12;
+
+    private static void verifyZeroReply(byte[] reply) throws Exception {
+        int count = 0;
+        for (byte b : reply) {
+            if (b != 0) {
+                count++;
+            }
+        }
+        assertEquals("reply has " + count + " nonzero values", 0 /* expected */, count);
+    }
+
+    // @FunctionalInterface
+    private interface TestEffect {
+        void test(AudioEffect audioEffect) throws Exception;
+    }
+
+    private static void testAllEffects(String testName, TestEffect testEffect) throws Exception {
+        int failures = 0;
+        for (AudioEffect.Descriptor descriptor : AudioEffect.queryEffects()) {
+            final AudioEffect audioEffect;
+            try {
+                audioEffect = (AudioEffect)AudioEffect.class.getConstructor(
+                        UUID.class, UUID.class, int.class, int.class).newInstance(
+                                descriptor.type,
+                                descriptor.uuid, // uuid overrides type
+                                0 /* priority */, 0 /* audioSession */);
+            } catch (Exception e) {
+                Log.w(TAG, "effect " + testName + " " + descriptor.name
+                        + " cannot be created (ignoring)");
+                continue; // OK;
+            }
+            try {
+                testEffect.test(audioEffect);
+                Log.d(TAG, "effect " + testName + " " + descriptor.name + " success");
+            } catch (Exception e) {
+                Log.e(TAG, "effect " + testName + " " + descriptor.name + " failed!");
+                ++failures;
+            } catch (AssertionError e) {
+                Log.e(TAG, "effect " + testName + " " + descriptor.name + " failed!");
+                ++failures;
+            }
+        }
+        assertEquals("found " + testName + " " + failures + " failures",
+                0 /* expected */, failures);
+    }
+
+    // b/28173666
+    public void testAllEffectsGetParameterAttemptOffload_CVE_2016_3745() throws Exception {
+        testAllEffects("get parameter attempt offload",
+                new TestEffect() {
+            @Override
+            public void test(AudioEffect audioEffect) throws Exception {
+                testAudioEffectGetParameter(audioEffect, true /* offload */);
+            }
+        });
+    }
+
+    // b/32438594
+    // b/32624850
+    // b/32635664
+    public void testAllEffectsGetParameter2AttemptOffload_CVE_2017_0398() throws Exception {
+        testAllEffects("get parameter2 attempt offload",
+                new TestEffect() {
+            @Override
+            public void test(AudioEffect audioEffect) throws Exception {
+                testAudioEffectGetParameter2(audioEffect, true /* offload */);
+            }
+        });
+    }
+
+    // b/30204301
+    public void testAllEffectsSetParameterAttemptOffload_CVE_2016_3924() throws Exception {
+        testAllEffects("set parameter attempt offload",
+                new TestEffect() {
+            @Override
+            public void test(AudioEffect audioEffect) throws Exception {
+                testAudioEffectSetParameter(audioEffect, true /* offload */);
+            }
+        });
+    }
+
+    private static void testAudioEffectGetParameter(
+            AudioEffect audioEffect, boolean offload) throws Exception {
+        if (audioEffect == null) {
+            return;
+        }
+        try {
+            // 1) set offload_enabled
+            if (offload) {
+                byte command[] = new byte[8];
+                Arrays.fill(command, (byte)1);
+                byte reply[] = new byte[4]; // ignored
+
+                /* ignored */ AudioEffect.class.getDeclaredMethod(
+                        "command", int.class, byte[].class, byte[].class).invoke(
+                                audioEffect, EFFECT_CMD_OFFLOAD, command, reply);
+            }
+
+            // 2) get parameter with invalid psize
+            {
+                byte command[] = new byte[30];
+                Arrays.fill(command, (byte)0xDD);
+                byte reply[] = new byte[30];
+
+                Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
+                        "command", int.class, byte[].class, byte[].class).invoke(
+                                audioEffect, EFFECT_CMD_GET_PARAM, command, reply);
+
+                assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
+                verifyZeroReply(reply);
+            }
+
+            // NOTE: an alternative way of checking crash:
+            //
+            // Thread.sleep(1000 /* millis */);
+            // assertTrue("Audio server might have crashed",
+            //        audioEffect.setEnabled(false) != AudioEffect.ERROR_DEAD_OBJECT);
+        } catch (NoSuchMethodException e) {
+            Log.w(TAG, "AudioEffect.command() does not exist (ignoring)"); // OK
+        } finally {
+            audioEffect.release();
+        }
+    }
+
+    private static void testAudioEffectGetParameter2(
+            AudioEffect audioEffect, boolean offload) throws Exception {
+        if (audioEffect == null) {
+            return;
+        }
+        try {
+            // 1) set offload_enabled
+            if (offload) {
+                byte command[] = new byte[8];
+                Arrays.fill(command, (byte)1);
+                byte reply[] = new byte[4]; // ignored
+
+                /* ignored */ AudioEffect.class.getDeclaredMethod(
+                        "command", int.class, byte[].class, byte[].class).invoke(
+                                audioEffect, EFFECT_CMD_OFFLOAD, command, reply);
+            }
+
+            // 2) get parameter with small command size but large psize
+            {
+                final int parameterSize = 0x100000;
+
+                byte command[] = ByteBuffer.allocate(5 * 4 /* capacity */)
+                        .order(ByteOrder.nativeOrder())
+                        .putInt(0)             // status (unused)
+                        .putInt(parameterSize) // psize (very large)
+                        .putInt(0)             // vsize
+                        .putInt(0x04030201)    // data[0] (param too small for psize)
+                        .putInt(0x08070605)    // data[4]
+                        .array();
+                byte reply[] = new byte[parameterSize + SIZEOF_EFFECT_PARAM_T];
+
+                Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
+                        "command", int.class, byte[].class, byte[].class).invoke(
+                                audioEffect, EFFECT_CMD_GET_PARAM, command, reply);
+
+                verifyZeroReply(reply);
+                assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
+            }
+        } catch (NoSuchMethodException e) {
+            Log.w(TAG, "AudioEffect.command() does not exist (ignoring)"); // OK
+        } finally {
+            audioEffect.release();
+        }
+    }
+
+    private static void testAudioEffectGetParameter3(AudioEffect audioEffect) throws Exception {
+        if (audioEffect == null) {
+            return;
+        }
+        try {
+            // 1) get parameter with zero command size
+            {
+                final int parameterSize = 0x10;
+
+                Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
+                        "command", int.class, byte[].class, byte[].class).invoke(
+                                audioEffect,
+                                EFFECT_CMD_GET_PARAM,
+                                new byte[0] /* command */,
+                                new byte[parameterSize + SIZEOF_EFFECT_PARAM_T] /* reply */);
+
+                assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
+            }
+        } catch (NoSuchMethodException e) {
+            Log.w(TAG, "AudioEffect.command() does not exist (ignoring)"); // OK
+        } finally {
+            audioEffect.release();
+        }
+    }
+
+    private static void testAudioEffectSetParameter(
+            AudioEffect audioEffect, boolean offload) throws Exception {
+        if (audioEffect == null) {
+            return;
+        }
+        try {
+            // 1) set offload_enabled
+            if (offload) {
+                byte command[] = new byte[8];
+                Arrays.fill(command, (byte)1);
+                byte reply[] = new byte[4]; // ignored
+
+                /* ignored */ AudioEffect.class.getDeclaredMethod(
+                        "command", int.class, byte[].class, byte[].class).invoke(
+                                audioEffect, EFFECT_CMD_OFFLOAD, command, reply);
+            }
+
+            // 2) set parameter with invalid psize
+            {
+                byte command[] = ByteBuffer.allocate(5 * 4 /* capacity */)
+                        .order(ByteOrder.nativeOrder())
+                        .putInt(0)          // status (unused)
+                        .putInt(0xdddddddd) // psize (very large)
+                        .putInt(4)          // vsize
+                        .putInt(1)          // data[0] (param too small for psize)
+                        .putInt(0)          // data[4]
+                        .array();
+                byte reply[] = new byte[4]; // returns status code (ignored)
+
+                Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
+                        "command", int.class, byte[].class, byte[].class).invoke(
+                                audioEffect, EFFECT_CMD_SET_PARAM, command, reply);
+
+                assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
+                // on failure reply may contain the status code.
+            }
+        } catch (NoSuchMethodException e) {
+            Log.w(TAG, "AudioEffect.command() does not exist (ignoring)"); // OK
+        } finally {
+            audioEffect.release();
+        }
+    }
+
+    private static void testAudioEffectSetOffload(AudioEffect audioEffect) throws Exception {
+        if (audioEffect == null) {
+            return;
+        }
+        try {
+            // 1) set offload_enabled with zero command and reply size
+            {
+                Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
+                        "command", int.class, byte[].class, byte[].class).invoke(
+                                audioEffect,
+                                EFFECT_CMD_OFFLOAD,
+                                new byte[0] /* command */,
+                                new byte[0] /* reply */);
+
+                assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
+            }
+         } catch (NoSuchMethodException e) {
+            Log.w(TAG, "AudioEffect.command() does not exist (ignoring)"); // OK
+        } finally {
+            audioEffect.release();
+        }
+    }
+
+    // should match effect_visualizer.h (native)
+    private static final String VISUALIZER_TYPE = "e46b26a0-dddd-11db-8afd-0002a5d5c51b";
+    private static final int VISUALIZER_CMD_CAPTURE = 0x10000;
+    private static final int VISUALIZER_PARAM_CAPTURE_SIZE = 0;
+
+    // b/31781965
+    public void testVisualizerCapture_CVE_2017_0396() throws Exception {
+        // Capture params
+        final int CAPTURE_SIZE = 1 << 24; // 16MB seems to be large enough to cause a SEGV.
+        final byte[] captureBuf = new byte[CAPTURE_SIZE];
+
+        // Track params
+        final int sampleRate = 48000;
+        final int format = AudioFormat.ENCODING_PCM_16BIT;
+        final int loops = 1;
+        final int seconds = 1;
+        final int channelCount = 2;
+        final int bufferFrames = seconds * sampleRate;
+        final int bufferSamples = bufferFrames * channelCount;
+        final int bufferSize = bufferSamples * 2; // bytes per sample for 16 bits
+        final short data[] = new short[bufferSamples]; // zero data
+
+        for (AudioEffect.Descriptor descriptor : AudioEffect.queryEffects()) {
+            if (descriptor.type.compareTo(UUID.fromString(VISUALIZER_TYPE)) != 0) {
+                continue;
+            }
+
+            AudioEffect audioEffect = null;
+            AudioTrack audioTrack = null;
+
+            try {
+                // create track and play
+                {
+                    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
+                            AudioFormat.CHANNEL_OUT_STEREO, format, bufferSize,
+                            AudioTrack.MODE_STATIC);
+                    assertEquals("Cannot write to audio track",
+                            bufferSamples,
+                            audioTrack.write(data, 0 /* offsetInBytes */, data.length));
+                    assertEquals("AudioTrack not initialized",
+                            AudioTrack.STATE_INITIALIZED,
+                            audioTrack.getState());
+                    assertEquals("Cannot set loop points",
+                            android.media.AudioTrack.SUCCESS,
+                            audioTrack.setLoopPoints(0 /* startInFrames */, bufferFrames, loops));
+                    audioTrack.play();
+                }
+
+                // wait for track to really begin playing
+                Thread.sleep(200 /* millis */);
+
+                // create effect
+                {
+                    audioEffect = (AudioEffect) AudioEffect.class.getConstructor(
+                            UUID.class, UUID.class, int.class, int.class).newInstance(
+                                    descriptor.type, descriptor.uuid, 0 /* priority */,
+                                    audioTrack.getAudioSessionId());
+                }
+
+                // set capture size
+                {
+                    byte command[] = ByteBuffer.allocate(5 * 4 /* capacity */)
+                            .order(ByteOrder.nativeOrder())
+                            .putInt(0)                             // status (unused)
+                            .putInt(4)                             // psize (sizeof(param))
+                            .putInt(4)                             // vsize (sizeof(value))
+                            .putInt(VISUALIZER_PARAM_CAPTURE_SIZE) // data[0] (param)
+                            .putInt(CAPTURE_SIZE)                  // data[4] (value)
+                            .array();
+
+                    Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
+                            "command", int.class, byte[].class, byte[].class).invoke(
+                                    audioEffect,
+                                    EFFECT_CMD_SET_PARAM,
+                                    command, new byte[4] /* reply */);
+                    Log.d(TAG, "setparam returns " + ret);
+                    assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
+                }
+
+                // enable effect
+                {
+                    final int ret = audioEffect.setEnabled(true);
+                    assertEquals("Cannot enable audio effect", 0 /* expected */, ret);
+                }
+
+                // wait for track audio data to be processed, otherwise capture
+                // will not really return audio data.
+                Thread.sleep(200 /* millis */);
+
+                // capture data
+                {
+                    Integer ret = (Integer) AudioEffect.class.getDeclaredMethod(
+                            "command", int.class, byte[].class, byte[].class).invoke(
+                                    audioEffect,
+                                    VISUALIZER_CMD_CAPTURE,
+                                    new byte[0] /* command */, captureBuf /* reply */);
+                    Log.d(TAG, "capture returns " + ret);
+                    assertTrue("Audio server might have crashed", ret != ERROR_DEAD_OBJECT);
+                }
+            } finally {
+                if (audioEffect != null) {
+                    audioEffect.release();
+                }
+                if (audioTrack != null) {
+                    audioTrack.release();
+                }
+            }
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/MotionEventTest.java b/tests/tests/security/src/android/security/cts/MotionEventTest.java
new file mode 100644
index 0000000..b407f5c
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MotionEventTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Gravity;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.compatibility.common.util.PollingCheck;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class MotionEventTest {
+    private static final String TAG = "MotionEventTest";
+    private Activity mActivity;
+    private Instrumentation mInstrumentation;
+
+    @Rule
+    public ActivityTestRule<MotionEventTestActivity> mActivityRule =
+            new ActivityTestRule<>(MotionEventTestActivity.class);
+
+    @Before
+    public void setup() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mActivity = mActivityRule.getActivity();
+        PollingCheck.waitFor(mActivity::hasWindowFocus);
+    }
+
+    /**
+     * Test for whether ACTION_OUTSIDE events contain information about whether touches are
+     * obscured.
+     *
+     * If ACTION_OUTSIDE_EVENTS contain information about whether the touch is obscured, then a
+     * pattern of invisible, untouchable, unfocusable SYSTEM_ALERT_WINDOWS can be placed across the
+     * screen to determine approximate locations of touch events without the user knowing.
+     */
+    @Test
+    public void testActionOutsideDoesNotContainedObscuredInformation() throws Exception {
+        enableAppOps();
+        final OnTouchListener listener = new OnTouchListener();
+        final Point size = new Point();
+        final View[] viewHolder = new View[1];
+        mActivity.runOnUiThread(() -> {
+            final WindowManager wm = mActivity.getSystemService(WindowManager.class);
+            wm.getDefaultDisplay().getSize(size);
+
+            WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(
+                    WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
+                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
+                    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
+                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
+            wmlp.width = size.x / 4;
+            wmlp.height = size.y / 4;
+            wmlp.gravity = Gravity.TOP | Gravity.LEFT;
+            wmlp.setTitle(mActivity.getPackageName());
+
+            ViewGroup.LayoutParams vglp = new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT);
+
+            View v = new View(mActivity);
+            v.setOnTouchListener(listener);
+            v.setBackgroundColor(Color.GREEN);
+            v.setLayoutParams(vglp);
+            wm.addView(v, wmlp);
+
+            wmlp.gravity = Gravity.TOP | Gravity.RIGHT;
+
+            v = new View(mActivity);
+            v.setBackgroundColor(Color.BLUE);
+            v.setOnTouchListener(listener);
+            v.setLayoutParams(vglp);
+            viewHolder[0] = v;
+
+            wm.addView(v, wmlp);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        FutureTask<Point> task = new FutureTask<>(() -> {
+            final int[] viewLocation = new int[2];
+            viewHolder[0].getLocationOnScreen(viewLocation);
+            return new Point(viewLocation[0], viewLocation[1]);
+        });
+        mActivity.runOnUiThread(task);
+        Point viewLocation = task.get(5, TimeUnit.SECONDS);
+        injectTap(viewLocation.x, viewLocation.y);
+
+        List<MotionEvent> outsideEvents = listener.getOutsideEvents();
+        assertEquals(2, outsideEvents.size());
+        for (MotionEvent e : outsideEvents) {
+            assertEquals(0, e.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED);
+        }
+    }
+
+
+    private void enableAppOps() {
+        StringBuilder cmd = new StringBuilder();
+        cmd.append("appops set ");
+        cmd.append(mInstrumentation.getContext().getPackageName());
+        cmd.append(" android:system_alert_window allow");
+        mInstrumentation.getUiAutomation().executeShellCommand(cmd.toString());
+
+        StringBuilder query = new StringBuilder();
+        query.append("appops get ");
+        query.append(mInstrumentation.getContext().getPackageName());
+        query.append(" android:system_alert_window");
+        String queryStr = query.toString();
+
+        String result;
+        do {
+            ParcelFileDescriptor pfd =
+                    mInstrumentation.getUiAutomation().executeShellCommand(queryStr);
+            InputStream inputStream = new FileInputStream(pfd.getFileDescriptor());
+            result = convertStreamToString(inputStream);
+        } while (result.contains("No operations"));
+    }
+
+    private String convertStreamToString(InputStream is) {
+        try (Scanner s = new Scanner(is).useDelimiter("\\A")) {
+            return s.hasNext() ? s.next() : "";
+        }
+    }
+
+    private void injectTap(int x, int y) {
+        long downTime = SystemClock.uptimeMillis();
+        injectEvent(MotionEvent.ACTION_DOWN, x, y, downTime);
+        injectEvent(MotionEvent.ACTION_UP, x, y, downTime);
+    }
+
+    private void injectEvent(int action, int x, int y, long downTime) {
+        final UiAutomation automation = mInstrumentation.getUiAutomation();
+        final long eventTime = SystemClock.uptimeMillis();
+        MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, 0);
+        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        automation.injectInputEvent(event, true);
+        event.recycle();
+    }
+
+    private static class OnTouchListener implements View.OnTouchListener {
+        private List<MotionEvent> mOutsideEvents;
+
+        public OnTouchListener() {
+            mOutsideEvents = new ArrayList<>();
+        }
+
+        public boolean onTouch(View v, MotionEvent e) {
+            if (e.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                mOutsideEvents.add(MotionEvent.obtain(e));
+            }
+            return true;
+        }
+
+        public List<MotionEvent> getOutsideEvents() {
+            return mOutsideEvents;
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/MotionEventTestActivity.java b/tests/tests/security/src/android/security/cts/MotionEventTestActivity.java
new file mode 100644
index 0000000..d986aff
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MotionEventTestActivity.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.security.cts.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class MotionEventTestActivity extends Activity { }
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 50e6edf..e0642ba 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -33,6 +33,7 @@
 import android.media.MediaCodecList;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
+import android.media.MediaMetadataRetriever;
 import android.media.MediaPlayer;
 import android.opengl.GLES20;
 import android.opengl.GLES11Ext;
@@ -68,6 +69,10 @@
      before any existing test methods
      ***********************************************************/
 
+    public void testStagefright_bug_33137046() throws Exception {
+        doStagefrightTest(R.raw.bug_33137046);
+    }
+
     public void testStagefright_cve_2016_2507() throws Exception {
         doStagefrightTest(R.raw.cve_2016_2507);
     }
@@ -220,6 +225,7 @@
     private void doStagefrightTest(final int rid) throws Exception {
         doStagefrightTestMediaPlayer(rid);
         doStagefrightTestMediaCodec(rid);
+        doStagefrightTestMediaMetadataRetriever(rid);
     }
 
     private Surface getDummySurface() {
@@ -502,4 +508,60 @@
         thr.stopLooper();
         thr.join();
     }
+    private void doStagefrightTestMediaMetadataRetriever(final int rid) throws Exception {
+
+        final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+
+        LooperThread thr = new LooperThread(new Runnable() {
+            @Override
+            public void run() {
+
+                MediaPlayer mp = new MediaPlayer();
+                mp.setOnErrorListener(mpcl);
+                try {
+                    AssetFileDescriptor fd = getInstrumentation().getContext().getResources()
+                        .openRawResourceFd(R.raw.good);
+
+                    // the onErrorListener won't receive MEDIA_ERROR_SERVER_DIED until
+                    // setDataSource has been called
+                    mp.setDataSource(fd.getFileDescriptor(),
+                                     fd.getStartOffset(),
+                                     fd.getLength());
+                } catch (Exception e) {
+                    // this is a known-good file, so no failure should occur
+                    fail("setDataSource of known-good file failed");
+                }
+
+                synchronized(mpcl) {
+                    mpcl.notify();
+                }
+                Looper.loop();
+                mp.release();
+            }
+        });
+        thr.start();
+        // wait until the thread has initialized the MediaPlayer
+        synchronized(mpcl) {
+            mpcl.wait();
+        }
+
+        Resources resources =  getInstrumentation().getContext().getResources();
+        AssetFileDescriptor fd = resources.openRawResourceFd(rid);
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        try {
+            retriever.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+        } catch (IllegalArgumentException e) {
+            // ignore
+        }
+        retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
+        retriever.getEmbeddedPicture();
+        retriever.getFrameAtTime();
+
+        retriever.release();
+        String rname = resources.getResourceEntryName(rid);
+        String cve = rname.replace("_", "-").toUpperCase();
+        assertFalse("Device *IS* vulnerable to " + cve,
+                    mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+        thr.stopLooper();
+    }
 }
diff --git a/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
new file mode 100644
index 0000000..f81da6b
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/ZeroHeightTiffTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.test.AndroidTestCase;
+
+import java.io.InputStream;
+
+import android.security.cts.R;
+
+public class ZeroHeightTiffTest extends AndroidTestCase {
+    /**
+     * Verifies that the device fails to decode a zero height tiff file.
+     *
+     * Prior to fixing bug 33300701, decoding resulted in undefined behavior (divide by zero).
+     * With the fix, decoding will fail, without dividing by zero.
+     */
+    public void test_android_bug_33300701() {
+        InputStream exploitImage = mContext.getResources().openRawResource(R.raw.bug_33300701);
+        Bitmap bitmap = BitmapFactory.decodeStream(exploitImage);
+        assertNull(bitmap);
+    }
+}
diff --git a/tests/tests/shortcutmanager/AndroidManifest.xml b/tests/tests/shortcutmanager/AndroidManifest.xml
index 1fc96fb..d69ce5b 100755
--- a/tests/tests/shortcutmanager/AndroidManifest.xml
+++ b/tests/tests/shortcutmanager/AndroidManifest.xml
@@ -43,6 +43,13 @@
             </intent-filter>
         </activity-alias>
 
+        <activity-alias android:name="main_shortcut_config"
+                        android:targetActivity="android.content.pm.cts.shortcutmanager.MyActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.CREATE_SHORTCUT" />
+            </intent-filter>
+        </activity-alias>
+
         <!-- It's not exporeted, but should still be launchable. -->
         <activity android:name="android.content.pm.cts.shortcutmanager.ShortcutLaunchedActivity"
             android:exported="false"/>
diff --git a/tests/tests/shortcutmanager/common/src/android.content.pm.cts.shortcutmanager.common/Constants.java b/tests/tests/shortcutmanager/common/src/android.content.pm.cts.shortcutmanager.common/Constants.java
index 7ca5336..9d3db4a 100644
--- a/tests/tests/shortcutmanager/common/src/android.content.pm.cts.shortcutmanager.common/Constants.java
+++ b/tests/tests/shortcutmanager/common/src/android.content.pm.cts.shortcutmanager.common/Constants.java
@@ -15,11 +15,13 @@
  */
 package android.content.pm.cts.shortcutmanager.common;
 
+import java.security.SecureRandom;
+
 public class Constants {
     public static final String ACTION_THROTTLING_TEST =
             "android.content.pm.cts.shortcutmanager.ACTION_THROTTLING_TEST";
-    public static final String ACTION_THROTTLING_REPLY =
-            "android.content.pm.cts.shortcutmanager.ACTION_THROTTLING_REPLY";
+    public static final String ACTION_REPLY =
+            "android.content.pm.cts.shortcutmanager.ACTION_REPLY";
 
     public static final String EXTRA_METHOD = "method";
     public static final String EXTRA_REPLY_ACTION = "reply_action";
@@ -37,4 +39,14 @@
 
     public static final String INLINE_REPLY_TITLE = "InlineReplyTestTitle";
     public static final String INLINE_REPLY_REMOTE_INPUT_CAPTION = "__INLINE_REPLY_REMOTE_INPUT__";
+
+    public static final String IGNORE = "IGNORE";
+    public static final String REQUEST_IGNORED_MESSAGE = "REQUEST_IGNORED_MESSAGE";
+
+    public static final String ALREADY_PINNED = "ALREADY_PINNED";
+
+    public static final String HAS_ICON = "HAS_ICON";
+    public static final String LABEL = "LABEL";
+
+    public static final SecureRandom sRandom = new SecureRandom();
 }
diff --git a/tests/tests/shortcutmanager/common/src/android.content.pm.cts.shortcutmanager.common/ReplyUtil.java b/tests/tests/shortcutmanager/common/src/android.content.pm.cts.shortcutmanager.common/ReplyUtil.java
new file mode 100644
index 0000000..b1b0ae5
--- /dev/null
+++ b/tests/tests/shortcutmanager/common/src/android.content.pm.cts.shortcutmanager.common/ReplyUtil.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm.cts.shortcutmanager.common;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.retryUntil;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
+public class ReplyUtil {
+    private ReplyUtil() {
+    }
+
+    private static final String MAIN_CTS_PACKAGE = "android.content.pm.cts.shortcutmanager";
+
+    public static void runTestAndReply(Context context, String replyAction, Runnable test) {
+        try {
+            test.run();
+
+            sendReply(context, replyAction, null);
+        } catch (Throwable e) {
+            String error = "Test failed: " + e.getMessage() + "\n" + Log.getStackTraceString(e);
+            sendReply(context, replyAction, error);
+        }
+    }
+
+    public static void sendReply(Context context, String replyAction,
+            String failureMessageOrNullForSuccess) {
+        // Create the reply bundle.
+        final Bundle ret = new Bundle();
+        if (failureMessageOrNullForSuccess == null) {
+            ret.putBoolean("success", true);
+        } else {
+            ret.putString("error", failureMessageOrNullForSuccess);
+        }
+
+        // Send reply
+        final Intent reply = new Intent(replyAction).setPackage(MAIN_CTS_PACKAGE);
+        reply.putExtras(ret);
+
+        context.sendBroadcast(reply);
+    }
+
+    public static void sendSuccessReply(Context context, String replyAction) {
+        sendReply(context, replyAction, null);
+    }
+
+    public static void invokeAndWaitForReply(Context context, Consumer<String> r) {
+        final AtomicReference<Intent> ret = new AtomicReference<>();
+
+        // Register the reply receiver
+
+        // Use a random reply action every time.
+        final String replyAction = Constants.ACTION_REPLY + Constants.sRandom.nextLong();
+        final IntentFilter filter = new IntentFilter(replyAction);
+
+        final BroadcastReceiver resultReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                ret.set(intent);
+            }
+        };
+
+        context.registerReceiver(resultReceiver, filter);
+
+        try {
+            // Run the code.
+            r.accept(replyAction);
+
+            // Wait for the response.
+            retryUntil(() -> ret.get() != null, "Didn't receive result broadcast", 120);
+
+            if (ret.get().getExtras().getBoolean("success")) {
+                return;
+            }
+            Assert.fail(ret.get().getExtras().getString("error"));
+        } finally {
+            context.unregisterReceiver(resultReceiver);
+        }
+    }
+}
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk b/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk
index acdb149..a11c978 100644
--- a/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk
+++ b/tests/tests/shortcutmanager/packages/launchermanifest/Android.mk
@@ -23,7 +23,17 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-support-v4 \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    ShortcutManagerTestUtils
 
 LOCAL_SDK_VERSION := current
 
@@ -43,7 +53,17 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-support-v4 \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    ShortcutManagerTestUtils
 
 LOCAL_SDK_VERSION := current
 
@@ -63,7 +83,17 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-support-v4 \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    ShortcutManagerTestUtils
 
 LOCAL_SDK_VERSION := current
 
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml b/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml
index 4290c7f..ac4925e 100755
--- a/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml
+++ b/tests/tests/shortcutmanager/packages/launchermanifest/AndroidManifest.xml
@@ -43,6 +43,11 @@
                 <category android:name="android.intent.category.HOME" />
             </intent-filter>
         </activity-alias>
+        <activity android:name="ShortcutConfirmPin">
+            <intent-filter>
+                <action android:name="android.content.pm.action.CONFIRM_PIN_ITEM" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
 
diff --git a/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk b/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk
index 4aebb74..bc4aaa7 100644
--- a/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk
+++ b/tests/tests/shortcutmanager/packages/launchermanifest_nonshared/Android.mk
@@ -22,7 +22,17 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-support-v4 \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    ShortcutManagerTestUtils
 
 LOCAL_SDK_VERSION := current
 
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk b/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk
index 458cb4e..1103194 100644
--- a/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk
+++ b/tests/tests/shortcutmanager/packages/packagemanifest/Android.mk
@@ -22,7 +22,17 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-support-v4 \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    ShortcutManagerTestUtils
 
 LOCAL_SDK_VERSION := current
 
@@ -42,7 +52,17 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-support-v4 \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    ShortcutManagerTestUtils
 
 LOCAL_SDK_VERSION := current
 
@@ -62,7 +82,17 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-support-v4 \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    ShortcutManagerTestUtils
 
 LOCAL_SDK_VERSION := current
 
diff --git a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk b/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk
index 793fa66..0b1ff53 100644
--- a/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk
+++ b/tests/tests/shortcutmanager/packages/packagemanifest_nonshared/Android.mk
@@ -22,7 +22,17 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
+LOCAL_SRC_FILES := $(call all-java-files-under, ../src) \
+        $(call all-java-files-under, ../../common/src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-test \
+    android-support-v4 \
+    mockito-target-minus-junit4 \
+    compatibility-device-util \
+    ctstestrunner \
+    ub-uiautomator \
+    ShortcutManagerTestUtils
 
 LOCAL_SDK_VERSION := current
 
diff --git a/tests/tests/shortcutmanager/packages/src/android/content/pm/cts/shortcutmanager/packages/ShortcutConfirmPin.java b/tests/tests/shortcutmanager/packages/src/android/content/pm/cts/shortcutmanager/packages/ShortcutConfirmPin.java
new file mode 100644
index 0000000..9a2659b
--- /dev/null
+++ b/tests/tests/shortcutmanager/packages/src/android/content/pm/cts/shortcutmanager/packages/ShortcutConfirmPin.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm.cts.shortcutmanager.packages;
+
+import android.app.Activity;
+import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.PinItemRequest;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.cts.shortcutmanager.common.Constants;
+import android.content.pm.cts.shortcutmanager.common.ReplyUtil;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+import java.util.Objects;
+
+/**
+ * Activity that receives a "pin shortcut" request, and accepts automatically.
+ */
+public class ShortcutConfirmPin extends Activity {
+    private static final String TAG = "ShortcutConfirmPin";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Log.i(TAG, "ShortcutConfirmPin.onCreate");
+
+        String replyAction = null;
+        try {
+            final LauncherApps launcherApps = getSystemService(LauncherApps.class);
+            final PinItemRequest request = launcherApps.getPinItemRequest(getIntent());
+
+            // This really must be non-null; otherwise we can't send a reply.
+            final ShortcutInfo shortcut = request.getShortcutInfo();
+            if (shortcut == null) {
+                Log.e(TAG, "request.getShortcutInfo() NOT expected to be NULL");
+                return;
+            }
+
+            replyAction = shortcut.getExtras().getString(Constants.EXTRA_REPLY_ACTION);
+
+            if (!request.isValid()) {
+                ReplyUtil.sendReply(this, replyAction, "request.isValid() expected to be TRUE");
+                return;
+            }
+            if (request.getRequestType() != PinItemRequest.REQUEST_TYPE_SHORTCUT) {
+                ReplyUtil.sendReply(this, replyAction,
+                        "request.getRequestType() expected to be REQUEST_TYPE_SHORTCUT");
+                return;
+            }
+
+            if (shortcut.getExtras().getBoolean(Constants.IGNORE)) {
+                // Send a reply so that the caller can tell if the request has been sent,
+                // and ignored.
+                ReplyUtil.sendReply(this, replyAction, Constants.REQUEST_IGNORED_MESSAGE);
+                return;
+            }
+
+            // Check the shortcut's fields.
+            final boolean expectPinned = shortcut.getExtras().getBoolean(Constants.ALREADY_PINNED);
+            if (shortcut.isPinned() != expectPinned) {
+                ReplyUtil.sendReply(this, replyAction, "isPinned() expected to be " + expectPinned);
+                return;
+            }
+
+            final String expectLabel = shortcut.getExtras().getString(Constants.LABEL);
+            if (!Objects.equals(expectLabel, shortcut.getShortLabel())) {
+                ReplyUtil.sendReply(this, replyAction,
+                        "getShortLabel() expected to be '" + expectLabel + "', but was '"
+                        + shortcut.getShortLabel() + "'");
+                return;
+            }
+            final Drawable icon = launcherApps.getShortcutBadgedIconDrawable(
+                    shortcut, DisplayMetrics.DENSITY_DEFAULT);
+            if (shortcut.getExtras().getBoolean(Constants.HAS_ICON)) {
+                // Send a reply so that the caller can tell if the request has been sent,
+                // and ignored.
+                if (icon == null) {
+                    ReplyUtil.sendReply(this, replyAction, "Expected to have icon");
+                    return;
+                }
+            } else {
+                if (icon != null) {
+                    ReplyUtil.sendReply(this, replyAction, "Not expected to have icon");
+                    return;
+                }
+            }
+
+            request.accept();
+            if (request.isValid()) {
+                ReplyUtil.sendReply(this, replyAction,
+                        "request.isValid() expected to be FALSE after accept()");
+                return;
+            }
+            ReplyUtil.sendSuccessReply(this, replyAction);
+        } catch (Exception e) {
+            Log.e(TAG, "Caught exception", e);
+            if (replyAction != null) {
+                ReplyUtil.sendReply(this, replyAction, "Caught exception: " + e);
+            }
+        } finally {
+            finish();
+        }
+    }
+}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerConfigActivityTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerConfigActivityTest.java
new file mode 100644
index 0000000..0614d84
--- /dev/null
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerConfigActivityTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm.cts.shortcutmanager;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps.PinItemRequest;
+import android.content.pm.ShortcutInfo;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tests for various APIs related to starting shortcut config activity.
+ */
+@SmallTest
+public class ShortcutManagerConfigActivityTest extends ShortcutManagerCtsTestsBase {
+
+    private static final String SHORTCUT_ID = "s12345";
+
+    private static final String CONFIG_ACTIVITY_NAME =
+            "android.content.pm.cts.shortcutmanager.main_shortcut_config";
+
+    public void testGetShortcutConfigActivityList() throws Exception {
+        setDefaultLauncher(getInstrumentation(), mLauncherContext1);
+
+        runWithCaller(mLauncherContext1, () -> {
+            assertNotNull(getConfigActivity());
+            assertNotNull(getLauncherApps().getShortcutConfigActivityIntent(getConfigActivity()));
+        });
+
+        // Get config activity works even for non-default activity.
+        setDefaultLauncher(getInstrumentation(), mLauncherContext4);
+
+        runWithCaller(mLauncherContext1, () -> {
+            assertNotNull(getConfigActivity());
+            // throws exception when default launcher is different.
+            assertExpectException(SecurityException.class, null, () ->
+                getLauncherApps().getShortcutConfigActivityIntent(getConfigActivity()));
+        });
+    }
+
+    public void testCorrectIntentSenderCreated() throws Throwable {
+        setDefaultLauncher(getInstrumentation(), mLauncherContext1);
+        final AtomicReference<IntentSender> sender = new AtomicReference<>();
+        runWithCaller(mLauncherContext1, () ->
+            sender.set(getLauncherApps().getShortcutConfigActivityIntent(getConfigActivity())));
+
+        Instrumentation.ActivityMonitor monitor =
+                getInstrumentation().addMonitor((String) null, null, false);
+
+        runTestOnUiThread(() -> {
+            try {
+                mLauncherContext1.startIntentSender(sender.get(), null, 0, 0, 0);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+        // Verify that the config activity was launched with proper action.
+        Activity activity = monitor.waitForActivityWithTimeout(10000);
+        assertNotNull(activity);
+        Intent intent = activity.getIntent();
+        assertEquals(Intent.ACTION_CREATE_SHORTCUT, intent.getAction());
+        assertEquals(CONFIG_ACTIVITY_NAME, intent.getComponent().getClassName());
+        activity.finish();
+    }
+
+    public void testCreateShortcutResultIntent_defaultLauncher() throws Exception {
+        setDefaultLauncher(getInstrumentation(), mLauncherContext1);
+        PinItemRequest request = getShortcutRequestForPackage1();
+        runWithCaller(mLauncherContext1, () -> {
+            assertTrue(request.isValid());
+            assertTrue(request.accept());
+        });
+    }
+
+    public void testCreateShortcutResultIntent_defaultChanges() throws Exception {
+        setDefaultLauncher(getInstrumentation(), mLauncherContext1);
+        PinItemRequest request = getShortcutRequestForPackage1();
+
+        setDefaultLauncher(getInstrumentation(), mLauncherContext4);
+        // Launcher1 can still access the request
+        runWithCaller(mLauncherContext1, () -> {
+            assertTrue(request.isValid());
+            assertTrue(request.accept());
+        });
+    }
+
+    public void testCreateShortcutResultIntent_noDefault() throws Exception {
+        setDefaultLauncher(getInstrumentation(), mLauncherContext4);
+        PinItemRequest request = getShortcutRequestForPackage1();
+
+        // Launcher1 can still access the request
+        runWithCaller(mLauncherContext1, () -> {
+            assertFalse(request.isValid());
+            assertExpectException(SecurityException.class, null, request::accept);
+        });
+    }
+
+    private PinItemRequest getShortcutRequestForPackage1() {
+        final AtomicReference<PinItemRequest> result = new AtomicReference<>();
+        runWithCaller(mPackageContext1, () -> {
+            final ShortcutInfo shortcut = makeShortcutBuilder(SHORTCUT_ID)
+                    .setShortLabel("label1")
+                    .setIntent(new Intent(Intent.ACTION_MAIN))
+                    .build();
+            Intent intent = getManager().createShortcutResultIntent(shortcut);
+            assertNotNull(intent);
+            PinItemRequest request = getLauncherApps().getPinItemRequest(intent);
+            assertNotNull(request);
+            assertEquals(PinItemRequest.REQUEST_TYPE_SHORTCUT, request.getRequestType());
+            assertEquals(SHORTCUT_ID, request.getShortcutInfo().getId());
+            result.set(request);
+        });
+        return result.get();
+    }
+
+    private LauncherActivityInfo getConfigActivity() {
+        for (LauncherActivityInfo info : getLauncherApps().getShortcutConfigActivityList(
+                getTestContext().getPackageName(), getUserHandle())) {
+            if (CONFIG_ACTIVITY_NAME.equals(info.getComponentName().getClassName())) {
+                return info;
+            }
+        }
+        return null;
+    }
+}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerCtsTestsBase.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerCtsTestsBase.java
index 0242b41..610fada 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerCtsTestsBase.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerCtsTestsBase.java
@@ -63,8 +63,6 @@
         }
     }
 
-    protected static final SecureRandom sRandom = new SecureRandom();
-
     private Context mCurrentCallerPackage;
     private int mUserId;
     private UserHandle mUserHandle;
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerRequestPinTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerRequestPinTest.java
new file mode 100644
index 0000000..34ce2d5
--- /dev/null
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerRequestPinTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm.cts.shortcutmanager;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.retryUntil;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.setDefaultLauncher;
+
+import android.content.Intent;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.content.pm.cts.shortcutmanager.common.Constants;
+import android.content.pm.cts.shortcutmanager.common.ReplyUtil;
+import android.os.PersistableBundle;
+import android.util.Log;
+
+import java.util.List;
+
+public class ShortcutManagerRequestPinTest extends ShortcutManagerCtsTestsBase {
+    private static final String TAG = "ShortcutMRPT";
+
+    public void testIsRequestPinShortcutSupported() {
+
+        // Launcher 1 supports it.
+        setDefaultLauncher(getInstrumentation(), mLauncherContext1);
+
+        runWithCaller(mPackageContext1, () -> {
+            assertTrue(getManager().isRequestPinShortcutSupported());
+        });
+
+        // Launcher 4 does *not* supports it.
+        setDefaultLauncher(getInstrumentation(), mLauncherContext4);
+
+        runWithCaller(mPackageContext1, () -> {
+            assertFalse(getManager().isRequestPinShortcutSupported());
+        });
+    }
+
+    /**
+     * A test for {@link ShortcutManager#requestPinShortcut}, a very simple case.
+     */
+    public void testRequestPinShortcut() {
+        setDefaultLauncher(getInstrumentation(), mLauncherContext1);
+
+        final String SHORTCUT_ID = "s12345";
+
+        runWithCaller(mPackageContext1, () -> {
+            assertTrue(getManager().isRequestPinShortcutSupported());
+
+            ReplyUtil.invokeAndWaitForReply(getTestContext(), (replyAction) -> {
+                final PersistableBundle extras = new PersistableBundle();
+                extras.putString(Constants.EXTRA_REPLY_ACTION, replyAction);
+                extras.putString(Constants.LABEL, "label1");
+
+                final ShortcutInfo shortcut = makeShortcutBuilder(SHORTCUT_ID)
+                        .setShortLabel("label1")
+                        .setIntent(new Intent(Intent.ACTION_MAIN))
+                        .setExtras(extras)
+                        .build();
+
+                Log.i(TAG, "Calling requestPinShortcut...");
+                assertTrue(getManager().requestPinShortcut(shortcut, /* intent sender */ null));
+                Log.i(TAG, "Done.");
+            });
+        });
+        runWithCaller(mLauncherContext1, () -> {
+            final ShortcutQuery query = new ShortcutQuery()
+                    .setPackage(mPackageContext1.getPackageName())
+                    .setShortcutIds(list(SHORTCUT_ID))
+                    .setQueryFlags(ShortcutQuery.FLAG_MATCH_DYNAMIC
+                            | ShortcutQuery.FLAG_MATCH_PINNED | ShortcutQuery.FLAG_MATCH_MANIFEST);
+            Log.i(TAG, "Waiting for shortcut to be visible to launcher...");
+            retryUntil(() -> {
+                final List<ShortcutInfo> shortcuts = getLauncherApps().getShortcuts(query,
+                        android.os.Process.myUserHandle());
+                if (shortcuts == null) {
+                    // Launcher not responded yet.
+                    return false;
+                }
+                assertWith(shortcuts)
+                        .haveIds(SHORTCUT_ID)
+                        .areAllPinned()
+                        .areAllNotDynamic()
+                        .areAllNotManifest();
+                return true;
+            }, "Shortcut still not pinned");
+        });
+    }
+
+    // TODO Various other cases (already pinned, etc)
+    // TODO Various error cases (missing mandatory fields, etc)
+}
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerThrottlingTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerThrottlingTest.java
index 3eb42cf..55afe48 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerThrottlingTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerThrottlingTest.java
@@ -19,15 +19,12 @@
 import static android.content.pm.cts.shortcutmanager.common.Constants.INLINE_REPLY_REMOTE_INPUT_CAPTION;
 
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.resetThrottling;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.retryUntil;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.runCommandForNoOutput;
 
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.cts.shortcutmanager.common.Constants;
+import android.content.pm.cts.shortcutmanager.common.ReplyUtil;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
@@ -36,8 +33,6 @@
 import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 
-import java.util.concurrent.atomic.AtomicReference;
-
 /**
  * The actual test is implemented in the CtsShortcutManagerThrottlingTest module.
  * This class uses broadcast receivers to communicate with it, because if we just used an
@@ -52,45 +47,14 @@
             "android.content.pm.cts.shortcutmanager.throttling";
 
     private void callTest(String method) {
-
-        final AtomicReference<Intent> ret = new AtomicReference<>();
-
-        // Register the reply receiver
-
-        // Use a random reply action every time.
-        final String replyAction = Constants.ACTION_THROTTLING_REPLY + sRandom.nextLong();
-        final IntentFilter filter = new IntentFilter(replyAction);
-
-        final BroadcastReceiver r = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                ret.set(intent);
-            }
-        };
-
-        getTestContext().registerReceiver(r, filter);
-
-        try {
-            // Send the request broadcast.
-
+        ReplyUtil.invokeAndWaitForReply(getTestContext(), (replyAction) -> {
             final Intent i = new Intent(Constants.ACTION_THROTTLING_TEST);
             i.putExtra(Constants.EXTRA_METHOD, method);
             i.putExtra(Constants.EXTRA_REPLY_ACTION, replyAction);
             i.setComponent(ComponentName.unflattenFromString(
                     TARGET_PACKAGE + "/.ShortcutManagerThrottlingTestReceiver"));
             getTestContext().sendBroadcast(i);
-
-            // Wait for the response.
-            retryUntil(() -> ret.get() != null, "Didn't receive result broadcast",
-                    120); // Wait much longer
-
-            if (ret.get().getExtras().getBoolean("success")) {
-                return;
-            }
-            fail(ret.get().getExtras().getString("error"));
-        } finally {
-            getTestContext().unregisterReceiver(r);
-        }
+        });
     }
 
     @Override
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerUsageTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerUsageTest.java
index aa0ad82..56e842f 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerUsageTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerUsageTest.java
@@ -23,6 +23,7 @@
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStatsManager;
+import android.content.pm.cts.shortcutmanager.common.Constants;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.format.Time;
 
@@ -54,7 +55,7 @@
         Time tobj = new Time();
         tobj.set(System.currentTimeMillis());
         return tobj.format("%Y-%m-%d %H:%M:%S") + "." + signature + "."
-                + sRandom.nextLong();
+                + Constants.sRandom.nextLong();
     }
 
     private boolean hasEvent(UsageEvents events, String packageName, String id) {
diff --git a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/BgService.java b/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/BgService.java
index fbf8079..a6468ef 100644
--- a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/BgService.java
+++ b/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/BgService.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.content.pm.ShortcutManager;
 import android.content.pm.cts.shortcutmanager.common.Constants;
+import android.content.pm.cts.shortcutmanager.common.ReplyUtil;
 import android.os.IBinder;
 import android.util.Log;
 
diff --git a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/FgService.java b/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/FgService.java
index 86f9dc7..a040715 100644
--- a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/FgService.java
+++ b/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/FgService.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.cts.shortcutmanager.common.Constants;
+import android.content.pm.cts.shortcutmanager.common.ReplyUtil;
 import android.os.IBinder;
 import android.util.Log;
 
diff --git a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/MyActivity.java b/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/MyActivity.java
index d04a890..ecd9964 100644
--- a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/MyActivity.java
+++ b/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/MyActivity.java
@@ -17,6 +17,7 @@
 
 import android.app.Activity;
 import android.content.pm.cts.shortcutmanager.common.Constants;
+import android.content.pm.cts.shortcutmanager.common.ReplyUtil;
 import android.os.Bundle;
 import android.util.Log;
 
diff --git a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/ReplyUtil.java b/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/ReplyUtil.java
deleted file mode 100644
index 1b0471c..0000000
--- a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/ReplyUtil.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.content.pm.cts.shortcutmanager.throttling;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-
-public class ReplyUtil {
-    private ReplyUtil() {
-    }
-
-    public static void runTestAndReply(Context context, String replyAction, Runnable test) {
-        try {
-            test.run();
-
-            sendReply(context, replyAction, null);
-        } catch (Throwable e) {
-            String error = "Test failed: " + e.getMessage() + "\n" + Log.getStackTraceString(e);
-            sendReply(context, replyAction, error);
-        }
-    }
-
-    public static void sendReply(Context context, String replyAction,
-            String failureMessageOrNullForSuccess) {
-        // Create the reply bundle.
-        final Bundle ret = new Bundle();
-        if (failureMessageOrNullForSuccess == null) {
-            ret.putBoolean("success", true);
-        } else {
-            ret.putString("error", failureMessageOrNullForSuccess);
-        }
-
-        // Send reply
-        final Intent reply = new Intent(replyAction);
-        reply.putExtras(ret);
-
-        context.sendBroadcast(reply);
-    }
-}
diff --git a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/ShortcutManagerThrottlingTestReceiver.java b/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/ShortcutManagerThrottlingTestReceiver.java
index 6edf7a8..6e067e5 100644
--- a/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/ShortcutManagerThrottlingTestReceiver.java
+++ b/tests/tests/shortcutmanager/throttling/src/android/content/pm/cts/shortcutmanager/throttling/ShortcutManagerThrottlingTestReceiver.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.content.pm.ShortcutManager;
 import android.content.pm.cts.shortcutmanager.common.Constants;
+import android.content.pm.cts.shortcutmanager.common.ReplyUtil;
 import android.util.Log;
 
 
diff --git a/tests/tests/speech/Android.mk b/tests/tests/speech/Android.mk
index 68e0cba..1134398 100755
--- a/tests/tests/speech/Android.mk
+++ b/tests/tests/speech/Android.mk
@@ -21,7 +21,10 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner \
+    android-support-test \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/systemui/Android.mk b/tests/tests/systemui/Android.mk
index c31d825..6aed2f8 100644
--- a/tests/tests/systemui/Android.mk
+++ b/tests/tests/systemui/Android.mk
@@ -26,7 +26,10 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner \
+    android-support-test \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/telephony/Android.mk b/tests/tests/telephony/Android.mk
index 75da56e..e502384 100644
--- a/tests/tests/telephony/Android.mk
+++ b/tests/tests/telephony/Android.mk
@@ -24,7 +24,10 @@
 
 LOCAL_JAVA_LIBRARIES := telephony-common
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner \
+    compatibility-device-util \
+    legacy-android-test
 
 LOCAL_HOST_SHARED_LIBRARIES := compatibility-device-telephony-preconditions
 
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index 83c3833..7d581c5 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -37,6 +37,7 @@
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
@@ -46,13 +47,12 @@
 import com.android.compatibility.common.util.TestThread;
 import com.android.internal.telephony.PhoneConstants;
 
+import java.util.regex.Pattern;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.regex.Pattern;
-
 @RunWith(AndroidJUnit4.class)
 public class TelephonyManagerTest {
     private TelephonyManager mTelephonyManager;
@@ -183,8 +183,11 @@
         mTelephonyManager.getDeviceId();
         mTelephonyManager.getDeviceId(mTelephonyManager.getDefaultSim());
         mTelephonyManager.getDeviceSoftwareVersion();
+        mTelephonyManager.getImei();
+        mTelephonyManager.getImei(mTelephonyManager.getDefaultSim());
         mTelephonyManager.getPhoneCount();
         mTelephonyManager.getDataEnabled();
+        mTelephonyManager.getNetworkSpecifier();
 
         TelecomManager telecomManager = (TelecomManager) getContext()
             .getSystemService(Context.TELECOM_SERVICE);
@@ -474,6 +477,70 @@
         assertEquals(mServiceState, mTelephonyManager.getServiceState());
     }
 
+    @Test
+    public void testGetCarrierConfig() {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+        CarrierConfigManager carrierConfigManager =
+                getContext().getSystemService(CarrierConfigManager.class);
+        assertEquals(mTelephonyManager.getCarrierConfig(), carrierConfigManager.getConfig());
+    }
+
+    /**
+     * Tests that the device properly reports either a valid IMEI if GSM or null.
+     */
+    @Test
+    public void testGetImei() {
+        String imei = mTelephonyManager.getImei();
+        if (mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_ABSENT && imei == null) {
+            // If no SIM card is present, IMEI can be null.
+            return;
+        }
+        verifyImei(imei, mTelephonyManager.getDeviceId());
+    }
+
+    /**
+     * Tests that the device properly reports either a valid IMEI if GSM or null.
+     */
+    @Test
+    public void testGetImeiForSlotId() {
+        // Test for slot id = 0.
+        String imei = mTelephonyManager.getImei(0);
+        verifyImei(imei, mTelephonyManager.getDeviceId(0));
+        // Also verify that no exception is thrown for any slot id (including invalid ones)
+        for (int i = -1; i <= mTelephonyManager.getPhoneCount(); i++) {
+            mTelephonyManager.getImei(i);
+        }
+    }
+
+    private void verifyImei(String imei, String deviceId) {
+        int phoneType = mTelephonyManager.getPhoneType();
+        switch (phoneType) {
+            case TelephonyManager.PHONE_TYPE_GSM:
+                assertGsmDeviceId(imei);
+                assertEquals(imei, deviceId);
+                break;
+            case TelephonyManager.PHONE_TYPE_CDMA:
+                // LTE device is using IMEI as device id
+                if (mTelephonyManager.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) {
+                    assertGsmDeviceId(imei);
+                    assertEquals(imei, deviceId);
+                    break;
+                }
+                // Fall through
+            case TelephonyManager.PHONE_TYPE_NONE:
+                if (imei != null) {
+                    assertGsmDeviceId(imei);
+                }
+                // An IMEI is not required for PHONE_TYPE_NONE or non-LTE PHONE_TYPE_CDMA
+                break;
+            default:
+                throw new IllegalArgumentException("Did you add a new phone type? " + phoneType);
+        }
+    }
+
     private static Context getContext() {
         return InstrumentationRegistry.getContext();
     }
diff --git a/tests/tests/telephony2/Android.mk b/tests/tests/telephony2/Android.mk
index 08a7df3..3ba6018 100644
--- a/tests/tests/telephony2/Android.mk
+++ b/tests/tests/telephony2/Android.mk
@@ -22,7 +22,10 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner compatibility-device-util
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    ctstestrunner \
+    compatibility-device-util \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java
index 5055972..24f9932 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java
@@ -173,8 +173,7 @@
 
         debugLayout(source, staticLayout);
 
-        int lineCount = staticLayout.getLineCount();
-        assertTrue("Number of lines", lineCount <= maxLines);
+        final int lineCount = staticLayout.getLineCount();
 
         for (int line = 0; line < lineCount; line++) {
             int lineStart = staticLayout.getLineStart(line);
diff --git a/tests/tests/uirendering/Android.mk b/tests/tests/uirendering/Android.mk
index e1f6eef..9d00124 100644
--- a/tests/tests/uirendering/Android.mk
+++ b/tests/tests/uirendering/Android.mk
@@ -30,7 +30,8 @@
     compatibility-device-util \
     ctstestrunner \
     mockito-target-minus-junit4 \
-    android-support-test
+    android-support-test \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java
new file mode 100644
index 0000000..d9b8d7f
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.uirendering.cts.testclasses;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.uirendering.cts.R;
+import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
+import android.uirendering.cts.bitmapverifiers.ColorCountVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.ViewInitializer;
+import android.view.FrameMetrics;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.Window;
+import android.widget.FrameLayout;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class BitmapTests extends ActivityTestBase {
+    class BitmapView extends View {
+        private Bitmap mBitmap;
+        private int mColor;
+
+        public BitmapView(Context context) {
+            super(context);
+            mBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+            setColor(Color.BLUE);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            canvas.drawBitmap(mBitmap, new Rect(0, 0, 1, 1), canvas.getClipBounds(), null);
+        }
+
+        public void setColor(int color) {
+            mColor = color;
+            mBitmap.setPixel(0, 0, color);
+        }
+
+        public int getColor() {
+            return mColor;
+        }
+    }
+
+    /*
+     * The following test verifies that bitmap changes during render thread animation won't
+     * be visible: we changed a bitmap from blue to red during circular reveal (an RT animation),
+     * and changed it back to blue before the end of the animation; we should never see any
+     * red pixel.
+     */
+    @Test
+    public void testChangeDuringRtAnimation() {
+        class RtOnlyFrameCounter implements Window.OnFrameMetricsAvailableListener {
+            private int count = 0;
+
+            @Override
+            public void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics,
+                    int dropCountSinceLastInvocation) {
+                if (frameMetrics.getMetric(FrameMetrics.ANIMATION_DURATION) == 0
+                        && frameMetrics.getMetric(FrameMetrics.INPUT_HANDLING_DURATION) == 0
+                        && frameMetrics.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION) == 0) {
+                    count++;
+                };
+            }
+
+            public boolean isLargeEnough() {
+                return count >= 5;
+            }
+        }
+
+        ViewInitializer initializer = new ViewInitializer() {
+            Animator mAnimator;
+            RtOnlyFrameCounter mCounter = new RtOnlyFrameCounter();
+
+            @Override
+            public void initializeView(View view) {
+                FrameLayout root = (FrameLayout) view.findViewById(R.id.frame_layout);
+
+                final BitmapView child = new BitmapView(view.getContext());
+                child.setLayoutParams(new FrameLayout.LayoutParams(50, 50));
+                root.addView(child);
+
+                mAnimator = ViewAnimationUtils.createCircularReveal(child, 0, 0, 0, 90);
+                mAnimator.setDuration(3000);
+                mAnimator.start();
+
+                Handler handler = new Handler();
+                handler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        child.setColor(Color.RED);
+                        try {
+                            Thread.sleep(1000);
+                        } catch (Exception e) {
+                            // do nothing
+                        }
+                        child.setColor(Color.BLUE);
+                    }
+                }, 1000);
+                getActivity().getWindow().addOnFrameMetricsAvailableListener(mCounter, handler);
+            }
+
+            @Override
+            public void teardownView() {
+                mAnimator.cancel();
+                Assert.assertTrue(mCounter.isLargeEnough());
+            }
+        };
+
+        createTest()
+                .addLayout(R.layout.frame_layout, initializer, true)
+                .runWithAnimationVerifier(new ColorCountVerifier(Color.RED, 0));
+    }
+
+    /*
+     * The following test verifies that bitmap changes during UI thread animation are
+     * visible: we keep changing a bitmap's color between red and blue in sync with the
+     * background, and we should only see pure blue or red.
+    */
+    @Test
+    public void testChangeDuringUiAnimation() {
+        class PureBlueOrRedVerifier extends BitmapVerifier {
+            @Override
+            public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
+                int blueCount = 0;
+                int redCount = 0;
+                for (int x = 0; x < width; x++) {
+                    for (int y = 0; y < height; y++) {
+                        if (bitmap[indexFromXAndY(x, y, stride, offset)] == Color.BLUE) {
+                            blueCount++;
+                        } else if (bitmap[indexFromXAndY(x, y, stride, offset)] == Color.RED) {
+                            redCount++;
+                        }
+                    }
+                }
+                return blueCount == width * height || redCount == width * height;
+            }
+        }
+
+        ViewInitializer initializer = new ViewInitializer() {
+            ValueAnimator mAnimator;
+
+            @Override
+            public void initializeView(View view) {
+                FrameLayout root = (FrameLayout) view.findViewById(R.id.frame_layout);
+                root.setBackgroundColor(Color.BLUE);
+
+                final BitmapView child = new BitmapView(view.getContext());
+
+                // The child size is strictly less than the test canvas size,
+                // and we are moving it up and down inside the canvas.
+                child.setLayoutParams(new FrameLayout.LayoutParams(ActivityTestBase.TEST_WIDTH / 2,
+                        ActivityTestBase.TEST_HEIGHT / 2));
+                root.addView(child);
+                child.setColor(Color.BLUE);
+
+                mAnimator = ValueAnimator.ofInt(0, ActivityTestBase.TEST_HEIGHT / 2);
+                mAnimator.setRepeatMode(mAnimator.REVERSE);
+                mAnimator.setRepeatCount(mAnimator.INFINITE);
+                mAnimator.setDuration(400);
+                mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        int v = (Integer) mAnimator.getAnimatedValue();
+                        child.setTranslationY(v);
+                        if (child.getColor() == Color.BLUE) {
+                            root.setBackgroundColor(Color.RED);
+                            child.setColor(Color.RED);
+                        } else {
+                            root.setBackgroundColor(Color.BLUE);
+                            child.setColor(Color.BLUE);
+                        }
+                    }
+                });
+                mAnimator.start();
+            }
+
+            @Override
+            public void teardownView() {
+                mAnimator.cancel();
+            }
+        };
+
+        createTest()
+                .addLayout(R.layout.frame_layout, initializer, true)
+                .runWithAnimationVerifier(new PureBlueOrRedVerifier());
+    }
+}
diff --git a/tests/tests/util/Android.mk b/tests/tests/util/Android.mk
index 866e566..32d4584 100644
--- a/tests/tests/util/Android.mk
+++ b/tests/tests/util/Android.mk
@@ -24,7 +24,11 @@
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-annotations android-support-test ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-annotations \
+    android-support-test \
+    ctstestrunner \
+    legacy-android-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index 9b505dd..f582b41 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -34,7 +34,8 @@
     ctstestrunner \
     mockito-target-minus-junit4 \
     platform-test-annotations \
-    ub-uiautomator
+    ub-uiautomator \
+    legacy-android-test
 
 LOCAL_JNI_SHARED_LIBRARIES := libctsview_jni libnativehelper_compat_libc++
 
diff --git a/tests/tests/view/res/layout/tooltip_layout.xml b/tests/tests/view/res/layout/tooltip_layout.xml
index 8291b31..eac341d 100644
--- a/tests/tests/view/res/layout/tooltip_layout.xml
+++ b/tests/tests/view/res/layout/tooltip_layout.xml
@@ -39,7 +39,7 @@
                 android:layout_height="wrap_content"
                 android:layout_margin="10dp"
                 android:text="View with tooltip"
-                android:tooltip="tooltip text"/>
+                android:tooltipText="tooltip text"/>
 
     </LinearLayout>
 
@@ -57,4 +57,28 @@
             android:layout_margin="10dp"
             android:background="#ddd"/>
 
+    <RelativeLayout
+            android:id="@+id/overlap_group"
+            android:layout_width="100dp"
+            android:layout_height="30dp"
+            android:layout_margin="10dp"
+            android:tooltipText="overlap tooltip group"
+            android:background="#ddd">
+        <View
+                android:id="@+id/overlap1"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:tooltipText="overlap tooltip 1" />
+        <View
+                android:id="@+id/overlap2"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:tooltipText="overlap tooltip 2" />
+        <View
+                android:id="@+id/overlap3"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:tooltipText="overlap tooltip 3" />
+    </RelativeLayout>
+
 </LinearLayout>
diff --git a/tests/tests/view/res/layout/view_layout.xml b/tests/tests/view/res/layout/view_layout.xml
index 64ebe39..920da83 100644
--- a/tests/tests/view/res/layout/view_layout.xml
+++ b/tests/tests/view/res/layout/view_layout.xml
@@ -123,6 +123,26 @@
       </LinearLayout>
     </LinearLayout>
 
+    <RelativeLayout
+      android:id="@+id/pointer_icon_overlap"
+      android:layout_width="100px"
+      android:layout_height="100px"
+      android:pointerIcon="crosshair">
+      <View
+        android:id="@+id/pointer_icon_overlap_child1"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+      <View
+        android:id="@+id/pointer_icon_overlap_child2"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+      <View
+        android:id="@+id/pointer_icon_overlap_child3"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:pointerIcon="help" />
+    </RelativeLayout>
+
     <FrameLayout
         android:id="@+id/aggregate_visibility_parent"
         android:layout_width="wrap_content"
diff --git a/tests/tests/view/res/menu/content_description.xml b/tests/tests/view/res/menu/content_description.xml
new file mode 100644
index 0000000..45b594a
--- /dev/null
+++ b/tests/tests/view/res/menu/content_description.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:id="@+id/item1"
+          android:title="item1"
+          android:contentDescription="description1" />
+
+    <item android:id="@+id/item2"
+          android:title="item2"
+          android:contentDescription="description2" />
+
+    <item android:id="@+id/item3"
+          android:title="item3" />
+
+</menu>
diff --git a/tests/tests/view/res/menu/tooltip.xml b/tests/tests/view/res/menu/tooltip.xml
new file mode 100644
index 0000000..b15a9b4
--- /dev/null
+++ b/tests/tests/view/res/menu/tooltip.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:id="@+id/item1"
+          android:title="item1"
+          android:tooltipText="tooltip1" />
+
+    <item android:id="@+id/item2"
+          android:title="item2"
+          android:tooltipText="tooltip2" />
+
+    <item android:id="@+id/item3"
+          android:title="item3" />
+
+</menu>
diff --git a/tests/tests/view/src/android/view/cts/MenuInflaterTest.java b/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
index 9da739e..bc9933f 100644
--- a/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
+++ b/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
@@ -32,6 +33,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.view.Menu;
 import android.view.MenuInflater;
+import android.view.MenuItem;
 import android.view.SubMenu;
 import android.widget.PopupMenu;
 
@@ -251,6 +253,50 @@
         assertTrue(mMenu.findItem(R.id.nongroup_checkable_item_3).isChecked());
     }
 
+    @UiThreadTest
+    @Test
+    public void testInflateTooltipFromXml() {
+        mMenuInflater.inflate(R.menu.tooltip, mMenu);
+
+        MenuItem item1 = mMenu.findItem(R.id.item1);
+        MenuItem item2 = mMenu.findItem(R.id.item2);
+        MenuItem item3 = mMenu.findItem(R.id.item3);
+
+        assertEquals("tooltip1", item1.getTooltipText());
+
+        assertEquals("tooltip2", item2.getTooltipText());
+        item2.setTooltipText(null);
+        assertNull(item2.getTooltipText());
+        item2.setTooltipText("tooltip2_new");
+        assertEquals("tooltip2_new", item2.getTooltipText());
+
+        assertNull(item3.getTooltipText());
+        item3.setTooltipText("tooltip3");
+        assertEquals("tooltip3", item3.getTooltipText());
+    }
+
+    @UiThreadTest
+    @Test
+    public void testInflateContentDescriptionFromXml() {
+        mMenuInflater.inflate(R.menu.content_description, mMenu);
+
+        MenuItem item1 = mMenu.findItem(R.id.item1);
+        MenuItem item2 = mMenu.findItem(R.id.item2);
+        MenuItem item3 = mMenu.findItem(R.id.item3);
+
+        assertEquals("description1", item1.getContentDescription());
+
+        assertEquals("description2", item2.getContentDescription());
+        item2.setContentDescription(null);
+        assertNull(item2.getContentDescription());
+        item2.setContentDescription("description2_new");
+        assertEquals("description2_new", item2.getContentDescription());
+
+        assertNull(item3.getContentDescription());
+        item3.setContentDescription("description3");
+        assertEquals("description3", item3.getContentDescription());
+    }
+
     private void verifyDrawableContent(BitmapDrawable b, int resId) {
         Bitmap expected = BitmapFactory.decodeResource(mActivity.getResources(), resId);
         WidgetTestUtils.assertEquals(expected, b.getBitmap());
diff --git a/tests/tests/view/src/android/view/cts/TooltipTest.java b/tests/tests/view/src/android/view/cts/TooltipTest.java
index 1903431..2c0c581 100644
--- a/tests/tests/view/src/android/view/cts/TooltipTest.java
+++ b/tests/tests/view/src/android/view/cts/TooltipTest.java
@@ -93,8 +93,8 @@
         }
     }
 
-    private void setTooltip(View view, CharSequence tooltip) throws Throwable {
-        mActivityRule.runOnUiThread(() -> view.setTooltip(tooltip));
+    private void setTooltipText(View view, CharSequence tooltipText) throws Throwable {
+        mActivityRule.runOnUiThread(() -> view.setTooltipText(tooltipText));
     }
 
     private boolean hasTooltip(View view) {
@@ -113,6 +113,10 @@
         mInstrumentation.waitForIdleSync();
     }
 
+    private void setVisibility(View view, int visibility) throws Throwable {
+        mActivityRule.runOnUiThread(() -> view.setVisibility(visibility));
+    }
+
     private void callPerformLongClick(View view) throws Throwable {
         mActivityRule.runOnUiThread(() -> view.performLongClick(0, 0));
     }
@@ -191,28 +195,28 @@
     @Test
     public void testGetSetTooltip() throws Throwable {
         // No tooltip set in resource
-        assertEquals(null, mNoTooltipView.getTooltip());
+        assertEquals(null, mNoTooltipView.getTooltipText());
 
         // Set the tooltip, read it back
-        final String tooltipString1 = "new tooltip";
-        setTooltip(mNoTooltipView, tooltipString1);
-        assertEquals(tooltipString1, mNoTooltipView.getTooltip());
+        final String tooltipText1 = "new tooltip";
+        setTooltipText(mNoTooltipView, tooltipText1);
+        assertEquals(tooltipText1, mNoTooltipView.getTooltipText());
 
         // Clear the tooltip.
-        setTooltip(mNoTooltipView, null);
-        assertEquals(null, mNoTooltipView.getTooltip());
+        setTooltipText(mNoTooltipView, null);
+        assertEquals(null, mNoTooltipView.getTooltipText());
 
         // Check the tooltip set in resource
-        assertEquals("tooltip text", mTooltipView.getTooltip());
+        assertEquals("tooltip text", mTooltipView.getTooltipText());
 
         // Clear the tooltip set in resource
-        setTooltip(mTooltipView, null);
-        assertEquals(null, mTooltipView.getTooltip());
+        setTooltipText(mTooltipView, null);
+        assertEquals(null, mTooltipView.getTooltipText());
 
         // Set the tooltip again, read it back
-        final String tooltipString2 = "new tooltip 2";
-        setTooltip(mTooltipView, tooltipString2);
-        assertEquals(tooltipString2, mTooltipView.getTooltip());
+        final String tooltipText2 = "new tooltip 2";
+        setTooltipText(mTooltipView, tooltipText2);
+        assertEquals(tooltipText2, mTooltipView.getTooltipText());
     }
 
     @Test
@@ -249,10 +253,10 @@
         callPerformLongClick(mTooltipView);
         assertTrue(hasTooltip(mTooltipView));
 
-        setTooltip(mTooltipView, "updated tooltip");
+        setTooltipText(mTooltipView, "updated tooltip");
         assertTrue(hasTooltip(mTooltipView));
 
-        setTooltip(mTooltipView, null);
+        setTooltipText(mTooltipView, null);
         assertFalse(hasTooltip(mTooltipView));
     }
 
@@ -627,7 +631,7 @@
     @Test
     public void testMouseHoverTooltipUnsetWhileHovering() throws Throwable {
         injectHoverMove(mTooltipView);
-        setTooltip(mTooltipView, null);
+        setTooltipText(mTooltipView, null);
         waitOut(ViewConfiguration.getHoverTooltipShowTimeout());
         assertFalse(hasTooltip(mTooltipView));
     }
@@ -646,7 +650,7 @@
         mNoTooltipView.setOnHoverListener((v, event) -> true);
         mTooltipView.setOnHoverListener((v, event) -> true);
 
-        setTooltip(mTopmostView, "tooltip");
+        setTooltipText(mTopmostView, "tooltip");
 
         // Hover over a child with a tooltip works normally.
         injectLongHoverMove(mTooltipView);
@@ -680,7 +684,7 @@
         assertFalse(hasTooltip(mTopmostView));
 
         // Set a tooltip on the intermediate parent, now it is showing tooltips.
-        setTooltip(mGroupView, "tooltip");
+        setTooltipText(mGroupView, "tooltip");
         injectLongHoverMove(mNoTooltipView);
         assertFalse(hasTooltip(mNoTooltipView));
         assertFalse(hasTooltip(mTopmostView));
@@ -743,4 +747,27 @@
         addView(mTopmostView, mGroupView);
         assertFalse(hasTooltip(mTooltipView));
     }
+
+    @Test
+    public void testMouseHoverOverlap() throws Throwable {
+        final View parent = mActivity.findViewById(R.id.overlap_group);
+        final View child1 = mActivity.findViewById(R.id.overlap1);
+        final View child2 = mActivity.findViewById(R.id.overlap2);
+        final View child3 = mActivity.findViewById(R.id.overlap3);
+
+        injectLongHoverMove(parent);
+        assertTrue(hasTooltip(child3));
+
+        setVisibility(child3, View.GONE);
+        injectLongHoverMove(parent);
+        assertTrue(hasTooltip(child2));
+
+        setTooltipText(child2, null);
+        injectLongHoverMove(parent);
+        assertTrue(hasTooltip(child1));
+
+        setVisibility(child1, View.INVISIBLE);
+        injectLongHoverMove(parent);
+        assertTrue(hasTooltip(parent));
+    }
 }
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index 57fb3b6..868a398 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -117,6 +117,7 @@
     public void testAddFocusables() {
         mMockViewGroup.setFocusable(true);
 
+        // Child is focusable.
         ArrayList<View> list = new ArrayList<>();
         list.add(mTextView);
         mMockViewGroup.addView(mTextView);
@@ -124,12 +125,33 @@
 
         assertEquals(2, list.size());
 
+        // Parent blocks descendants.
         list = new ArrayList<>();
         list.add(mTextView);
         mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
         mMockViewGroup.setFocusable(false);
         mMockViewGroup.addFocusables(list, 0);
         assertEquals(1, list.size());
+
+        // Both parent and child are focusable.
+        list.clear();
+        mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+        mTextView.setFocusable(true);
+        mMockViewGroup.setFocusable(true);
+        mMockViewGroup.addFocusables(list, 0);
+        assertEquals(2, list.size());
+
+        // Group is a cluster.
+        list.clear();
+        mMockViewGroup.setKeyboardNavigationCluster(true);
+        mMockViewGroup.addFocusables(list, View.FOCUS_FORWARD);
+        assertEquals(0, list.size());
+        mMockViewGroup.addFocusables(list, View.FOCUS_DOWN);
+        assertEquals(2, list.size());
+        list.clear();
+        mTextView.requestFocus();
+        mMockViewGroup.addFocusables(list, View.FOCUS_FORWARD);
+        assertEquals(2, list.size());
     }
 
     @UiThreadTest
@@ -751,6 +773,22 @@
 
     @UiThreadTest
     @Test
+    public void testFindFocusWithCluster() {
+        // v1 is a cluster, so it doesn't accept focus from outside if it.
+        View v1 = new MockView(mContext);
+        v1.setFocusable(true);
+        v1.setKeyboardNavigationCluster(true);
+        View v2 = new MockView(mContext);
+        v2.setFocusable(true);
+        mMockViewGroup.addView(v1);
+        mMockViewGroup.addView(v2);
+
+        mMockViewGroup.requestFocus();
+        assertSame(v2, mMockViewGroup.findFocus());
+    }
+
+    @UiThreadTest
+    @Test
     public void testFitSystemWindows() {
         Rect rect = new Rect(1, 1, 100, 100);
         assertFalse(mMockViewGroup.fitSystemWindows(rect));
@@ -806,12 +844,33 @@
         MockView child = new MockView(mContext);
         mMockViewGroup.addView(child);
         child.addView(mMockTextView);
-        assertNotNull(child.focusSearch(mMockTextView, 1));
         assertSame(mMockTextView, child.focusSearch(mMockTextView, 1));
     }
 
     @UiThreadTest
     @Test
+    public void testFocusSearchWithCluster() {
+        // focusSearch for FORWARD treats cluster like a root.
+        View view = new View(mContext);
+        view.setFocusable(true);
+        View auntView = new View(mContext);
+        auntView.setFocusable(true);
+        MockViewGroup viewParent = new MockViewGroup(mContext);
+        viewParent.addView(view);
+        mMockViewGroup.addView(viewParent);
+        mMockViewGroup.addView(auntView);
+        mMockViewGroup.returnActualFocusSearchResult = true;
+        viewParent.returnActualFocusSearchResult = true;
+        mMockViewGroup.setIsRootNamespace(true);
+        view.requestFocus();
+
+        assertSame(auntView, view.focusSearch(View.FOCUS_FORWARD));
+        viewParent.setKeyboardNavigationCluster(true);
+        assertSame(view, view.focusSearch(View.FOCUS_FORWARD));
+    }
+
+    @UiThreadTest
+    @Test
     public void testGatherTransparentRegion() {
         Region region = new Region();
         mMockTextView.setAnimation(new AlphaAnimation(mContext, null));
@@ -1469,6 +1528,23 @@
 
     @UiThreadTest
     @Test
+    public void testRequestFocusWithCluster() {
+        // requestFocus skips nested clusters.
+        View v1 = new View(mContext);
+        v1.setFocusable(true);
+        View v2 = new View(mContext);
+        v2.setFocusable(true);
+        mMockViewGroup.addView(v1);
+        mMockViewGroup.addView(v2);
+
+        assertSame(null, mMockViewGroup.findFocus());
+        v1.setKeyboardNavigationCluster(true);
+        assertTrue(mMockViewGroup.requestFocus());
+        assertSame(v2, mMockViewGroup.findFocus());
+    }
+
+    @UiThreadTest
+    @Test
     public void testRequestTransparentRegion() {
         MockViewGroup parent = new MockViewGroup(mContext);
         MockView child1 = new MockView(mContext);
@@ -2338,6 +2414,7 @@
         public int top;
         public int right;
         public int bottom;
+        public boolean returnActualFocusSearchResult;
 
         public MockViewGroup(Context context, AttributeSet attrs, int defStyle) {
             super(context, attrs, defStyle);
@@ -2605,8 +2682,12 @@
 
         @Override
         public View focusSearch(View focused, int direction) {
-            super.focusSearch(focused, direction);
-            return focused;
+            if (returnActualFocusSearchResult) {
+                return super.focusSearch(focused, direction);
+            } else {
+                super.focusSearch(focused, direction);
+                return focused;
+            }
         }
 
         @Override
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 4701fda..6512f1b 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -440,6 +440,39 @@
     }
 
     @Test
+    public void testPointerIconOverlap() throws Throwable {
+        View parent = mActivity.findViewById(R.id.pointer_icon_overlap);
+        View child1 = mActivity.findViewById(R.id.pointer_icon_overlap_child1);
+        View child2 = mActivity.findViewById(R.id.pointer_icon_overlap_child2);
+        View child3 = mActivity.findViewById(R.id.pointer_icon_overlap_child3);
+
+        PointerIcon iconParent = PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HAND);
+        PointerIcon iconChild1 = PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HELP);
+        PointerIcon iconChild2 = PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT);
+        PointerIcon iconChild3 = PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_GRAB);
+
+        parent.setPointerIcon(iconParent);
+        child1.setPointerIcon(iconChild1);
+        child2.setPointerIcon(iconChild2);
+        child3.setPointerIcon(iconChild3);
+
+        MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0);
+
+        assertEquals(iconChild3, parent.onResolvePointerIcon(event, 0));
+
+        setVisibilityOnUiThread(child3, View.GONE);
+        assertEquals(iconChild2, parent.onResolvePointerIcon(event, 0));
+
+        child2.setPointerIcon(null);
+        assertEquals(iconChild1, parent.onResolvePointerIcon(event, 0));
+
+        setVisibilityOnUiThread(child1, View.GONE);
+        assertEquals(iconParent, parent.onResolvePointerIcon(event, 0));
+
+        event.recycle();
+    }
+
+    @Test
     public void testCreatePointerIcons() {
         assertSystemPointerIcon(PointerIcon.TYPE_NULL);
         assertSystemPointerIcon(PointerIcon.TYPE_DEFAULT);
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index c19c27e..c6d85c6 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/Android.mk
@@ -27,7 +27,8 @@
     android-common \
     compatibility-device-util \
     ctstestrunner \
-    platform-test-annotations
+    platform-test-annotations \
+    legacy-android-test
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 577c52a..e102ec5 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -3356,22 +3356,6 @@
                 "\"smcp\" on", mTextView.getFontFeatureSettings());
     }
 
-    @UiThreadTest
-    @Test
-    public void testSetGetFontVariationSettings() {
-        mTextView = new TextView(mActivity);
-
-        // The default font variation settings should be null.
-        assertNull(mTextView.getFontVariationSettings());
-
-        final String setting = "'wdth' 2.0";
-        mTextView.setFontVariationSettings(setting);
-        assertEquals(setting, mTextView.getFontVariationSettings());
-
-        mTextView.setFontVariationSettings("");
-        assertNull(mTextView.getFontVariationSettings());
-    }
-
     @Test
     public void testGetOffsetForPositionSingleLineLtr() throws Throwable {
         // asserts getOffsetPosition returns correct values for a single line LTR text
@@ -6618,6 +6602,32 @@
         assertTrue(autoSizeTextViewXY.getTextSize() < sizeSetInPixels);
     }
 
+    @UiThreadTest
+    @Test
+    public void testOnInitializeA11yNodeInfo_populatesHintTextProperly() {
+        final TextView textView = new TextView(mActivity);
+        textView.setText("", BufferType.EDITABLE);
+        final String hintText = "Hint text";
+        textView.setHint(hintText);
+        AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+        textView.onInitializeAccessibilityNodeInfo(info);
+        assertTrue("Hint text flag set incorrectly for accessibility", info.isShowingHintText());
+        assertTrue("Hint text not showing as accessibility text",
+                TextUtils.equals(hintText, info.getText()));
+        assertTrue("Hint text not provided to accessibility",
+                TextUtils.equals(hintText, info.getHintText()));
+
+        final String nonHintText = "Something else";
+        textView.setText(nonHintText, BufferType.EDITABLE);
+        textView.onInitializeAccessibilityNodeInfo(info);
+        assertFalse("Hint text flag set incorrectly for accessibility", info.isShowingHintText());
+        assertTrue("Text not provided to accessibility",
+                TextUtils.equals(nonHintText, info.getText()));
+        assertTrue("Hint text not provided to accessibility",
+                TextUtils.equals(hintText, info.getHintText()));
+    }
+
+
     /**
      * Some TextView attributes require non-fixed width and/or layout height. This function removes
      * all other existing views from the layout leaving only one auto-size TextView (for exercising
diff --git a/tools/cts-tradefed/res/config/deqp-tests-for-n.xml b/tools/cts-tradefed/res/config/deqp-tests-for-n.xml
deleted file mode 100644
index 014cd0b..0000000
--- a/tools/cts-tradefed/res/config/deqp-tests-for-n.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Run deqp tests that were used for NYC">
-
-    <include name="cts" />
-
-    <option name="plan" value="cts-deqp-nyc" />
-
-    <option name="skip-preconditions" value="true" />
-    <option name="skip-connectivity-check" value="true" />
-
-    <!-- Include all Vulkan tests, exclude N tests -->
-    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-EGL.*" />
-    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-GLES2.*" />
-    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-GLES3.*" />
-    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter-file:nyc-gles31-master.txt" />
-    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter-file:nyc-vk-master.txt" />
-</configuration>
diff --git a/tools/cts-tradefed/res/config/deqp-tests-new-for-o.xml b/tools/cts-tradefed/res/config/deqp-tests-new-for-o.xml
deleted file mode 100644
index 4cdb52e..0000000
--- a/tools/cts-tradefed/res/config/deqp-tests-new-for-o.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Run deqp tests new in OC">
-
-    <include name="cts" />
-
-    <option name="plan" value="cts-deqp-staging" />
-
-    <option name="skip-preconditions" value="true" />
-    <option name="skip-connectivity-check" value="true" />
-
-    <!-- Include all Vulkan tests, exclude N tests -->
-    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-GLES31.*" />
-    <option name="compatibility:module-arg" value="CtsDeqpTestCases:exclude-filter-file:nyc-vk-master.txt" />
-    <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-VK.*" />
-    <option name="compatibility:module-arg" value="CtsDeqpTestCases:exclude-filter-file:nyc-gles31-master.txt" />
-</configuration>