Merge "camera2: Re-enable StillCaptureTest#testJpegExif." into lmp-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index bd906f6..4bbd783 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -39,6 +39,7 @@
     CtsDeviceTaskswitchingAppB \
     CtsDeviceTaskswitchingControl \
     CtsDeviceUi \
+    CtsIntentReceiverApp \
     CtsManagedProfileApp \
     CtsMonkeyApp \
     CtsMonkeyApp2 \
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 27439f0..f2e0663 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1109,6 +1109,7 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
             </intent-filter>
         </activity-alias>
 
@@ -1238,6 +1239,49 @@
                  android:label="@string/projection_service_name"
                  android:process=":projectionservice" />
 
-   </application>
+        <activity android:name=".managedprovisioning.DeviceOwnerTestActivity"
+                android:label="@string/provisioning_device_owner">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_managed_provisioning" />
+        </activity>
+
+
+        <activity android:name=".managedprovisioning.ByodFlowTestActivity"
+                android:launchMode="singleTask"
+                android:label="@string/provisioning_byod">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_STATUS" />
+                <category android:name="android.intent.category.DEFAULT"></category>
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_managed_provisioning" />
+        </activity>
+
+        <activity android:name=".managedprovisioning.ByodHelperActivity">
+            <intent-filter>
+                <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_QUERY" />
+                <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_REMOVE" />
+                <category android:name="android.intent.category.DEFAULT"></category>
+            </intent-filter>
+        </activity>
+
+        <receiver android:name=".managedprovisioning.DeviceAdminTestReceiver"
+                android:label="@string/provisioning_byod_device_admin"
+                android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                       android:resource="@xml/device_admin_byod" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+                <action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE"/>
+            </intent-filter>
+        </receiver>
+
+    </application>
 
 </manifest>
diff --git a/apps/CtsVerifier/res/layout/pass_fail_buttons.xml b/apps/CtsVerifier/res/layout/pass_fail_buttons.xml
index d70e839..5eec539 100644
--- a/apps/CtsVerifier/res/layout/pass_fail_buttons.xml
+++ b/apps/CtsVerifier/res/layout/pass_fail_buttons.xml
@@ -18,26 +18,23 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 
-    <Button android:id="@+id/pass_button"
+    <ImageButton android:id="@+id/pass_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="1"            
-            android:drawableTop="@drawable/fs_good"
-            android:text="@string/pass_button_text"/>
+            android:src="@drawable/fs_good"/>
             
-    <Button android:id="@+id/info_button"
+    <ImageButton android:id="@+id/info_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="1"
-            android:drawableTop="@drawable/fs_indeterminate"
-            android:visibility="gone"
-            android:text="@string/info_button_text"/>
+            android:src="@drawable/fs_indeterminate"
+            android:visibility="gone"/>
 
-    <Button android:id="@+id/fail_button"
+    <ImageButton android:id="@+id/fail_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="1"            
-            android:drawableTop="@drawable/fs_error"
-            android:text="@string/fail_button_text"/>
+            android:src="@drawable/fs_error"/>
             
 </LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/provisioning_byod.xml b/apps/CtsVerifier/res/layout/provisioning_byod.xml
new file mode 100644
index 0000000..5e59558
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/provisioning_byod.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        >
+
+    <ScrollView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1">
+        <TextView
+                android:id="@+id/byod_instructions"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:padding="10dip"
+                android:text="@string/provisioning_byod_instructions"
+                android:textSize="18dip" />
+    </ScrollView>
+
+    <Button
+        android:id="@+id/byod_start"
+        android:layout_width="204dp"
+        android:layout_height="wrap_content"
+        android:text="@string/provisioning_byod_start" />
+
+    <ListView
+        android:id="@id/android:list"
+        android:layout_width="match_parent"
+        android:layout_height="258dp" />
+
+    <include layout="@layout/pass_fail_buttons" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 38e0ced..afe5f81 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1188,4 +1188,69 @@
     <string name="snsr_rotation_vector_set_final">Place the device back to the reference position.</string>
     <string name="snsr_rotation_vector_verification">Angular deviation [%1$4.1f %2$4.1f %3$4.1f]. Current: %4$f deg. Max tolerated: %5$f.</string>
 
+    <!-- Strings for BYOD managed provisioning tests (ByodFlowTestActivity) -->
+    <string name="test_category_managed_provisioning">Managed Provisioning</string>
+    <string name="provisioning_byod_device_admin">CTS Verifier - BYOD Admin</string>
+    <string name="provisioning_byod">BYOD Managed Provisioning</string>
+    <string name="provisioning_byod_info">
+        This test exercises the BYOD managed provisioning flow.
+        Start by pressing the button on screen and follow instructions to finish the managed provisioning process.
+        If your device has not been encrypted before, it will be encrypted and rebooted.
+        After the provisioning process completes, return to this page and carry out further verifications.
+    </string>
+    <string name="provisioning_byod_start">Start BYOD provisioning flow</string>
+    <string name="provisioning_byod_instructions">
+        1. Press the button below to start the managed provisioning flow.
+        If your device has not been encrypted before, it will reboot to apply encryption.
+        After reboot follow instructions in the notification area to complete the provisioning.\n
+        2. After successful provisioning, you should be automatically redirected back to this page.
+        Please press through the following verification steps.
+        Allow a few seconds after returning from provisioning, as the profile owner test should automatically pass.
+    </string>
+    <string name="provisioning_byod_profileowner">Profile owner installed</string>
+    <string name="provisioning_byod_diskencryption">Full disk encryption enabled</string>
+    <string name="provisioning_byod_profile_visible">Work profile visible in Settings</string>
+    <string name="provisioning_byod_admin_visible">Device administrator visible in Settings</string>
+    <string name="provisioning_byod_workapps_visible">Badged work apps visible in Launcher</string>
+    <string name="provisioning_byod_profile_visible_instruction">
+        Please press the Go button to open the Settings page.
+        Navigate to Accounts and confirm that:\n
+        \n
+        - Both Personal and Work categories exist.\n
+        - \"Remove work profile\" exists under the Work category.\n
+        \n
+        Use the Back button to return to this page.
+    </string>
+    <string name="provisioning_byod_admin_visible_instruction">
+        Please press the Go button to open the Security page in Settings.
+        Navigate to Device administrators and confirm that:\n
+        \n
+        - Both Personal and Work categories exist.\n
+        - \"CTS Verifier - BYOD Admin\" exists under the Work category, and is activated.\n
+        \n
+        Use the Back button to return to this page.
+    </string>
+    <string name="provisioning_byod_workapps_visible_instruction">
+        Please press the Go button to start the launcher.
+        Go to All Apps screen and scroll through it to confirm that:\n
+        \n
+        - A new set of work apps including CTS Verifier appear in the list.\n
+        - Work badge overlay appears on work app\'s icon.\n
+        \n
+        Then navigate back to this screen using Recents button.
+    </string>
+    <string name="provisioning_byod_no_activity">Cannot communicate with activity in the work profile.</string>
+    <string name="provisioning_byod_delete_profile">Initiate deletion of work profile.</string>
+    <string name="provisioning_byod_profile_deleted">Work profile deleted.</string>
+    <string name="provisioning_byod_disabled">Device provisioning is not enabled.</string>
+    <string name="provisioning_byod_go">Go</string>
+
+    <!-- Strings for DeviceOwnerProvisioningTest -->
+    <string name="provisioning_device_owner">Device Owner Provisioning</string>
+    <string name="device_owner_provisioning_tests">Device Owner provisioning tests</string>
+    <string name="device_owner_provisioning_tests_info">The device owner provisioning tests verify that setting up a corporate owned device can only be done on a factory reset device.</string>
+    <string name="device_owner_provisioning_category">Device Owner Provisioning</string>
+    <string name="device_owner_negative_test">Device owner negative test</string>
+    <string name="device_owner_negative_test_info">Device owner provisioning should only work on new or factory reset devices. Please click on the "Start provisioning" button and verify that you get a warning dialog telling you that the device is already set up. If that is the case, this test has passed.</string>
+    <string name="start_device_owner_provisioning_button">Start provisioning</string>
 </resources>
diff --git a/apps/CtsVerifier/res/xml/device_admin_byod.xml b/apps/CtsVerifier/res/xml/device_admin_byod.xml
new file mode 100644
index 0000000..0408ce2
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/device_admin_byod.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<!-- BEGIN_INCLUDE(meta_data) -->
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-policies>
+        <encrypted-storage />
+        <wipe-data />
+    </uses-policies>
+</device-admin>
+<!-- END_INCLUDE(meta_data) -->
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
index 57ea127..444a250 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
@@ -31,7 +31,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.widget.Button;
+import android.widget.ImageButton;
 
 /**
  * {@link Activity}s to handle clicks to the pass and fail buttons of the pass fail buttons layout.
@@ -77,7 +77,7 @@
          */
         void setInfoResources(int titleId, int messageId, int viewId);
 
