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

Commit 59da30ff authored by Alex Kershaw's avatar Alex Kershaw Committed by Android (Google) Code Review
Browse files

Merge "Add hidden API to clear all cross-profile app-ops" into rvc-dev

parents edc77996 ec19b8d0
Loading
Loading
Loading
Loading
+28 −0
Original line number Original line Diff line number Diff line
@@ -487,6 +487,34 @@ public class CrossProfileApps {
        }
        }
    }
    }


    /**
     * Clears the app-op for {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} back to
     * its default value for every package on the device.
     *
     * <p>This method can be used to ensure that app-op state is not left around on existing users
     * for previously-configured profiles.
     *
     * <p>If the caller does not have the {@link android.Manifest.permission
     * #CONFIGURE_INTERACT_ACROSS_PROFILES} permission, then they must have the permissions that
     * would have been required to call {@link android.app.AppOpsManager#setMode(int, int, String,
     * int)}, which includes {@link android.Manifest.permission#MANAGE_APP_OPS_MODES}.
     *
     * <p>Also requires either {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or {@link
     * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
     *
     * @hide
     */
    @RequiresPermission(
            allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
                    android.Manifest.permission.INTERACT_ACROSS_USERS})
    public void clearInteractAcrossProfilesAppOps() {
        try {
            mService.clearInteractAcrossProfilesAppOps();
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

    private void verifyCanAccessUser(UserHandle userHandle) {
    private void verifyCanAccessUser(UserHandle userHandle) {
        if (!getTargetUserProfiles().contains(userHandle)) {
        if (!getTargetUserProfiles().contains(userHandle)) {
            throw new SecurityException("Not allowed to access " + userHandle);
            throw new SecurityException("Not allowed to access " + userHandle);
+1 −0
Original line number Original line Diff line number Diff line
@@ -40,4 +40,5 @@ interface ICrossProfileApps {
    boolean canConfigureInteractAcrossProfiles(in String packageName);
    boolean canConfigureInteractAcrossProfiles(in String packageName);
    boolean canUserAttemptToConfigureInteractAcrossProfiles(in String packageName);
    boolean canUserAttemptToConfigureInteractAcrossProfiles(in String packageName);
    void resetInteractAcrossProfilesAppOps(in List<String> packageNames);
    void resetInteractAcrossProfilesAppOps(in List<String> packageNames);
    void clearInteractAcrossProfilesAppOps();
}
}
+20 −1
Original line number Original line Diff line number Diff line
@@ -64,6 +64,7 @@ import com.android.server.wm.ActivityTaskManagerInternal;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.stream.Collectors;


public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
    private static final String TAG = "CrossProfileAppsService";
    private static final String TAG = "CrossProfileAppsService";
@@ -447,7 +448,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
        final int uid = mInjector.getPackageManager()
        final int uid = mInjector.getPackageManager()
                .getPackageUidAsUser(packageName, /* flags= */ 0, userId);
                .getPackageUidAsUser(packageName, /* flags= */ 0, userId);
        if (currentModeEquals(newMode, packageName, uid)) {
        if (currentModeEquals(newMode, packageName, uid)) {
            Slog.w(TAG, "Attempt to set mode to existing value of " + newMode + " for "
            Slog.i(TAG, "Attempt to set mode to existing value of " + newMode + " for "
                    + packageName + " on user ID " + userId);
                    + packageName + " on user ID " + userId);
            return;
            return;
        }
        }
@@ -577,6 +578,24 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
        setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op));
        setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op));
    }
    }


    @Override
    public void clearInteractAcrossProfilesAppOps() {
        final int defaultMode =
                AppOpsManager.opToDefaultMode(
                        AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES));
        findAllPackageNames()
                .forEach(packageName -> setInteractAcrossProfilesAppOp(packageName, defaultMode));
    }

    private List<String> findAllPackageNames() {
        return mInjector.getPackageManagerInternal()
                .getInstalledApplications(
                        /* flags= */ 0, mInjector.getCallingUserId(), mInjector.getCallingUid())
                .stream()
                .map(applicationInfo -> applicationInfo.packageName)
                .collect(Collectors.toList());
    }

    CrossProfileAppsInternal getLocalService() {
    CrossProfileAppsInternal getLocalService() {
        return mLocalService;
        return mLocalService;
    }
    }
+18 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.pm;
package com.android.server.pm;


