blob: 2220d80172ba0bb3e51c836dfe4bad30d204b846 [file] [log] [blame]
package com.android.cts.devicepolicy;
import static android.stats.devicepolicy.EventId.CROSS_PROFILE_APPS_GET_TARGET_USER_PROFILES_VALUE;
import static android.stats.devicepolicy.EventId.CROSS_PROFILE_APPS_START_ACTIVITY_AS_USER_VALUE;
import static android.stats.devicepolicy.EventId.START_ACTIVITY_BY_INTENT_VALUE;
import static com.android.cts.devicepolicy.metrics.DevicePolicyEventLogVerifier.assertMetricsLogged;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import android.platform.test.annotations.FlakyTest;
import android.platform.test.annotations.LargeTest;
import com.android.cts.devicepolicy.metrics.DevicePolicyEventWrapper;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.util.StreamUtil;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.util.Collections;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
/**
* In the test, managed profile and secondary user are created. We then verify
* {@link android.content.pm.crossprofile.CrossProfileApps} APIs in different directions, like
* primary user to managed profile.
*
* Tests to verify
* {@link android.content.pm.crossprofile.CrossProfileApps#canRequestInteractAcrossProfiles()},
* {@link android.content.pm.crossprofile.CrossProfileApps#canInteractAcrossProfiles()}, and
* {@link
* android.content.pm.crossprofile.CrossProfileApps#createRequestInteractAcrossProfilesIntent()}
* can be found in {@link CrossProfileAppsPermissionHostSideTest}.
*/
public class CrossProfileAppsHostSideTest extends BaseDevicePolicyTest {
private static final String TEST_PACKAGE = "com.android.cts.crossprofileappstest";
private static final String NON_TARGET_USER_TEST_CLASS = ".CrossProfileAppsNonTargetUserTest";
private static final String TARGET_USER_TEST_CLASS = ".CrossProfileAppsTargetUserTest";
private static final String START_ACTIVITY_TEST_CLASS = ".CrossProfileAppsStartActivityTest";
private static final String PARAM_TARGET_USER = "TARGET_USER";
private static final String EXTRA_TEST_APK = "CtsCrossProfileAppsTests.apk";
private static final String SIMPLE_APP_APK ="CtsSimpleApp.apk";
private int mProfileId;
private int mSecondaryUserId;
private boolean mHasManagedUserFeature;
private boolean mCanTestMultiUser;
@Override
public void setUp() throws Exception {
super.setUp();
// We need managed users to be supported in order to create a profile of the user owner.
mHasManagedUserFeature = hasDeviceFeature("android.software.managed_users");
installRequiredApps(mPrimaryUserId);
if (mHasManagedUserFeature) {
createAndStartManagedProfile();
installRequiredApps(mProfileId);
}
waitForBroadcastIdle();
if (canCreateAdditionalUsers(1)) {
mSecondaryUserId = createUser();
installRequiredApps(mSecondaryUserId);
mCanTestMultiUser = true;
}
waitForBroadcastIdle();
}
private void installRequiredApps(int userId)
throws FileNotFoundException, DeviceNotAvailableException {
installAppAsUser(EXTRA_TEST_APK, userId);
installAppAsUser(SIMPLE_APP_APK, userId);
}
@FlakyTest
@LargeTest
@Test
public void testPrimaryUserToPrimaryUser() throws Exception {
verifyCrossProfileAppsApi(mPrimaryUserId, mPrimaryUserId, NON_TARGET_USER_TEST_CLASS);
}
@FlakyTest
@LargeTest
@Test
public void testPrimaryUserToManagedProfile() throws Exception {
if (!mHasManagedUserFeature) {
return;
}
verifyCrossProfileAppsApi(mPrimaryUserId, mProfileId, TARGET_USER_TEST_CLASS);
}
@LargeTest
@Test
public void testManagedProfileToPrimaryUser() throws Exception {
if (!mHasManagedUserFeature) {
return;
}
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, TARGET_USER_TEST_CLASS);
}
@LargeTest
@Test
public void testStartActivityComponent() throws Exception {
if (!mHasManagedUserFeature) {
return;
}
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCanStartMainActivityByComponent");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCanStartNonMainActivityByComponent");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCannotStartNotExportedActivityByComponent");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCannotStartActivityInOtherPackageByComponent");
}
@LargeTest
@Test
public void testStartActivityIntent() throws Exception {
if (!mHasManagedUserFeature) {
return;
}
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCannotStartActivityWithImplicitIntent");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCanStartMainActivityByIntent");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCanStartMainActivityByIntent_withOptionsBundle");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCanStartNonMainActivityByIntent");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCanStartNotExportedActivityByIntent");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCannotStartActivityInOtherPackageByIntent");
}
@LargeTest
@Test
public void testStartActivityIntentPermissions() throws Exception {
if (!mHasManagedUserFeature) {
return;
}
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCannotStartActivityByIntentWithNoPermissions");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCanStartActivityByIntentWithInteractAcrossProfilesPermission");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCanStartActivityByIntentWithInteractAcrossUsersPermission");
verifyCrossProfileAppsApi(mProfileId, mPrimaryUserId, START_ACTIVITY_TEST_CLASS, "testCanStartActivityByIntentWithInteractAcrossUsersFullPermission");
}
@LargeTest
@Test
public void testStartActivityIntent_isLogged() throws Exception {
if (!mHasManagedUserFeature) {
return;
}
assertMetricsLogged(
getDevice(),
() -> verifyCrossProfileAppsApi(
mProfileId,
mPrimaryUserId,
START_ACTIVITY_TEST_CLASS,
"testStartActivityByIntent_noAsserts"),
new DevicePolicyEventWrapper
.Builder(START_ACTIVITY_BY_INTENT_VALUE)
.setStrings(TEST_PACKAGE)
.setBoolean(true) // from work profile
.build());
}
@LargeTest
@Test
public void testStartActivityIntent_sameTaskByDefault() throws Exception {
// TODO(b/171957840): replace with device-side test using an inter-process communication
// library.
if (!mHasManagedUserFeature) {
return;
}
getDevice().clearLogcat();
verifyCrossProfileAppsApi(
mProfileId,
mPrimaryUserId,
START_ACTIVITY_TEST_CLASS,
"testStartActivityIntent_sameTaskByDefault");
assertThat(findTaskId("CrossProfileSameTaskLauncherActivity"))
.isEqualTo(findTaskId("NonMainActivity"));
}
private int findTaskId(String className) throws Exception {
final Matcher matcher =
Pattern.compile(className + "#taskId#" + "(.*?)" + "#").matcher(readLogcat());
boolean isFound = matcher.find();
if (!isFound) {
fail("Task not found for " + className);
return -1;
}
return Integer.parseInt(matcher.group(1));
}
@LargeTest
@Test
public void testStartActivityIntent_crossProfile_returnsResult() throws Exception {
// TODO(b/171957840): replace with device-side test using an inter-process communication
// library.
if (!mHasManagedUserFeature) {
return;
}
verifyCrossProfileAppsApi(
mProfileId,
mPrimaryUserId,
START_ACTIVITY_TEST_CLASS,
"testStartActivityIntent_crossProfile_returnsResult");
}
@LargeTest
@Test
public void testPrimaryUserToSecondaryUser() throws Exception {
if (!mCanTestMultiUser) {
return;
}
verifyCrossProfileAppsApi(mPrimaryUserId, mSecondaryUserId, NON_TARGET_USER_TEST_CLASS);
}
@LargeTest
@Test
public void testSecondaryUserToManagedProfile() throws Exception {
if (!mCanTestMultiUser || !mHasManagedUserFeature) {
return;
}
verifyCrossProfileAppsApi(mSecondaryUserId, mProfileId, NON_TARGET_USER_TEST_CLASS);
}
@LargeTest
@Test
public void testManagedProfileToSecondaryUser() throws Exception {
if (!mCanTestMultiUser || !mHasManagedUserFeature) {
return;
}
verifyCrossProfileAppsApi(mProfileId, mSecondaryUserId, NON_TARGET_USER_TEST_CLASS);
}
@LargeTest
@Test
public void testStartMainActivity_logged() throws Exception {
if (!mHasManagedUserFeature) {
return;
}
assertMetricsLogged(
getDevice(),
() -> {
runDeviceTest(
mProfileId,
mPrimaryUserId,
TARGET_USER_TEST_CLASS,
"testStartMainActivity_noAsserts");
},
new DevicePolicyEventWrapper
.Builder(CROSS_PROFILE_APPS_START_ACTIVITY_AS_USER_VALUE)
.setStrings(new String[] {"com.android.cts.crossprofileappstest"})
.build());
}
@LargeTest
@Test
public void testGetTargetUserProfiles_logged() throws Exception {
if (!mHasManagedUserFeature) {
return;
}
assertMetricsLogged(
getDevice(),
() -> {
runDeviceTest(
mProfileId,
mPrimaryUserId,
TARGET_USER_TEST_CLASS,
"testGetTargetUserProfiles_noAsserts");
},
new DevicePolicyEventWrapper
.Builder(CROSS_PROFILE_APPS_GET_TARGET_USER_PROFILES_VALUE)
.setStrings(new String[] {"com.android.cts.crossprofileappstest"})
.build());
}
private void verifyCrossProfileAppsApi(int fromUserId, int targetUserId, String testClass)
throws Exception {
verifyCrossProfileAppsApi(fromUserId, targetUserId, testClass, /* testMethod= */ null);
}
private void verifyCrossProfileAppsApi(int fromUserId, int targetUserId, String testClass, String testMethod)
throws Exception {
runDeviceTest(fromUserId, targetUserId, testClass, testMethod);
}
private void runDeviceTest(
int fromUserId, int targetUserId, String testClass, @Nullable String testMethod)
throws Exception {
runDeviceTestsAsUser(
TEST_PACKAGE,
testClass,
testMethod,
fromUserId,
createTargetUserParam(targetUserId));
}
private void createAndStartManagedProfile() throws Exception {
mProfileId = createManagedProfile(mPrimaryUserId);
switchUser(mPrimaryUserId);
startUser(mProfileId);
}
private Map<String, String> createTargetUserParam(int targetUserId) throws Exception {
return Collections.singletonMap(PARAM_TARGET_USER,
Integer.toString(getUserSerialNumber(targetUserId)));
}
private String readLogcat() throws Exception {
getDevice().stopLogcat();
final String logcat;
try (InputStreamSource logcatStream = getDevice().getLogcat()) {
logcat = StreamUtil.getStringFromSource(logcatStream);
}
getDevice().startLogcat();
return logcat;
}
}