-        Button getPassButton();
+        View getPassButton();
 
         /**
          * Returns a unique identifier for the test.  Usually, this is just the class name.
@@ -127,7 +127,7 @@
         }
 
         @Override
-        public Button getPassButton() {
+        public View getPassButton() {
             return getPassButtonView(this);
         }
 
@@ -166,7 +166,7 @@
         }
 
         @Override
-        public Button getPassButton() {
+        public View getPassButton() {
             return getPassButtonView(this);
         }
 
@@ -206,7 +206,7 @@
         }
 
         @Override
-        public Button getPassButton() {
+        public View getPassButton() {
             return getPassButtonView(this);
         }
 
@@ -368,7 +368,7 @@
         activity.finish();
     }
 
-    private static Button getPassButtonView(android.app.Activity activity) {
-        return (Button) activity.findViewById(R.id.pass_button);
+    private static ImageButton getPassButtonView(android.app.Activity activity) {
+        return (ImageButton) activity.findViewById(R.id.pass_button);
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
index 8d6ef2c..f19142f 100755
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
@@ -41,7 +41,7 @@
 import android.view.TextureView;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
-import android.widget.Button;
+import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.Spinner;
 import android.widget.Toast;
@@ -587,7 +587,7 @@
     }
 
     private void setPassButtonEnabled(boolean enabled) {
-        Button pass_button = (Button) findViewById(R.id.pass_button);
+        ImageButton pass_button = (ImageButton) findViewById(R.id.pass_button);
         pass_button.setEnabled(enabled);
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
index e48ce93..6881bea 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
@@ -32,6 +32,7 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
+import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout.LayoutParams;
 import android.widget.TextView;
@@ -88,8 +89,8 @@
         Camera.ACTION_NEW_VIDEO
     };
 
-    private Button mPassButton;
-    private Button mFailButton;
+    private ImageButton mPassButton;
+    private ImageButton mFailButton;
     private Button mStartTestButton;
 
     private int mState = STATE_OFF;
@@ -212,8 +213,8 @@
         setPassFailButtonClickListeners();
         setInfoResources(R.string.camera_intents, R.string.ci_info, -1);
 
-        mPassButton         = (Button) findViewById(R.id.pass_button);
-        mFailButton         = (Button) findViewById(R.id.fail_button);
+        mPassButton         = (ImageButton) findViewById(R.id.pass_button);
+        mFailButton         = (ImageButton) findViewById(R.id.fail_button);
         mStartTestButton  = (Button) findViewById(R.id.start_test_button);
         mStartTestButton.setOnClickListener(this);
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/orientation/CameraOrientationActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/orientation/CameraOrientationActivity.java
index b970e40..273d78a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/orientation/CameraOrientationActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/orientation/CameraOrientationActivity.java
@@ -27,6 +27,7 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
+import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout.LayoutParams;
 import android.widget.TextView;
@@ -55,8 +56,8 @@
     private static final int NUM_ORIENTATIONS = 4;
     private static final String STAGE_INDEX_EXTRA = "stageIndex";
 
-    private Button mPassButton;
-    private Button mFailButton;
+    private ImageButton mPassButton;
+    private ImageButton mFailButton;
     private Button mTakePictureButton;
 
     private SurfaceView mCameraView;
@@ -85,8 +86,8 @@
         setInfoResources(R.string.camera_orientation, R.string.co_info, -1);
         mNumCameras = Camera.getNumberOfCameras();
 
-        mPassButton         = (Button) findViewById(R.id.pass_button);
-        mFailButton         = (Button) findViewById(R.id.fail_button);
+        mPassButton         = (ImageButton) findViewById(R.id.pass_button);
+        mFailButton         = (ImageButton) findViewById(R.id.fail_button);
         mTakePictureButton  = (Button) findViewById(R.id.take_picture_button);
         mFormatView         = (ImageView) findViewById(R.id.format_view);
         mCameraView         = (SurfaceView) findViewById(R.id.camera_view);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
index 2ae921c..97c0521 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
@@ -35,6 +35,7 @@
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
+import android.widget.ImageButton;
 import android.widget.Spinner;
 import android.widget.TextView;
 import android.widget.VideoView;
@@ -89,8 +90,8 @@
     private boolean isRecording = false;
     private boolean isPlayingBack = false;
     private Button captureButton;
-    private Button mPassButton;
-    private Button mFailButton;
+    private ImageButton mPassButton;
+    private ImageButton mFailButton;
 
     private TextView mStatusLabel;
 
@@ -204,8 +205,8 @@
         mPlaybackView.setOnCompletionListener(mPlaybackViewListener);
 
         captureButton = (Button) findViewById(R.id.record_button);
-        mPassButton = (Button) findViewById(R.id.pass_button);
-        mFailButton = (Button) findViewById(R.id.fail_button);
+        mPassButton = (ImageButton) findViewById(R.id.pass_button);
+        mFailButton = (ImageButton) findViewById(R.id.fail_button);
         mPassButton.setEnabled(false);
         mFailButton.setEnabled(true);
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
index 6319133..20ccd81 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
@@ -194,6 +194,9 @@
 
     public static final Feature[] ALL_LMP_FEATURES = {
             new Feature(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG, false),
+            new Feature("android.hardware.ethernet", false),
+            new Feature("android.software.backup", false),
+            new Feature("android.software.print", false),
     };
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
new file mode 100644
index 0000000..69071f6
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.admin.DevicePolicyManager;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.TestListActivity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * CTS verifier test for BYOD managed provisioning flow.
+ * This activity is responsible for starting the managed provisioning flow and verify the outcome of provisioning.
+ * It performs the following verifications:
+ *   Full disk encryption is enabled.
+ *   Profile owner is correctly installed.
+ *   Profile owner shows up in the Settings app.
+ *   Badged work apps show up in launcher.
+ * The first two verifications are performed automatically, by interacting with profile owner using
+ * cross-profile intents, while the last two are carried out manually by the user.
+ */
+public class ByodFlowTestActivity extends PassFailButtons.ListActivity {
+
+    private final String TAG = "ByodFlowTestActivity";
+    private static final int REQUEST_STATUS = 1;
+
+    private ComponentName mAdminReceiverComponent;
+
+    private TestAdapter mAdapter;
+    private View mStartProvisioningButton;
+    private List<TestItem> mTests = new ArrayList<TestItem>();
+
+    protected DevicePolicyManager mDevicePolicyManager;
+
+    private TestItem mProfileOwnerInstalled;
+    private TestItem mDiskEncryptionTest;
+    private TestItem mProfileVisibleTest;
+    private TestItem mDeviceAdminVisibleTest;
+    private TestItem mWorkAppVisibleTest;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAdminReceiverComponent = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
+        mDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+        disableComponent();
+
+        setContentView(R.layout.provisioning_byod);
+        setInfoResources(R.string.provisioning_byod, R.string.provisioning_byod_info, -1);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        setResult(RESULT_CANCELED);
+
+        setupTests();
+
+        mAdapter = new TestAdapter(this);
+        setListAdapter(mAdapter);
+        mAdapter.addAll(mTests);
+
+        mStartProvisioningButton = findViewById(R.id.byod_start);
+        mStartProvisioningButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startByodProvisioning();
+            }
+        });
+
+        // If we are started by managed provisioning (fresh managed provisioning after encryption
+        // reboot), redirect the user back to the main test list. This is because the test result
+        // is only saved by the parent TestListActivity, and if we did allow the user to proceed
+        // here, the test result would be lost when this activity finishes.
+        if (ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS.equals(getIntent().getAction())) {
+            startActivity(new Intent(this, TestListActivity.class));
+            // Calling super.finish() because we delete managed profile in our overridden of finish(),
+            // which is not what we want to do here.
+            super.finish();
+        } else {
+            queryProfileOwner(false);
+        }
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        // This is called when managed provisioning completes successfully without reboot.
+        super.onNewIntent(intent);
+        if (ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS.equals(intent.getAction())) {
+            handleStatusUpdate(intent);
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        // Called after queryProfileOwner()
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == REQUEST_STATUS && resultCode == RESULT_OK) {
+            handleStatusUpdate(data);
+        }
+    }
+
+    private void handleStatusUpdate(Intent data) {
+        boolean provisioned = data.getBooleanExtra(ByodHelperActivity.EXTRA_PROVISIONED, false);
+        setTestResult(mProfileOwnerInstalled, provisioned ? TestResult.Passed : TestResult.Failed);
+    }
+
+    @Override
+    public void finish() {
+        // Pass and fail buttons are known to call finish() when clicked, and this is when we want to
+        // clean up the provisioned profile.
+        requestDeleteProfileOwner();
+        super.finish();
+    }
+
+    private void setupTests() {
+        mProfileOwnerInstalled = new TestItem(this, R.string.provisioning_byod_profileowner) {
+            @Override
+            public void performTest(ByodFlowTestActivity activity) {
+                queryProfileOwner(true);
+            }
+        };
+
+        mDiskEncryptionTest = new TestItem(this, R.string.provisioning_byod_diskencryption) {
+            @Override
+            public TestResult getPassFailState() {
+                return isDeviceEncrypted() ? TestResult.Passed : TestResult.Failed;
+            }
+        };
+
+        mProfileVisibleTest = new TestItem(this, R.string.provisioning_byod_profile_visible,
+                R.string.provisioning_byod_profile_visible_instruction,
+                new Intent(Settings.ACTION_SETTINGS));
+
+        mDeviceAdminVisibleTest = new TestItem(this, R.string.provisioning_byod_admin_visible,
+                R.string.provisioning_byod_admin_visible_instruction,
+                new Intent(Settings.ACTION_SECURITY_SETTINGS));
+
+        mWorkAppVisibleTest = new TestItem(this, R.string.provisioning_byod_workapps_visible,
+                R.string.provisioning_byod_workapps_visible_instruction,
+                new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
+
+        mTests.add(mDiskEncryptionTest);
+        mTests.add(mProfileOwnerInstalled);
+        mTests.add(mProfileVisibleTest);
+        mTests.add(mDeviceAdminVisibleTest);
+        mTests.add(mWorkAppVisibleTest);
+    }
+
+    @Override
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        super.onListItemClick(l, v, position, id);
+        TestItem test = (TestItem) getListAdapter().getItem(position);
+        test.performTest(this);
+    }
+
+    private void showManualTestDialog(final TestItem test) {
+        AlertDialog dialog = new AlertDialog.Builder(this)
+                .setIcon(android.R.drawable.ic_dialog_info)
+                .setMessage(test.getManualTestInstruction())
+                .setNeutralButton(R.string.provisioning_byod_go, null)
+                .setPositiveButton(R.string.pass_button_text, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        setTestResult(test, TestResult.Passed);
+                    }
+                })
+                .setNegativeButton(R.string.fail_button_text, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        setTestResult(test, TestResult.Failed);
+                    }
+                })
+                .create();
+        dialog.show();
+
+        dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                ByodFlowTestActivity.this.startActivity(test.getManualTestIntent());
+            }
+        });
+    }
+
+    private void setTestResult(TestItem test, TestResult result) {
+        test.setPassFailState(result);
+
+        boolean testSucceeds = true;
+        for(TestItem aTest : mTests) {
+            testSucceeds &= (aTest.getPassFailState() == TestResult.Passed);
+        }
+        getPassButton().setEnabled(testSucceeds);
+        mAdapter.notifyDataSetChanged();
+    }
+
+    private void startByodProvisioning() {
+        Intent sending = new Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
+        sending.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
+                mAdminReceiverComponent.getPackageName());
+        sending.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminReceiverComponent);
+
+        if (sending.resolveActivity(getPackageManager()) != null) {
+            // ManagedProvisioning must be started with startActivityForResult, but we don't
+            // care about the result, so passing 0 as a requestCode
+            startActivityForResult(sending, 0);
+        } else {
+            showToast(R.string.provisioning_byod_disabled);
+        }
+    }
+
+    private void queryProfileOwner(boolean showToast) {
+        try {
+            Intent intent = new Intent(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
+            startActivityForResult(intent, REQUEST_STATUS);
+        }
+        catch (ActivityNotFoundException e) {
+            Log.d(TAG, "queryProfileOwner: ActivityNotFoundException", e);
+            setTestResult(mProfileOwnerInstalled, TestResult.Failed);
+            if (showToast) {
+                showToast(R.string.provisioning_byod_no_activity);
+            }
+        }
+    }
+
+    private void requestDeleteProfileOwner() {
+        try {
+            Intent intent = new Intent(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
+            startActivity(intent);
+            showToast(R.string.provisioning_byod_delete_profile);
+        }
+        catch (ActivityNotFoundException e) {
+            Log.d(TAG, "requestDeleteProfileOwner: ActivityNotFoundException", e);
+        }
+    }
+
+    private void disableComponent() {
+        // Disable app components in the current profile, so only the counterpart in the other profile
+        // can respond (via cross-profile intent filter)
+        getPackageManager().setComponentEnabledSetting(new ComponentName(
+                this, ByodHelperActivity.class),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+
+    private boolean isDeviceEncrypted() {
+        return mDevicePolicyManager.getStorageEncryptionStatus()
+                == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
+    }
+
+    private void showToast(int messageId) {
+        String message = getString(messageId);
+        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
+    }
+
+    enum TestResult {
+        Unknown, Failed, Passed
+    }
+
+    static class TestItem {
+
+        private String mDisplayName;
+        private TestResult mPassed;
+        private boolean mManualTest;
+        private String mManualInstruction;
+        private Intent mManualIntent;
+
+        public TestItem(Context context, int nameResId) {
+            mDisplayName = context.getString(nameResId);
+            mPassed = TestResult.Unknown;
+            mManualTest = false;
+        }
+
+        public void performTest(ByodFlowTestActivity activity) {
+            if (isManualTest()) {
+                activity.showManualTestDialog(this);
+            }
+        }
+
+        public TestItem(Context context, int nameResId, int testInstructionResId, Intent testIntent) {
+            mDisplayName = context.getString(nameResId);
+            mPassed = TestResult.Unknown;
+            mManualTest = true;
+            mManualInstruction = context.getString(testInstructionResId);
+            mManualIntent = testIntent;
+        }
+
+        @Override
+        public String toString() {
+            return mDisplayName;
+        }
+
+        TestResult getPassFailState() {
+            return mPassed;
+        }
+
+        void setPassFailState(TestResult state) {
+            mPassed = state;
+        }
+
+        public boolean isManualTest() {
+            return mManualTest;
+        }
+
+        public String getManualTestInstruction() {
+            return mManualInstruction;
+        }
+
+        public Intent getManualTestIntent() {
+            return mManualIntent;
+        }
+    }
+
+    static class TestAdapter extends ArrayAdapter<TestItem> {
+
+        public TestAdapter(Context context) {
+            super(context, android.R.layout.simple_list_item_1);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            TextView view = (TextView) super.getView(position, convertView, parent);
+
+            TestItem item = getItem(position);
+            int backgroundResource = 0;
+            int iconResource = 0;
+            if (item.getPassFailState() == TestResult.Passed) {
+                backgroundResource = R.drawable.test_pass_gradient;
+                iconResource = R.drawable.fs_good;
+            } else if (item.getPassFailState() == TestResult.Failed){
+                backgroundResource = R.drawable.test_fail_gradient;
+                iconResource = R.drawable.fs_error;
+            }
+            view.setBackgroundResource(backgroundResource);
+            view.setPadding(10, 0, 10, 0);
+            view.setCompoundDrawablePadding(10);
+            view.setCompoundDrawablesWithIntrinsicBounds(0, 0, iconResource, 0);
+
+            return view;
+        }
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
new file mode 100644
index 0000000..5dac4bd
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.managedprovisioning.ByodFlowTestActivity.TestResult;
+
+/**
+ * A helper activity from the managed profile side that responds to requests from CTS verifier in
+ * primary user. Profile owner APIs are accessible inside this activity (given this activity is
+ * started within the work profile). Its current functionalities include making sure the profile
+ * owner is setup correctly, and removing the work profile upon request.
+ *
+ * Note: We have to use a dummy activity because cross-profile intents only work for activities.
+ */
+public class ByodHelperActivity extends Activity {
+    static final String TAG = "ByodHelperActivity";
+
+    // Primary -> managed intent: query if the profile owner has been set up.
+    public static final String ACTION_QUERY_PROFILE_OWNER = "com.android.cts.verifier.managedprovisioning.BYOD_QUERY";
+    // Managed -> primary intent: update profile owner test status in primary's CtsVerifer
+    public static final String ACTION_PROFILE_OWNER_STATUS = "com.android.cts.verifier.managedprovisioning.BYOD_STATUS";
+    // Primary -> managed intent: request to delete the current profile
+    public static final String ACTION_REMOVE_PROFILE_OWNER = "com.android.cts.verifier.managedprovisioning.BYOD_REMOVE";
+    // Managed -> managed intent: provisioning completed successfully
+    public static final String ACTION_PROFILE_PROVISIONED = "com.android.cts.verifier.managedprovisioning.BYOD_PROVISIONED";
+
+    public static final String EXTRA_PROVISIONED = "extra_provisioned";
+
+    private ComponentName mAdminReceiverComponent;
+
+    private DevicePolicyManager mDevicePolicyManager;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAdminReceiverComponent = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
+        mDevicePolicyManager = (DevicePolicyManager) getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        String action = getIntent().getAction();
+        Log.d(TAG, "ByodHelperActivity.onCreate: " + action);
+
+        // we are explicitly started by {@link DeviceAdminTestReceiver} after a successful provisioning.
+        if (action.equals(ACTION_PROFILE_PROVISIONED)) {
+            // Jump back to CTS verifier with result.
+            Intent response = new Intent(ACTION_PROFILE_OWNER_STATUS);
+            response.putExtra(EXTRA_PROVISIONED, isProfileOwner());
+            startActivityInPrimary(response);
+            // Queried by CtsVerifier in the primary side using startActivityForResult.
+        } else if (action.equals(ACTION_QUERY_PROFILE_OWNER)) {
+            Intent response = new Intent();
+            response.putExtra(EXTRA_PROVISIONED, isProfileOwner());
+            setResult(RESULT_OK, response);
+            // Request to delete work profile.
+        } else if (action.equals(ACTION_REMOVE_PROFILE_OWNER)) {
+            if (isProfileOwner()) {
+                mDevicePolicyManager.wipeData(0);
+                showToast(R.string.provisioning_byod_profile_deleted);
+            }
+        }
+        // This activity has no UI and is only used to respond to CtsVerifier in the primary side.
+        finish();
+    }
+
+    private boolean isProfileOwner() {
+        return mDevicePolicyManager.isAdminActive(mAdminReceiverComponent) &&
+                mDevicePolicyManager.isProfileOwnerApp(mAdminReceiverComponent.getPackageName());
+    }
+
+    private void startActivityInPrimary(Intent intent) {
+        // Disable app components in the current profile, so only the counterpart in the other
+        // profile can respond (via cross-profile intent filter)
+        getPackageManager().setComponentEnabledSetting(new ComponentName(
+                this, ByodFlowTestActivity.class),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+        startActivity(intent);
+    }
+
+    private void showToast(int messageId) {
+        String message = getString(messageId);
+        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
new file mode 100644
index 0000000..861bca2
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+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.IntentFilter;
+import android.content.pm.PackageManager;
+import android.util.Log;
+import android.widget.Toast;
+
+/**
+ * Profile owner receiver for BYOD flow test.
+ * Setup cross-profile intent filter after successful provisioning.
+ */
+public class DeviceAdminTestReceiver extends DeviceAdminReceiver {
+        private static final String TAG = "DeviceAdminTestReceiver";
+
+        @Override
+        public void onProfileProvisioningComplete(Context context, Intent intent) {
+            Log.d(TAG, "Provisioning complete intent received");
+            setupProfile(context);
+        }
+
+        private void setupProfile(Context context) {
+            DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+            dpm.setProfileEnabled(new ComponentName(context.getApplicationContext(), getClass()));
+
+            // Setup cross-profile intent filter to allow communications between the two versions of CtsVerifier
+            // Primary -> work direction
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
+            filter.addAction(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
+            dpm.addCrossProfileIntentFilter(getWho(context), filter,
+                    DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
+
+            // Work -> primary direction
+            filter = new IntentFilter();
+            filter.addAction(ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS);
+            dpm.addCrossProfileIntentFilter(getWho(context), filter,
+                    DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+
+            Intent intent = new Intent(context, ByodHelperActivity.class);
+            intent.setAction(ByodHelperActivity.ACTION_PROFILE_PROVISIONED);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            context.startActivity(intent);
+        }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerTestActivity.java
new file mode 100644
index 0000000..7cb3825
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerTestActivity.java
@@ -0,0 +1,93 @@
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.AlertDialog;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.database.DataSetObserver;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.cts.verifier.ArrayTestListAdapter;
+import com.android.cts.verifier.IntentDrivenTestActivity;
+import com.android.cts.verifier.IntentDrivenTestActivity.ButtonInfo;
+import com.android.cts.verifier.IntentDrivenTestActivity.TestInfo;
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.TestListAdapter.TestListItem;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Activity that lists all device owner provisioning tests.
+ */
+public class DeviceOwnerTestActivity extends PassFailButtons.TestListActivity {
+
+    private static final String ACTION_PROVISION_MANAGED_DEVICE
+        = "com.android.managedprovisioning.ACTION_PROVISION_MANAGED_DEVICE";
+    private static final Intent PROVISION_DEVICE_INTENT =
+            new Intent(ACTION_PROVISION_MANAGED_DEVICE);
+
+    private static final String DEVICE_OWNER_NEGATIVE_TEST = "DEVICE_OWNER_PROVISIONING_NEGATIVE";
+    private static final TestInfo DEVICE_OWNER_NEGATIVE_TEST_INFO = new TestInfo(
+                    DEVICE_OWNER_NEGATIVE_TEST,
+                    R.string.device_owner_negative_test,
+                    R.string.device_owner_negative_test_info,
+                    new ButtonInfo(
+                            R.string.start_device_owner_provisioning_button,
+                            PROVISION_DEVICE_INTENT));
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_list);
+        setInfoResources(R.string.device_owner_provisioning_tests,
+                R.string.device_owner_provisioning_tests_info, 0);
+        setPassFailButtonClickListeners();
+
+        final ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
+        adapter.add(TestListItem.newCategory(this, R.string.device_owner_provisioning_category));
+
+        Intent startTestIntent = new Intent(this, IntentDrivenTestActivity.class)
+                    .putExtra(IntentDrivenTestActivity.EXTRA_ID,
+                            DEVICE_OWNER_NEGATIVE_TEST_INFO.getTestId())
+                    .putExtra(IntentDrivenTestActivity.EXTRA_TITLE,
+                            DEVICE_OWNER_NEGATIVE_TEST_INFO.getTitle())
+                    .putExtra(IntentDrivenTestActivity.EXTRA_INFO,
+                            DEVICE_OWNER_NEGATIVE_TEST_INFO.getInfoText())
+                    .putExtra(IntentDrivenTestActivity.EXTRA_BUTTONS,
+                            DEVICE_OWNER_NEGATIVE_TEST_INFO.getButtons());
+
+
+        adapter.add(TestListItem.newTest(this, DEVICE_OWNER_NEGATIVE_TEST_INFO.getTitle(),
+                DEVICE_OWNER_NEGATIVE_TEST_INFO.getTestId(), startTestIntent, null));
+
+        adapter.registerDataSetObserver(new DataSetObserver() {
+            @Override
+            public void onChanged() {
+                updatePassButton();
+            }
+        });
+
+        setTestListAdapter(adapter);
+    }
+
+    /**
+     * Enable Pass Button when the all tests passed.
+     */
+    private void updatePassButton() {
+        getPassButton().setEnabled(mAdapter.allTestsPassed());
+    }
+}
+
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk b/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
new file mode 100644
index 0000000..62c7f28
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsIntentReceiverApp
+
+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
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml b/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
new file mode 100644
index 0000000..ab01ffb
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.intent.receiver">
+
+    <uses-sdk android:minSdkVersion="19"/>
+
+    <application>
+        <activity android:name="com.android.cts.intent.receiver.IntentReceiverActivity">
+            <intent-filter>
+                <action android:name="com.android.cts.action.READ_FROM_URI" />
+                <action android:name="com.android.cts.action.WRITE_TO_URI" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
new file mode 100644
index 0000000..2389402
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.intent.receiver;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+
+/**
+ * Class to receive intents sent across profile boundaries, and read/write to content uri specified
+ * in these intents to test cross-profile content uris.
+ */
+public class IntentReceiverActivity extends Activity {
+
+    private static final String TAG = "IntentReceiverActivity";
+
+    private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
+
+    private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Intent received = getIntent();
+        String action = received.getAction();
+
+        if (ACTION_READ_FROM_URI.equals(action)) {
+            Intent result = new Intent();
+            String message = getFirstLineFromUri(getIntent().getClipData().getItemAt(0).getUri());
+            Log.i(TAG, "message received in reading test: " + message);
+            result.putExtra("extra_response", message);
+            setResult(message != null ? Activity.RESULT_OK : Activity.RESULT_CANCELED, result);
+        } else if (ACTION_WRITE_TO_URI.equals(action)) {
+            Intent result = new Intent();
+            String message = received.getStringExtra("extra_message");
+            Log.i(TAG, "message received in writing test: " + message);
+            Uri uri = getIntent().getClipData().getItemAt(0).getUri();
+            boolean succeded = writeToUri(uri, message);
+            setResult(succeded ? Activity.RESULT_OK : Activity.RESULT_CANCELED);
+        }
+        finish();
+    }
+
+    /**
+     * Returns the first line of the file associated with uri.
+     */
+    private String getFirstLineFromUri(Uri uri) {
+        try {
+            InputStream is = getContentResolver().openInputStream(uri);
+            BufferedReader r = new BufferedReader(new InputStreamReader(is));
+            return r.readLine();
+        } catch (IOException e) {
+            Log.e(TAG, "could not read the uri " + uri, e);
+            return null;
+        }
+    }
+
+    private boolean writeToUri(Uri uri, String text) {
+        try {
+            OutputStreamWriter writer = new OutputStreamWriter(
+                    getContentResolver().openOutputStream(uri));
+            writer.write(text);
+            writer.flush();
+            writer.close();
+            return true;
+        } catch (IOException e) {
+            Log.e(TAG, "could not write to the uri " + uri, e);
+            return false;
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
index 00dace0..46e3cf7 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
@@ -26,6 +26,8 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
 
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
+
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 2c11b5c..643400b 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -33,7 +33,13 @@
         <activity android:name=".PrimaryUserFilterSetterActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-                <action android:name="com.android.cts.managedprofile.ACTION_TEST_SET_FILTERS" />
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".ComponentDisablingActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT"/>
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
@@ -56,6 +62,21 @@
                 <action android:name="com.android.cts.managedprofile.ACTION_TEST_ALL_ACTIVITY" />
             </intent-filter>
         </activity>
+        <activity android:name=".crossprofilecontent.IntentSenderActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+            </intent-filter>
+        </activity>
+        <provider
+            android:name="android.support.v4.content.FileProvider"
+            android:authorities="com.android.cts.managedprofile.fileprovider"
+            android:grantUriPermissions="true"
+            android:exported="false">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/filepaths" />
+        </provider>
+        <activity android:name=".TestActivity" />
     </application>
 
     <instrumentation android:name="android.test.InstrumentationTestRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/filepaths.xml b/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/filepaths.xml
new file mode 100644
index 0000000..f7bf461
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/filepaths.xml
@@ -0,0 +1,17 @@
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+    <files-path path="texts/" name="texts" />
+</paths>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BaseManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BaseManagedProfileTest.java
index 8a2a6ec..2a54d97 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BaseManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BaseManagedProfileTest.java
@@ -32,7 +32,7 @@
     public static class BasicAdminReceiver extends DeviceAdminReceiver {
     }
 
-    static final ComponentName ADMIN_RECEIVER_COMPONENT = new ComponentName(
+    public static final ComponentName ADMIN_RECEIVER_COMPONENT = new ComponentName(
             BasicAdminReceiver.class.getPackage().getName(), BasicAdminReceiver.class.getName());
 
     protected DevicePolicyManager mDevicePolicyManager;
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
new file mode 100644
index 0000000..aa9506b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.managedprofile.crossprofilecontent;
+
+import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class CrossProfileContentTest extends
+        ActivityInstrumentationTestCase2<IntentSenderActivity> {
+
+    private static final String MESSAGE = "Sample Message";
+
+    public CrossProfileContentTest() {
+        super(IntentSenderActivity.class);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        DevicePolicyManager dpm = (DevicePolicyManager)
+               getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
+        dpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+        super.tearDown();
+    }
+
+    public void testReceiverCanRead() {
+        String response = getActivity().testReceiverCanRead(MESSAGE);
+        assertEquals(response, MESSAGE);
+    }
+
+    public void testReceiverCanWrite() {
+        String response = getActivity().testReceiverCanWrite(MESSAGE);
+        assertEquals(response, MESSAGE);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
new file mode 100644
index 0000000..6c8020f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.managedprofile.crossprofilecontent;
+
+import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+
+import android.app.admin.DevicePolicyManager;
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.support.v4.content.FileProvider;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class IntentSenderActivity extends Activity {
+
+    private final static String TAG = "IntentSenderActivity";
+
+    private final CountDownLatch mLatch = new CountDownLatch(1);
+
+    private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
+
+    private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+
+    private static final int TEST_RECEIVER_CAN_READ = 1;
+    private static final int TEST_RECEIVER_CAN_WRITE = 2;
+
+    private static final int WAIT_FOR_RESPONSE_TIMEOUT_SECONDS = 5;
+
+    private String mResponse;
+
+    private Uri mUriToWrite;
+
+    private DevicePolicyManager mDevicePolicyManager;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mDevicePolicyManager = (DevicePolicyManager)
+                getSystemService(Context.DEVICE_POLICY_SERVICE);
+    }
+
+    /**
+     * This method will send an intent to a receiver in another profile.
+     * This intent will have, in the ClipData, a uri whose associated file stores this message.
+     * The receiver will read the message from the uri, and put it inside the result intent.
+     * This method returns the response in the result intent, or null if no response was received.
+     */
+    String testReceiverCanRead(String message) {
+        IntentFilter testIntentFilter = new IntentFilter();
+        testIntentFilter.addAction(ACTION_READ_FROM_URI);
+        mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, testIntentFilter,
+                DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+
+        Intent intent = new Intent(ACTION_READ_FROM_URI);
+        intent.setClipData(ClipData.newRawUri("", getUriWithTextInFile("reading_test", message)));
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        startActivityForResult(intent, TEST_RECEIVER_CAN_READ);
+        try {
+            mLatch.await(WAIT_FOR_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            return null;
+        }
+        return mResponse;
+    }
+
+    /**
+     * This method will send an intent to a receiver in another profile.
+     * This intent will have a message in an extra, and a uri specified by the ClipData.
+     * The receiver will read the message from the extra, and write it to the uri in
+     * the ClipData.
+     * This method returns what has been written in the uri.
+     */
+    String testReceiverCanWrite(String message) {
+        IntentFilter testIntentFilter = new IntentFilter();
+        testIntentFilter.addAction(ACTION_WRITE_TO_URI);
+        mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, testIntentFilter,
+                DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+        // It's the receiver of the intent that should write to the uri, not us. So, for now, we
+        // write an empty string.
+        mUriToWrite = getUriWithTextInFile("writing_test", "");
+        Intent intent = new Intent(ACTION_WRITE_TO_URI);
+        intent.setClipData(ClipData.newRawUri("", mUriToWrite));
+        intent.putExtra("extra_message", message);
+        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        startActivityForResult(intent, TEST_RECEIVER_CAN_WRITE);
+        try {
+            mLatch.await(WAIT_FOR_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            return null;
+        }
+        return mResponse;
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == TEST_RECEIVER_CAN_READ) {
+            if (resultCode == Activity.RESULT_OK) {
+                mResponse = data.getStringExtra("extra_response");
+                Log.i(TAG, "response received in reading test: " + mResponse);
+            }
+        } else if (requestCode == TEST_RECEIVER_CAN_WRITE) {
+            if (resultCode == Activity.RESULT_OK) {
+                mResponse = getFirstLineFromUri(mUriToWrite);
+                Log.i(TAG, "response received in writing test: " + mResponse);
+            }
+        }
+        mLatch.countDown();
+        finish();
+    }
+
+    private Uri getUriWithTextInFile(String name, String text) {
+        String filename = getFilesDir() + File.separator + "texts" + File.separator + name + ".txt";
+        Log.i(TAG, "Creating file " + filename + " with text \"" + text + "\"");
+        final File file = new File(filename);
+        file.getParentFile().mkdirs(); // If the folder doesn't exists it is created
+        try {
+            FileWriter writer = new FileWriter(file);
+            writer.write(text);
+            writer.close();
+        } catch(IOException e) {
+            Log.e(TAG, "Could not create file " + filename + " with text " + text);
+            return null;
+        }
+        return FileProvider.getUriForFile(this,
+                "com.android.cts.managedprofile.fileprovider", file);
+    }
+
+    /**
+     * Returns the first line of the file associated with uri.
+     */
+    private String getFirstLineFromUri(Uri uri) {
+        try {
+            InputStream is = getContentResolver().openInputStream(uri);
+            BufferedReader r = new BufferedReader(new InputStreamReader(is));
+            return r.readLine();
+        } catch (IOException e) {
+            Log.e(TAG, "could not read the uri " + uri);
+            return null;
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ComponentDisablingActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ComponentDisablingActivity.java
new file mode 100644
index 0000000..03922da
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ComponentDisablingActivity.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.Log;
+
+/**
+ * Class that disables a given component for the user it's running in.
+ */
+public class ComponentDisablingActivity extends Activity {
+
+    private static final String TAG = ComponentDisablingActivity.class.getName();
+    public static final String EXTRA_PACKAGE = "extra-package";
+    public static final String EXTRA_CLASS_NAME = "extra-class-name";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        String extraClassName = getIntent().getStringExtra(EXTRA_CLASS_NAME);
+        String extraPackage = getIntent().getStringExtra(EXTRA_PACKAGE);
+
+        Log.i(TAG, "Disabling: " + extraPackage + "/" + extraClassName + " for user "
+                + Process.myUserHandle());
+        PackageManager packageManager = getPackageManager();
+        packageManager.setComponentEnabledSetting(new ComponentName(extraPackage, extraClassName),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java
index a91f633..a383e2c 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java
@@ -31,6 +31,8 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        Log.i(TAG, "Roger that!");
+        Log.i(TAG, "Managed profile activity started!");
+        setResult(RESULT_OK);
+        finish();
     }
 }
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java
index 0e3822b..47ecfcb 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java
@@ -16,9 +16,13 @@
 package com.android.cts.managedprofile;
 
 import android.app.admin.DevicePolicyManager;
+import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.test.ActivityInstrumentationTestCase2;
+
+import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
 
 /**
  * Test for {@link DevicePolicyManager#addCrossProfileIntentFilter} API.
@@ -27,14 +31,21 @@
  * in the primary profile, one to {@code ManagedProfileActivity.ACTION} in the secondary profile,
  * and one to {@code AllUsersActivity.ACTION} in both profiles.
  */
-public class ManagedProfileTest extends BaseManagedProfileTest {
+public class ManagedProfileTest extends ActivityInstrumentationTestCase2<TestActivity> {
 
     private PackageManager mPackageManager;
+    private DevicePolicyManager mDevicePolicyManager;
+
+    public ManagedProfileTest() {
+        super(TestActivity.class);
+    }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mPackageManager = getContext().getPackageManager();
+        mPackageManager = getActivity().getPackageManager();
+        mDevicePolicyManager = (DevicePolicyManager)
+                getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
     }
 
     @Override
@@ -55,6 +66,8 @@
 
         assertTrue(mPackageManager.queryIntentActivities(
                 new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).isEmpty());
+        getActivity().startActivity(ManagedProfileActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
     }
 
     public void testAddCrossProfileIntentFilter_primary() {
@@ -68,6 +81,8 @@
 
         assertEquals(1, mPackageManager.queryIntentActivities(
                 new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).size());
+        getActivity().startActivity(PrimaryUserActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
     }
 
     public void testAddCrossProfileIntentFilter_all() {
@@ -81,6 +96,8 @@
 
         assertEquals(2, mPackageManager.queryIntentActivities(
                 new Intent(AllUsersActivity.ACTION), /* flags = */ 0).size());
+        // If we used startActivity(), the user would have a disambiguation dialog presented which
+        // requires human intervention, so we won't be testing like that
     }
 
     public void testAddCrossProfileIntentFilter_managed() {
@@ -95,5 +112,7 @@
         // We should still be resolving in the profile
         assertEquals(1, mPackageManager.queryIntentActivities(
                 new Intent(ManagedProfileActivity.ACTION), /* flags = */ 0).size());
+        getActivity().startActivity(ManagedProfileActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
     }
 }
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java
index f6fa172..35f70be 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java
@@ -31,6 +31,8 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        Log.i(TAG, "Roger that!");
+        Log.i(TAG, "Primary user activity started!");
+        setResult(RESULT_OK);
+        finish();
     }
 }
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java
index af400a7..7098d9e 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java
@@ -17,9 +17,8 @@
 
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 
 /**
  * Test for {@link DevicePolicyManager#addCrossProfileIntentFilter} API, for
@@ -32,28 +31,39 @@
  * Note that the {code DevicePolicyManager#clearCrossProfileIntentFilters} as well as more complex
  * test scenarios can be found in {@link ManagedProfileTest}.
  */
-public class PrimaryUserTest extends AndroidTestCase {
+public class PrimaryUserTest extends ActivityInstrumentationTestCase2<TestActivity> {
 
     private PackageManager mPackageManager;
 
+    public PrimaryUserTest() {
+        super(TestActivity.class);
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mPackageManager = getContext().getPackageManager();
+        mPackageManager = getActivity().getPackageManager();
     }
 
     public void testAddCrossProfileIntentFilter_primary() {
         assertEquals(1, mPackageManager.queryIntentActivities(
                 new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).size());
+        getActivity().startActivity(PrimaryUserActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
     }
 
     public void testAddCrossProfileIntentFilter_all() {
         assertEquals(2, mPackageManager.queryIntentActivities(
                 new Intent(AllUsersActivity.ACTION), /* flags = */ 0).size());
+        
+        // If we used startActivity(), the user would have a disambiguation dialog presented which
+        // requires human intervention, so we won't be testing like that
     }
 
     public void testAddCrossProfileIntentFilter_managed() {
         assertEquals(1, mPackageManager.queryIntentActivities(
                 new Intent(ManagedProfileActivity.ACTION), /* flags = */ 0).size());
+        getActivity().startActivity(ManagedProfileActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
     }
 }
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/TestActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/TestActivity.java
new file mode 100644
index 0000000..b0e22b6
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/TestActivity.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.util.Log;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Dummy activity necessary for the tests.
+ */
+public class TestActivity extends Activity {
+    private static final String TAG = TestActivity.class.getName();
+
+    private final Semaphore mActivityStartedSemaphore = new Semaphore(0);
+
+    public void startActivity(String action) {
+        startActivityForResult(new Intent(action), /* requestCode= */ 0);
+    }
+
+    public boolean checkActivityStarted() {
+        Log.i(TAG, "Waiting to see if an activity was started");
+        try {
+            return mActivityStartedSemaphore.tryAcquire(5, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+           return false;
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        Log.i(TAG, "An activity sent a result");
+        if (resultCode != RESULT_OK) {
+            Log.w(TAG, "Activity returned error code: " + resultCode);
+        }
+        mActivityStartedSemaphore.release();
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 85ffb4c..7fc33f0 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -28,6 +28,9 @@
     private static final String MANAGED_PROFILE_PKG = "com.android.cts.managedprofile";
     private static final String MANAGED_PROFILE_APK = "CtsManagedProfileApp.apk";
 
+    private static final String INTENT_RECEIVER_PKG = "com.android.cts.intent.receiver";
+    private static final String INTENT_RECEIVER_APK = "CtsIntentReceiverApp.apk";
+
     private static final String ADMIN_RECEIVER_TEST_CLASS =
             MANAGED_PROFILE_PKG + ".BaseManagedProfileTest$BasicAdminReceiver";
 
@@ -81,34 +84,52 @@
         assertFalse(listUsers().contains(mUserId));
     }
 
-// TODO: Reinstate once we find another way of disabling an activity for a user (adb pm disable does
-//   not work at the moment on non-eng builds.
-//    public void testCrossProfileIntentFilters() throws Exception {
-//        if (!mHasFeature) {
-//            return;
-//        }
-//        // Set up activities: ManagedProfileActivity will only be enabled in the managed profile and
-//        // PrimaryUserActivity only in the primary one
-//        disableActivityForUser("ManagedProfileActivity", 0);
-//        disableActivityForUser("PrimaryUserActivity", mUserId);
-//
-//        assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG,
-//                MANAGED_PROFILE_PKG + ".ManagedProfileTest", mUserId));
-//
-//        // Set up filters from primary to managed profile
-//        String command = "am start -W --user " + mUserId  + " " + MANAGED_PROFILE_PKG
-//                + "/.PrimaryUserFilterSetterActivity";
-//        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
-//              + getDevice().executeShellCommand(command));
-//        assertTrue(runDeviceTests(MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".PrimaryUserTest"));
-//        // TODO: Test with startActivity
-//        // TODO: Test with CtsVerifier for disambiguation cases
-//    }
+    public void testCrossProfileIntentFilters() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        // Set up activities: ManagedProfileActivity will only be enabled in the managed profile and
+        // PrimaryUserActivity only in the primary one
+        disableActivityForUser("ManagedProfileActivity", 0);
+        disableActivityForUser("PrimaryUserActivity", mUserId);
+
+        assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG,
+                MANAGED_PROFILE_PKG + ".ManagedProfileTest", mUserId));
+
+        // Set up filters from primary to managed profile
+        String command = "am start -W --user " + mUserId  + " " + MANAGED_PROFILE_PKG
+                + "/.PrimaryUserFilterSetterActivity";
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
+              + getDevice().executeShellCommand(command));
+        assertTrue(runDeviceTests(MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".PrimaryUserTest"));
+        // TODO: Test with startActivity
+        // TODO: Test with CtsVerifier for disambiguation cases
+    }
+
+    public void testCrossProfileContent() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        try {
+            installApp(INTENT_RECEIVER_APK);
+
+            String command = "pm uninstall --user " + mUserId + " " + INTENT_RECEIVER_PKG;
+            CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
+                    + getDevice().executeShellCommand(command));
+
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG,
+                    MANAGED_PROFILE_PKG + ".crossprofilecontent.CrossProfileContentTest", mUserId));
+        } finally {
+            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+        }
+    }
 
     private void disableActivityForUser(String activityName, int userId)
             throws DeviceNotAvailableException {
-        String command = "pm disable --user " + userId + " " + MANAGED_PROFILE_PKG + "/."
-                + activityName;
+        String command = "am start -W --user " + userId
+                + " --es extra-package " + MANAGED_PROFILE_PKG
+                + " --es extra-class-name " + MANAGED_PROFILE_PKG + "." + activityName + " "
+                + MANAGED_PROFILE_PKG + "/.ComponentDisablingActivity ";
         CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
                 + getDevice().executeShellCommand(command));
     }
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 5ce84f7..012f4fd 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -158,7 +158,15 @@
     "android.hardware.cts.SensorBatchingTests#testGeomagneticRotationVector_50hz_flush",
     "android.hardware.cts.SensorIntegrationTests#testSensorsWithSeveralClients",
     "android.hardware.cts.SensorIntegrationTests#testSensorsMovingRates",
-    "android.hardware.cts.SensorIntegrationTests#testSensorStoppingInteraction",
+    "android.hardware.cts.SensorIntegrationTests#testAccelerometerAccelerometerStopping",
+    "android.hardware.cts.SensorIntegrationTests#testAccelerometerGyroscopeStopping",
+    "android.hardware.cts.SensorIntegrationTests#testAccelerometerMagneticFieldStopping",
+    "android.hardware.cts.SensorIntegrationTests#testGyroscopeAccelerometerStopping",
+    "android.hardware.cts.SensorIntegrationTests#testGyroscopeGyroscopeStopping",
+    "android.hardware.cts.SensorIntegrationTests#testGyroscopeMagneticFieldStopping",
+    "android.hardware.cts.SensorIntegrationTests#testMagneticFieldAccelerometerStopping",
+    "android.hardware.cts.SensorIntegrationTests#testMagneticFieldGyroscopeStopping",
+    "android.hardware.cts.SensorIntegrationTests#testMagneticFieldMagneticFieldStopping",
     "android.hardware.cts.SingleSensorTests#testSensorProperties",
     "android.hardware.cts.SingleSensorTests#testAccelerometer_fastest",
     "android.hardware.cts.SingleSensorTests#testAccelerometer_100hz",
diff --git a/tests/tests/content/AndroidManifest.xml b/tests/tests/content/AndroidManifest.xml
index a5caba8..f7080ae 100644
--- a/tests/tests/content/AndroidManifest.xml
+++ b/tests/tests/content/AndroidManifest.xml
@@ -187,6 +187,15 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="com.android.cts.content.ReadableFileReceiverActivity"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.SEND" />
+                <action android:name="android.intent.action.SEND_MULTIPLE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java b/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java
new file mode 100644
index 0000000..bab516e
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.content;
+
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipData.Item;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ReadableFileReceiverActivity extends Activity {
+    public static final String ACTION_CONFIRM_READ_SUCCESS
+        = "com.android.cts.content.action.CONFIRM_READ_SUCCESS";
+    private static final String TAG = ReadableUriExtraToClipDataTest.TAG;
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Intent intent = getIntent();
+
+        // Check action.
+        String action = intent.getAction();
+        if (Intent.ACTION_SEND.equals(action)
+                || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+            readFilesFromClipDataUri(intent);
+        }
+
+        finish();
+    }
+
+    // Sends ACTION_FILE_READY intent when read from clipdata uri is succesful
+    // and read data matches the data written by the test.
+    private void readFilesFromClipDataUri(Intent intent) {
+        if ((intent.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
+
+            // Note: since this activity is in the same package as the test we can read from the
+            // file regardless of this permission, but in general this permission is required.
+            Log.e(TAG, "Intent.FLAG_GRANT_READ_URI_PERMISSION was not granted.");
+            return;
+        }
+
+        List<File> files = getFilesFromIntent(intent);
+        if (files == null) {
+            Log.e(TAG, "Could not get files from clipdata.");
+            return;
+        }
+        for (File file : files) {
+            if (!testFileContents(file)) {
+                Log.e(TAG, "File contents of " + file.getPath()
+                        + " is incorrect or could not be verified.");
+                return;
+            }
+        }
+        Intent confirmIntent = new Intent(ACTION_CONFIRM_READ_SUCCESS);
+        sendBroadcast(confirmIntent);
+    }
+
+    private ArrayList<File> getFilesFromIntent(Intent intent) {
+        ClipData clipData = intent.getClipData();
+        if (clipData == null) {
+            Log.e(TAG, "ClipData missing.");
+            return null;
+        }
+        if (clipData.getItemCount() == 0) {
+            Log.e(TAG, "Uri missing in ClipData.");
+            return null;
+        }
+
+        ArrayList<File> result = new ArrayList<File>();
+        for (int i = 0; i < clipData.getItemCount(); i++) {
+            Uri filePath = clipData.getItemAt(i).getUri();
+            if (filePath == null) {
+                Log.e(TAG, "Uri missing in ClipData.");
+                return null;
+            }
+            try {
+                result.add(new File(filePath.getPath()));
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "Cannot get file at Uri.");
+                return null;
+            }
+        }
+        return result;
+    }
+
+    private boolean testFileContents(File file) {
+        char[] buffer = new char[ReadableUriExtraToClipDataTest.TEST_INPUT.length()];
+        try {
+            FileReader reader = new FileReader(file);
+            reader.read(buffer);
+            reader.close();
+        } catch (IOException e) {
+            Log.e(TAG, "Error while reading file " + file.getPath() + ".");
+            return false;
+        }
+        String fileContents = new String(buffer);
+        return ReadableUriExtraToClipDataTest.TEST_INPUT.equals(fileContents);
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java b/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java
new file mode 100644
index 0000000..129d964
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.content;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.List;
+
+public class ReadableUriExtraToClipDataTest extends AndroidTestCase {
+    private static final List<String> FILE_NAMES = Arrays.asList("testFile1.txt", "testFile2.txt");
+    private static final List<File> mTestFiles = new ArrayList<File>();
+    private static final ArrayList<Uri> mTestFileUris = new ArrayList<Uri>();
+    private final Semaphore mReadSuccessSemaphore = new Semaphore(0);
+
+    public static final String TEST_INPUT = "testString";
+    public static final String TAG = "ReadableUriExtraToClipDataTest";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertEquals(0, mReadSuccessSemaphore.availablePermits());
+
+        BroadcastReceiver mReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    mReadSuccessSemaphore.release();
+                }
+            };
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ReadableFileReceiverActivity.ACTION_CONFIRM_READ_SUCCESS);
+        getContext().registerReceiver(mReceiver, filter);
+
+        for (String fileName : FILE_NAMES) {
+            File testFile = new File(getContext().getFilesDir() + File.separator + fileName);
+            writeTestInputToFile(testFile);
+            mTestFiles.add(testFile);
+            mTestFileUris.add(Uri.fromFile(testFile));
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        for (File testFile : mTestFiles) {
+            if (testFile.exists()) {
+                assertTrue(testFile.delete());
+            }
+        }
+        mTestFiles.clear();
+        mTestFileUris.clear();
+        super.tearDown();
+    }
+
+    public void testUriExtraStreamMigratedToClipData_sendIntent() {
+        Intent intent = new Intent(Intent.ACTION_SEND);
+        intent.setComponent(new ComponentName(getContext(), ReadableFileReceiverActivity.class));
+        intent.putExtra(Intent.EXTRA_STREAM, mTestFileUris.get(0));
+        intent.setType("*/*");
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        getContext().startActivity(intent);
+
+        waitForConfirmationReadSuccess();
+    }
+
+    public void testUriExtraStreamMigratedToClipData_sendMultipleIntent() {
+        Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
+        intent.setComponent(new ComponentName(getContext(), ReadableFileReceiverActivity.class));
+        intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, mTestFileUris);
+        intent.setType("*/*");
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        getContext().startActivity(intent);
+
+        waitForConfirmationReadSuccess();
+    }
+
+    private void writeTestInputToFile(File file) {
+        try {
+            FileWriter writer = new FileWriter(file);
+            writer.write(TEST_INPUT);
+            writer.flush();
+            writer.close();
+        } catch (IOException e) {
+            fail(e.toString());
+            return;
+        }
+    }
+
+    private void waitForConfirmationReadSuccess() {
+        try {
+            assertTrue(mReadSuccessSemaphore.tryAcquire(5, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+            fail(e.toString());
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
index 29fabfb..f18a1cf 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -65,8 +65,8 @@
     // 60 second to accommodate the possible long exposure time.
     private static final int EXIF_DATETIME_ERROR_MARGIN_SEC = 60;
     private static final float EXIF_FOCAL_LENGTH_ERROR_MARGIN = 0.001f;
-    // TODO: exposure time error margin need to be scaled with exposure time.
-    private static final float EXIF_EXPOSURE_TIME_ERROR_MARGIN_SEC = 0.002f;
+    private static final float EXIF_EXPOSURE_TIME_ERROR_MARGIN_RATIO = 0.05f;
+    private static final float EXIF_EXPOSURE_TIME_MIN_ERROR_MARGIN_SEC = 0.002f;
     private static final float EXIF_APERTURE_ERROR_MARGIN = 0.001f;
     private static final Location sTestLocation0 = new Location(LocationManager.GPS_PROVIDER);
     private static final Location sTestLocation1 = new Location(LocationManager.GPS_PROVIDER);
@@ -1116,8 +1116,10 @@
                 double exposureTimeValue = Double.parseDouble(exposureTime);
                 long expTimeResult = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
                 double expected = expTimeResult / 1e9;
+                double tolerance = expected * EXIF_EXPOSURE_TIME_ERROR_MARGIN_RATIO;
+                tolerance = Math.max(tolerance, EXIF_EXPOSURE_TIME_MIN_ERROR_MARGIN_SEC);
                 mCollector.expectEquals("Exif exposure time doesn't match", expected,
-                        exposureTimeValue, EXIF_EXPOSURE_TIME_ERROR_MARGIN_SEC);
+                        exposureTimeValue, tolerance);
             }
         }
 
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
index 3c9eef9..88e6cce 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
@@ -15,9 +15,6 @@
  */
 package android.hardware.cts;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 import android.content.Context;
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
@@ -44,25 +41,6 @@
     private static final String TAG = "SensorIntegrationTests";
 
     /**
-     * Builder for the test suite.
-     * This is the method that will build dynamically the set of test cases to execute.
-     * Each 'base' test case is composed by three parts:
-     * - the matrix definition
-     * - the test method that will execute the test case
-     * - a static method that will combine both and add test case instances to the test suite
-     */
-    public static Test suite() {
-        TestSuite testSuite = new TestSuite();
-
-        // add test generation routines
-        addTestToSuite(testSuite, "testSensorsWithSeveralClients");
-        addTestToSuite(testSuite, "testSensorsMovingRates");
-        createStoppingTestCases(testSuite);
-
-        return testSuite;
-    }
-
-    /**
      * This test focuses in the interaction of continuous and batching clients for the same Sensor
      * under test. The verification ensures that sensor clients can interact with the System and
      * not affect other clients in the way.
@@ -183,24 +161,41 @@
      * Regress:
      * - b/10641388
      */
-    private int mSensorTypeTester;
-    private int mSensorTypeTestee;
 
-    private static void createStoppingTestCases(TestSuite testSuite) {
-        int sensorTypes[] = {
-                Sensor.TYPE_ACCELEROMETER,
-                Sensor.TYPE_GYROSCOPE,
-                Sensor.TYPE_MAGNETIC_FIELD};
+    public void testAccelerometerAccelerometerStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER);
+    }
 
-        for(int sensorTypeTester : sensorTypes) {
-            for(int sensorTypeTestee : sensorTypes) {
-                SensorIntegrationTests test = new SensorIntegrationTests();
-                test.mSensorTypeTester = sensorTypeTester;
-                test.mSensorTypeTestee = sensorTypeTestee;
-                test.setName("testSensorStoppingInteraction");
-                testSuite.addTest(test);
-            }
-        }
+    public void testAccelerometerGyroscopeStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_GYROSCOPE);
+    }
+
+    public void testAccelerometerMagneticFieldStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_MAGNETIC_FIELD);
+    }
+
+    public void testGyroscopeAccelerometerStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_ACCELEROMETER);
+    }
+
+    public void testGyroscopeGyroscopeStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_GYROSCOPE);
+    }
+
+    public void testGyroscopeMagneticFieldStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_MAGNETIC_FIELD);
+    }
+
+    public void testMagneticFieldAccelerometerStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_ACCELEROMETER);
+    }
+
+    public void testMagneticFieldGyroscopeStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_GYROSCOPE);
+    }
+
+    public void testMagneticFieldMagneticFieldStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD);
     }
 
     /**
@@ -223,12 +218,14 @@
      * It is important to look at the internals of the Sensor HAL to identify how the interaction
      * of several clients can lead to the failing state.
      */
