Merge "Add new hidden API in CrossProfileApps and other minor changes" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-03-24 13:46:23 +00:00
committed by Android (Google) Code Review
4 changed files with 75 additions and 11 deletions

View File

@@ -268,15 +268,17 @@ public class CrossProfileApps {
}
/**
* Returns whether the calling package can request user consent to interact across profiles.
* Returns whether the calling package can request to navigate the user to
* the relevant settings page to request user consent to interact across profiles.
*
* <p>If {@code true}, user consent can be obtained via {@link
* <p>If {@code true}, the navigation intent can be obtained via {@link
* #createRequestInteractAcrossProfilesIntent()}. The package can then listen to {@link
* #ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED} broadcasts.
*
* <p>Specifically, returns whether the following are all true:
* <ul>
* <li>{@link #getTargetUserProfiles()} returns a non-empty list for the calling user.</li>
* <li>{@code UserManager#getEnabledProfileIds(int)} ()} returns at least one other profile for
* the calling user.</li>
* <li>The calling app has requested</li>
* {@code android.Manifest.permission.INTERACT_ACROSS_PROFILES} in its manifest.
* <li>The calling package has either been whitelisted by default by the OEM or has been
@@ -285,6 +287,10 @@ public class CrossProfileApps {
* </li>
* </ul>
*
* <p>Note that in order for the user to be able to grant the consent, the requesting package
* must be whitelisted by the admin or the OEM and installed in the other profile. If this is
* not the case the user will be shown a message explaining why they can't grant the consent.
*
* <p>Note that user consent could already be granted if given a return value of {@code true}.
* The package's current ability to interact across profiles can be checked with {@link
* #canInteractAcrossProfiles()}.
@@ -421,6 +427,23 @@ public class CrossProfileApps {
}
}
/**
* Returns {@code true} if the given package has requested
* {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} and the user has at least one
* other profile in the same profile group.
*
* <p>This differs from {@link #canConfigureInteractAcrossProfiles(String)} since it will
* not return {@code false} if the app is not whitelisted or not installed in the other profile.
*
* @hide
*/
public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
try {
return mService.canUserAttemptToConfigureInteractAcrossProfiles(packageName);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
/**
* For each of the packages defined in {@code previousCrossProfilePackages} but not included in
* {@code newCrossProfilePackages}, resets the app-op for {@link android.Manifest.permission

View File

@@ -38,5 +38,6 @@ interface ICrossProfileApps {
boolean canRequestInteractAcrossProfiles(in String callingPackage);
void setInteractAcrossProfilesAppOp(in String packageName, int newMode);
boolean canConfigureInteractAcrossProfiles(in String packageName);
boolean canUserAttemptToConfigureInteractAcrossProfiles(in String packageName);
void resetInteractAcrossProfilesAppOps(in List<String> packageNames);
}

View File

@@ -249,16 +249,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
}
private boolean canRequestInteractAcrossProfilesUnchecked(String packageName) {
List<UserHandle> targetUserProfiles =
getTargetUserProfilesUnchecked(packageName, mInjector.getCallingUserId());
if (targetUserProfiles.isEmpty()) {
final int[] enabledProfileIds =
mInjector.getUserManager().getEnabledProfileIds(mInjector.getCallingUserId());
if (enabledProfileIds.length < 2) {
return false;
}
if (!hasRequestedAppOpPermission(
AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) {
return false;
}
return isCrossProfilePackageWhitelisted(packageName);
return hasRequestedAppOpPermission(
AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName);
}
private boolean hasRequestedAppOpPermission(String permission, String packageName) {
@@ -540,6 +537,17 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
return isCrossProfilePackageWhitelisted(packageName);
}
@Override
public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
final int[] profileIds = mInjector.getUserManager().getProfileIds(
mInjector.getCallingUserId(), /* enabledOnly= */ false);
if (profileIds.length < 2) {
return false;
}
return hasRequestedAppOpPermission(
AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName);
}
private boolean hasOtherProfileWithPackageInstalled(String packageName, @UserIdInt int userId) {
return mInjector.withCleanCallingIdentity(() -> {
final int[] profileIds =

View File

@@ -419,6 +419,38 @@ public class CrossProfileAppsServiceImplRoboTest {
.isTrue();
}
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsTrue() {
mockUninstallCrossProfileAppFromWorkProfile();
assertThat(mCrossProfileAppsServiceImpl
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
.isTrue();
}
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_packageDoesNotRequestInteractAcrossProfiles_returnsFalse()
throws Exception {
mockCrossProfileAppDoesNotRequestInteractAcrossProfiles();
assertThat(mCrossProfileAppsServiceImpl
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
.isFalse();
}
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_packageNotWhitelisted_returnsTrue() {
mockCrossProfileAppNotWhitelisted();
assertThat(mCrossProfileAppsServiceImpl
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
.isTrue();
}
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_returnsTrue() {
assertThat(mCrossProfileAppsServiceImpl
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
.isTrue();
}
private void explicitlySetInteractAcrossProfilesAppOp(@Mode int mode) {
explicitlySetInteractAcrossProfilesAppOp(PERSONAL_PROFILE_UID, mode);
}