Merge "Tests for DocumentsProvider and DocumentsUI." into lmp-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index c01f827..ce67d37 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -36,11 +36,28 @@
CtsSplitApp_mips \
CtsSplitAppDiffVersion \
CtsSplitAppDiffCert \
+ CtsSplitAppFeature \
CtsTargetInstrumentationApp \
CtsUsePermissionDiffCert \
CtsWriteExternalStorageApp \
CtsMultiUserStorageApp
+cts_security_keysets_list := \
+ CtsKeySetTestApp \
+ CtsKeySetPermDefSigningA \
+ CtsKeySetPermDefSigningB\
+ CtsKeySetPermUseSigningA \
+ CtsKeySetPermUseSigningB \
+ CtsKeySetSigningAUpgradeA \
+ CtsKeySetSigningBUpgradeA \
+ CtsKeySetSigningAUpgradeAAndB \
+ CtsKeySetSigningAUpgradeAOrB \
+ CtsKeySetSigningAUpgradeB \
+ CtsKeySetSigningBUpgradeB \
+ CtsKeySetSigningAAndBUpgradeA \
+ CtsKeySetSigningAAndCUpgradeB \
+ CtsKeySetSigningAUpgradeNone
+
cts_support_packages := \
CtsAccelerationTestStubs \
CtsAppTestStubs \
@@ -60,7 +77,8 @@
TestDeviceSetup \
CtsUiAutomatorApp \
CtsUsbSerialTestApp \
- $(cts_security_apps_list)
+ $(cts_security_apps_list) \
+ $(cts_security_keysets_list)
cts_external_packages := \
com.replica.replicaisland \
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 503d024..f37e1fa 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1247,6 +1247,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_managed_provisioning" />
+ <meta-data android:name="test_required_features" android:value="android.software.managed_users:android.software.device_admin" />
</activity>
@@ -1262,6 +1263,7 @@
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_managed_provisioning" />
+ <meta-data android:name="test_required_features" android:value="android.software.managed_users:android.software.device_admin" />
</activity>
<activity android:name=".managedprovisioning.ByodHelperActivity">
@@ -1272,6 +1274,13 @@
</intent-filter>
</activity>
+ <activity android:name=".managedprovisioning.CrossProfileTestActivity">
+ <intent-filter>
+ <action android:name="com.android.cts.verifier.managedprovisioning.CROSS_PROFILE" />
+ <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">
diff --git a/apps/CtsVerifier/res/layout/provisioning_byod.xml b/apps/CtsVerifier/res/layout/provisioning_byod.xml
index 5e59558..989266f 100644
--- a/apps/CtsVerifier/res/layout/provisioning_byod.xml
+++ b/apps/CtsVerifier/res/layout/provisioning_byod.xml
@@ -41,7 +41,7 @@
<ListView
android:id="@id/android:list"
android:layout_width="match_parent"
- android:layout_height="258dp" />
+ android:layout_height="wrap_content" />
<include layout="@layout/pass_fail_buttons" />
diff --git a/apps/CtsVerifier/res/layout/provisioning_cross_profile.xml b/apps/CtsVerifier/res/layout/provisioning_cross_profile.xml
new file mode 100644
index 0000000..345e99d
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/provisioning_cross_profile.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+ <TextView android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <Button
+ android:id="@+id/button_finish"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/provisioning_button_finish" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index bb755cd..22e0cff 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1215,6 +1215,19 @@
<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_cross_profile">Open app cross profiles</string>
+ <string name="provisioning_byod_cross_profile_app_personal">
+ You selected the CTS Verifier option.
+ </string>
+ <string name="provisioning_byod_cross_profile_app_work">You selected the Work option.</string>
+ <string name="provisioning_byod_cross_profile_instruction">
+ Please press the Go button to start an action.\n
+ \n
+ You should be asked to choose either \"CTS Verifier\" or \"Work\" to complete the action.
+ Pressing either should bring up a page stating your choice.\n
+ \n
+ Verify that you are prompted with the above choices and both options work as intended. Then mark this test accordingly.
+ </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
@@ -1247,6 +1260,8 @@
<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>
+ <string name="provisioning_button_finish">Finish</string>
+ <string name="provisioning_cross_profile_chooser">Choose an app to complete action</string>
<!-- Strings for DeviceOwnerProvisioningTest -->
<string name="provisioning_device_owner">Device Owner Provisioning</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
index d71dca2..178a811 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
@@ -69,7 +69,7 @@
private List<SelectableResolution> mSupportedResolutions;
private ArrayAdapter<SelectableResolution> mAdapter;
- private int mCameraId;
+ private SelectableResolution mSelectedResolution;
private Camera mCamera;
private Size mSurfaceSize;
private boolean mCameraInitialized = false;
@@ -165,12 +165,7 @@
AdapterView<?> parent, View view, int position, long id) {
if (mSupportedResolutions != null) {
SelectableResolution resolution = mSupportedResolutions.get(position);
-
- switchToCamera(resolution.cameraId, false);
-
- Camera.Parameters params = mCamera.getParameters();
- params.setPictureSize(resolution.width, resolution.height);
- mCamera.setParameters(params);
+ switchToCamera(resolution, false);
// It should be guaranteed that the FOV is correctly updated after setParameters().
mReportedFovPrePictureTaken = mCamera.getParameters().getHorizontalViewAngle();
@@ -376,7 +371,7 @@
public void onCancel(DialogInterface arg0) {
// User cancelled preview size selection.
mPreviewSizes = null;
- switchToCamera(mCameraId, true);
+ switchToCamera(mSelectedResolution, true);
}
}).
setSingleChoiceItems(choices, 0, new DialogInterface.OnClickListener() {
@@ -389,7 +384,7 @@
if (mPreviewSizeCamerasToProcess.isEmpty()) {
// We're done, re-initialize camera.
- switchToCamera(mCameraId, true);
+ switchToCamera(mSelectedResolution, true);
} else {
// Process other cameras.
showNextDialogToChoosePreviewSize();
@@ -415,7 +410,7 @@
// Either use chosen preview size for current camera or automatically
// choose preview size based on view dimensions.
- Size selectedPreviewSize = (mPreviewSizes != null) ? mPreviewSizes[mCameraId] :
+ Size selectedPreviewSize = (mPreviewSizes != null) ? mPreviewSizes[mSelectedResolution.cameraId] :
getBestPreviewSize(mSurfaceSize.width, mSurfaceSize.height, params);
if (selectedPreviewSize != null) {
params.setPreviewSize(selectedPreviewSize.width, selectedPreviewSize.height);
@@ -427,19 +422,20 @@
private void startPreview() {
if (mCameraInitialized && mCamera != null) {
- setCameraDisplayOrientation(this, mCameraId, mCamera);
+ setCameraDisplayOrientation(this, mSelectedResolution.cameraId, mCamera);
mCamera.startPreview();
mPreviewActive = true;
}
}
- private void switchToCamera(int cameraId, boolean initializeCamera) {
+ private void switchToCamera(SelectableResolution resolution, boolean initializeCamera) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
}
- mCameraId = cameraId;
- mCamera = Camera.open(cameraId);
+
+ mSelectedResolution = resolution;
+ mCamera = Camera.open(mSelectedResolution.cameraId);
if (initializeCamera){
initializeCamera();
@@ -472,7 +468,7 @@
* Set the common camera parameters on the given camera and returns the
* parameter object for further modification, if needed.
*/
- private static Camera.Parameters setCameraParams(Camera camera) {
+ private Camera.Parameters setCameraParams(Camera camera) {
// The picture size is taken and set from the spinner selection
// callback.
Camera.Parameters params = camera.getParameters();
@@ -480,6 +476,7 @@
params.setJpegQuality(100);
params.setFocusMode(getFocusMode(camera));
params.setZoom(0);
+ params.setPictureSize(mSelectedResolution.width, mSelectedResolution.height);
return params;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index 69071f6..da823e8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -73,6 +73,7 @@
private TestItem mProfileVisibleTest;
private TestItem mDeviceAdminVisibleTest;
private TestItem mWorkAppVisibleTest;
+ private TestItem mCrossProfileIntentFiltersTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -173,11 +174,19 @@
R.string.provisioning_byod_workapps_visible_instruction,
new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
+ Intent intent = new Intent(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
+ Intent chooser = Intent.createChooser(intent, getResources().getString(R.string.provisioning_cross_profile_chooser));
+ mCrossProfileIntentFiltersTest = new TestItem(this,
+ R.string.provisioning_byod_cross_profile,
+ R.string.provisioning_byod_cross_profile_instruction,
+ chooser);
+
mTests.add(mDiskEncryptionTest);
mTests.add(mProfileOwnerInstalled);
mTests.add(mProfileVisibleTest);
mTests.add(mDeviceAdminVisibleTest);
mTests.add(mWorkAppVisibleTest);
+ mTests.add(mCrossProfileIntentFiltersTest);
}
@Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CrossProfileTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CrossProfileTestActivity.java
new file mode 100644
index 0000000..6c38e12
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CrossProfileTestActivity.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+//package com.android.cts.verifier.managedprovisioning;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserManager;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import com.android.cts.verifier.R;
+
+/**
+ * Test activity for cross profile intents.
+ */
+public class CrossProfileTestActivity extends Activity {
+ // Intent for app in both profiles
+ public static final String ACTION_CROSS_PROFILE = "com.android.cts.verifier.managedprovisioning.CROSS_PROFILE";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.provisioning_cross_profile);
+ TextView textView = (TextView) findViewById(R.id.text);
+
+ // Check if we are running in the work or personal side, by testing if currently we are the
+ // profile owner or not.
+ textView.setText(isProfileOwner() ? R.string.provisioning_byod_cross_profile_app_work
+ : R.string.provisioning_byod_cross_profile_app_personal);
+
+ findViewById(R.id.button_finish).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ CrossProfileTestActivity.this.finish();
+ }
+ });
+ }
+
+ private boolean isProfileOwner() {
+ ComponentName adminReceiver = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
+ DevicePolicyManager dpm = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
+ return dpm.isAdminActive(adminReceiver) && dpm.isProfileOwnerApp(adminReceiver.getPackageName());
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
index 861bca2..8dccac3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -26,6 +26,8 @@
import android.util.Log;
import android.widget.Toast;
+import com.android.cts.verifier.managedprovisioning.ByodHelperActivity;
+
/**
* Profile owner receiver for BYOD flow test.
* Setup cross-profile intent filter after successful provisioning.
@@ -48,6 +50,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
filter.addAction(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
+ filter.addAction(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
dpm.addCrossProfileIntentFilter(getWho(context), filter,
DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
diff --git a/hostsidetests/appsecurity/certs/keysets/README b/hostsidetests/appsecurity/certs/keysets/README
new file mode 100644
index 0000000..251dab1
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/README
@@ -0,0 +1,9 @@
+# Generated with:
+development/tools/make_key cts-keyset-test-a '/CN=unit_test_a'
+development/tools/make_key cts-keyset-test-b '/CN=unit_test_b'
+development/tools/make_key cts-keyset-test-c '/CN=unit_test_c'
+
+# Display public key (for use in Manifest) with:
+openssl x509 -in cts-keyset-test-a.x509.pem -inform PEM -pubkey
+openssl x509 -in cts-keyset-test-b.x509.pem -inform PEM -pubkey
+openssl x509 -in cts-keyset-test-c.x509.pem -inform PEM -pubkey
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.pk8 b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.pk8
new file mode 100644
index 0000000..b0dd6a3
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.x509.pem b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.x509.pem
new file mode 100644
index 0000000..cee8227
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIJAJ126KYAFwgTMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMMEWN0cy1rZXlzZXQtdGVzdC1hMB4XDTE0MDkxMTAwNDQ0OFoXDTQyMDEyNzAw
+NDQ0OFowHDEaMBgGA1UEAwwRY3RzLWtleXNldC10ZXN0LWEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDB/nMluW9hIHtibuiv/saCAAC7uantGvKQ8mxe
+Gh3x2gWFVPmzt4XcDgwITnm+8A0/se/AzDZv5PqrHs+rRUm1ttIO2UEcG0hzjs+O
+rQKwODn3QFRyAqns90n0npRWC3MOdXpwYSleZJqDexj6WqJbTjK0+EJXDNhNYZ1h
+735MiXjtwGu95F8s6Uaty4VB77MJOYMWrMEoJEcr1vuXk8Na9dfKDrlS78wFQD9N
+lY7R8So6XFkb+efoNQpAuE92YlFdYndaow0yEkYP6cq2SZ1fvTfFGqaDiH7qDRLs
+z1jchDY1QbLDTkBjMKC4cH8y/q5UiJbrn3ClvJvjlOAobdSFAgMBAAGjUDBOMB0G
+A1UdDgQWBBTev2AuCLdXO85IFqwy6rIV+wUokjAfBgNVHSMEGDAWgBTev2AuCLdX
+O85IFqwy6rIV+wUokjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCS
+8bjQglLYCNMFHc6AeAvSfu/j9rbZNTmK+0SCCUYbb4s1LoMNQ1hmHhs+nrmrOTe9
+3VgaKPUz2h6+toOM5KhMpkxDUHxe+VKJF4V+TRxMWZbPaz0wgj21FKcV7u5wnWnj
+i08O9dzksIzkD9UrOaxlExG20YFJE9kizoR0i2mZJWhR+1g6SeNc7PeaUnEI344G
+LfSDGt27EqZhmZ1BhJ4lRRUMq3TJFEfdFeVc3z+AgtyrZnxc7jNQ0PFdOXDtzz6B
+iC6AmFsMC/mRettVxjTeOpLo+12UE7FwO+wRa57pNGtljzlKz+DGBAZxi+gLcRDf
+i0TJhPAB4dFqrDgxr+4Y
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.pk8 b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.pk8
new file mode 100644
index 0000000..bf6dee1
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.x509.pem b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.x509.pem
new file mode 100644
index 0000000..912861f
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIJAOZwpbLsHooSMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMMEWN0cy1rZXlzZXQtdGVzdC1iMB4XDTE0MDkxMTAwNDQ0MVoXDTQyMDEyNzAw
+NDQ0MVowHDEaMBgGA1UEAwwRY3RzLWtleXNldC10ZXN0LWIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCh4VmoypNtmKjMVNcyRe1IolHOfao4NmC9VcAD
+ApOLnTFhxs9wdN8rG2J/z6rs4Kn/nQlgMffZuDrCRS6efn50RoeTFljx3u7Djq1C
+2Xl00aL7pxzgx7NUsJLqeSo0O6wCB2+AtToWXpIaLTYpOnW+S3oLAs73vtgk/uS3
+2i4NFMbsBImKrc7JFGg6pgeEP2CmxtSrjD7VtcZ+65m6MDV1fKi9e2+sdQY50UgQ
+Fg5VgZ8JzCHeVc+aM0kyUe0pCS6urz8sftrUHmhyhcIazJHxgd2VZ+upEB/OA4HU
+oKc02ZaqyRT0s5yLe5Cf0gN4wQWYB3wWoXxLBX7gu52T/FYZAgMBAAGjUDBOMB0G
+A1UdDgQWBBTM1NnUfcwYiJ3Loy3jfmVwyI+BCTAfBgNVHSMEGDAWgBTM1NnUfcwY
+iJ3Loy3jfmVwyI+BCTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBh
+lRz5yaYpswtWDVPWKnJ5btyXsLIQtWeFkxGxRXSrsFLvCMq7CxjO9VF1l+q+6UmK
+B6BEcrjm7uhmjAXS/ygUGjY1FZNVHwydJ/60Nn/Q0jx242A1+dBtLSS0FnEg+r3P
+3fvocr0SemAt6FY61gJ+4Zr8IQZc8C1qr5e/eDiMPBKectGzH1cniWqq1/5nc/vC
+hTTokZSnXh7PZLzF+iKOceO+nvx4yzm7q/YOM0tAP8PknrWcNAeIPRDvsERwp9fR
+IRTnyd3Ds4H/xD6OioMO+lk45H7vDU3TmoAYbDtCNvgS9Sd1lB/h3XPVH29QqwkW
+4xScMf6rzziGC+RdETpU
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.pk8 b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.pk8
new file mode 100644
index 0000000..303f1ad
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.x509.pem b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.x509.pem
new file mode 100644
index 0000000..324f218
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIJAI8ugk5OF4ENMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMMEWN0cy1rZXlzZXQtdGVzdC1jMB4XDTE0MDkxMTAwNDQyMloXDTQyMDEyNzAw
+NDQyMlowHDEaMBgGA1UEAwwRY3RzLWtleXNldC10ZXN0LWMwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCvAgn+n3NnqkZ7uHWUElQsTmVthsLeaHkbjc6w
+n4HQJ5s3grMQrJWD7CaS4ZK8bbFdSnUGVuKlKOdMnltS3aIG7AHzUu+6aD0Y58Kl
+MEa18ThriKC1+jt7ZTwhtHMRhuFpmUESYLUENS91MV0xEZk+6FRwyTCK3hGkeQvq
+u22459p6gnCyASNsQvLOByb7Vnj0N6f8maZc0YzDX9AyJsEUa8aSG7aseD9JiIqm
+6lyVTgUh4Atw5Kc+Sutjou5IBMcOdi+68rdWG7QQEogP6sC/mPoE2+e7blIB/caB
+Ls8u7JWWGITmneFN69efmD/u2MmVdrQWxsyWcV/ndbI/2lFbAgMBAAGjUDBOMB0G
+A1UdDgQWBBQbgTfHOXShdjNob5N5in97g4W97TAfBgNVHSMEGDAWgBQbgTfHOXSh
+djNob5N5in97g4W97TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAn
+bOLKe3ixKqLkMsgocHWvkeUqFahYbiPN11JKTFrgQVYwfpUnXN/YQfLSjAWDyzZ3
+niXYSai2COtIqEpQICp4JceEfoZUCbHdATA7Wxvfr+yrv+HG7F8wzhyxa5Pbcu9y
+b3ekjKT1rF4SxK0Ixt9vv34VSO98qAzx2Yq7VQwOKLJG6MDxqXX/tiTxpK7sEfAb
+pgJjHVZkX1rgQtv2e0RLFgcRyiYpxFbFzBLi/1b6EzK2kkg9FNLm+44CYkYFj7WC
+bjlY7o94DQ/CuEDVHCu/DSTp4QjvHC2ewTeXu05XkzSWKKLdsqecnZxXNueuqT5F
+Uhj9Fi4KQqT7tKqd+CuK
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java
new file mode 100644
index 0000000..dae5ee7
--- /dev/null
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java
@@ -0,0 +1,435 @@
+/*
+ * 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 android.cts.appsecurity;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Map;
+
+/**
+ * Tests for Keyset based features.
+ */
+public class KeySetHostTest extends DeviceTestCase implements IBuildReceiver {
+
+ private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+
+ /* package with device-side tests */
+ private static final String KEYSET_TEST_PKG = "com.android.cts.keysets.testapp";
+ private static final String KEYSET_TEST_APP_APK = "CtsKeySetTestApp.apk";
+
+ /* plain test apks with different signing and upgrade keysets */
+ private static final String KEYSET_PKG = "com.android.cts.keysets";
+ private static final String A_SIGNED_NO_UPGRADE =
+ "CtsKeySetSigningAUpgradeNone.apk";
+ private static final String A_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningAUpgradeA.apk";
+ private static final String A_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningAUpgradeB.apk";
+ private static final String A_SIGNED_A_OR_B_UPGRADE =
+ "CtsKeySetSigningAUpgradeAOrB.apk";
+ private static final String B_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningBUpgradeA.apk";
+ private static final String B_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningBUpgradeB.apk";
+ private static final String A_AND_B_SIGNED_A_UPGRADE =
+ "CtsKeySetSigningAAndBUpgradeA.apk";
+ private static final String A_AND_B_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningAAndBUpgradeB.apk";
+ private static final String A_AND_C_SIGNED_B_UPGRADE =
+ "CtsKeySetSigningAAndCUpgradeB.apk";
+
+ /* package which defines the KEYSET_PERM_NAME signature permission */
+ private static final String KEYSET_PERM_DEF_PKG =
+ "com.android.cts.keysets_permdef";
+
+ /* The apks defining and using the permission have both A and B as upgrade keys */
+ private static final String PERM_DEF_A_SIGNED =
+ "CtsKeySetPermDefSigningA.apk";
+ private static final String PERM_DEF_B_SIGNED =
+ "CtsKeySetPermDefSigningB.apk";
+ private static final String PERM_USE_A_SIGNED =
+ "CtsKeySetPermUseSigningA.apk";
+ private static final String PERM_USE_B_SIGNED =
+ "CtsKeySetPermUseSigningB.apk";
+
+ private static final String PERM_TEST_CLASS =
+ "com.android.cts.keysets.KeySetPermissionsTest";
+
+ private static final String LOG_TAG = "AppsecurityHostTests";
+
+ private File getTestAppFile(String fileName) throws FileNotFoundException {
+ return mCtsBuild.getTestApp(fileName);
+ }
+
+ /**
+ * Helper method that checks that all tests in given result passed, and attempts to generate
+ * a meaningful error message if they failed.
+ *
+ * @param result
+ */
+ private void assertDeviceTestsPass(TestRunResult result) {
+ assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
+ result.getName(), result.getRunFailureMessage()), result.isRunFailure());
+
+ if (result.hasFailedTests()) {
+
+ /* build a meaningful error message */
+ StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+ for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ result.getTestResults().entrySet()) {
+ if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ fail(errorBuilder.toString());
+ }
+ }
+
+ /**
+ * Helper method that checks that all tests in given result passed, and attempts to generate
+ * a meaningful error message if they failed.
+ *
+ * @param result
+ */
+ private void assertDeviceTestsFail(String msg, TestRunResult result) {
+ assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
+ result.getName(), result.getRunFailureMessage()), result.isRunFailure());
+
+ if (!result.hasFailedTests()) {
+ fail(msg);
+ }
+ }
+
+ /**
+ * Helper method that will run the specified packages tests on device.
+ *
+ * @param pkgName Android application package for tests
+ * @return <code>true</code> if all tests passed.
+ * @throws DeviceNotAvailableException if connection to device was lost.
+ */
+ private boolean runDeviceTests(String pkgName) throws DeviceNotAvailableException {
+ return runDeviceTests(pkgName, null, null);
+ }
+
+ /**
+ * Helper method that will run the specified packages tests on device.
+ *
+ * @param pkgName Android application package for tests
+ * @return <code>true</code> if all tests passed.
+ * @throws DeviceNotAvailableException if connection to device was lost.
+ */
+ private boolean runDeviceTests(String pkgName, String testClassName, String testMethodName)
+ throws DeviceNotAvailableException {
+ TestRunResult runResult = doRunTests(pkgName, testClassName, testMethodName);
+ return !runResult.hasFailedTests();
+ }
+
+ /**
+ * Helper method to run tests and return the listener that collected the results.
+ *
+ * @param pkgName Android application package for tests
+ * @return the {@link TestRunResult}
+ * @throws DeviceNotAvailableException if connection to device was lost.
+ */
+ private TestRunResult doRunTests(String pkgName, String testClassName,
+ String testMethodName) throws DeviceNotAvailableException {
+
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName,
+ RUNNER, getDevice().getIDevice());
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ }
+ CollectingTestListener listener = new CollectingTestListener();
+ getDevice().runInstrumentationTests(testRunner, listener);
+ return listener.getCurrentRunResults();
+ }
+
+ /**
+ * Helper method which installs a package and an upgrade to it.
+ *
+ * @param pkgName - package name of apk.
+ * @param firstApk - first apk to install
+ * @param secondApk - apk to which we attempt to upgrade
+ * @param expectedResult - null if successful, otherwise expected error.
+ */
+ private String testPackageUpgrade(String pkgName, String firstApk,
+ String secondApk) throws Exception {
+ String installResult;
+ try {
+
+ /* cleanup test apps that might be installed from previous partial test run */
+ mDevice.uninstallPackage(pkgName);
+
+ installResult = mDevice.installPackage(getTestAppFile(firstApk),
+ false);
+ /* we should always succeed on first-install */
+ assertNull(String.format("failed to install %s, Reason: %s", pkgName,
+ installResult), installResult);
+
+ /* attempt to install upgrade */
+ installResult = mDevice.installPackage(getTestAppFile(secondApk),
+ true);
+ } finally {
+ mDevice.uninstallPackage(pkgName);
+ }
+ return installResult;
+ }
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ private CtsBuildHelper mCtsBuild;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+ assertNotNull(mCtsBuild);
+ }
+
+ /**
+ * Tests for KeySet based key rotation
+ */
+
+ /*
+ * Check if an apk which does not specify an upgrade-key-set may be upgraded
+ * to an apk which does.
+ */
+ public void testNoKSToUpgradeKS() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_NO_UPGRADE, A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from no specified upgrade-key-set"
+ + "to version with specified upgrade-key-set, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk which does specify an upgrade-key-set may be upgraded
+ * to an apk which does not.
+ */
+ public void testUpgradeKSToNoKS() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_NO_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from specified upgrade-key-set"
+ + "to version without specified upgrade-key-set, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by a key other than the upgrade keyset can update
+ * an app
+ */
+ public void testUpgradeKSWithWrongKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, B_SIGNED_A_UPGRADE);
+ assertNotNull("upgrade to improperly signed app succeeded!", installResult);
+ }
+
+ /*
+ * Check if an apk signed by its signing key, which is not an upgrade key,
+ * can upgrade an app.
+ */
+ public void testUpgradeKSWithWrongSigningKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, A_SIGNED_B_UPGRADE);
+ assertNotNull("upgrade to improperly signed app succeeded!",
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by its upgrade key, which is not its signing key,
+ * can upgrade an app.
+ */
+ public void testUpgradeKSWithUpgradeKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, B_SIGNED_B_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by its upgrade key, which is its signing key, can
+ * upgrade an app.
+ */
+ public void testUpgradeKSWithSigningUpgradeKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by multiple keys, one of which is its upgrade key,
+ * can upgrade an app.
+ */
+ public void testMultipleUpgradeKSWithUpgradeKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE,
+ A_AND_B_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /*
+ * Check if an apk signed by multiple keys, its signing keys,
+ * but none of which is an upgrade key, can upgrade an app.
+ */
+ public void testMultipleUpgradeKSWithSigningKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_AND_C_SIGNED_B_UPGRADE,
+ A_AND_C_SIGNED_B_UPGRADE);
+ assertNotNull("upgrade to improperly signed app succeeded!", installResult);
+ }
+
+ /*
+ * Check if an apk which defines multiple (two) upgrade keysets is
+ * upgrade-able by either.
+ */
+ public void testUpgradeKSWithMultipleUpgradeKeySetsFirstKey() throws Exception {
+ String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
+ A_SIGNED_A_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to one signed by first upgrade keyset key-a, Reason: %s", installResult),
+ installResult);
+ installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
+ B_SIGNED_B_UPGRADE);
+ assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+ + "to one signed by second upgrade keyset key-b, Reason: %s", installResult),
+ installResult);
+ }
+
+ /**
+ * Helper method which installs a package defining a permission and a package
+ * using the permission, and then rotates the signing keys for one of them.
+ * A device-side test is then used to ascertain whether or not the permission
+ * was appropriately gained or lost.
+ *
+ * @param permDefApk - apk to install which defines the sig-permissoin
+ * @param permUseApk - apk to install which declares it uses the permission
+ * @param upgradeApk - apk to install which upgrades one of the first two
+ * @param hasPermBeforeUpgrade - whether we expect the consuming app to have
+ * the permission before the upgrade takes place.
+ * @param hasPermAfterUpgrade - whether we expect the consuming app to have
+ * the permission after the upgrade takes place.
+ */
+ private void testKeyRotationPerm(String permDefApk, String permUseApk,
+ String upgradeApk, boolean hasPermBeforeUpgrade,
+ boolean hasPermAfterUpgrade) throws Exception {
+ try {
+
+ /* cleanup test apps that might be installed from previous partial test run */
+ mDevice.uninstallPackage(KEYSET_PKG);
+ mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
+ mDevice.uninstallPackage(KEYSET_TEST_PKG);
+
+ /* install PERM_DEF, KEYSET_APP and KEYSET_TEST_APP */
+ String installResult = mDevice.installPackage(
+ getTestAppFile(permDefApk), false);
+ assertNull(String.format("failed to install keyset perm-def app, Reason: %s",
+ installResult), installResult);
+ installResult = getDevice().installPackage(
+ getTestAppFile(permUseApk), false);
+ assertNull(String.format("failed to install keyset test app. Reason: %s",
+ installResult), installResult);
+ installResult = getDevice().installPackage(
+ getTestAppFile(KEYSET_TEST_APP_APK), false);
+ assertNull(String.format("failed to install keyset test app. Reason: %s",
+ installResult), installResult);
+
+ /* verify package does have perm */
+ TestRunResult result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
+ "testHasPerm");
+ if (hasPermBeforeUpgrade) {
+ assertDeviceTestsPass(result);
+ } else {
+ assertDeviceTestsFail(" has permission permission it should not have.", result);
+ }
+
+ /* rotate keys */
+ installResult = mDevice.installPackage(getTestAppFile(upgradeApk),
+ true);
+ result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
+ "testHasPerm");
+ if (hasPermAfterUpgrade) {
+ assertDeviceTestsPass(result);
+ } else {
+ assertDeviceTestsFail(KEYSET_PKG + " has permission it should not have.", result);
+ }
+ } finally {
+ mDevice.uninstallPackage(KEYSET_PKG);
+ mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
+ mDevice.uninstallPackage(KEYSET_TEST_PKG);
+ }
+ }
+
+ /*
+ * Check if an apk gains signature-level permission after changing to a new
+ * signature, for which a permission should be granted.
+ */
+ public void testUpgradeSigPermGained() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_USE_A_SIGNED,
+ false, true);
+ }
+
+ /*
+ * Check if an apk loses signature-level permission after changing to a new
+ * signature, from one for which a permission was previously granted.
+ */
+ public void testUpgradeSigPermLost() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_USE_B_SIGNED,
+ true, false);
+ }
+
+ /*
+ * Check if an apk gains signature-level permission after the app defining
+ * it rotates to the same signature.
+ */
+ public void testUpgradeDefinerSigPermGained() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_DEF_B_SIGNED,
+ false, true);
+ }
+
+ /*
+ * Check if an apk loses signature-level permission after the app defining
+ * it rotates to a different signature.
+ */
+ public void testUpgradeDefinerSigPermLost() throws Exception {
+ testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_DEF_B_SIGNED,
+ true, false);
+ }
+}
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
index c6aa56b..264c0b1 100644
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
@@ -60,6 +60,9 @@
private static final String APK_DIFF_VERSION_v7 = "CtsSplitAppDiffVersion_v7.apk";
private static final String APK_DIFF_CERT_v7 = "CtsSplitAppDiffCert_v7.apk";
+ private static final String APK_FEATURE = "CtsSplitAppFeature.apk";
+ private static final String APK_FEATURE_v7 = "CtsSplitAppFeature_v7.apk";
+
private static final HashMap<String, String> ABI_TO_APK = new HashMap<>();
static {
@@ -231,8 +234,14 @@
new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
}
- public void testInheritNewSplit() throws Exception {
- // TODO: flesh out this test
+ public void testFeatureBase() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_FEATURE).run();
+ runDeviceTests(PKG, ".SplitAppTest", "testFeatureBase");
+ }
+
+ public void testFeatureApi() throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_FEATURE).addApk(APK_FEATURE_v7).run();
+ runDeviceTests(PKG, ".SplitAppTest", "testFeatureApi");
}
public void testInheritUpdatedBase() throws Exception {
@@ -243,10 +252,6 @@
// TODO: flesh out this test
}
- public void testSplitOrdering() throws Exception {
- // TODO: flesh out this test
- }
-
class InstallMultiple {
private List<String> mArgs = new ArrayList<>();
private List<File> mApks = new ArrayList<>();
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
index fc24aee..bc3acaf 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
@@ -22,7 +22,7 @@
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CtsSplitApp
LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4 v7 fr de
@@ -47,7 +47,7 @@
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CtsSplitAppDiffVersion
LOCAL_PACKAGE_SPLITS := v7
@@ -70,7 +70,7 @@
LOCAL_SDK_VERSION := current
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CtsSplitAppDiffCert
LOCAL_PACKAGE_SPLITS := v7
@@ -85,5 +85,5 @@
ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call all-makefiles-under,$(LOCAL_PATH)/libs)
+include $(LOCAL_PATH)/libs/Android.mk $(LOCAL_PATH)/feature/Android.mk
endif
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
new file mode 100644
index 0000000..9965f60
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
@@ -0,0 +1,38 @@
+#
+# 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_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := CtsSplitAppFeature
+LOCAL_PACKAGE_SPLITS := v7
+
+LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundred --replace-version -c mdpi
+
+LOCAL_MODULE_TAGS := tests
+
+featureOf := CtsSplitApp
+featureOfApk := $(call intermediates-dir-for,APPS,$(featureOf))/package.apk
+localRStamp := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)/src/R.stamp
+$(localRStamp): $(featureOfApk)
+
+LOCAL_AAPT_FLAGS += --feature-of $(featureOfApk)
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/feature/AndroidManifest.xml
new file mode 100644
index 0000000..8ba3c2f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?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.splitapp"
+ featureName="feature">
+
+ <!-- New permission should be ignored -->
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <!-- New application flag should be ignored -->
+ <application android:largeHeap="true">
+ <activity android:name=".FeatureActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <meta-data android:name="android.service.wallpaper" android:resource="@xml/my_activity_meta" />
+ </activity>
+ <receiver android:name=".FeatureReceiver"
+ android:enabled="@bool/feature_receiver_enabled">
+ <intent-filter>
+ <action android:name="android.intent.action.DATE_CHANGED" />
+ </intent-filter>
+ </receiver>
+ <service android:name=".FeatureService">
+ <intent-filter>
+ <action android:name="com.android.cts.splitapp.service" />
+ </intent-filter>
+ </service>
+ <provider android:name=".FeatureProvider" android:authorities="com.android.cts.splitapp.provider" />
+ </application>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/dir/dirfile2.txt b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/dir/dirfile2.txt
new file mode 100644
index 0000000..c4a2fff
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/dir/dirfile2.txt
@@ -0,0 +1 @@
+DIRFILE2
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/file2.txt b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/file2.txt
new file mode 100644
index 0000000..d77231c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/file2.txt
@@ -0,0 +1 @@
+FILE2
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values-v7/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values-v7/values.xml
new file mode 100644
index 0000000..8d91234
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values-v7/values.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<resources>
+ <bool name="feature_receiver_enabled">false</bool>
+ <integer name="feature_integer">321</integer>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values/values.xml
new file mode 100644
index 0000000..7d670cf
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values/values.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<resources>
+ <bool name="feature_receiver_enabled">true</bool>
+ <string name="feature_string">red</string>
+ <integer name="feature_integer">123</integer>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureActivity.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureActivity.java
new file mode 100644
index 0000000..a4df004
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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.splitapp;
+
+import android.app.Activity;
+
+public class FeatureActivity extends Activity {
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureLogic.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureLogic.java
new file mode 100644
index 0000000..0481546
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureLogic.java
@@ -0,0 +1,28 @@
+/*
+ * 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.splitapp;
+
+import android.util.Log;
+
+public class FeatureLogic {
+ private static final String TAG = "FeatureLogic";
+
+ public static int mult(int a, int b) {
+ Log.d(TAG, "FeatureLogic.mult(" + a + ", " + b + ")");
+ return a * b;
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureProvider.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureProvider.java
new file mode 100644
index 0000000..087aeb7
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureProvider.java
@@ -0,0 +1,85 @@
+/*
+ * 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.splitapp;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+
+public class FeatureProvider extends ContentProvider {
+ private static final String TAG = "FeatureProvider";
+
+ public static boolean sCreated = false;
+
+ @Override
+ public boolean onCreate() {
+ Log.d(TAG, "FeatureProvider.onCreate()");
+
+ sCreated = true;
+
+ try {
+ // Just reach out and touch
+ final Class<?> test = Class.forName("com.android.cts.splitapp.SplitAppTest");
+ final Field touched = test.getDeclaredField("sFeatureTouched");
+ touched.set(null, true);
+
+ // Also make sure we can read a resource from the base; we just
+ // stash the value we saw over on the test for them to verify.
+ final Class<?> baseR = Class.forName("com.android.cts.splitapp.BaseR");
+ final int stringId = (int) baseR.getDeclaredField("my_string1").get(null);
+ final Field value = test.getDeclaredField("sFeatureValue");
+ value.set(null, getContext().getResources().getString(stringId));
+
+ } catch (Throwable t) {
+ // We're okay if anything above fails, since the test later verifies
+ // that we actually touched the boolean.
+ Log.e(TAG, "Failed to communicate back to base", t);
+ }
+
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureR.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureR.java
new file mode 100644
index 0000000..3dbd83b
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureR.java
@@ -0,0 +1,23 @@
+/*
+ * 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.splitapp;
+
+public class FeatureR {
+ public static final int feature_receiver_enabled = R.bool.feature_receiver_enabled;
+ public static final int feature_integer = R.integer.feature_integer;
+ public static final int feature_string = R.string.feature_string;
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureReceiver.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureReceiver.java
new file mode 100644
index 0000000..49559f3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureReceiver.java
@@ -0,0 +1,28 @@
+/*
+ * 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.splitapp;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class FeatureReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Ignored
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureService.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureService.java
new file mode 100644
index 0000000..b07297f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureService.java
@@ -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.
+ */
+
+package com.android.cts.splitapp;
+
+import android.app.IntentService;
+import android.content.Intent;
+
+public class FeatureService extends IntentService {
+ public FeatureService() {
+ super("Feature1Service");
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ // Ignored
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseR.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseR.java
new file mode 100644
index 0000000..ecf6975
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseR.java
@@ -0,0 +1,21 @@
+/*
+ * 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.splitapp;
+
+public class BaseR {
+ public static final int my_string1 = R.string.my_string1;
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
index 9eb17cd..277a1a2 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
@@ -20,7 +20,9 @@
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -37,11 +39,17 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.List;
import java.util.Locale;
public class SplitAppTest extends AndroidTestCase {
private static final String TAG = "SplitAppTest";
+ private static final String PKG = "com.android.cts.splitapp";
+
+ public static boolean sFeatureTouched = false;
+ public static String sFeatureValue = null;
public void testSingleBase() throws Exception {
final Resources r = getContext().getResources();
@@ -78,7 +86,7 @@
// Should only have base manifest items
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
- intent.setPackage("com.android.cts.splitapp");
+ intent.setPackage(PKG);
List<ResolveInfo> result = pm.queryIntentActivities(intent, 0);
assertEquals(1, result.size());
@@ -86,7 +94,7 @@
// Receiver disabled by default in base
intent = new Intent(Intent.ACTION_DATE_CHANGED);
- intent.setPackage("com.android.cts.splitapp");
+ intent.setPackage(PKG);
result = pm.queryBroadcastReceivers(intent, 0);
assertEquals(0, result.size());
@@ -157,7 +165,7 @@
// Receiver should be enabled now
Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
- intent.setPackage("com.android.cts.splitapp");
+ intent.setPackage(PKG);
List<ResolveInfo> result = pm.queryBroadcastReceivers(intent, 0);
assertEquals(1, result.size());
@@ -187,6 +195,121 @@
assertEquals(11642, Native.add(4933, 6709));
}
+ public void testFeatureBase() throws Exception {
+ final Resources r = getContext().getResources();
+ final PackageManager pm = getContext().getPackageManager();
+
+ // Should have untouched resources from base
+ assertEquals(false, r.getBoolean(R.bool.my_receiver_enabled));
+
+ assertEquals("blue", r.getString(R.string.my_string1));
+ assertEquals("purple", r.getString(R.string.my_string2));
+
+ assertEquals(0xff00ff00, r.getColor(R.color.my_color));
+ assertEquals(123, r.getInteger(R.integer.my_integer));
+
+ assertEquals("base", getXmlTestValue(r.getXml(R.xml.my_activity_meta)));
+
+ // And that we can access resources from feature
+ // TODO: enable these once 17924027 is fixed
+// assertEquals("red", r.getString(r.getIdentifier("feature_string", "string", PKG)));
+// assertEquals(123, r.getInteger(r.getIdentifier("feature_integer", "integer", PKG)));
+
+ final Class<?> featR = Class.forName("com.android.cts.splitapp.FeatureR");
+ final int boolId = (int) featR.getDeclaredField("feature_receiver_enabled").get(null);
+ final int intId = (int) featR.getDeclaredField("feature_integer").get(null);
+ final int stringId = (int) featR.getDeclaredField("feature_string").get(null);
+ assertEquals(true, r.getBoolean(boolId));
+ assertEquals(123, r.getInteger(intId));
+ assertEquals("red", r.getString(stringId));
+
+ // Should have both base and feature assets
+ assertAssetContents(r, "file1.txt", "FILE1");
+ assertAssetContents(r, "file2.txt", "FILE2");
+ assertAssetContents(r, "dir/dirfile1.txt", "DIRFILE1");
+ assertAssetContents(r, "dir/dirfile2.txt", "DIRFILE2");
+
+ // Should have both base and feature components
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setPackage(PKG);
+ List<ResolveInfo> result = pm.queryIntentActivities(intent, 0);
+ assertEquals(2, result.size());
+ assertEquals("com.android.cts.splitapp.MyActivity", result.get(0).activityInfo.name);
+ assertEquals("com.android.cts.splitapp.FeatureActivity", result.get(1).activityInfo.name);
+
+ // Receiver only enabled in feature
+ intent = new Intent(Intent.ACTION_DATE_CHANGED);
+ intent.setPackage(PKG);
+ result = pm.queryBroadcastReceivers(intent, 0);
+ assertEquals(1, result.size());
+ assertEquals("com.android.cts.splitapp.FeatureReceiver", result.get(0).activityInfo.name);
+
+ // And we should have a service
+ intent = new Intent("com.android.cts.splitapp.service");
+ intent.setPackage(PKG);
+ result = pm.queryIntentServices(intent, 0);
+ assertEquals(1, result.size());
+ assertEquals("com.android.cts.splitapp.FeatureService", result.get(0).serviceInfo.name);
+
+ // And a provider too
+ ProviderInfo info = pm.resolveContentProvider("com.android.cts.splitapp.provider", 0);
+ assertEquals("com.android.cts.splitapp.FeatureProvider", info.name);
+
+ // And assert that we spun up the provider in this process
+ final Class<?> provider = Class.forName("com.android.cts.splitapp.FeatureProvider");
+ final Field field = provider.getDeclaredField("sCreated");
+ assertTrue("Expected provider to have been created", (boolean) field.get(null));
+ assertTrue("Expected provider to have touched us", sFeatureTouched);
+ assertEquals(r.getString(R.string.my_string1), sFeatureValue);
+
+ // Finally ensure that we can execute some code from split
+ final Class<?> logic = Class.forName("com.android.cts.splitapp.FeatureLogic");
+ final Method method = logic.getDeclaredMethod("mult", new Class[] {
+ Integer.TYPE, Integer.TYPE });
+ assertEquals(72, (int) method.invoke(null, 12, 6));
+
+ // Make sure we didn't get an extra flag from feature split
+ assertTrue("Someone parsed application flag!",
+ (getContext().getApplicationInfo().flags & ApplicationInfo.FLAG_LARGE_HEAP) == 0);
+
+ // Make sure we have permission from base APK
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.CAMERA, null);
+
+ try {
+ // But no new permissions from the feature APK
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, null);
+ fail("Whaaa, we somehow gained permission from feature?");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ public void testFeatureApi() throws Exception {
+ final Resources r = getContext().getResources();
+ final PackageManager pm = getContext().getPackageManager();
+
+ // Should have untouched resources from base
+ assertEquals(false, r.getBoolean(R.bool.my_receiver_enabled));
+
+ // And that we can access resources from feature
+ // TODO: enable these once 17924027 is fixed
+// assertEquals(321, r.getInteger(r.getIdentifier("feature_integer", "integer", PKG)));
+
+ final Class<?> featR = Class.forName("com.android.cts.splitapp.FeatureR");
+ final int boolId = (int) featR.getDeclaredField("feature_receiver_enabled").get(null);
+ final int intId = (int) featR.getDeclaredField("feature_integer").get(null);
+ final int stringId = (int) featR.getDeclaredField("feature_string").get(null);
+ assertEquals(false, r.getBoolean(boolId));
+ assertEquals(321, r.getInteger(intId));
+ assertEquals("red", r.getString(stringId));
+
+ // And now both receivers should be disabled
+ Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
+ intent.setPackage(PKG);
+ List<ResolveInfo> result = pm.queryBroadcastReceivers(intent, 0);
+ assertEquals(0, result.size());
+ }
+
private static void updateDpi(Resources r, int densityDpi) {
final Configuration c = new Configuration(r.getConfiguration());
c.densityDpi = densityDpi;
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk
new file mode 100644
index 0000000..eb71540
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk
@@ -0,0 +1,41 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermDefSigningA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermDefSigningB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/permDef/AndroidManifest.xml
new file mode 100644
index 0000000..7b84f6a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.keysets_permdef">
+ <application android:hasCode="false">
+ </application>
+ <permission android:description="@string/keysets_perm_desc"
+ android:label="@string/keysets_perm_label"
+ android:name="com.android.cts.keysets_permdef.keysets_perm"
+ android:protectionLevel="signature" />
+ <key-sets>
+ <key-set android:name="A" >
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ </key-set>
+ <key-set android:name="B" >
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="A"/>
+ <upgrade-key-set android:name="B"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/keysets/permDef/res/values/strings.xml
new file mode 100644
index 0000000..4e5e870
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keysets_perm_desc">keysets_perm_description</string>
+ <string name="keysets_perm_label">keysets_perm_label</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk
new file mode 100644
index 0000000..000b12a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk
@@ -0,0 +1,41 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermUseSigningA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermUseSigningB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/permUse/AndroidManifest.xml
new file mode 100644
index 0000000..40ca1cb
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.keysets">
+ <application android:hasCode="false">
+ </application>
+ <uses-permission android:name="com.android.cts.keysets_permdef.keysets_perm" />
+ <key-sets>
+ <key-set android:name="A">
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ </key-set>
+ <key-set android:name="B">
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="A"/>
+ <upgrade-key-set android:name="B"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/keysets/permUse/res/values/strings.xml
new file mode 100644
index 0000000..4e5e870
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="keysets_perm_desc">keysets_perm_description</string>
+ <string name="keysets_perm_label">keysets_perm_label</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk
new file mode 100644
index 0000000..ed6db69
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk
@@ -0,0 +1,26 @@
+# 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_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetTestApp
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/testApp/AndroidManifest.xml
new file mode 100644
index 0000000..38edf5f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?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.keysets.testapp">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:targetPackage="com.android.cts.keysets.testapp"
+ android:name="android.support.test.runner.AndroidJUnitRunner" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/src/com/android/cts/keysets/KeySetPermissionsTest.java b/hostsidetests/appsecurity/test-apps/keysets/testApp/src/com/android/cts/keysets/KeySetPermissionsTest.java
new file mode 100644
index 0000000..467a212
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/src/com/android/cts/keysets/KeySetPermissionsTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.keysets;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.util.Log;
+import android.test.AndroidTestCase;
+
+import java.lang.Override;
+
+/**
+ * KeySets device-side tests involving permissions
+ */
+public class KeySetPermissionsTest extends AndroidTestCase {
+
+ private static final String KEYSET_APP_PKG = "com.android.cts.keysets";
+ private static final String KEYSET_PERM_DEF_PKG = "com.android.cts.keysets_permdef";
+ private static final String KEYSET_PERM_NAME = "com.android.cts.keysets_permdef.keysets_perm";
+
+ public void testHasPerm() throws Exception {
+ PackageManager pm = getContext().getPackageManager();
+ assertTrue(KEYSET_PERM_NAME + " not granted to " + KEYSET_APP_PKG,
+ pm.checkPermission(KEYSET_PERM_NAME, KEYSET_APP_PKG) == PackageManager.PERMISSION_GRANTED);
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk
new file mode 100644
index 0000000..6220790
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk
@@ -0,0 +1,53 @@
+# 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)
+
+#apks signed by cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed by cts-keyset-test-b
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningBUpgradeA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed by cts-keyset-test-a and cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAAndBUpgradeA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_ADDITIONAL_CERTIFICATES := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uA/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uA/AndroidManifest.xml
new file mode 100644
index 0000000..8813c37
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uA/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.keysets">
+ <application android:hasCode="false">
+ </application>
+ <key-sets>
+ <key-set android:name="A" >
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="A"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk
new file mode 100644
index 0000000..534dba3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk
@@ -0,0 +1,28 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeAAndB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAB/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uAB/AndroidManifest.xml
new file mode 100644
index 0000000..65f78e3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAB/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.keysets">
+ <application android:hasCode="false">
+ </application>
+ <key-sets>
+ <key-set android:name="AB" >
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="AB"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk
new file mode 100644
index 0000000..75729e0
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk
@@ -0,0 +1,28 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeAOrB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAuB/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uAuB/AndroidManifest.xml
new file mode 100644
index 0000000..546c5fe
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAuB/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.keysets">
+ <application android:hasCode="false">
+ </application>
+ <key-sets>
+ <key-set android:name="A" >
+ <public-key android:name="keyA"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+ </key-set>
+ <key-set android:name="B" >
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="A"/>
+ <upgrade-key-set android:name="B"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk
new file mode 100644
index 0000000..121c342
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk
@@ -0,0 +1,55 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningBUpgradeB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed by cts-keyset-test-a and cts-keyset-test-c
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAAndCUpgradeB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_ADDITIONAL_CERTIFICATES := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uB/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uB/AndroidManifest.xml
new file mode 100644
index 0000000..9c837bc
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uB/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.keysets">
+ <application android:hasCode="false">
+ </application>
+ <key-sets>
+ <key-set android:name="B" >
+ <public-key android:name="keyB"
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+ </key-set>
+ <upgrade-key-set android:name="B"/>
+ </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk
new file mode 100644
index 0000000..a8746ec
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk
@@ -0,0 +1,28 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeNone
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uNone/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uNone/AndroidManifest.xml
new file mode 100644
index 0000000..55304f4
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uNone/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.keysets">
+ <application android:hasCode="false">
+ </application>
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml b/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
index ab01ffb..e1f6886 100644
--- a/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
@@ -19,11 +19,14 @@
<uses-sdk android:minSdkVersion="19"/>
+ <uses-permission android:name="com.android.cts.managedprofile.permission.SAMPLE"/>
+
<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" />
+ <action android:name="com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
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
index 2389402..17dc3f1 100644
--- 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
@@ -40,24 +40,48 @@
private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+ private static final String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+ "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+ private static final String EXTRA_CAUGHT_SECURITY_EXCEPTION = "extra_caught_security_exception";
+
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent received = getIntent();
String action = received.getAction();
-
+ Uri uri = getIntent().getClipData().getItemAt(0).getUri();
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);
+ String message = null;
+ try {
+ message = getFirstLineFromUri(uri);
+ } catch (SecurityException e) {
+ Log.i(TAG, "Caught a SecurityException while trying to read " + uri, e);
+ result.putExtra(EXTRA_CAUGHT_SECURITY_EXCEPTION, true);
+ } catch (IOException e) {
+ Log.i(TAG, "Caught a IOException while trying to read " + uri, e);
+ }
+ Log.i(TAG, "Message received in reading test: " + message);
result.putExtra("extra_response", message);
- setResult(message != null ? Activity.RESULT_OK : Activity.RESULT_CANCELED, result);
+ setResult(Activity.RESULT_OK, 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);
+ Log.i(TAG, "Message received in writing test: " + message);
+ try {
+ writeToUri(uri, message);
+ } catch (SecurityException e) {
+ Log.i(TAG, "Caught a SecurityException while trying to write to " + uri, e);
+ result.putExtra(EXTRA_CAUGHT_SECURITY_EXCEPTION, true);
+ } catch (IOException e) {
+ Log.i(TAG, "Caught a IOException while trying to write to " + uri, e);
+ }
+ setResult(Activity.RESULT_OK, result);
+ } else if (ACTION_TAKE_PERSISTABLE_URI_PERMISSION.equals(action)) {
+ Log.i(TAG, "Taking persistable uri permission to " + uri);
+ getContentResolver().takePersistableUriPermission(uri,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ setResult(Activity.RESULT_OK);
}
finish();
}
@@ -65,28 +89,17 @@
/**
* 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 String getFirstLineFromUri(Uri uri) throws IOException {
+ InputStream is = getContentResolver().openInputStream(uri);
+ BufferedReader r = new BufferedReader(new InputStreamReader(is));
+ return r.readLine();
}
- 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;
- }
+ private void writeToUri(Uri uri, String text) throws IOException {
+ OutputStreamWriter writer = new OutputStreamWriter(
+ getContentResolver().openOutputStream(uri));
+ writer.write(text);
+ writer.flush();
+ writer.close();
}
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 643400b..56b3671 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -19,6 +19,9 @@
<uses-sdk android:minSdkVersion="20"/>
+ <permission android:name="com.android.cts.managedprofile.permission.SAMPLE"
+ android:label="Sample Permission"/>
+
<application>
<uses-library android:name="android.test.runner" />
<receiver
@@ -67,6 +70,13 @@
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
+ <activity android:name=".UserRestrictionActivity" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".TestActivity" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.android.cts.managedprofile.fileprovider"
@@ -76,7 +86,13 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
- <activity android:name=".TestActivity" />
+ <provider
+ android:name="com.android.cts.managedprofile.crossprofilecontent.BasicContentProvider"
+ android:authorities="com.android.cts.managedprofile.basiccontentProvider"
+ android:grantUriPermissions="true"
+ android:exported="true"
+ android:permission="com.android.cts.managedprofile.permission.SAMPLE"
+ />
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/UserRestrictionActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/UserRestrictionActivity.java
new file mode 100644
index 0000000..e8decf8
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/UserRestrictionActivity.java
@@ -0,0 +1,83 @@
+/*
+ * 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.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.Log;
+
+import com.android.cts.managedprofile.BaseManagedProfileTest;
+
+/**
+ * Simple activity that adds or clears a user restriction depending on the value of the extras.
+ */
+public class UserRestrictionActivity extends Activity {
+
+ private static final String TAG = UserRestrictionActivity.class.getName();
+
+ private static final String EXTRA_RESTRICTION_KEY = "extra-restriction-key";
+ private static final String EXTRA_COMMAND = "extra-command";
+
+ private static final String ADD_COMMAND = "add-restriction";
+ private static final String CLEAR_COMMAND = "clear-restriction";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ handleIntent(getIntent());
+ }
+
+ // Overriding this method in case another intent is sent to this activity before finish()
+ @Override
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ handleIntent(intent);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // Calling finish() here because doing it in onCreate(), onStart() or onResume() makes
+ // "adb shell am start" timeout if using the -W option.
+ finish();
+ }
+
+ private void handleIntent(Intent intent) {
+ DevicePolicyManager dpm = (DevicePolicyManager)
+ getSystemService(Context.DEVICE_POLICY_SERVICE);
+ String restrictionKey = intent.getStringExtra(EXTRA_RESTRICTION_KEY);
+ String command = intent.getStringExtra(EXTRA_COMMAND);
+ Log.i(TAG, "Command: \"" + command + "\". Restriction: \"" + restrictionKey + "\"");
+
+ if (ADD_COMMAND.equals(command)) {
+ dpm.addUserRestriction(BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
+ Log.i(TAG, "Added user restriction " + restrictionKey
+ + " for user " + Process.myUserHandle());
+ } else if (CLEAR_COMMAND.equals(command)) {
+ dpm.clearUserRestriction(
+ BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
+ Log.i(TAG, "Cleared user restriction " + restrictionKey
+ + " for user " + Process.myUserHandle());
+ } else {
+ Log.e(TAG, "Invalid command: " + command);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
new file mode 100644
index 0000000..f91d404
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
@@ -0,0 +1,72 @@
+/*
+ * 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.managedprofile.crossprofilecontent;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Empty content provider, all permissions are enforced in manifest
+ */
+public class BasicContentProvider extends ContentProvider {
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ // do nothing
+ return 0;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return "";
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public boolean onCreate() {
+ return false;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection,
+ String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ return ParcelFileDescriptor.open(
+ new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+ }
+}
+
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
index aa9506b..85e7d1b 100644
--- 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
@@ -18,33 +18,194 @@
import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
import android.app.admin.DevicePolicyManager;
+import android.content.ClipData;
+import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.support.v4.content.FileProvider;
import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
public class CrossProfileContentTest extends
ActivityInstrumentationTestCase2<IntentSenderActivity> {
private static final String MESSAGE = "Sample Message";
+ 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 String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+ "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+ private static final String TAG = "CrossProfileContentTest";
+
+ private static final String BASIC_CONTENT_PROVIDER_AUTHORITY =
+ "com.android.cts.managedprofile.basiccontentProvider";
+
+
+ private DevicePolicyManager mDpm;
+
+ private Context mContext;
+
public CrossProfileContentTest() {
super(IntentSenderActivity.class);
}
@Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getInstrumentation().getTargetContext();
+ mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_READ_FROM_URI);
+ intentFilter.addAction(ACTION_WRITE_TO_URI);
+ intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+ mDpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+ DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+ }
+
+ @Override
protected void tearDown() throws Exception {
- DevicePolicyManager dpm = (DevicePolicyManager)
- getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
- dpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+ mDpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
super.tearDown();
}
+ /**
+ * 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 a message.
+ * The receiver will read the message from the uri, and put it inside the result intent.
+ */
public void testReceiverCanRead() {
- String response = getActivity().testReceiverCanRead(MESSAGE);
- assertEquals(response, MESSAGE);
+ Uri uri = getUriWithTextInFile("reading_test", MESSAGE);
+ assertTrue(uri != null);
+ Intent intent = new Intent(ACTION_READ_FROM_URI);
+ intent.setClipData(ClipData.newRawUri("", uri));
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ Intent result = getActivity().getResultForIntent(intent);
+ assertTrue(result != null);
+ assertEquals(MESSAGE, result.getStringExtra("extra_response"));
}
+ /**
+ * 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.
+ */
public void testReceiverCanWrite() {
- String response = getActivity().testReceiverCanWrite(MESSAGE);
- assertEquals(response, MESSAGE);
+ // It's the receiver of the intent that should write to the uri, not us. So, for now, we
+ // write an empty string.
+ Uri uri = getUriWithTextInFile("writing_test", "");
+ assertTrue(uri != null);
+ Intent intent = new Intent(ACTION_WRITE_TO_URI);
+ intent.setClipData(ClipData.newRawUri("", uri));
+ intent.putExtra("extra_message", MESSAGE);
+ intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ getActivity().getResultForIntent(intent);
+ assertEquals(MESSAGE, getFirstLineFromUri(uri));
+ }
+
+ public void testPersistablePermission() {
+ Uri uri = getUriWithTextInFile("persistable_test", MESSAGE);
+ grantPersistableReadPermission(uri);
+
+ // Now checking if the receiver can read this uri, without re-granting the read permission.
+ Intent intent = new Intent(ACTION_READ_FROM_URI);
+ intent.setClipData(ClipData.newRawUri("", uri));
+ Intent result = getActivity().getResultForIntent(intent);
+ assertTrue(result != null);
+ assertEquals(MESSAGE, result.getStringExtra("extra_response"));
+ }
+
+ /**
+ * The intent receiver will try to read uriNotGranted.
+ * Inside the same user, this uri can be read if the receiver has the
+ * com.android.cts.managedprofile.permission.SAMPLE permission. But since we cross
+ * user-boundaries, it should not be able to (only uri grants work accross users for apps
+ * without special permission).
+ * We also grant uriGranted to the receiver (this uri belongs to the same content provider as
+ * uriNotGranted), to enforce that even if an app has permission to one uri of a
+ * ContentProvider, it still cannot access a uri it does not have access to.
+ */
+ public void testAppPermissionsDontWorkAcrossProfiles() {
+ // The FileProvider does not allow to use app permissions. So we need to use another
+ // ContentProvider.
+ Uri uriGranted = getBasicContentProviderUri("uri_granted");
+ Uri uriNotGranted = getBasicContentProviderUri("uri_not_granted");
+
+ // Granting uriGranted to the receiver
+ // Using a persistable permission so that it is kept even after we restart the receiver
+ // activity with another intent.
+ grantPersistableReadPermission(uriGranted);
+
+ Intent notGrant = new Intent(ACTION_READ_FROM_URI);
+ notGrant.setClipData(ClipData.newRawUri("", uriNotGranted));
+
+ Intent result = getActivity().getResultForIntent(notGrant);
+ assertTrue(result != null);
+ // The receiver did not have permission to read the uri. So it should have caught a security
+ // exception.
+ assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
+ }
+
+ private void grantPersistableReadPermission(Uri uri) {
+ Intent grantPersistable = new Intent(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+ grantPersistable.setClipData(ClipData.newRawUri("", uri));
+ grantPersistable.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+ getActivity().getResultForIntent(grantPersistable);
+ }
+
+ private Uri getBasicContentProviderUri(String path) {
+ // The uris created here are not associated with any data. But this does not prevent us from
+ // granting these uris to other apps, or these apps from trying to access these uris.
+ return new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(BASIC_CONTENT_PROVIDER_AUTHORITY)
+ .path(path)
+ .build();
+ }
+
+ private Uri getUriWithTextInFile(String name, String text) {
+ String filename = mContext.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(mContext, "com.android.cts.managedprofile.fileprovider",
+ file);
+ }
+
+ /**
+ * Returns the first line of the file associated with uri.
+ */
+ private String getFirstLineFromUri(Uri uri) {
+ try {
+ InputStream is = mContext.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/crossprofilecontent/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
index 6c8020f..e4c8ddf 100644
--- 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
@@ -17,152 +17,36 @@
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 CountDownLatch mLatch;
private static final int WAIT_FOR_RESPONSE_TIMEOUT_SECONDS = 5;
- private String mResponse;
+ private Intent mResult;
- 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);
+ Intent getResultForIntent(Intent intent) {
+ mLatch = new CountDownLatch(1);
+ mResult = null;
+ startActivityForResult(intent, 0);
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;
+ return mResult;
}
@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);
- }
+ protected void onActivityResult(int requestCode, int resultCode, Intent result) {
+ if (resultCode == Activity.RESULT_OK) {
+ mResult = result;
}
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/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 4e57b28..88a3b70 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -124,16 +124,55 @@
}
}
+ // TODO: This test is not specific to managed profiles, but applies to multi-user in general.
+ // Move it to a MultiUserTest class when there is one. Should probably move
+ // UserRestrictionActivity to a more generic apk too as it might be useful for different kinds
+ // of tests (same applies to ComponentDisablingActivity).
+ public void testNoDebuggingFeaturesRestriction() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ String restriction = "no_debugging_features"; // UserManager.DISALLOW_DEBUGGING_FEATURES
+ String command = "add-restriction";
+
+ String addRestrictionCommandOutput =
+ changeUserRestrictionForUser(restriction, command, mUserId);
+ assertTrue("Command was expected to succeed " + addRestrictionCommandOutput,
+ addRestrictionCommandOutput.contains("Status: ok"));
+
+ // This should now fail, as the shell is not available to start activities under a different
+ // user once the restriction is in place.
+ addRestrictionCommandOutput =
+ changeUserRestrictionForUser(restriction, command, mUserId);
+ assertTrue(
+ "Expected SecurityException when starting the activity "
+ + addRestrictionCommandOutput,
+ addRestrictionCommandOutput.contains("SecurityException"));
+ }
+
private void disableActivityForUser(String activityName, int userId)
throws DeviceNotAvailableException {
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 ";
+ + " --es extra-class-name " + MANAGED_PROFILE_PKG + "." + activityName
+ + " " + MANAGED_PROFILE_PKG + "/.ComponentDisablingActivity ";
CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
+ getDevice().executeShellCommand(command));
}
+ private String changeUserRestrictionForUser(String key, String command, int userId)
+ throws DeviceNotAvailableException {
+ String adbCommand = "am start -W --user " + userId
+ + " -c android.intent.category.DEFAULT "
+ + " --es extra-command " + command
+ + " --es extra-restriction-key " + key
+ + " " + MANAGED_PROFILE_PKG + "/.UserRestrictionActivity";
+ String commandOutput = getDevice().executeShellCommand(adbCommand);
+ CLog.logAndDisplay(LogLevel.INFO,
+ "Output for command " + adbCommand + ": " + commandOutput);
+ return commandOutput;
+ }
+
private int createManagedProfile() throws DeviceNotAvailableException {
String command =
"pm create-user --profileOf 0 --managed TestProfile_" + System.currentTimeMillis();
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index b4c9ebb..40a66d2 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -91,19 +91,6 @@
bug: 17496766
},
{
- description: "As per new CTS test case adding policy",
- names: [
- "com.android.cts.managedprofile.PrimaryUserTest#testAddCrossProfileIntentFilter_primary",
- "com.android.cts.managedprofile.PrimaryUserTest#testAddCrossProfileIntentFilter_all",
- "com.android.cts.managedprofile.PrimaryUserTest#testAddCrossProfileIntentFilter_managed",
- "com.android.cts.managedprofile.ManagedProfile#testClearCrossProfileIntentFilters",
- "com.android.cts.managedprofile.ManagedProfile#testAddCrossProfileIntentFilter_primary",
- "com.android.cts.managedprofile.ManagedProfile#testAddCrossProfileIntentFilter_all",
- "com.android.cts.managedprofile.ManagedProfile#testAddCrossProfileIntentFilter_managed"
- ],
- bug: 15900074
-},
-{
description: "these tests locks the screen with an emtpy password or swipe-to-unlock, blocking subsequent test to dismiss keyguard",
names: [
"com.android.cts.devicepolicy.DeviceOwnerTest#testKeyManagement"
@@ -128,7 +115,8 @@
"com.android.cts.devicepolicy.ManagedProfileTest#testManagedProfileSetup",
"com.android.cts.devicepolicy.ManagedProfileTest#testWipeData",
"com.android.cts.devicepolicy.ManagedProfileTest#testCrossProfileIntentFilters",
- "com.android.cts.devicepolicy.ManagedProfileTest#testCrossProfileContent"
+ "com.android.cts.devicepolicy.ManagedProfileTest#testCrossProfileContent",
+ "com.android.cts.devicepolicy.ManagedProfileTest#testNoDebuggingFeaturesRestriction"
]
},
{
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
index a68f78d..61f25fb 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -88,6 +88,10 @@
try {
Log.v(TAG, "Testing jpeg capture for Camera " + id);
openDevice(id);
+ if (mStaticInfo.isHardwareLevelLegacy()) {
+ Log.i(TAG, "Skipping test on legacy devices");
+ continue;
+ }
bufferFormatTestByCamera(ImageFormat.JPEG, /*repeating*/false);
} finally {
closeDevice(id);
@@ -113,6 +117,10 @@
try {
Log.v(TAG, "Testing repeating jpeg capture for Camera " + id);
openDevice(id);
+ if (mStaticInfo.isHardwareLevelLegacy()) {
+ Log.i(TAG, "Skipping test on legacy devices");
+ continue;
+ }
bufferFormatTestByCamera(ImageFormat.JPEG, /*repeating*/true);
} finally {
closeDevice(id);
@@ -148,7 +156,10 @@
try {
Log.v(TAG, "YUV and JPEG testing for camera " + id);
openDevice(id);
-
+ if (mStaticInfo.isHardwareLevelLegacy()) {
+ Log.i(TAG, "Skipping test on legacy devices");
+ continue;
+ }
bufferFormatWithYuvTestByCamera(ImageFormat.JPEG);
} finally {
closeDevice(id);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
index 7a6e088..ea15c19 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
@@ -497,6 +497,11 @@
openDevice(id);
+ if (mStaticInfo.isHardwareLevelLegacy()) {
+ Log.i(TAG, "Skipping test on legacy devices");
+ continue;
+ }
+
initSupportedVideoSize(id);
videoSnapshotTestByCamera(burstTest);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
index 11ba02c..7960200 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -185,6 +185,11 @@
final StaticMetadata staticInfo = new StaticMetadata(cc);
+ if (staticInfo.isHardwareLevelLegacy()) {
+ Log.i(TAG, "Skipping test on legacy devices");
+ continue;
+ }
+
openDevice(id);
// Always run legacy-level tests