blob: f0d69e80564436e863d6567be0fe715674d3af39 [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 static android.Manifest.permission.READ_CONTACTS;
import static android.Manifest.permission.WRITE_CONTACTS;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY;
import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT;
import static android.app.admin.DevicePolicyManager.PERMISSION_POLICY_PROMPT;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.cts.devicepolicy.PermissionUtils.permissionGrantStateToString;
import static com.android.cts.devicepolicy.PermissionUtils.permissionPolicyToString;
import static com.google.common.truth.Truth.assertWithMessage;
import android.Manifest.permission;
import android.app.UiAutomation;
import android.app.admin.DevicePolicyManager;
import android.content.IntentFilter;
import android.os.Process;
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.util.Log;
import com.android.cts.devicepolicy.PermissionBroadcastReceiver;
import com.android.cts.devicepolicy.PermissionUtils;
import com.google.android.collect.Sets;
import java.util.Set;
/**
* 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 PRE_M_APP_PACKAGE_NAME
= "com.android.cts.launcherapps.simplepremapp";
private static final String PERMISSIONS_ACTIVITY_NAME
= PERMISSION_APP_PACKAGE_NAME + ".PermissionActivity";
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 ACTION_PERMISSION_RESULT
= "com.android.cts.permission.action.PERMISSION_RESULT";
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 static final Set<String> LOCATION_PERMISSIONS = Sets.newHashSet(
permission.ACCESS_FINE_LOCATION,
permission.ACCESS_BACKGROUND_LOCATION,
permission.ACCESS_COARSE_LOCATION);
private static final Set<String> SENSORS_PERMISSIONS = Sets.newHashSet(
permission.ACCESS_FINE_LOCATION,
permission.ACCESS_COARSE_LOCATION,
permission.CAMERA,
permission.ACTIVITY_RECOGNITION,
permission.BODY_SENSORS);
private PermissionBroadcastReceiver mReceiver;
private UiDevice mDevice;
private UiAutomation mUiAutomation;
@Override
protected void setUp() throws Exception {
super.setUp();
mReceiver = new PermissionBroadcastReceiver();
mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PERMISSION_RESULT));
mDevice = UiDevice.getInstance(getInstrumentation());
mUiAutomation = getInstrumentation().getUiAutomation();
}
@Override
protected void tearDown() throws Exception {
mContext.unregisterReceiver(mReceiver);
mDevice.removeWatcher(CRASH_WATCHER_ID);
super.tearDown();
}
public void testPermissionGrantStateDenied() throws Exception {
setPermissionGrantState(READ_CONTACTS, PERMISSION_GRANT_STATE_DENIED);
assertPermissionGrantState(READ_CONTACTS, PERMISSION_GRANT_STATE_DENIED);
assertCannotRequestPermissionFromActivity(READ_CONTACTS);
}
public void testPermissionGrantStateDenied_mixedPolicies() throws Exception {
int grantState = mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, READ_CONTACTS);
int permissionPolicy = mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT);
try {
setPermissionGrantState(READ_CONTACTS, PERMISSION_GRANT_STATE_DENIED);
// Check no permission by launching an activity and requesting the permission
// Should stay denied if grant state is denied
setPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertCannotRequestPermissionFromActivity(READ_CONTACTS);
setPermissionPolicy(PERMISSION_POLICY_AUTO_DENY);
assertPermissionPolicy(PERMISSION_POLICY_AUTO_DENY);
assertCannotRequestPermissionFromActivity(READ_CONTACTS);
setPermissionPolicy(PERMISSION_POLICY_PROMPT);
assertPermissionPolicy(PERMISSION_POLICY_PROMPT);
assertCannotRequestPermissionFromActivity(READ_CONTACTS);
} finally {
// Restore original state
setPermissionGrantState(READ_CONTACTS, grantState);
setPermissionPolicy(permissionPolicy);
}
}
public void testPermissionGrantStateDenied_otherPermissionIsGranted() throws Exception {
int grantStateA = mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, CUSTOM_PERM_A_NAME);
int grantStateB = mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, CUSTOM_PERM_B_NAME);
try {
setPermissionGrantState(CUSTOM_PERM_A_NAME, PERMISSION_GRANT_STATE_GRANTED);
setPermissionGrantState(CUSTOM_PERM_B_NAME, PERMISSION_GRANT_STATE_DENIED);
assertPermissionGrantState(CUSTOM_PERM_A_NAME, PERMISSION_GRANT_STATE_GRANTED);
assertPermissionGrantState(CUSTOM_PERM_B_NAME, PERMISSION_GRANT_STATE_DENIED);
/*
* 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.
*/
assertCannotRequestPermissionFromActivity(CUSTOM_PERM_B_NAME);
} finally {
// Restore original state
setPermissionGrantState(CUSTOM_PERM_A_NAME, grantStateA);
setPermissionGrantState(CUSTOM_PERM_B_NAME, grantStateB);
}
}
public void testPermissionGrantStateGranted() throws Exception {
setPermissionGrantState(READ_CONTACTS, PERMISSION_GRANT_STATE_GRANTED);
assertPermissionGrantState(READ_CONTACTS, PERMISSION_GRANT_STATE_GRANTED);
assertCanRequestPermissionFromActivity(READ_CONTACTS);
}
public void testPermissionGrantStateGranted_mixedPolicies() throws Exception {
int grantState = mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, READ_CONTACTS);
int permissionPolicy = mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT);
try {
setPermissionGrantState(READ_CONTACTS, PERMISSION_GRANT_STATE_GRANTED);
// Check permission by launching an activity and requesting the permission
setPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertCanRequestPermissionFromActivity(READ_CONTACTS);
setPermissionPolicy(PERMISSION_POLICY_AUTO_DENY);
assertPermissionPolicy(PERMISSION_POLICY_AUTO_DENY);
assertCanRequestPermissionFromActivity(READ_CONTACTS);
setPermissionPolicy(PERMISSION_POLICY_PROMPT);
assertPermissionPolicy(PERMISSION_POLICY_PROMPT);
assertCanRequestPermissionFromActivity(READ_CONTACTS);
} finally {
// Restore original state
setPermissionGrantState(READ_CONTACTS, grantState);
setPermissionPolicy(permissionPolicy);
}
}
public void testPermissionGrantState_preMApp_preQDeviceAdmin() 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
assertCannotSetPermissionGrantStatePreMApp(READ_CONTACTS, PERMISSION_GRANT_STATE_DENIED);
assertCannotSetPermissionGrantStatePreMApp(READ_CONTACTS, PERMISSION_GRANT_STATE_GRANTED);
}
private void assertCannotSetPermissionGrantStatePreMApp(String permission, int value)
throws Exception {
assertFalse(mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PRE_M_APP_PACKAGE_NAME, permission, value));
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PRE_M_APP_PACKAGE_NAME, permission), PERMISSION_GRANT_STATE_DEFAULT);
// Install runtime permissions should always be granted
PermissionUtils.checkPermission(permission, PERMISSION_GRANTED, PRE_M_APP_PACKAGE_NAME);
PermissionUtils.checkPermissionAndAppOps(permission, PERMISSION_GRANTED,
PRE_M_APP_PACKAGE_NAME);
}
public void testPermissionGrantState_preMApp() 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
assertCanSetPermissionGrantStatePreMApp(READ_CONTACTS, PERMISSION_GRANT_STATE_DENIED);
assertCanSetPermissionGrantStatePreMApp(READ_CONTACTS, PERMISSION_GRANT_STATE_GRANTED);
}
private void assertCanSetPermissionGrantStatePreMApp(String permission, int value)
throws Exception {
assertTrue(mDevicePolicyManager.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PRE_M_APP_PACKAGE_NAME, permission, value));
assertEquals(mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PRE_M_APP_PACKAGE_NAME, permission), value);
// Install time permissions should always be granted
PermissionUtils.checkPermission(permission, PERMISSION_GRANTED, PRE_M_APP_PACKAGE_NAME);
// For pre-M apps the access to the data might be prevented via app-ops. Hence check that
// they are correctly set
switch (value) {
case PERMISSION_GRANT_STATE_GRANTED:
PermissionUtils.checkPermissionAndAppOps(permission, PERMISSION_GRANTED,
PRE_M_APP_PACKAGE_NAME);
break;
case PERMISSION_GRANT_STATE_DENIED:
PermissionUtils.checkPermissionAndAppOps(permission, PERMISSION_DENIED,
PRE_M_APP_PACKAGE_NAME);
break;
default:
fail("unsupported policy value");
}
}
public void testPermissionPolicyAutoDeny() throws Exception {
setPermissionPolicy(PERMISSION_POLICY_AUTO_DENY);
assertPermissionPolicy(PERMISSION_POLICY_AUTO_DENY);
assertCannotRequestPermissionFromActivity(READ_CONTACTS);
}
public void testPermissionPolicyAutoDeny_permissionLocked() throws Exception {
int grantState = mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, READ_CONTACTS);
int permissionPolicy = mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT);
try {
setPermissionGrantState(READ_CONTACTS, PERMISSION_GRANT_STATE_DENIED);
setPermissionGrantState(READ_CONTACTS, PERMISSION_GRANT_STATE_DEFAULT);
testPermissionPolicyAutoDeny();
// Permission should be locked, so changing the policy should not change the grant state
setPermissionPolicy(PERMISSION_POLICY_PROMPT);
assertPermissionPolicy(PERMISSION_POLICY_PROMPT);
assertCannotRequestPermissionFromActivity(READ_CONTACTS);
setPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertCannotRequestPermissionFromActivity(READ_CONTACTS);
} finally {
// Restore original state
setPermissionGrantState(READ_CONTACTS, grantState);
setPermissionPolicy(permissionPolicy);
}
}
public void testPermissionPolicyAutoGrant() throws Exception {
int permissionPolicy = mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT);
try {
setPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertCanRequestPermissionFromActivity(READ_CONTACTS);
} finally {
// Restore original state
setPermissionPolicy(permissionPolicy);
}
}
public void testPermissionPolicyAutoGrant_permissionLocked() throws Exception {
int grantState = mDevicePolicyManager.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, READ_CONTACTS);
int permissionPolicy = mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT);
try {
setPermissionGrantState(READ_CONTACTS, PERMISSION_GRANT_STATE_DEFAULT);
setPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertCanRequestPermissionFromActivity(READ_CONTACTS);
// permission should be locked, so changing the policy should not change the grant state
setPermissionPolicy(PERMISSION_POLICY_PROMPT);
assertPermissionPolicy(PERMISSION_POLICY_PROMPT);
assertCanRequestPermissionFromActivity(READ_CONTACTS);
setPermissionPolicy(PERMISSION_POLICY_AUTO_DENY);
assertPermissionPolicy(PERMISSION_POLICY_AUTO_DENY);
assertCanRequestPermissionFromActivity(READ_CONTACTS);
} finally {
// Restore original state
setPermissionGrantState(READ_CONTACTS, grantState);
setPermissionPolicy(permissionPolicy);
}
}
public void testPermissionPolicyAutoGrant_multiplePermissionsInGroup() throws Exception {
int permissionPolicy = mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT);
try {
setPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
// Both permissions should be granted
assertPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
assertCanRequestPermissionFromActivity(READ_CONTACTS);
assertCanRequestPermissionFromActivity(WRITE_CONTACTS);
} finally {
// Restore original state
setPermissionPolicy(permissionPolicy);
}
}
public void testCannotRequestPermission() throws Exception {
assertCannotRequestPermissionFromActivity(READ_CONTACTS);
}
public void testCanRequestPermission() throws Exception {
assertCanRequestPermissionFromActivity(READ_CONTACTS);
}
public void testPermissionPrompts() throws Exception {
// register a crash watcher
mDevice.registerWatcher(CRASH_WATCHER_ID, () -> {
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();
setPermissionPolicy(PERMISSION_POLICY_PROMPT);
assertPermissionPolicy(PERMISSION_POLICY_PROMPT);
PermissionUtils.launchActivityAndRequestPermission(mReceiver, mDevice, READ_CONTACTS,
PERMISSION_DENIED, PERMISSION_APP_PACKAGE_NAME, PERMISSIONS_ACTIVITY_NAME);
PermissionUtils.checkPermission(READ_CONTACTS, PERMISSION_DENIED,
PERMISSION_APP_PACKAGE_NAME);
PermissionUtils.launchActivityAndRequestPermission(mReceiver, mDevice, READ_CONTACTS,
PERMISSION_GRANTED, PERMISSION_APP_PACKAGE_NAME, PERMISSIONS_ACTIVITY_NAME);
PermissionUtils.checkPermission(READ_CONTACTS, PERMISSION_GRANTED,
PERMISSION_APP_PACKAGE_NAME);
}
public void testSensorsRelatedPermissionsNotGrantedViaPolicy() throws Exception {
int permissionPolicy = mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT);
try {
setPermissionPolicy(PERMISSION_POLICY_AUTO_GRANT);
for (String sensorPermission : SENSORS_PERMISSIONS) {
try {
// The permission is not granted by default.
PermissionUtils.checkPermission(sensorPermission, PERMISSION_DENIED,
PERMISSION_APP_PACKAGE_NAME);
// But the user can grant it.
PermissionUtils.launchActivityAndRequestPermission(mReceiver, mDevice,
sensorPermission,
PERMISSION_GRANTED, PERMISSION_APP_PACKAGE_NAME,
PERMISSIONS_ACTIVITY_NAME);
// And the package manager should show it as granted.
PermissionUtils.checkPermission(sensorPermission, PERMISSION_GRANTED,
PERMISSION_APP_PACKAGE_NAME);
} finally {
revokePermission(sensorPermission);
}
}
} finally {
// Restore original state
setPermissionPolicy(permissionPolicy);
}
}
private void revokePermission(String sensorPermission) {
if (LOCATION_PERMISSIONS.contains(sensorPermission)) {
mUiAutomation.revokeRuntimePermission(PERMISSION_APP_PACKAGE_NAME,
permission.ACCESS_FINE_LOCATION);
mUiAutomation.revokeRuntimePermission(PERMISSION_APP_PACKAGE_NAME,
permission.ACCESS_COARSE_LOCATION);
} else {
mUiAutomation.revokeRuntimePermission(PERMISSION_APP_PACKAGE_NAME, sensorPermission);
}
}
private void setPermissionPolicy(int permissionPolicy) {
Log.d(TAG, "Calling setPermissionPolicy(" + permissionPolicyToString(permissionPolicy)
+ ") using DPM " + mDevicePolicyManager + " on uid " + Process.myUid());
mDevicePolicyManager.setPermissionPolicy(ADMIN_RECEIVER_COMPONENT, permissionPolicy);
}
private boolean setPermissionGrantState(String permission, int grantState) {
return setPermissionGrantState(mDevicePolicyManager, permission, grantState);
}
private boolean setPermissionGrantState(DevicePolicyManager dpm, String permission,
int grantState) {
boolean result = dpm.setPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, permission, grantState);
Log.d(TAG, "setPermissionGrantState(" + permission + "): requested " + grantState + " ("
+ permissionGrantStateToString(grantState) + ") using DPM " + mDevicePolicyManager
+ " on uid " + Process.myUid() + ", got " + result);
return result;
}
private void assertPermissionGrantState(String permission, int expectedState) {
assertPermissionGrantState(mDevicePolicyManager, permission, expectedState);
}
private void assertPermissionGrantState(DevicePolicyManager dpm, String permission,
int expectedState) {
int actualState = dpm.getPermissionGrantState(ADMIN_RECEIVER_COMPONENT,
PERMISSION_APP_PACKAGE_NAME, permission);
assertWithMessage("%s.getPermissionGrantState(%s, %s, %s) (where %s=%s and %s=%s)",
mDevicePolicyManager, ADMIN_RECEIVER_COMPONENT, PERMISSION_APP_PACKAGE_NAME,
permission, expectedState, permissionGrantStateToString(expectedState),
actualState, permissionGrantStateToString(actualState))
.that(actualState)
.isEqualTo(expectedState);
}
private void assertPermissionPolicy(int expectedPolicy) {
int actualPolicy = mDevicePolicyManager.getPermissionPolicy(ADMIN_RECEIVER_COMPONENT);
assertWithMessage("%s.getPermissionPolicy(%s) (where %s=%s and %s=%s)",
mDevicePolicyManager, ADMIN_RECEIVER_COMPONENT,
expectedPolicy, permissionPolicyToString(expectedPolicy),
actualPolicy, permissionPolicyToString(actualPolicy))
.that(actualPolicy)
.isEqualTo(expectedPolicy);
}
private void assertCanRequestPermissionFromActivity(String permission) throws Exception {
PermissionUtils.launchActivityAndRequestPermission(
mReceiver, permission, PERMISSION_GRANTED,
PERMISSION_APP_PACKAGE_NAME, PERMISSIONS_ACTIVITY_NAME);
}
private void assertCannotRequestPermissionFromActivity(String permission) throws Exception {
PermissionUtils.launchActivityAndRequestPermission(
mReceiver, permission, PERMISSION_DENIED,
PERMISSION_APP_PACKAGE_NAME, PERMISSIONS_ACTIVITY_NAME);
}
}