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> </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();