blob: 364995f4e95892eabef2adaded636ed3e50095cb [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 android.devicepolicy.cts;
import static android.content.pm.CrossProfileApps.ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED;
import static android.provider.Settings.ACTION_MANAGE_CROSS_PROFILE_ACCESS;
import static com.android.bedstead.harrier.UserType.ADDITIONAL_USER;
import static com.android.bedstead.harrier.UserType.INITIAL_USER;
import static com.android.bedstead.harrier.UserType.WORK_PROFILE;
import static com.android.bedstead.metricsrecorder.truth.MetricQueryBuilderSubject.assertThat;
import static com.android.bedstead.nene.permissions.CommonPermissions.INTERACT_ACROSS_PROFILES;
import static com.android.bedstead.nene.permissions.CommonPermissions.INTERACT_ACROSS_USERS;
import static com.android.bedstead.nene.permissions.CommonPermissions.INTERACT_ACROSS_USERS_FULL;
import static com.android.bedstead.nene.permissions.CommonPermissions.START_CROSS_PROFILE_ACTIVITIES;
import static com.android.bedstead.nene.types.OptionalBoolean.TRUE;
import static com.android.eventlib.truth.EventLogsSubject.assertThat;
import static com.android.queryable.queries.ActivityQuery.activity;
import static com.android.queryable.queries.IntentFilterQuery.intentFilter;
import static com.google.common.truth.Truth.assertThat;
import static org.testng.Assert.assertThrows;
import android.app.ActivityOptions;
import android.app.AppOpsManager;
import android.app.admin.RemoteDevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.CrossProfileApps;
import android.os.UserHandle;
import android.stats.devicepolicy.EventId;
import androidx.test.core.app.ApplicationProvider;
import com.android.activitycontext.ActivityContext;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
import com.android.bedstead.harrier.annotations.CrossUserTest;
import com.android.bedstead.harrier.annotations.EnsureDoesNotHavePermission;
import com.android.bedstead.harrier.annotations.EnsureHasNoProfile;
import com.android.bedstead.harrier.annotations.EnsureHasPermission;
import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile;
import com.android.bedstead.harrier.annotations.PermissionTest;
import com.android.bedstead.harrier.annotations.Postsubmit;
import com.android.bedstead.harrier.annotations.RequireRunOnInitialUser;
import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;
import com.android.bedstead.harrier.annotations.UserPair;
import com.android.bedstead.harrier.annotations.UserTest;
import com.android.bedstead.metricsrecorder.EnterpriseMetricsRecorder;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.appops.AppOpsMode;
import com.android.bedstead.nene.packages.Package;
import com.android.bedstead.nene.packages.ProcessReference;
import com.android.bedstead.testapp.TestApp;
import com.android.bedstead.testapp.TestAppActivityReference;
import com.android.bedstead.testapp.TestAppInstance;
import com.android.eventlib.EventLogs;
import com.android.eventlib.events.activities.ActivityCreatedEvent;
import com.android.eventlib.events.activities.ActivityEvents;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@RunWith(BedsteadJUnit4.class)
public final class CrossProfileAppsTest {
private static final Context sContext = ApplicationProvider.getApplicationContext();
private static final CrossProfileApps sCrossProfileApps =
sContext.getSystemService(CrossProfileApps.class);
@ClassRule @Rule
public static final DeviceState sDeviceState = new DeviceState();
private static final TestApp sCrossProfileTestApp = sDeviceState.testApps().query()
.whereCrossProfile().isTrue()
// TODO: Add query for a receiver for ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED
.wherePermissions().contains("android.permission.INTERACT_ACROSS_PROFILES").get();
private static final TestApp sNonCrossProfileTestApp = sDeviceState.testApps().query()
.wherePermissions().doesNotContain("android.permission.INTERACT_ACROSS_PROFILES").get();
private static final TestApp sTestAppWithMainActivity = sDeviceState.testApps().query()
.whereActivities().contains(
activity().where().intentFilters().contains(
intentFilter().where().actions().contains(Intent.ACTION_MAIN))
).get();
private static final TestApp sTestAppWithActivity = sTestAppWithMainActivity;
// TODO(b/191637162): When we have permissions in test apps we won't need to use the
// instrumented app for this
private static final ComponentName MAIN_ACTIVITY =
new ComponentName(sContext, "android.devicepolicy.cts.MainActivity");
private static final ComponentName NOT_EXPORTED_ACTIVITY =
new ComponentName(sContext, "android.devicepolicy.cts.NotExportedMainActivity");
private static final ComponentName NOT_MAIN_ACTIVITY =
new ComponentName(sContext, "android.devicepolicy.cts.NotMainActivity");
@Before
@After
public void cleanupOtherUsers() {
// As these tests start this package on other users, we should kill all processes on other
// users for this package
Package pkg = TestApis.packages().instrumented();
pkg.runningProcesses().stream()
.filter(p -> !p.user().equals(TestApis.users().instrumented()))
.forEach(ProcessReference::kill);
}
@CrossUserTest({
@UserPair(from = INITIAL_USER, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = ADDITIONAL_USER),
@UserPair(from = WORK_PROFILE, to = ADDITIONAL_USER),
@UserPair(from = ADDITIONAL_USER, to = WORK_PROFILE)
})
@Postsubmit(reason = "new test")
public void getTargetUserProfiles_doesNotContainOtherUser() {
TestApis.packages().instrumented().installExisting(sDeviceState.otherUser());
List<UserHandle> targetProfiles = sCrossProfileApps.getTargetUserProfiles();
assertThat(targetProfiles).doesNotContain(sDeviceState.otherUser().userHandle());
}
@CrossUserTest({
@UserPair(from = WORK_PROFILE, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = WORK_PROFILE)
}) @Postsubmit(reason = "new test")
public void getTargetUserProfiles_containsOtherUser() {
TestApis.packages().instrumented().installExisting(sDeviceState.otherUser());
List<UserHandle> targetProfiles = sCrossProfileApps.getTargetUserProfiles();
assertThat(targetProfiles).contains(sDeviceState.otherUser().userHandle());
}
@CrossUserTest({
@UserPair(from = WORK_PROFILE, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = WORK_PROFILE)
})
@Postsubmit(reason = "new test")
public void getTargetUserProfiles_appNotInstalledInOtherUser_doesNotContainOtherUser() {
TestApis.packages().instrumented().uninstall(sDeviceState.otherUser());
List<UserHandle> targetProfiles = sCrossProfileApps.getTargetUserProfiles();
assertThat(targetProfiles).doesNotContain(sDeviceState.otherUser().userHandle());
}
@Postsubmit(reason = "new test")
@UserTest({INITIAL_USER, WORK_PROFILE})
public void getTargetUserProfiles_logged() {
try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create()) {
sCrossProfileApps.getTargetUserProfiles();
assertThat(metrics.query()
.whereType().isEqualTo(
EventId.CROSS_PROFILE_APPS_GET_TARGET_USER_PROFILES_VALUE)
.whereStrings().contains(sContext.getPackageName())
).wasLogged();
}
}
@CrossUserTest({
@UserPair(from = WORK_PROFILE, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = WORK_PROFILE)
})
@Postsubmit(reason = "new test")
public void startMainActivity_launches() {
TestApis.packages().instrumented().installExisting(sDeviceState.otherUser());
sCrossProfileApps.startMainActivity(MAIN_ACTIVITY, sDeviceState.otherUser().userHandle());
assertThat(
ActivityEvents.forActivity(MAIN_ACTIVITY, sDeviceState.otherUser())
.activityCreated()
).eventOccurred();
}
@CrossUserTest({
@UserPair(from = WORK_PROFILE, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = WORK_PROFILE)
})
@Postsubmit(reason = "new test")
public void startMainActivity_logged() {
TestApis.packages().instrumented().installExisting(sDeviceState.otherUser());
try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create()) {
sCrossProfileApps.startMainActivity(MAIN_ACTIVITY,
sDeviceState.otherUser().userHandle());
assertThat(metrics.query()
.whereType().isEqualTo(EventId.CROSS_PROFILE_APPS_START_ACTIVITY_AS_USER_VALUE)
.whereStrings().contains(sContext.getPackageName())
).wasLogged();
}
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@Postsubmit(reason = "new test")
public void startMainActivity_activityNotExported_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.startMainActivity(
NOT_EXPORTED_ACTIVITY, sDeviceState.workProfile().userHandle());
});
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@Postsubmit(reason = "new test")
public void startMainActivity_activityNotMain_throwsSecurityException() {
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.startMainActivity(
NOT_MAIN_ACTIVITY, sDeviceState.workProfile().userHandle());
});
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@Postsubmit(reason = "new test")
public void startMainActivity_activityIncorrectPackage_throwsSecurityException() {
try (TestAppInstance instance =
sTestAppWithMainActivity.install(sDeviceState.workProfile())) {
TestAppActivityReference activity = instance.activities().query()
.whereActivity().exported().isTrue()
.whereActivity().intentFilters().contains(
intentFilter().where().actions().contains(
Intent.ACTION_MAIN
)
)
.get();
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.startMainActivity(
activity.component().componentName(),
sDeviceState.workProfile().userHandle());
});
}
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
@Postsubmit(reason = "new test")
public void startActivity_byIntent_noComponent_throwsException() throws Exception {
Intent intent = new Intent();
intent.setAction("test");
ActivityContext.runWithContext(activity ->
assertThrows(NullPointerException.class, () ->
sCrossProfileApps.startActivity(
intent, sDeviceState.workProfile().userHandle(), activity)));
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
@Postsubmit(reason = "new test")
public void startActivity_byIntent_differentPackage_throwsException() throws Exception {
try (TestAppInstance testAppInstance =
sTestAppWithActivity.install(sDeviceState.workProfile())) {
TestAppActivityReference targetActivity = testAppInstance.activities().any();
Intent intent = new Intent();
intent.setComponent(targetActivity.component().componentName());
ActivityContext.runWithContext(activity ->
assertThrows(SecurityException.class, () ->
sCrossProfileApps.startActivity(
intent, sDeviceState.workProfile().userHandle(), activity)));
}
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
@Postsubmit(reason = "new test")
public void startActivity_byComponent_differentPackage_throwsException() throws Exception {
try (TestAppInstance testAppInstance =
sTestAppWithActivity.install(sDeviceState.workProfile())) {
TestAppActivityReference targetActivity = testAppInstance.activities().any();
ActivityContext.runWithContext(activity ->
assertThrows(SecurityException.class, () ->
sCrossProfileApps.startActivity(
targetActivity.component().componentName(),
sDeviceState.workProfile().userHandle())));
}
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
@EnsureDoesNotHavePermission({
INTERACT_ACROSS_PROFILES, INTERACT_ACROSS_USERS,
INTERACT_ACROSS_USERS_FULL, START_CROSS_PROFILE_ACTIVITIES})
@Postsubmit(reason = "new test")
public void startActivity_byIntent_withoutPermissions_throwsException() throws Exception {
Intent intent = new Intent();
intent.setComponent(NOT_MAIN_ACTIVITY);
ActivityContext.runWithContext(activity ->
assertThrows(SecurityException.class, () ->
sCrossProfileApps.startActivity(
intent, sDeviceState.workProfile().userHandle(), activity)));
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
@EnsureDoesNotHavePermission({
INTERACT_ACROSS_PROFILES, INTERACT_ACROSS_USERS,
INTERACT_ACROSS_USERS_FULL, START_CROSS_PROFILE_ACTIVITIES})
@Postsubmit(reason = "new test")
public void startActivity_byComponent_withoutPermissions_throwsException() throws Exception {
ActivityContext.runWithContext(activity ->
assertThrows(SecurityException.class, () ->
sCrossProfileApps.startActivity(
NOT_MAIN_ACTIVITY, sDeviceState.workProfile().userHandle())));
}
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@PermissionTest({
INTERACT_ACROSS_PROFILES, INTERACT_ACROSS_USERS,
INTERACT_ACROSS_USERS_FULL})
@Postsubmit(reason = "new test")
public void startActivity_byIntent_withPermission_startsActivity() throws Exception {
Intent intent = new Intent();
intent.setComponent(NOT_MAIN_ACTIVITY);
ActivityContext.runWithContext(activity -> {
sCrossProfileApps.startActivity(
intent, sDeviceState.workProfile().userHandle(), activity);
});
assertThat(
ActivityEvents.forActivity(NOT_MAIN_ACTIVITY, sDeviceState.workProfile())
.activityCreated()
).eventOccurred();
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(START_CROSS_PROFILE_ACTIVITIES)
@Postsubmit(reason = "new test")
public void startActivity_byIntent_withCrossProfileActivitiesPermission_throwsException()
throws Exception {
Intent intent = new Intent();
intent.setComponent(NOT_MAIN_ACTIVITY);
ActivityContext.runWithContext(activity -> {
assertThrows(SecurityException.class, () -> sCrossProfileApps.startActivity(
intent, sDeviceState.workProfile().userHandle(), activity));
});
}
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@PermissionTest({
INTERACT_ACROSS_PROFILES, INTERACT_ACROSS_USERS,
INTERACT_ACROSS_USERS_FULL, START_CROSS_PROFILE_ACTIVITIES})
@Postsubmit(reason = "new test")
public void startActivity_byComponent_withPermission_startsActivity()
throws Exception {
ActivityContext.runWithContext(activity -> {
sCrossProfileApps.startActivity(
NOT_MAIN_ACTIVITY, sDeviceState.workProfile().userHandle());
});
assertThat(
ActivityEvents.forActivity(NOT_MAIN_ACTIVITY, sDeviceState.workProfile())
.activityCreated()
).eventOccurred();
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(INTERACT_ACROSS_PROFILES)
@Postsubmit(reason = "new test")
public void startActivity_byIntent_withOptionsBundle_startsActivity()
throws Exception {
Intent intent = new Intent();
intent.setComponent(NOT_MAIN_ACTIVITY);
ActivityContext.runWithContext(activity -> {
sCrossProfileApps.startActivity(
intent, sDeviceState.workProfile().userHandle(), activity,
ActivityOptions.makeBasic().toBundle());
});
assertThat(
ActivityEvents.forActivity(NOT_MAIN_ACTIVITY, sDeviceState.workProfile())
.activityCreated()
).eventOccurred();
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(INTERACT_ACROSS_PROFILES)
@Postsubmit(reason = "new test")
public void startActivity_byIntent_notExported_startsActivity()
throws Exception {
Intent intent = new Intent();
intent.setComponent(NOT_EXPORTED_ACTIVITY);
ActivityContext.runWithContext(activity -> {
sCrossProfileApps.startActivity(
intent, sDeviceState.workProfile().userHandle(), activity);
});
assertThat(
ActivityEvents.forActivity(NOT_EXPORTED_ACTIVITY, sDeviceState.workProfile())
.activityCreated()
).eventOccurred();
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(INTERACT_ACROSS_PROFILES)
@Postsubmit(reason = "new test")
public void startActivity_byComponent_notExported_throwsException()
throws Exception {
ActivityContext.runWithContext(activity -> {
assertThrows(SecurityException.class, () -> sCrossProfileApps.startActivity(
NOT_EXPORTED_ACTIVITY, sDeviceState.workProfile().userHandle()));
});
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(INTERACT_ACROSS_PROFILES)
@Postsubmit(reason = "new test")
public void startActivity_byIntent_sameTaskByDefault() throws Exception {
Intent intent = new Intent();
intent.setComponent(NOT_MAIN_ACTIVITY);
int originalTaskId = ActivityContext.getWithContext(activity -> {
sCrossProfileApps.startActivity(
intent, sDeviceState.workProfile().userHandle(), activity);
return activity.getTaskId();
});
ActivityCreatedEvent event =
ActivityEvents.forActivity(NOT_MAIN_ACTIVITY, sDeviceState.workProfile())
.activityCreated().waitForEvent();
assertThat(event.taskId()).isEqualTo(originalTaskId);
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(START_CROSS_PROFILE_ACTIVITIES)
@Postsubmit(reason = "new test")
public void startMainActivity_byComponent_nullActivity_newTask() throws Exception {
int originalTaskId = ActivityContext.getWithContext(activity -> {
sCrossProfileApps.startMainActivity(
MAIN_ACTIVITY,
sDeviceState.workProfile().userHandle(),
/* callingActivity */ null,
/* options */ null);
return activity.getTaskId();
});
ActivityCreatedEvent event =
ActivityEvents.forActivity(MAIN_ACTIVITY, sDeviceState.workProfile())
.activityCreated().waitForEvent();
assertThat(event.taskId()).isNotEqualTo(originalTaskId);
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(START_CROSS_PROFILE_ACTIVITIES)
@Postsubmit(reason = "new test")
public void startMainActivity_byComponent_setsActivity_sameTask() throws Exception {
int originalTaskId = ActivityContext.getWithContext(activity -> {
sCrossProfileApps.startMainActivity(
MAIN_ACTIVITY,
sDeviceState.workProfile().userHandle(),
activity,
/* options */ null);
return activity.getTaskId();
});
ActivityCreatedEvent event =
ActivityEvents.forActivity(MAIN_ACTIVITY, sDeviceState.workProfile())
.activityCreated().waitForEvent();
assertThat(event.taskId()).isEqualTo(originalTaskId);
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(START_CROSS_PROFILE_ACTIVITIES)
@Postsubmit(reason = "new test")
public void startNonMainActivity_byComponent_nullActivity_newTask() throws Exception {
int originalTaskId = ActivityContext.getWithContext(activity -> {
sCrossProfileApps.startActivity(
NOT_MAIN_ACTIVITY,
sDeviceState.workProfile().userHandle(),
/* callingActivity */ null,
/* options */ null);
return activity.getTaskId();
});
ActivityCreatedEvent event =
ActivityEvents.forActivity(NOT_MAIN_ACTIVITY, sDeviceState.workProfile())
.activityCreated().waitForEvent();
assertThat(event.taskId()).isNotEqualTo(originalTaskId);
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(START_CROSS_PROFILE_ACTIVITIES)
@Postsubmit(reason = "new test")
public void startNonMainActivity_byComponent_setsActivity_sameTask() throws Exception {
int originalTaskId = ActivityContext.getWithContext(activity -> {
sCrossProfileApps.startActivity(
NOT_MAIN_ACTIVITY,
sDeviceState.workProfile().userHandle(),
activity,
/* options */ null);
return activity.getTaskId();
});
ActivityCreatedEvent event =
ActivityEvents.forActivity(NOT_MAIN_ACTIVITY, sDeviceState.workProfile())
.activityCreated().waitForEvent();
assertThat(event.taskId()).isEqualTo(originalTaskId);
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@EnsureHasPermission(INTERACT_ACROSS_PROFILES)
@Postsubmit(reason = "new test")
public void startActivity_byIntent_logged() throws Exception {
Intent intent = new Intent();
intent.setComponent(NOT_MAIN_ACTIVITY);
try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create()) {
ActivityContext.runWithContext(activity ->
sCrossProfileApps.startActivity(
intent, sDeviceState.workProfile().userHandle(), activity));
assertThat(metrics.query()
.whereType().isEqualTo(EventId.START_ACTIVITY_BY_INTENT_VALUE)
.whereStrings().contains(sContext.getPackageName())
.whereBoolean().isFalse() // Not from work profile
).wasLogged();
}
}
@Test
@RequireRunOnWorkProfile(installInstrumentedAppInParent = TRUE)
@EnsureHasPermission(INTERACT_ACROSS_PROFILES)
@Postsubmit(reason = "new test")
public void startActivity_byIntent_fromWorkProfile_logged() throws Exception {
Intent intent = new Intent();
intent.setComponent(NOT_MAIN_ACTIVITY);
try (EnterpriseMetricsRecorder metrics = EnterpriseMetricsRecorder.create()) {
ActivityContext.runWithContext(activity ->
sCrossProfileApps.startActivity(
intent, sDeviceState.initialUser().userHandle(), activity));
assertThat(metrics.query()
.whereType().isEqualTo(EventId.START_ACTIVITY_BY_INTENT_VALUE)
.whereStrings().contains(sContext.getPackageName())
.whereBoolean().isTrue() // From work profile
).wasLogged();
}
}
@Test
@CrossUserTest({
@UserPair(from = INITIAL_USER, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = ADDITIONAL_USER),
@UserPair(from = WORK_PROFILE, to = ADDITIONAL_USER),
@UserPair(from = ADDITIONAL_USER, to = WORK_PROFILE)
})
public void
startMainActivity_targetIsInvalid_throwsSecurityException() {
TestApis.packages().instrumented().installExisting(sDeviceState.otherUser());
assertThrows(SecurityException.class,
() -> sCrossProfileApps.startMainActivity(
MAIN_ACTIVITY, sDeviceState.otherUser().userHandle()));
}
@Test
@CrossUserTest({
@UserPair(from = INITIAL_USER, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = ADDITIONAL_USER),
@UserPair(from = WORK_PROFILE, to = ADDITIONAL_USER),
@UserPair(from = ADDITIONAL_USER, to = WORK_PROFILE)
})
public void getProfileSwitchingLabel_targetIsInvalid_throwsSecurityException() {
TestApis.packages().instrumented().installExisting(sDeviceState.otherUser());
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.getProfileSwitchingLabel(sDeviceState.otherUser().userHandle());
});
}
@Test
@CrossUserTest({
@UserPair(from = WORK_PROFILE, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = WORK_PROFILE)
})
public void getProfileSwitchingLabel_targetIsValid_notNull() {
TestApis.packages().instrumented().installExisting(sDeviceState.otherUser());
assertThat(sCrossProfileApps.getProfileSwitchingLabel(
sDeviceState.otherUser().userHandle())).isNotNull();
}
@Test
@CrossUserTest({
@UserPair(from = INITIAL_USER, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = ADDITIONAL_USER),
@UserPair(from = WORK_PROFILE, to = ADDITIONAL_USER),
@UserPair(from = ADDITIONAL_USER, to = WORK_PROFILE)
})
public void getProfileSwitchingLabelIconDrawable_targetIsInvalid_throwsSecurityException() {
TestApis.packages().instrumented().installExisting(sDeviceState.otherUser());
assertThrows(SecurityException.class, () -> {
sCrossProfileApps.getProfileSwitchingIconDrawable(
sDeviceState.otherUser().userHandle());
});
}
@Test
@CrossUserTest({
@UserPair(from = WORK_PROFILE, to = INITIAL_USER),
@UserPair(from = INITIAL_USER, to = WORK_PROFILE)
})
public void getProfileSwitchingIconDrawable_targetIsValid_notNull() {
TestApis.packages().instrumented().installExisting(sDeviceState.otherUser());
assertThat(sCrossProfileApps.getProfileSwitchingIconDrawable(
sDeviceState.otherUser().userHandle())).isNotNull();
}
@Test
@CrossUserTest({
@UserPair(from = INITIAL_USER, to = WORK_PROFILE),
@UserPair(from = WORK_PROFILE, to = INITIAL_USER)
})
public void canRequestInteractAcrossProfiles_hasValidTarget_returnsTrue()
throws Exception {
RemoteDevicePolicyManager profileOwner = sDeviceState.profileOwner(WORK_PROFILE)
.devicePolicyManager();
try (TestAppInstance currentApp = sCrossProfileTestApp.install();
TestAppInstance otherApp = sCrossProfileTestApp.install(sDeviceState.otherUser())) {
profileOwner.setCrossProfilePackages(
sDeviceState.profileOwner(WORK_PROFILE).componentName(),
Set.of(sCrossProfileTestApp.packageName()));
assertThat(currentApp.crossProfileApps().canRequestInteractAcrossProfiles()).isTrue();
}
}
@Test
@EnsureHasNoProfile
@RequireRunOnInitialUser
public void canRequestInteractAcrossProfiles_noOtherProfiles_returnsFalse()
throws Exception {
try (TestAppInstance personalApp = sCrossProfileTestApp.install(
sDeviceState.initialUser())) {
assertThat(personalApp.crossProfileApps().canRequestInteractAcrossProfiles()).isFalse();
}
}
@Test
@EnsureHasWorkProfile
@RequireRunOnInitialUser
public void canRequestInteractAcrossProfiles_packageNotInAllowList_returnsTrue()
throws Exception {
RemoteDevicePolicyManager profileOwner = sDeviceState.profileOwner(WORK_PROFILE)
.devicePolicyManager();
try (TestAppInstance personalApp = sCrossProfileTestApp.install(
sDeviceState.initialUser());
TestAppInstance workApp = sCrossProfileTestApp.install(
sDeviceState.workProfile())) {
profileOwner.setCrossProfilePackages(
sDeviceState.profileOwner(WORK_PROFILE).componentName(),
Collections.emptySet());
assertThat(personalApp.crossProfileApps().canRequestInteractAcrossProfiles()).isTrue();
}
}
@Test
@EnsureHasWorkProfile
@RequireRunOnInitialUser
public void canRequestInteractAcrossProfiles_packageNotInstalledInPersonalProfile_returnsTrue()
throws Exception {
RemoteDevicePolicyManager profileOwner = sDeviceState.profileOwner(WORK_PROFILE)
.devicePolicyManager();
try (TestAppInstance workApp = sCrossProfileTestApp.install(
sDeviceState.workProfile())) {
profileOwner.setCrossProfilePackages(
sDeviceState.profileOwner(WORK_PROFILE).componentName(),
Set.of(sCrossProfileTestApp.packageName()));
assertThat(workApp.crossProfileApps().canRequestInteractAcrossProfiles()).isTrue();
}
}
@Test
@EnsureHasWorkProfile
@RequireRunOnInitialUser
public void canRequestInteractAcrossProfiles_packageNotInstalledInWorkProfile_returnsTrue()
throws Exception {
RemoteDevicePolicyManager profileOwner = sDeviceState.profileOwner(WORK_PROFILE)
.devicePolicyManager();
try (TestAppInstance personalApp = sCrossProfileTestApp.install(
sDeviceState.initialUser())) {
profileOwner.setCrossProfilePackages(
sDeviceState.profileOwner(WORK_PROFILE).componentName(),
Set.of(sCrossProfileTestApp.packageName()));
assertThat(personalApp.crossProfileApps().canRequestInteractAcrossProfiles()).isTrue();
}
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
public void canRequestInteractAcrossProfiles_permissionNotRequested_returnsFalse()
throws Exception {
RemoteDevicePolicyManager profileOwner = sDeviceState.profileOwner(WORK_PROFILE)
.devicePolicyManager();
try (TestAppInstance personalApp = sNonCrossProfileTestApp.install(
sDeviceState.initialUser());
TestAppInstance workApp = sNonCrossProfileTestApp.install(
sDeviceState.workProfile())) {
profileOwner.setCrossProfilePackages(
sDeviceState.profileOwner(WORK_PROFILE).componentName(),
Set.of(sCrossProfileTestApp.packageName()));
assertThat(personalApp.crossProfileApps().canRequestInteractAcrossProfiles()).isFalse();
}
}
// TODO(b/199148889): add require INTERACT_ACROSS_PROFILE permission for the dpc.
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
public void canRequestInteractAcrossProfiles_profileOwner_returnsFalse()
throws Exception {
RemoteDevicePolicyManager profileOwner = sDeviceState.profileOwner(WORK_PROFILE)
.devicePolicyManager();
profileOwner.setCrossProfilePackages(
sDeviceState.profileOwner(WORK_PROFILE).componentName(),
Set.of(sDeviceState.profileOwner(WORK_PROFILE).componentName().getPackageName()));
assertThat(
sDeviceState.profileOwner(WORK_PROFILE).crossProfileApps()
.canRequestInteractAcrossProfiles()
).isFalse();
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
public void canInteractAcrossProfiles_appOpIsSetOnAllProfiles_returnsTrue() {
try (TestAppInstance primaryApp = sCrossProfileTestApp.install();
TestAppInstance workApp = sCrossProfileTestApp.install(sDeviceState.workProfile())) {
sCrossProfileTestApp.pkg().appOps().set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES, AppOpsMode.ALLOWED);
sCrossProfileTestApp.pkg().appOps(sDeviceState.workProfile()).set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES,
AppOpsMode.ALLOWED);
assertThat(primaryApp.crossProfileApps().canInteractAcrossProfiles()).isTrue();
assertThat(workApp.crossProfileApps().canInteractAcrossProfiles()).isTrue();
}
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
public void canInteractAcrossProfiles_appOpDisabledOnCaller_returnsFalse() {
try (TestAppInstance primaryApp = sCrossProfileTestApp.install();
TestAppInstance workApp = sCrossProfileTestApp.install(sDeviceState.workProfile())) {
sCrossProfileTestApp.pkg().appOps().set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES, AppOpsMode.DEFAULT);
sCrossProfileTestApp.pkg().appOps(sDeviceState.workProfile()).set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES,
AppOpsMode.ALLOWED);
assertThat(primaryApp.crossProfileApps().canInteractAcrossProfiles()).isFalse();
}
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
public void canInteractAcrossProfiles_appOpDisabledOnOtherProfile_returnsFalse() {
try (TestAppInstance primaryApp = sCrossProfileTestApp.install();
TestAppInstance workApp = sCrossProfileTestApp.install(sDeviceState.workProfile())) {
sCrossProfileTestApp.pkg().appOps().set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES, AppOpsMode.ALLOWED);
sCrossProfileTestApp.pkg().appOps(sDeviceState.workProfile()).set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES,
AppOpsMode.DEFAULT);
assertThat(primaryApp.crossProfileApps().canInteractAcrossProfiles()).isFalse();
}
}
@Test
@RequireRunOnInitialUser
public void canInteractAcrossProfiles_noOtherProfile_returnsFalse() {
try (TestAppInstance primaryApp = sCrossProfileTestApp.install()) {
sCrossProfileTestApp.pkg().appOps().set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES, AppOpsMode.ALLOWED);
assertThat(primaryApp.crossProfileApps().canInteractAcrossProfiles()).isFalse();
}
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
@PermissionTest({
INTERACT_ACROSS_PROFILES, INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL})
// TODO(b/191637162): When we can adopt permissions for testapps, we can use testapps here
public void canInteractAcrossProfiles_permissionIsSet_returnsTrue() {
TestApis.packages().instrumented().appOps(sDeviceState.workProfile()).set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES,
AppOpsMode.ALLOWED);
assertThat(sCrossProfileApps.canInteractAcrossProfiles()).isTrue();
}
@Test
@RequireRunOnInitialUser
@EnsureHasNoProfile
public void createRequestInteractAcrossProfilesIntent_canNotRequest_throwsException() {
try (TestAppInstance primaryApp = sCrossProfileTestApp.install()) {
assertThrows(SecurityException.class,
() -> primaryApp.crossProfileApps()
.createRequestInteractAcrossProfilesIntent());
}
}
@Test
@RequireRunOnInitialUser
@EnsureHasWorkProfile
public void createRequestInteractAcrossProfilesIntent_canRequest_returnsIntent() {
try (TestAppInstance primaryApp = sCrossProfileTestApp.install();
TestAppInstance workApp = sCrossProfileTestApp.install(sDeviceState.workProfile())) {
sCrossProfileTestApp.pkg().appOps().set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES, AppOpsMode.ALLOWED);
sCrossProfileTestApp.pkg().appOps(sDeviceState.workProfile()).set(
AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES,
AppOpsMode.ALLOWED);
Intent intent = primaryApp.crossProfileApps()
.createRequestInteractAcrossProfilesIntent();
assertThat(intent.getAction()).isEqualTo(ACTION_MANAGE_CROSS_PROFILE_ACCESS);
assertThat(intent.getData().getSchemeSpecificPart())
.isEqualTo(sCrossProfileTestApp.packageName());
}
}
@Test
@RequireRunOnWorkProfile
public void setCrossProfilePackages_packageRemoved_packageReceivesBroadcast() {
try (TestAppInstance parentTestApp = sCrossProfileTestApp.install(TestApis.users().instrumented().parent());
TestAppInstance workTestApp = sCrossProfileTestApp.install()) {
sDeviceState.dpc().devicePolicyManager()
.setCrossProfilePackages(
sDeviceState.dpc().componentName(), Set.of(sCrossProfileTestApp.packageName()));
parentTestApp.appOps().setPermission(INTERACT_ACROSS_PROFILES, AppOpsMode.ALLOWED);
workTestApp.appOps().setPermission(INTERACT_ACROSS_PROFILES, AppOpsMode.ALLOWED);
EventLogs.resetLogs(); // Ignore any broadcasts related to setting the appOps
sDeviceState.dpc().devicePolicyManager()
.setCrossProfilePackages(
sDeviceState.dpc().componentName(), Set.of());
assertThat(parentTestApp.events().broadcastReceived()
.whereIntent().action().isEqualTo(ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED))
.eventOccurred();
assertThat(workTestApp.events().broadcastReceived()
.whereIntent().action().isEqualTo(ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED))
.eventOccurred();
}
}
}