blob: 74790f366c57183f7b40d9bf4e3ada3a49d737df [file] [log] [blame]
/*
* Copyright (C) 2020 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.devicepolicy;
import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import android.Manifest;
import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
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.Until;
import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PermissionUtils {
private static final String LOG_TAG = PermissionUtils.class.getName();
private static final Set<String> LOCATION_PERMISSIONS = new HashSet<String>();
static {
LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION);
LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
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 EXTRA_PERMISSION = "com.android.cts.permission.extra.PERMISSION";
public static void launchActivityAndCheckPermission(PermissionBroadcastReceiver receiver,
String permission, int expected, String packageName, String activityName)
throws Exception {
launchActivityWithAction(permission, ACTION_CHECK_HAS_PERMISSION,
packageName, activityName);
assertEquals(expected, receiver.waitForBroadcast());
}
public static void launchActivityAndRequestPermission(PermissionBroadcastReceiver receiver,
String permission, int expected, String packageName, String activityName)
throws Exception {
launchActivityWithAction(permission, ACTION_REQUEST_PERMISSION,
packageName, activityName);
assertEquals(expected, receiver.waitForBroadcast());
}
public static void launchActivityAndRequestPermission(PermissionBroadcastReceiver
receiver, UiDevice device, String permission, int expected,
String packageName, String activityName) throws Exception {
final List<String> resNames = new ArrayList<>();
switch(expected) {
case PERMISSION_DENIED:
resNames.add("permission_deny_button");
resNames.add("permission_deny_and_dont_ask_again_button");
break;
case PERMISSION_GRANTED:
resNames.add("permission_allow_button");
// For some permissions, different buttons may be available.
if (LOCATION_PERMISSIONS.contains(permission)
|| RECORD_AUDIO.equals(permission)
|| CAMERA.equals(permission)) {
resNames.add("permission_allow_foreground_only_button");
resNames.add("permission_allow_one_time_button");
}
break;
default:
throw new IllegalArgumentException("Invalid expected permission");
}
launchActivityWithAction(permission, ACTION_REQUEST_PERMISSION,
packageName, activityName);
pressPermissionPromptButton(device, resNames.toArray(new String[0]));
assertEquals(expected, receiver.waitForBroadcast());
}
private static void launchActivityWithAction(String permission, String action,
String packageName, String activityName) {
Intent launchIntent = new Intent();
launchIntent.setComponent(new ComponentName(packageName, activityName));
launchIntent.putExtra(EXTRA_PERMISSION, permission);
launchIntent.setAction(action);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
getContext().startActivity(launchIntent);
}
public static void checkPermission(String permission, int expected, String packageName) {
assertEquals(getContext().getPackageManager()
.checkPermission(permission, packageName), expected);
}
/**
* Correctly check a runtime permission. This also works for pre-m apps.
*/
public static void checkPermissionAndAppOps(String permission, int expected, String packageName)
throws Exception {
assertEquals(checkPermissionAndAppOps(permission, packageName), expected);
}
private static int checkPermissionAndAppOps(String permission, String packageName)
throws Exception {
PackageInfo packageInfo = getContext().getPackageManager().getPackageInfo(packageName, 0);
if (getContext().checkPermission(permission, -1, packageInfo.applicationInfo.uid)
== PERMISSION_DENIED) {
return PERMISSION_DENIED;
}
AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
if (appOpsManager != null && appOpsManager.noteProxyOpNoThrow(
AppOpsManager.permissionToOp(permission), packageName,
packageInfo.applicationInfo.uid, null, null)
!= AppOpsManager.MODE_ALLOWED) {
return PERMISSION_DENIED;
}
return PERMISSION_GRANTED;
}
public static Context getContext() {
return InstrumentationRegistry.getInstrumentation().getContext();
}
private static void pressPermissionPromptButton(UiDevice mDevice, String[] resNames) {
if ((resNames == null) || (resNames.length == 0)) {
throw new IllegalArgumentException("resNames must not be null or empty");
}
// The dialog was moved from the packageinstaller to the permissioncontroller.
// Search in multiple packages so the test is not affixed to a particular package.
String[] possiblePackages = new String[]{
"com.android.permissioncontroller.permission.ui",
"com.android.packageinstaller",
"com.android.permissioncontroller"};
boolean foundButton = false;
for (String resName : resNames) {
for (String possiblePkg : possiblePackages) {
BySelector selector = By
.clazz(android.widget.Button.class.getName())
.res(possiblePkg, resName);
mDevice.wait(Until.hasObject(selector), 5000);
UiObject2 button = mDevice.findObject(selector);
Log.d(LOG_TAG, String.format("Resource %s in Package %s found? %b", resName,
possiblePkg, button != null));
if (button != null) {
foundButton = true;
button.click();
break;
}
}
if (foundButton) {
break;
}
}
assertTrue("Couldn't find any button", foundButton);
}
}