blob: 1c633c3eaff8f8f045b476b4bd30988c821c322b [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.cts.deviceandprofileowner;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.PermissionChecker;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiWatcher;
import android.support.test.uiautomator.Until;
import android.test.suitebuilder.annotation.Suppress;
import android.util.Log;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* Test Runtime Permissions APIs in DevicePolicyManager.
*/
public class PermissionsTest extends BaseDeviceAdminTest {
private static final String TAG = "PermissionsTest";
private static final String PERMISSION_APP_PACKAGE_NAME
= "com.android.cts.permissionapp";
private static final String SIMPLE_PRE_M_APP_PACKAGE_NAME =
"com.android.cts.launcherapps.simplepremapp";
private static final String PERMISSION_NAME = "android.permission.READ_CONTACTS";
private static final String CUSTOM_PERM_A_NAME = "com.android.cts.permissionapp.permA";
private static final String CUSTOM_PERM_B_NAME = "com.android.cts.permissionapp.permB";
private static final String DEVELOPMENT_PERMISSION = "android.permission.INTERACT_ACROSS_USERS";
private static final String PERMISSIONS_ACTIVITY_NAME
= PERMISSION_APP_PACKAGE_NAME + ".PermissionActivity";
private static final String ACTION_CHECK_HAS_PERMISSION
= "com.android.cts.permission.action.CHECK_HAS_PERMISSION";
private static final String ACTION_REQUEST_PERMISSION
= "com.android.cts.permission.action.REQUEST_PERMISSION";
private static final String ACTION_PERMISSION_RESULT
= "com.android.cts.permission.action.PERMISSION_RESULT";
private static final String EXTRA_PERMISSION
= "com.android.cts.permission.extra.PERMISSION";
private static final String EXTRA_GRANT_STATE
= "com.android.cts.permission.extra.GRANT_STATE";
private static final int PERMISSION_ERROR = -2;
private static final BySelector CRASH_POPUP_BUTTON_SELECTOR = By
.clazz(android.widget.Button.class.getName())
.text("OK")
.pkg("android");
private static final BySelector CRASH_POPUP_TEXT_SELECTOR = By
.clazz(android.widget.TextView.class.getName())
.pkg("android");
private static final String CRASH_WATCHER_ID = "CRASH";
private PermissionBroadcastReceiver mReceiver;
private PackageManager mPackageManager;
private UiDevice mDevice;
@Override
protected void setUp() throws Exception {
super.setUp();
mReceiver = new PermissionBroadcastReceiver();
mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PERMISSION_RESULT));
mPackageManager = mContext.getPackageManager();
mDevice = UiDevice.getInstance(getInstrumentation());
}
@Override
protected void tearDown() throws Exception {
mContext.unregisterReceiver(mReceiver);
mDevice.removeWatcher(CRASH_WATCHER_ID);
super.tearDown();
}
public void testPermissionGrantState() throws Exception {
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
assertPermissionGrantState(PackageManager.PERMISSION_DENIED);
assertPermissionRequest(PackageManager.PERMISSION_DENIED);
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
// Should stay denied
assertPermissionGrantState(PackageManager.PERMISSION_DENIED);
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
assertPermissionGrantState(PackageManager.PERMISSION_GRANTED);
assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
// Should stay granted
assertPermissionGrantState(PackageManager.PERMISSION_GRANTED);
}
public void testPermissionPolicy() throws Exception {
// reset permission to denied and unlocked
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
assertPermissionRequest(PackageManager.PERMISSION_DENIED);
// permission should be locked, so changing the policy should not change the grant state
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
assertPermissionRequest(PackageManager.PERMISSION_DENIED);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
assertPermissionRequest(PackageManager.PERMISSION_DENIED);
// reset permission to denied and unlocked
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
// permission should be locked, so changing the policy should not change the grant state
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
}
public void testPermissionMixedPolicies() throws Exception {
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
assertPermissionRequest(PackageManager.PERMISSION_DENIED);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
assertPermissionRequest(PackageManager.PERMISSION_DENIED);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
assertPermissionRequest(PackageManager.PERMISSION_DENIED);
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
}
public void testPermissionGrantOfDisallowedPermissionWhileOtherPermIsGranted() throws Exception {
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
CUSTOM_PERM_A_NAME);
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED,
CUSTOM_PERM_B_NAME);
/*
* CUSTOM_PERM_A_NAME and CUSTOM_PERM_B_NAME are in the same permission group and one is
* granted the other one is not.
*
* It should not be possible to get the permission that was denied via policy granted by
* requesting it.
*/
assertPermissionRequest(PackageManager.PERMISSION_DENIED, null, CUSTOM_PERM_B_NAME);
}
@Suppress // Flakey.
public void testPermissionPrompts() throws Exception {
// register a crash watcher
mDevice.registerWatcher(CRASH_WATCHER_ID, new UiWatcher() {
@Override
public boolean checkForCondition() {
UiObject2 button = mDevice.findObject(CRASH_POPUP_BUTTON_SELECTOR);
if (button != null) {
UiObject2 text = mDevice.findObject(CRASH_POPUP_TEXT_SELECTOR);
Log.d(TAG, "Removing an error dialog: " + text != null ? text.getText() : null);
button.click();
return true;
}
return false;
}
});
mDevice.runWatchers();
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_PROMPT);
assertPermissionRequest(PackageManager.PERMISSION_DENIED, "permission_deny_button");
assertPermissionRequest(PackageManager.PERMISSION_GRANTED, "permission_allow_button");
}
public void testPermissionUpdate_setDeniedState() throws Exception {
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, PERMISSION_NAME),
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
}
public void testPermissionUpdate_setAutoDeniedPolicy() throws Exception {
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, PERMISSION_NAME),
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY);
assertPermissionRequest(PackageManager.PERMISSION_DENIED);
}
public void testPermissionUpdate_checkDenied() throws Exception {
assertPermissionRequest(PackageManager.PERMISSION_DENIED);
assertPermissionGrantState(PackageManager.PERMISSION_DENIED);
}
public void testPermissionUpdate_setGrantedState() throws Exception {
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, PERMISSION_NAME),
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
assertSetPermissionGrantState(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
}
public void testPermissionUpdate_setAutoGrantedPolicy() throws Exception {
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, PERMISSION_NAME),
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
assertSetPermissionPolicy(DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT);
assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
}
public void testPermissionUpdate_checkGranted() throws Exception {
assertPermissionRequest(PackageManager.PERMISSION_GRANTED);
assertPermissionGrantState(PackageManager.PERMISSION_GRANTED);
}
public void testPermissionGrantStateAppPreMDeviceAdminPreQ() throws Exception {
// These tests are to make sure that pre-M apps are not granted/denied runtime permissions
// by a profile owner that targets pre-Q
assertCannotSetPermissionGrantStateAppPreM(
DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
assertCannotSetPermissionGrantStateAppPreM(
DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
}
public void testPermissionGrantStatePreMApp() throws Exception {
// These tests are to make sure that pre-M apps can be granted/denied runtime permissions
// by a profile owner targets Q or later
assertCanSetPermissionGrantStateAppPreM(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
assertCanSetPermissionGrantStateAppPreM(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
}
public void testPermissionGrantState_developmentPermission() throws Exception {
assertFailedToSetDevelopmentPermissionGrantState(
DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
assertFailedToSetDevelopmentPermissionGrantState(
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
assertFailedToSetDevelopmentPermissionGrantState(
DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
}
private void assertPermissionRequest(int expected) throws Exception {
assertPermissionRequest(expected, null);
}
private void assertPermissionRequest(int expected, String buttonResource) throws Exception {
assertPermissionRequest(expected, buttonResource, PERMISSION_NAME);
}
private void assertPermissionRequest(int expected, String buttonResource, String permission)
throws Exception {
Intent launchIntent = new Intent();
launchIntent.setComponent(new ComponentName(PERMISSION_APP_PACKAGE_NAME,
PERMISSIONS_ACTIVITY_NAME));
launchIntent.putExtra(EXTRA_PERMISSION, permission);
launchIntent.setAction(ACTION_REQUEST_PERMISSION);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
mContext.startActivity(launchIntent);
pressPermissionPromptButton(buttonResource);
assertEquals(expected, mReceiver.waitForBroadcast());
assertEquals(expected, mPackageManager.checkPermission(permission,
PERMISSION_APP_PACKAGE_NAME));
}
private void assertPermissionGrantState(int expected) throws Exception {
assertEquals(expected, mPackageManager.checkPermission(PERMISSION_NAME,
PERMISSION_APP_PACKAGE_NAME));
Intent launchIntent = new Intent();
launchIntent.setComponent(new ComponentName(PERMISSION_APP_PACKAGE_NAME,
PERMISSIONS_ACTIVITY_NAME));
launchIntent.putExtra(EXTRA_PERMISSION, PERMISSION_NAME);
launchIntent.setAction(ACTION_CHECK_HAS_PERMISSION);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
mContext.startActivity(launchIntent);
assertEquals(expected, mReceiver.waitForBroadcast());
}
private void assertSetPermissionPolicy(int value) throws Exception {
mDevicePolicyManager.setPermissionPolicy(ADMIN_RECEIVER_COMPONENT,
value);
assertEquals(mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT),
value);
}
private void assertSetPermissionGrantState(int value) throws Exception {
assertSetPermissionGrantState(value, PERMISSION_NAME);
}
private void assertSetPermissionGrantState(int value, String permission) throws Exception {
mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, permission,
value);
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, permission),
value);
}
private void assertFailedToSetDevelopmentPermissionGrantState(int value) throws Exception {
assertFalse(mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, DEVELOPMENT_PERMISSION, value));
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, DEVELOPMENT_PERMISSION),
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
assertEquals(mPackageManager.checkPermission(DEVELOPMENT_PERMISSION,
PERMISSION_APP_PACKAGE_NAME),
PackageManager.PERMISSION_DENIED);
}
private void assertCannotSetPermissionGrantStateAppPreM(int value) throws Exception {
assertFalse(mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
SIMPLE_PRE_M_APP_PACKAGE_NAME, PERMISSION_NAME,
value));
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
SIMPLE_PRE_M_APP_PACKAGE_NAME, PERMISSION_NAME),
DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
// Install time permissions should always be granted
PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(
SIMPLE_PRE_M_APP_PACKAGE_NAME, 0);
assertEquals(PackageManager.PERMISSION_GRANTED,
PermissionChecker.checkPermissionForDataDelivery(mContext, PERMISSION_NAME,
PermissionChecker.PID_UNKNOWN, packageInfo.applicationInfo.uid,
SIMPLE_PRE_M_APP_PACKAGE_NAME));
}
private void assertCanSetPermissionGrantStateAppPreM(int value) throws Exception {
assertTrue(mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
SIMPLE_PRE_M_APP_PACKAGE_NAME, PERMISSION_NAME,
value));
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
SIMPLE_PRE_M_APP_PACKAGE_NAME, PERMISSION_NAME),
value);
// Install time permissions should always be granted
assertEquals(mPackageManager.checkPermission(PERMISSION_NAME,
SIMPLE_PRE_M_APP_PACKAGE_NAME),
PackageManager.PERMISSION_GRANTED);
PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(
SIMPLE_PRE_M_APP_PACKAGE_NAME, 0);
// For pre-M apps the access to the data might be prevented via app-ops. Hence check that
// they are correctly set
boolean isGranted = (PermissionChecker.checkPermissionForDataDelivery(mContext,
PERMISSION_NAME, PermissionChecker.PID_UNKNOWN,
packageInfo.applicationInfo.uid, SIMPLE_PRE_M_APP_PACKAGE_NAME)
== PackageManager.PERMISSION_GRANTED);
switch (value) {
case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED:
assertTrue(isGranted);
break;
case DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED:
assertFalse(isGranted);
break;
default:
fail("unsupported policy value");
}
}
private void pressPermissionPromptButton(String resName) throws Exception {
if (resName == null) {
return;
}
BySelector selector = By
.clazz(android.widget.Button.class.getName())
.res("com.android.packageinstaller", resName);
mDevice.wait(Until.hasObject(selector), 5000);
UiObject2 button = mDevice.findObject(selector);
assertNotNull("Couldn't find button with resource id: " + resName, button);
button.click();
}
private class PermissionBroadcastReceiver extends BroadcastReceiver {
private BlockingQueue<Integer> mQueue = new ArrayBlockingQueue<Integer> (1);
@Override
public void onReceive(Context context, Intent intent) {
Integer result = new Integer(intent.getIntExtra(EXTRA_GRANT_STATE, PERMISSION_ERROR));
Log.d(TAG, "Grant state received " + result);
assertTrue(mQueue.add(result));
}
public int waitForBroadcast() throws Exception {
Integer result = mQueue.poll(30, TimeUnit.SECONDS);
mQueue.clear();
assertNotNull(result);
Log.d(TAG, "Grant state retrieved " + result.intValue());
return result.intValue();
}
}
}