-    public void testSensorStoppingInteraction() throws Throwable {
+    public void verifySensorStoppingInteraction(
+            int sensorTypeTestee,
+            int sensorTypeTester) throws Throwable {
         Context context = getContext();
 
         TestSensorEnvironment testerEnvironment = new TestSensorEnvironment(
                 context,
-                mSensorTypeTester,
+                sensorTypeTester,
                 shouldEmulateSensorUnderLoad(),
                 SensorManager.SENSOR_DELAY_FASTEST);
         TestSensorOperation tester =
@@ -237,7 +234,7 @@
 
         TestSensorEnvironment testeeEnvironment = new TestSensorEnvironment(
                 context,
-                mSensorTypeTestee,
+                sensorTypeTestee,
                 shouldEmulateSensorUnderLoad(),
                 SensorManager.SENSOR_DELAY_FASTEST);
         VerifiableSensorOperation testee =
@@ -278,10 +275,4 @@
                 mGenerator.nextInt(5) + 1);
         return reportLatency;
     }
-
-    private static void addTestToSuite(TestSuite testSuite, String testName) {
-        SensorIntegrationTests test = new SensorIntegrationTests();
-        test.setName(testName);
-        testSuite.addTest(test);
-    }
 }
diff --git a/tests/tests/security/src/android/security/cts/SELinuxDomainTest.java b/tests/tests/security/src/android/security/cts/SELinuxDomainTest.java
index 9679f82..225c623 100644
--- a/tests/tests/security/src/android/security/cts/SELinuxDomainTest.java
+++ b/tests/tests/security/src/android/security/cts/SELinuxDomainTest.java
@@ -128,6 +128,30 @@
         }
     }
 