import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_INTERACT_ACROSS_PROFILES;
import static android.app.AppOpsManager.OP_INTERACT_ACROSS_PROFILES;
import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
import static android.content.Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND;
import static android.content.Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND;
@@ -104,6 +105,7 @@ public class CrossProfileAppsServiceImplRoboTest {
    private final CrossProfileAppsServiceImpl mCrossProfileAppsServiceImpl =
    private final CrossProfileAppsServiceImpl mCrossProfileAppsServiceImpl =
            new CrossProfileAppsServiceImpl(mContext, mInjector);
            new CrossProfileAppsServiceImpl(mContext, mInjector);
    private final Map<UserHandle, Set<Intent>> mSentUserBroadcasts = new HashMap<>();
    private final Map<UserHandle, Set<Intent>> mSentUserBroadcasts = new HashMap<>();
    private final Map<Integer, List<ApplicationInfo>> installedApplications = new HashMap<>();


    @Mock private PackageManagerInternal mPackageManagerInternal;
    @Mock private PackageManagerInternal mPackageManagerInternal;
    @Mock private IPackageManager mIPackageManager;
    @Mock private IPackageManager mIPackageManager;
@@ -112,12 +114,18 @@ public class CrossProfileAppsServiceImplRoboTest {
    @Before
    @Before
    public void initializeMocks() throws Exception {
    public void initializeMocks() throws Exception {
        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.initMocks(this);
        initializeInstalledApplicationsMock();
        mockCrossProfileAppInstalledAndEnabledOnEachProfile();
        mockCrossProfileAppInstalledAndEnabledOnEachProfile();
        mockCrossProfileAppRequestsInteractAcrossProfiles();
        mockCrossProfileAppRequestsInteractAcrossProfiles();
        mockCrossProfileAppRegistersBroadcastReceiver();
        mockCrossProfileAppRegistersBroadcastReceiver();
        mockCrossProfileAppWhitelisted();
        mockCrossProfileAppWhitelisted();
    }
    }


    private void initializeInstalledApplicationsMock() {
        when(mPackageManagerInternal.getInstalledApplications(anyInt(), anyInt(), eq(CALLING_UID)))
                .thenAnswer(invocation -> installedApplications.get(invocation.getArgument(1)));
    }

    private void mockCrossProfileAppInstalledAndEnabledOnEachProfile() {
    private void mockCrossProfileAppInstalledAndEnabledOnEachProfile() {
        // They are enabled by default, so we simply have to ensure that a package info with an
        // They are enabled by default, so we simply have to ensure that a package info with an
        // application info is returned.
        // application info is returned.
@@ -138,11 +146,14 @@ public class CrossProfileAppsServiceImplRoboTest {
        when(mPackageManagerInternal.getPackage(uid))
        when(mPackageManagerInternal.getPackage(uid))
                .thenReturn(((ParsedPackage) PackageImpl.forTesting(CROSS_PROFILE_APP_PACKAGE_NAME)
                .thenReturn(((ParsedPackage) PackageImpl.forTesting(CROSS_PROFILE_APP_PACKAGE_NAME)
                        .hideAsParsed()).hideAsFinal());
                        .hideAsParsed()).hideAsFinal());
        installedApplications.putIfAbsent(userId, new ArrayList<>());
        installedApplications.get(userId).add(packageInfo.applicationInfo);
    }
    }


    private PackageInfo buildTestPackageInfo() {
    private PackageInfo buildTestPackageInfo() {
        PackageInfo packageInfo = new PackageInfo();
        PackageInfo packageInfo = new PackageInfo();
        packageInfo.applicationInfo = new ApplicationInfo();
        packageInfo.applicationInfo = new ApplicationInfo();
        packageInfo.applicationInfo.packageName = CROSS_PROFILE_APP_PACKAGE_NAME;
        return packageInfo;
        return packageInfo;
    }
    }


@@ -451,6 +462,13 @@ public class CrossProfileAppsServiceImplRoboTest {
                .isTrue();
                .isTrue();
    }
    }


    @Test
    public void clearInteractAcrossProfilesAppOps() {
        explicitlySetInteractAcrossProfilesAppOp(MODE_ALLOWED);
        mCrossProfileAppsServiceImpl.clearInteractAcrossProfilesAppOps();
        assertThat(getCrossProfileAppOp()).isEqualTo(MODE_DEFAULT);
    }

    private void explicitlySetInteractAcrossProfilesAppOp(@Mode int mode) {
    private void explicitlySetInteractAcrossProfilesAppOp(@Mode int mode) {
        explicitlySetInteractAcrossProfilesAppOp(PERSONAL_PROFILE_UID, mode);
        explicitlySetInteractAcrossProfilesAppOp(PERSONAL_PROFILE_UID, mode);
    }
    }