blob: 8f5ad3c7cd2958f3d32603904f0cffe1260f91a1 [file] [log] [blame]
/*
* Copyright (C) 2019 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.context;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import android.app.AppOpsManager;
import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.UserHandle;
import androidx.test.InstrumentationRegistry;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* This suite of test ensures that certain APIs in {@link Context} behaves correctly across users.
*/
@RunWith(JUnit4.class)
public class ContextCrossProfileDeviceTest {
private static final String INTERACT_ACROSS_USERS_FULL_PERMISSION =
"android.permission.INTERACT_ACROSS_USERS_FULL";
private static final String INTERACT_ACROSS_USERS_PERMISSION =
"android.permission.INTERACT_ACROSS_USERS";
private static final String INTERACT_ACROSS_PROFILES_PERMISSION =
"android.permission.INTERACT_ACROSS_PROFILES";
private static final String MANAGE_APP_OPS_MODE = "android.permission.MANAGE_APP_OPS_MODES";
private static final String TEST_SERVICE_PKG =
"com.android.cts.testService";
private static final String TEST_SERVICE_IN_DIFFERENT_PKG_CLASS =
TEST_SERVICE_PKG + ".ContextCrossProfileTestService";
public static final ComponentName TEST_SERVICE_IN_DIFFERENT_PKG_COMPONENT_NAME =
new ComponentName(TEST_SERVICE_PKG, TEST_SERVICE_IN_DIFFERENT_PKG_CLASS);
private static final String TEST_SERVICE_IN_SAME_PKG_CLASS =
InstrumentationRegistry.getContext().getPackageName()
+ ".ContextCrossProfileSamePackageTestService";
public static final ComponentName TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME =
new ComponentName(InstrumentationRegistry.getContext().getPackageName(),
TEST_SERVICE_IN_SAME_PKG_CLASS);
@After
public void tearDown() throws Exception {
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.dropShellPermissionIdentity();
}
private int getTestUser() {
final Bundle testArguments = InstrumentationRegistry.getArguments();
if (testArguments.containsKey("testUser")) {
try {
return Integer.parseInt(testArguments.getString("testUser"));
} catch (NumberFormatException ignore) {
}
}
fail("testUser not found.");
return -1;
}
@Test
public void testBindServiceAsUser_differentUser_bindsServiceToCorrectUser() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_USERS_PERMISSION);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_DIFFERENT_PKG_COMPONENT_NAME);
assertThat(context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(),
Context.BIND_AUTO_CREATE, otherProfileHandle))
.isTrue();
assertThat(context.bindService(
bindIntent, new ContextCrossProfileTestConnection(), Context.BIND_AUTO_CREATE))
.isFalse();
}
@Test
public void testBindServiceAsUser_sameProfileGroup_samePackage_withAcrossUsersPermission_bindsService() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_USERS_PERMISSION);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME);
assertThat(context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(),
Context.BIND_AUTO_CREATE, otherProfileHandle)).isTrue();
}
@Test
public void testBindServiceAsUser_sameProfileGroup_differentPackage_withAcrossUsersPermission_bindsService() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_USERS_PERMISSION);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_DIFFERENT_PKG_COMPONENT_NAME);
assertThat(context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(),
Context.BIND_AUTO_CREATE, otherProfileHandle)).isTrue();
}
@Test
public void testBindServiceAsUser_sameProfileGroup_samePackage_withAcrossProfilesPermission_bindsService() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
uiAutomation.adoptShellPermissionIdentity(MANAGE_APP_OPS_MODE);
appOpsManager.setMode(AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION),
Binder.getCallingUid(), context.getPackageName(), AppOpsManager.MODE_DEFAULT);
uiAutomation.dropShellPermissionIdentity();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_PROFILES_PERMISSION);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME);
assertThat(context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(),
Context.BIND_AUTO_CREATE, otherProfileHandle)).isTrue();
}
@Test
public void testBindServiceAsUser_sameProfileGroup_differentPackage_withAcrossProfilesPermission_throwsException() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_PROFILES_PERMISSION);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_DIFFERENT_PKG_COMPONENT_NAME);
try {
context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(), Context.BIND_AUTO_CREATE,
otherProfileHandle);
fail("Should throw a Security Exception");
} catch (SecurityException ignored) {
}
}
@Test
public void testBindServiceAsUser_sameProfileGroup_samePackage_withAcrossProfilesAppOp_bindsService(){
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
uiAutomation.adoptShellPermissionIdentity(MANAGE_APP_OPS_MODE);
appOpsManager.setMode(AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION),
Binder.getCallingUid(), context.getPackageName(), AppOpsManager.MODE_ALLOWED);
uiAutomation.dropShellPermissionIdentity();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME);
assertThat(context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(),
Context.BIND_AUTO_CREATE, otherProfileHandle)).isTrue();
}
@Test
public void testBindServiceAsUser_sameProfileGroup_differentPackage_withAcrossProfilesAppOp_throwsException(){
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
uiAutomation.adoptShellPermissionIdentity(MANAGE_APP_OPS_MODE);
appOpsManager.setMode(AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION),
Binder.getCallingUid(), context.getPackageName(), AppOpsManager.MODE_ALLOWED);
uiAutomation.dropShellPermissionIdentity();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_DIFFERENT_PKG_COMPONENT_NAME);
try {
context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(), Context.BIND_AUTO_CREATE,
otherProfileHandle);
fail("Should throw a Security Exception");
} catch (SecurityException ignored) {
}
}
@Test
public void testBindServiceAsUser_differentProfileGroup_samePackage_withAcrossUsersPermission_bindsService() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherUserId = getTestUser();
UserHandle otherUserHandle = UserHandle.of(otherUserId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_USERS_PERMISSION);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME);
assertThat(context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(), Context.BIND_AUTO_CREATE,
otherUserHandle)).isTrue();
}
@Test
public void testBindServiceAsUser_differentProfileGroup_differentPackage_withAcrossUsersPermission_throwsException() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherUserId = getTestUser();
UserHandle otherUserHandle = UserHandle.of(otherUserId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_USERS_PERMISSION);
try {
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_DIFFERENT_PKG_COMPONENT_NAME);
context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(), Context.BIND_AUTO_CREATE,
otherUserHandle);
fail("Should throw a Security Exception");
} catch (SecurityException ignored) {
}
}
@Test
public void testBindServiceAsUser_differentProfileGroup_withInteractAcrossProfilesPermission_throwsException() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherUserId = getTestUser();
UserHandle otherUserHandle = UserHandle.of(otherUserId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_PROFILES_PERMISSION);
try {
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME);
context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(), Context.BIND_AUTO_CREATE,
otherUserHandle);
fail("Should throw a Security Exception");
} catch (SecurityException ignored) {
}
}
@Test
public void testBindServiceAsUser_differentProfileGroup_withInteractAcrossProfilesAppOp_throwsException(){
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
uiAutomation.adoptShellPermissionIdentity(MANAGE_APP_OPS_MODE);
appOpsManager.setMode(AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION),
Binder.getCallingUid(), context.getPackageName(), AppOpsManager.MODE_ALLOWED);
uiAutomation.dropShellPermissionIdentity();
int otherUserId = getTestUser();
UserHandle otherUserHandle = UserHandle.of(otherUserId);
try {
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME);
context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(),
Context.BIND_AUTO_CREATE, otherUserHandle);
fail("Should throw a Security Exception");
} catch (SecurityException ignored) {
}
}
@Test
public void testBindServiceAsUser_sameProfileGroup_withNoPermissions_throwsException() {
final Context context = InstrumentationRegistry.getContext();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
try {
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME);
context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(), Context.BIND_AUTO_CREATE,
otherProfileHandle);
fail("Should throw a Security Exception");
} catch (SecurityException ignored) {
}
}
@Test
public void testBindServiceAsUser_withInteractAcrossProfilePermission_noAsserts() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
uiAutomation.adoptShellPermissionIdentity(MANAGE_APP_OPS_MODE);
appOpsManager.setMode(AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION),
Binder.getCallingUid(), context.getPackageName(), AppOpsManager.MODE_DEFAULT);
uiAutomation.dropShellPermissionIdentity();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_PROFILES_PERMISSION);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME);
context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(),
Context.BIND_AUTO_CREATE, otherProfileHandle);
}
@Test
public void testBindServiceAsUser_withInteractAcrossUsersFullPermission_noAsserts() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
uiAutomation.adoptShellPermissionIdentity(
INTERACT_ACROSS_USERS_FULL_PERMISSION, INTERACT_ACROSS_USERS_PERMISSION);
Intent bindIntent = new Intent();
bindIntent.setComponent(TEST_SERVICE_IN_SAME_PKG_COMPONENT_NAME);
context.bindServiceAsUser(
bindIntent, new ContextCrossProfileTestConnection(),
Context.BIND_AUTO_CREATE, otherProfileHandle);
}
@Test
public void testCreateContextAsUser_sameProfileGroup_withInteractAcrossProfilesPermission_throwsException() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_PROFILES_PERMISSION);
try {
context.createContextAsUser(otherProfileHandle, /*flags= */0);
fail("Should throw a Security Exception");
} catch (SecurityException ignored) {
}
}
@Test
public void testCreateContextAsUser_sameProfileGroup_withInteractAcrossUsersPermission_createsContext() {
final Context context = InstrumentationRegistry.getContext();
final UiAutomation uiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
int otherProfileId = getTestUser();
UserHandle otherProfileHandle = UserHandle.of(otherProfileId);
uiAutomation.adoptShellPermissionIdentity(INTERACT_ACROSS_USERS_PERMISSION);
Context otherProfileContext = context.createContextAsUser(
otherProfileHandle, /*flags= */0);
assertThat(otherProfileContext.getUserId()).isEqualTo(otherProfileId);
}
}