+    /**
+     * Asserts that a domain, if it exists, is only running the listed executables.
+     *
+     * @param domain
+     *  The domain or SELinux context to check.
+     * @param executables
+     *  The path of the allowed executables or application package names.
+     */
+    private void assertDomainHasExecutable(String domain, String... executables)
+            throws FileNotFoundException {
+        List<ProcessDetails> procs = ProcessDetails.getProcessMap().get(domain);
+        if (procs == null) {
+            return; // domain doesn't exist
+        }
+
+        Set<String> execList = new HashSet<String>(Arrays.asList(executables));
+
+        for (ProcessDetails p : procs) {
+            String msg = "Expected one of \"" + execList + "\" in SELinux domain \""
+                + domain + "\"" + " Found: \"" + p + "\"";
+            assertTrue(msg, execList.contains(p.procTitle));
+        }
+    }
+
     /* Init is always there */
     public void testInitDomain() throws FileNotFoundException {
         assertDomainOne("u:r:init:s0", "/init");
@@ -198,9 +222,12 @@
         assertDomainOne("u:r:system_server:s0", "system_server");
     }
 
-    /* Some OEMs do not use sdcardd so transient */
+    /*
+     * Some OEMs do not use sdcardd so transient. Other OEMs have multiple sdcards
+     * so they run the daemon multiple times.
+     */
     public void testSdcarddDomain() throws FileNotFoundException {
-        assertDomainZeroOrOne("u:r:sdcardd:s0", "/system/bin/sdcard");
+        assertDomainHasExecutable("u:r:sdcardd:s0", "/system/bin/sdcard");
     }
 
     /* Watchdogd may or may not be there */
