Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d6cf38c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Prevent DPCs from requesting INTERACT_ACROSS_PROFILES" into rvc-dev

parents 4586885a e6a81b38
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -217,4 +217,9 @@ public abstract class DevicePolicyManagerInternal {
     */
    public abstract void broadcastIntentToCrossProfileManifestReceiversAsUser(Intent intent,
            UserHandle parentHandle, boolean requiresPermission);

    /**
     * Returns the profile owner component for the given user, or {@code null} if there is not one.
     */
    public abstract ComponentName getProfileOwnerAsUser(int userHandle);
}
+26 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.app.AppOpsManager;
import android.app.AppOpsManager.Mode;
import android.app.IApplicationThread;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.Context;
@@ -256,6 +257,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
        if (enabledProfileIds.length < 2) {
            return false;
        }
        if (isProfileOwner(packageName, enabledProfileIds)) {
            return false;
        }
        return hasRequestedAppOpPermission(
                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName);
    }
@@ -575,6 +579,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
        if (profileIds.length < 2) {
            return false;
        }
        if (isProfileOwner(packageName, profileIds)) {
            return false;
        }
        return hasRequestedAppOpPermission(
                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)
                && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
@@ -698,6 +705,25 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
                        packageName);
    }

    private boolean isProfileOwner(String packageName, int[] userIds) {
        for (int userId : userIds) {
            if (isProfileOwner(packageName, userId)) {
                return true;
            }
        }
        return false;
    }

    private boolean isProfileOwner(String packageName, final @UserIdInt int userId) {
        final ComponentName profileOwner =
                mInjector.withCleanCallingIdentity(() ->
                        mInjector.getDevicePolicyManagerInternal().getProfileOwnerAsUser(userId));
        if (profileOwner == null) {
            return false;
        }
        return profileOwner.getPackageName().equals(packageName);
    }

    private static class InjectorImpl implements Injector {
        private Context mContext;

+5 −0
Original line number Diff line number Diff line
@@ -12730,6 +12730,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                Binder.restoreCallingIdentity(ident);
            }
        }
        @Override
        public ComponentName getProfileOwnerAsUser(int userHandle) {
            return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle);
        }
    }
    private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
+38 −0
Original line number Diff line number Diff line
@@ -37,7 +37,9 @@ import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.AppOpsManager.Mode;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -97,6 +99,7 @@ public class CrossProfileAppsServiceImplRoboTest {
    private static final int WORK_PROFILE_USER_ID = 10;
    private static final int WORK_PROFILE_UID = 3333;
    private static final int OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID = 20;
    private static final int OUTSIDE_PROFILE_GROUP_USER_ID = 30;

    private final ContextWrapper mContext = ApplicationProvider.getApplicationContext();
    private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
@@ -226,6 +229,7 @@ public class CrossProfileAppsServiceImplRoboTest {
                PERSONAL_PROFILE_USER_ID,
                WORK_PROFILE_USER_ID,
                OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID);
        shadowUserManager.addProfileIds(OUTSIDE_PROFILE_GROUP_USER_ID);
    }

    @Before
@@ -503,6 +507,36 @@ public class CrossProfileAppsServiceImplRoboTest {
                .isFalse();
    }

    @Test
    public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerWorkProfile_returnsFalse() {
        when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(WORK_PROFILE_USER_ID))
                .thenReturn(buildCrossProfileComponentName());
        assertThat(mCrossProfileAppsServiceImpl
                .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
                .isFalse();
    }

    @Test
    public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOtherProfile_returnsFalse() {
        // Normally, the DPC would not be a profile owner of the personal profile, but for the
        // purposes of this test, it is just a profile owner of any profile within the profile
        // group.
        when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(PERSONAL_PROFILE_USER_ID))
                .thenReturn(buildCrossProfileComponentName());
        assertThat(mCrossProfileAppsServiceImpl
                .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
                .isFalse();
    }

    @Test
    public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOutsideProfileGroup_returnsTrue() {
        when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OUTSIDE_PROFILE_GROUP_USER_ID))
                .thenReturn(buildCrossProfileComponentName());
        assertThat(mCrossProfileAppsServiceImpl
                .canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
                .isTrue();
    }

    @Test
    public void canUserAttemptToConfigureInteractAcrossProfiles_returnsTrue() {
        assertThat(mCrossProfileAppsServiceImpl
@@ -607,6 +641,10 @@ public class CrossProfileAppsServiceImplRoboTest {
                        .hideAsParsed()).hideAsFinal());
    }

    private ComponentName buildCrossProfileComponentName() {
        return new ComponentName(CROSS_PROFILE_APP_PACKAGE_NAME, "testClassName");
    }

    private class TestInjector implements CrossProfileAppsServiceImpl.Injector {

        @Override