diff options
| author | 2020-03-18 12:49:32 +0000 | |
|---|---|---|
| committer | 2020-03-23 17:23:17 +0000 | |
| commit | 2459a08f86b6d4794a8e95a08b77c4984f9a080a (patch) | |
| tree | 96e90428ddba50098bbfb93dbb6cd3846afca4fd | |
| parent | 8c6b17b1ad1c1d2d6687b95d71cf85639d99e0fb (diff) | |
Add new hidden API in CrossProfileApps and other minor changes
* Added a new hidden API canUserAttemptToConfigureInteractAcrossProfiles
to be used in settings.
* Changed canRequestToInteractAcrossProfiles to return true when app is
not whitelisted by the admin or installed in the other profile, this
enables the app to navigate the user to the cross profile settings page
were more information about why they can't grant the permission will be
provided.
Bug: 149742043
Test: atest CrossProfileAppsServiceImplRoboTest
Test: atest CrossProfileAppsPermissionHostSideTest
Test: CrossProfileAppsTest
Change-Id: I9c7734d7ab0c7436d84a27604146ff539e1cb26a
4 files changed, 75 insertions, 11 deletions
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java index 179fc5c661a5..6ba811e077ac 100644 --- a/core/java/android/content/pm/CrossProfileApps.java +++ b/core/java/android/content/pm/CrossProfileApps.java @@ -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()}. @@ -422,6 +428,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 * #INTERACT_ACROSS_PROFILES} back to its default value if it can no longer be configured by diff --git a/core/java/android/content/pm/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl index 4cecb30990e6..9b0dae221538 100644 --- a/core/java/android/content/pm/ICrossProfileApps.aidl +++ b/core/java/android/content/pm/ICrossProfileApps.aidl @@ -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); } diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java index 83da38195053..7069818e3894 100644 --- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java +++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java @@ -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()) { - return false; - } - if (!hasRequestedAppOpPermission( - AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) { + final int[] enabledProfileIds = + mInjector.getUserManager().getEnabledProfileIds(mInjector.getCallingUserId()); + if (enabledProfileIds.length < 2) { 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 = diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java index fa0febd7f20f..acdb68142178 100644 --- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java +++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java @@ -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); } |