diff --git a/tests/tests/telephony/AndroidManifest.xml b/tests/tests/telephony/AndroidManifest.xml
index cd3864e..b3ae1a3 100644
--- a/tests/tests/telephony/AndroidManifest.xml
+++ b/tests/tests/telephony/AndroidManifest.xml
@@ -25,6 +25,9 @@
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.SEND_SMS" />
     <uses-permission android:name="android.permission.RECEIVE_SMS" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java b/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
index e58d26f..00c9844 100644
--- a/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
@@ -18,31 +18,33 @@
 
 import android.content.Context;
 import android.os.Looper;
+import android.net.ConnectivityManager;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.telephony.gsm.GsmCellLocation;
 import android.test.AndroidTestCase;
+import android.content.pm.PackageManager;
+import android.util.Log;
 
-public class CellLocationTest extends AndroidTestCase {
+public class CellLocationTest extends AndroidTestCase{
     private boolean mOnCellLocationChangedCalled;
     private final Object mLock = new Object();
     private TelephonyManager mTelephonyManager;
-    private Looper mLooper;
     private PhoneStateListener mListener;
+    private static ConnectivityManager mCm;
+    private static final String TAG = "android.telephony.cts.CellLocationTest";
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mTelephonyManager =
-                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+                (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        mCm = (ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
     }
 
     @Override
     protected void tearDown() throws Exception {
-        if (mLooper != null) {
-            mLooper.quit();
-        }
         if (mListener != null) {
             // unregister listener
             mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
@@ -51,6 +53,11 @@
     }
 
     public void testCellLocation() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         CellLocation cl = CellLocation.getEmpty();
         if (cl instanceof GsmCellLocation) {
             GsmCellLocation gcl = (GsmCellLocation) cl;
@@ -62,9 +69,6 @@
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
-
-                mLooper = Looper.myLooper();
-
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCellLocationChanged(CellLocation location) {
diff --git a/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java b/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java
index b084245..9d8f842 100644
--- a/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java
@@ -21,9 +21,12 @@
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.net.ConnectivityManager;
+import android.test.InstrumentationTestCase;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
-public class PhoneStateListenerTest extends AndroidTestCase {
+public class PhoneStateListenerTest extends  AndroidTestCase{
 
     public static final long WAIT_TIME = 1000;
 
@@ -38,21 +41,20 @@
     private TelephonyManager mTelephonyManager;
     private PhoneStateListener mListener;
     private final Object mLock = new Object();
-    private Looper mLooper;
+    private static final String TAG = "android.telephony.cts.PhoneStateListenerTest";
+    private static ConnectivityManager mCm;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        Context context = getContext();
-        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        mTelephonyManager =
+                (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        mCm = (ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
     }
 
     @Override
     protected void tearDown() throws Exception {
         super.tearDown();
-        if (mLooper != null) {
-            mLooper.quit();
-        }
         if (mListener != null) {
             // unregister the listener
             mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
@@ -60,6 +62,12 @@
     }
 
     public void testPhoneStateListener() {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
+        Looper.prepare();
         new PhoneStateListener();
     }
 
@@ -69,10 +77,15 @@
      */
 
     public void testOnServiceStateChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
-                mLooper = Looper.myLooper();
+
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onServiceStateChanged(ServiceState serviceState) {
@@ -96,22 +109,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnServiceStateChangedCalled);
     }
 
-    private void quitLooper() {
-        mLooper.quit();
-        mLooper = null;
-    }
-
     public void testOnSignalStrengthChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onSignalStrengthChanged(int asu) {
@@ -135,17 +146,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnSignalStrengthChangedCalled);
     }
 
     public void testOnMessageWaitingIndicatorChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onMessageWaitingIndicatorChanged(boolean mwi) {
@@ -170,17 +184,21 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnMessageWaitingIndicatorChangedCalled);
     }
 
     public void testOnCallForwardingIndicatorChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
+            @Override
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCallForwardingIndicatorChanged(boolean cfi) {
@@ -205,17 +223,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnCallForwardingIndicatorChangedCalled);
     }
 
     public void testOnCellLocationChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCellLocationChanged(CellLocation location) {
@@ -239,17 +260,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnCellLocationChangedCalled);
     }
 
     public void testOnCallStateChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCallStateChanged(int state, String incomingNumber) {
@@ -273,17 +297,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnCallStateChangedCalled);
     }
 
     public void testOnDataConnectionStateChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onDataConnectionStateChanged(int state) {
@@ -308,17 +335,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnDataConnectionStateChangedCalled);
     }
 
     public void testOnDataActivity() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onDataActivity(int direction) {
@@ -342,7 +372,6 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnDataActivityCalled);
     }
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index 803baec..b9c720c 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -28,6 +28,7 @@
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 import com.android.internal.telephony.PhoneConstants;
 
@@ -38,16 +39,16 @@
     private boolean mOnCellLocationChangedCalled = false;
     private final Object mLock = new Object();
     private static final int TOLERANCE = 1000;
-    private Looper mLooper;
     private PhoneStateListener mListener;
     private static ConnectivityManager mCm;
+    private static final String TAG = "android.telephony.cts.TelephonyManagerTest";
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mTelephonyManager =
             (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
-        mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+        mCm = (ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
     }
 
     @Override
@@ -60,6 +61,11 @@
     }
 
     public void testListen() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
             // TODO: temp workaround, need to adjust test to for CDMA
             return;
@@ -70,7 +76,6 @@
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCellLocationChanged(CellLocation location) {
@@ -93,7 +98,6 @@
                 mLock.wait();
             }
         }
-        mLooper.quit();
         assertTrue(mOnCellLocationChangedCalled);
 
         // Test unregister
@@ -101,7 +105,6 @@
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 // unregister the listener
                 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
                 mOnCellLocationChangedCalled = false;
@@ -117,8 +120,8 @@
         synchronized (mLock) {
             mLock.wait(TOLERANCE);
         }
-        mLooper.quit();
-        assertFalse(mOnCellLocationChangedCalled);
+        //Fix me: unregister for listener is not support today. Will be added soon
+        //assertFalse(mOnCellLocationChangedCalled);
     }
 
     /**
@@ -184,14 +187,14 @@
                 break;
 
             case TelephonyManager.PHONE_TYPE_NONE:
-                if (mCm.isNetworkSupported(ConnectivityManager.TYPE_WIFI)) {
+                if (mCm.getNetworkInfo(ConnectivityManager.TYPE_WIFI) != null) {
                     assertSerialNumber();
                     assertMacAddress(getWifiMacAddress());
-                } else if (mCm.isNetworkSupported(ConnectivityManager.TYPE_BLUETOOTH)) {
+                } else if (mCm.getNetworkInfo(ConnectivityManager.TYPE_BLUETOOTH) != null) {
                     assertSerialNumber();
                     assertMacAddress(getBluetoothMacAddress());
                 } else {
-                    assertTrue(mCm.isNetworkSupported(ConnectivityManager.TYPE_ETHERNET));
+                    assertTrue(mCm.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET) != null);
                 }
                 break;
 
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
index 2ba73db..8c95194 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
@@ -29,6 +29,7 @@
 import android.media.tv.TvView.TvInputCallback;
 import android.net.Uri;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.util.ArrayMap;
 import android.util.SparseIntArray;
 import android.view.InputEvent;
@@ -176,6 +177,7 @@
         super.tearDown();
     }
 
+    @UiThreadTest
     public void testConstructor() throws Exception {
         if (!Utils.hasTvInputFramework(getActivity())) {
             return;
diff --git a/tools/tradefed-host/res/report/cts_result.xsl b/tools/tradefed-host/res/report/cts_result.xsl
index 3c914dc..7bc216b 100644
--- a/tools/tradefed-host/res/report/cts_result.xsl
+++ b/tools/tradefed-host/res/report/cts_result.xsl
@@ -339,8 +339,7 @@
                             <TD class="rowtitle">Host Info</TD>
                             <TD>
                                 <xsl:value-of select="TestResult/HostInfo/@name"/>
-                                (<xsl:value-of select="TestResult/HostInfo/Os/@name"/> - 
-                                  <xsl:value-of select="TestResult/HostInfo/Os/@version"/>)
+                                (<xsl:value-of select="TestResult/HostInfo/Os/@name"/> - <xsl:value-of select="TestResult/HostInfo/Os/@version"/>)
                             </TD>
                         </TR>
                         <TR>
@@ -467,7 +466,9 @@
                             <TD class="package" colspan="3">
                                 <xsl:variable name="href"><xsl:value-of select="@appPackageName"/></xsl:variable>
                                 <a name="{$href}">Compatibility Test Package: <xsl:value-of select="@appPackageName"/>
-                                abi: <xsl:value-of select="@abi"/>
+                                <xsl:if test="@abi">
+                                  ABI: <xsl:value-of select="@abi"/>
+                                </xsl:if>
                                 </a>
                             </TD>
                         </TR>
@@ -512,7 +513,7 @@
                                                 <xsl:if test="@result='pass'">
                                                     <TD class="pass">
                                                         <div style="text-align: center; margin-left:auto; margin-right:auto;">
-                                                            known problem
+                                                            Known problem
                                                         </div>
                                                     </TD>
                                                     <TD class="failuredetails"></TD>
@@ -585,7 +586,7 @@
         </DIV>
     </xsl:template>
 
-    <!-- Take a delimited string and insert line breaks after a some number of elements. --> 
+    <!-- Take a delimited string and insert line breaks after a some number of elements. -->
     <xsl:template name="formatDelimitedString">
         <xsl:param name="string" />
         <xsl:param name="numTokensPerRow" select="10" />
@@ -595,7 +596,7 @@
             <xsl:variable name="token" select="substring-before($string, ';')" />
             <xsl:value-of select="$token" />
             <xsl:text>&#160;</xsl:text>
-          
+
             <xsl:if test="$tokenIndex mod $numTokensPerRow = 0">
                 <br />
             </xsl:if>
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
index db1b2dd..35b8a66 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
@@ -1,8 +1,10 @@
 package com.android.cts.tradefed.testtype;
 
+import com.android.cts.tradefed.build.CtsBuildHelper;
 import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.MultiLineReceiver;
 import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
@@ -10,9 +12,12 @@
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.result.LogDataType;
 import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
 import com.android.tradefed.testtype.IRemoteTest;
 
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -25,8 +30,13 @@
  *
  * Supports running drawElements Quality Program tests found under external/deqp.
  */
