summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author kholoud mohamed <kholoudm@google.com> 2020-03-27 13:29:19 +0000
committer Kholoud Mohamed <kholoudm@google.com> 2020-04-06 10:13:09 +0000
commit9bbab6a6df969a7c3e703fcd6076f4415847841f (patch)
treee9d320365f45be0bfabdc8347cd81b351df0633f
parentea6a210cf54fd90c042de30dde70ca3a2a0bc3b0 (diff)
Remove platform-signed apps from configurable cross profile apps
Most apps that declare the INTERACT_ACROSS_PROFILES permission do not have it granted, but get the app-op instead. We do not normally want platform-signed apps that are actually given the permission to appear in the user-configurable section in Settings, so we remove them from the return value of canUserAttemptToConfigureInteractAcrossProfiles in this CL. Note that OEM can choose to allow some platform-signed apps to be user-configurable by including them in their OEM whitelist file. This CL respects that and allows these apps to be configured by the user, despite being granted the permission. If the user rejects the app-op, PermissionChecker correctly returns false. Bug: 149742043 Test: atest CrossProfileAppsServiceImplRoboTest Change-Id: I693338507eec9cdc0ba10a3584e994a58d2d113c
-rw-r--r--core/java/android/app/admin/DevicePolicyManagerInternal.java18
-rw-r--r--core/java/android/content/pm/CrossProfileApps.java3
-rw-r--r--services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java39
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java5
-rw-r--r--services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java24
5 files changed, 85 insertions, 4 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 80fa87152d78..41f04f73aa87 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -176,19 +176,31 @@ public abstract class DevicePolicyManagerInternal {
* for cross-profile communication, via {@link
* DevicePolicyManager#setCrossProfilePackages(ComponentName, Set)}.</li>
* <li>The default package names that are allowed to request user consent for cross-profile
- * communication without being explicitly enabled by the admin , via {@link
- * DevicePolicyManager#setDefaultCrossProfilePackages(ComponentName, UserHandle, Set)}.</li>
+ * communication without being explicitly enabled by the admin, via
+ * {@link com.android.internal.R.array#cross_profile_apps} and
+ * {@link com.android.internal.R.array#vendor_cross_profile_apps}.</li>
* </ul>
*
* @return the combined set of whitelisted package names set via
* {@link DevicePolicyManager#setCrossProfilePackages(ComponentName, Set)} and
- * {@link DevicePolicyManager#setDefaultCrossProfilePackages(ComponentName, UserHandle, Set)}
+ * {@link com.android.internal.R.array#cross_profile_apps} and
+ * {@link com.android.internal.R.array#vendor_cross_profile_apps}
*
* @hide
*/
public abstract List<String> getAllCrossProfilePackages();
/**
+ * Returns the default package names set by the OEM that are allowed to request user consent for
+ * cross-profile communication without being explicitly enabled by the admin, via
+ * {@link com.android.internal.R.array#cross_profile_apps} and
+ * {@link com.android.internal.R.array#vendor_cross_profile_apps}.
+ *
+ * @hide
+ */
+ public abstract List<String> getDefaultCrossProfilePackages();
+
+ /**
* Sends the {@code intent} to the packages with cross profile capabilities.
*
* <p>This means the application must have the {@code crossProfile} property and the
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
index 7578ede2648d..144a07eb4ea3 100644
--- a/core/java/android/content/pm/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -435,6 +435,9 @@ public class CrossProfileApps {
* <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.
*
+ * <p>Note that platform-signed apps that are automatically granted the permission and are not
+ * whitelisted by the OEM will not be included in this list.
+ *
* @hide
*/
public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 40876754eae8..28c8642d3e60 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -294,6 +294,12 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
.getAllCrossProfilePackages().contains(packageName));
}
+ private boolean isCrossProfilePackageWhitelistedByDefault(String packageName) {
+ return mInjector.withCleanCallingIdentity(() ->
+ mInjector.getDevicePolicyManagerInternal()
+ .getDefaultCrossProfilePackages().contains(packageName));
+ }
+
private List<UserHandle> getTargetUserProfilesUnchecked(
String packageName, @UserIdInt int userId) {
return mInjector.withCleanCallingIdentity(() -> {
@@ -528,6 +534,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
@Override
public boolean canConfigureInteractAcrossProfiles(String packageName) {
+ if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName)) {
+ return false;
+ }
if (!hasOtherProfileWithPackageInstalled(packageName, mInjector.getCallingUserId())) {
return false;
}
@@ -546,7 +555,35 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
return false;
}
return hasRequestedAppOpPermission(
- AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName);
+ AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)
+ && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
+ }
+
+ private boolean isPlatformSignedAppWithNonUserConfigurablePermission(
+ String packageName, int[] profileIds) {
+ return !isCrossProfilePackageWhitelistedByDefault(packageName)
+ && isPlatformSignedAppWithAutomaticProfilesPermission(packageName, profileIds);
+ }
+
+ /**
+ * Only platform-signed apps can be granted INTERACT_ACROSS_PROFILES automatically without user
+ * consent.
+ *
+ * Returns true if the app is automatically granted the permission in at least one profile.
+ */
+ private boolean isPlatformSignedAppWithAutomaticProfilesPermission(
+ String packageName, int[] profileIds) {
+ for (int userId : profileIds) {
+ final int uid = mInjector.getPackageManagerInternal().getPackageUidInternal(
+ packageName, /* flags= */ 0, userId);
+ if (uid == -1) {
+ continue;
+ }
+ if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_PROFILES, uid)) {
+ return true;
+ }
+ }
+ return false;
}
private boolean hasOtherProfileWithPackageInstalled(String packageName, @UserIdInt int userId) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d1c47d9feed7..67e83bad154f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -12459,6 +12459,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return DevicePolicyManagerService.this.getAllCrossProfilePackages();
}
+ @Override
+ public List<String> getDefaultCrossProfilePackages() {
+ return DevicePolicyManagerService.this.getDefaultCrossProfilePackages();
+ }
+
/**
* Sends the {@code intent} to the packages with cross profile capabilities.
*
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index 138f9829c088..f8d197acf883 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -199,6 +199,12 @@ public class CrossProfileAppsServiceImplRoboTest {
CROSS_PROFILE_APP_PACKAGE_NAME, PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID);
ShadowApplicationPackageManager.setPackageUidAsUser(
CROSS_PROFILE_APP_PACKAGE_NAME, WORK_PROFILE_UID, WORK_PROFILE_USER_ID);
+ when(mPackageManagerInternal.getPackageUidInternal(
+ CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, PERSONAL_PROFILE_USER_ID))
+ .thenReturn(PERSONAL_PROFILE_UID);
+ when(mPackageManagerInternal.getPackageUidInternal(
+ CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, WORK_PROFILE_USER_ID))
+ .thenReturn(WORK_PROFILE_UID);
}
@Before
@@ -456,6 +462,19 @@ public class CrossProfileAppsServiceImplRoboTest {
}
@Test
+ public void canUserAttemptToConfigureInteractAcrossProfiles_platformSignedAppWithAutomaticPermission_returnsFalse() {
+ mockCrossProfileAppNotWhitelistedByOem();
+ shadowOf(mContext).grantPermissions(
+ Process.myPid(),
+ PERSONAL_PROFILE_UID,
+ Manifest.permission.INTERACT_ACROSS_PROFILES);
+
+ assertThat(mCrossProfileAppsServiceImpl
+ .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
+ .isFalse();
+ }
+
+ @Test
public void canUserAttemptToConfigureInteractAcrossProfiles_returnsTrue() {
assertThat(mCrossProfileAppsServiceImpl
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
@@ -528,6 +547,11 @@ public class CrossProfileAppsServiceImplRoboTest {
.thenReturn(new ArrayList<>());
}
+ private void mockCrossProfileAppNotWhitelistedByOem() {
+ when(mDevicePolicyManagerInternal.getDefaultCrossProfilePackages())
+ .thenReturn(new ArrayList<>());
+ }
+
private boolean receivedManifestCanInteractAcrossProfilesChangedBroadcast() {
final UserHandle userHandle = UserHandle.of(PERSONAL_PROFILE_USER_ID);
if (!mSentUserBroadcasts.containsKey(userHandle)) {