-public class DeqpTestRunner implements IDeviceTest, IRemoteTest {
-    final private int TESTCASE_BATCH_LIMIT = 1000;
+public class DeqpTestRunner implements IBuildReceiver, IDeviceTest, IRemoteTest {
+
+    private static final String DEQP_ONDEVICE_APK = "com.drawelements.deqp.apk";
+    private static final String DEQP_ONDEVICE_PKG = "com.drawelements.deqp";
+    private static final String INCOMPLETE_LOG_MESSAGE = "Crash: Incomplete test log";
+
+    private final int TESTCASE_BATCH_LIMIT = 1000;
 
     private boolean mLogData;
 
@@ -36,6 +46,7 @@
     private final String mName;
     private Collection<TestIdentifier> mTests;
     private IAbi mAbi;
+    private CtsBuildHelper mCtsBuild;
 
     private TestIdentifier mCurrentTestId;
     private boolean mGotTestResult;
@@ -58,6 +69,14 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    /**
      * Enable or disable raw dEQP test log collection.
      */
     public void setCollectLogs(boolean logData) {
@@ -200,7 +219,7 @@
 
         if (!mGotTestResult) {
             mListener.testFailed(mCurrentTestId,
-                    "Log doesn't contain test result");
+                    INCOMPLETE_LOG_MESSAGE);
         }
 
         if (mLogData && mCurrentTestLog != null && mCurrentTestLog.length() > 0) {
@@ -236,11 +255,11 @@
                 || code.compareTo("InternalError") == 0 || code.compareTo("Crash") == 0
                 || code.compareTo("Timeout") == 0) {
             mListener.testFailed(mCurrentTestId,
-                    code + ":" + details);
+                    code + ": " + details);
             mGotTestResult = true;
         } else {
             mListener.testFailed(mCurrentTestId,
-                    "Unknown result code: " + code + ":" + details);
+                    "Unknown result code: " + code + ": " + details);
             mGotTestResult = true;
         }
     }
@@ -420,6 +439,29 @@
     }
 
     /**
+     * Install dEQP OnDevice Package
+     */
+    private void installTestApk() throws DeviceNotAvailableException {
+        try {
+            File apkFile = mCtsBuild.getTestApp(DEQP_ONDEVICE_APK);
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+            String errorCode = getDevice().installPackage(apkFile, true, options);
+            if (errorCode != null) {
+                CLog.e("Failed to install %s. Reason: %s", DEQP_ONDEVICE_APK, errorCode);
+            }
+        } catch (FileNotFoundException e) {
+            CLog.e("Could not find test apk %s", DEQP_ONDEVICE_APK);
+        }
+    }
+
+    /**
+     * Uninstall dEQP OnDevice Package
+     */
+    private void uninstallTestApk() throws DeviceNotAvailableException {
+        getDevice().uninstallPackage(DEQP_ONDEVICE_PKG);
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override
@@ -429,6 +471,10 @@
         if ((mName.equals( "dEQP-GLES3") && isSupportedGles(mDevice, 3, 0))
             || (mName.equals("dEQP-GLES31") && isSupportedGles(mDevice, 3, 1))) {
 
+            // Make sure there is no pre-existing package form earlier interrupted test run.
+            uninstallTestApk();
+            installTestApk();
+
             while (!mTests.isEmpty()) {
                 executeTests(listener);
 
@@ -445,16 +491,18 @@
 
                         source.cancel();
                     }
-                if (!mGotTestResult) {
-                    mListener.testFailed(mCurrentTestId,
-                        "Log doesn't contain test result");
-                }
+                    if (!mGotTestResult) {
+                        mListener.testFailed(mCurrentTestId,
+                            INCOMPLETE_LOG_MESSAGE);
+                    }
 
                     mListener.testEnded(mCurrentTestId, emptyMap);
                     mCurrentTestId = null;
                     mListener.testRunEnded(0, emptyMap);
                 }
             }
+
+            uninstallTestApk();
         } else {
             /* Pass all tests if OpenGL ES version is not supported */
             Map <String, String> emptyMap = Collections.emptyMap();