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

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

Merge "DO NOT MERGE Correctly reset cross-profile app-op" into rvc-qpr-dev

parents bced8a0b f764d9e9
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -222,4 +222,16 @@ public abstract class DevicePolicyManagerInternal {
     * Returns the profile owner component for the given user, or {@code null} if there is not one.
     */
    public abstract ComponentName getProfileOwnerAsUser(int userHandle);

    /**
     * Returns whether this class supports being deferred the responsibility for resetting the given
     * op.
     */
    public abstract boolean supportsResetOp(int op);

    /**
     * Resets the given op across the profile group of the given user for the given package. Assumes
     * {@link #supportsResetOp(int)} is true.
     */
    public abstract void resetOp(int op, String packageName, @UserIdInt int userId);
}
+11 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.content.pm;

import android.annotation.UserIdInt;
import android.app.AppOpsManager.Mode;
import android.os.UserHandle;

import java.util.List;
@@ -62,4 +63,14 @@ public abstract class CrossProfileAppsInternal {
     */
    public abstract List<UserHandle> getTargetUserProfiles(
            String packageName, @UserIdInt int userId);

    /**
     * Sets the app-op for {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} that is
     * configurable by users in Settings. This configures it for the profile group of the given
     * user.
     *
     * @see CrossProfileApps#setInteractAcrossProfilesAppOp(String, int)
     */
    public abstract void setInteractAcrossProfilesAppOp(
            String packageName, @Mode int newMode, @UserIdInt int userId);
}
+26 −7
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import android.Manifest;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
@@ -89,6 +90,7 @@ import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.app.AsyncNotedAppOp;
import android.app.RuntimeAppOpAccessMessage;
import android.app.SyncNotedAppOp;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -270,6 +272,8 @@ public class AppOpsService extends IAppOpsService.Stub {

    private final AppOpsManagerInternalImpl mAppOpsManagerInternal
            = new AppOpsManagerInternalImpl();
    @Nullable private final DevicePolicyManagerInternal dpmi =
            LocalServices.getService(DevicePolicyManagerInternal.class);

    /**
     * Registered callbacks, called from {@link #collectAsyncNotedOp}.
@@ -2675,6 +2679,10 @@ public class AppOpsService extends IAppOpsService.Stub {
                    Ops pkgOps = ent.getValue();
                    for (int j=pkgOps.size()-1; j>=0; j--) {
                        Op curOp = pkgOps.valueAt(j);
                        if (shouldDeferResetOpToDpm(curOp.op)) {
                            deferResetOpToDpm(curOp.op, reqPackageName, reqUserId);
                            continue;
                        }
                        if (AppOpsManager.opAllowsReset(curOp.op)
                                && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
                            int previousMode = curOp.mode;
@@ -2724,7 +2732,6 @@ public class AppOpsService extends IAppOpsService.Stub {
            }
        }

        if (allChanges != null) {
        int numChanges = allChanges.size();
        for (int i = 0; i < numChanges; i++) {
            ChangeRec change = allChanges.get(i);
@@ -2732,6 +2739,18 @@ public class AppOpsService extends IAppOpsService.Stub {
                    AppOpsManager.opToDefaultMode(change.op), change.previous_mode);
        }
    }

    private boolean shouldDeferResetOpToDpm(int op) {
        // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission
        //  pre-grants to a role-based mechanism or another general-purpose mechanism.
        return dpmi != null && dpmi.supportsResetOp(op);
    }

    /** Assumes {@link #shouldDeferResetOpToDpm(int)} is true. */
    private void deferResetOpToDpm(int op, String packageName, @UserIdInt int userId) {
        // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission
        //  pre-grants to a role-based mechanism or another general-purpose mechanism.
        dpmi.resetOp(op, packageName, userId);
    }

    private void evalAllForegroundOpsLocked() {
+86 −74
Original line number Diff line number Diff line
@@ -14,14 +14,17 @@
 * limitations under the License.
 */
package com.android.server.pm;

import static android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES;
import static android.Manifest.permission.INTERACT_ACROSS_PROFILES;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_APP_OPS_MODES;
import static android.app.AppOpsManager.OP_INTERACT_ACROSS_PROFILES;
import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY;
import static android.content.pm.CrossProfileApps.ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;

import android.Manifest;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -31,7 +34,6 @@ 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;
@@ -154,15 +156,15 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
            if (callerUserId != userId) {
                final int permissionFlag =  PermissionChecker.checkPermissionForPreflight(
                        mContext,
                        android.Manifest.permission.INTERACT_ACROSS_PROFILES,
                        INTERACT_ACROSS_PROFILES,
                        callingPid,
                        callingUid,
                        callingPackage);
                if (permissionFlag != PermissionChecker.PERMISSION_GRANTED
                        || !isSameProfileGroup(callerUserId, userId)) {
                    throw new SecurityException("Attempt to launch activity without required "
                            + android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
                            + " or target user is not in the same profile group.");
                            + INTERACT_ACROSS_PROFILES
                            + " permission or target user is not in the same profile group.");
                }
            }
            launchIntent.setComponent(component);
@@ -217,8 +219,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
        if (callerUserId != userId) {
            if (!hasCallerGotInteractAcrossProfilesPermission(callingPackage)) {
                throw new SecurityException("Attempt to launch activity without required "
                        + android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
                        + " or target user is not in the same profile group.");
                        + INTERACT_ACROSS_PROFILES
                        + " permission or target user is not in the same profile group.");
            }
        }

@@ -294,13 +296,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
                callingPackage, mInjector.getCallingUid(), mInjector.getCallingPid());
    }

    private boolean isCrossProfilePackageWhitelisted(String packageName) {
    private boolean isCrossProfilePackageAllowlisted(String packageName) {
        return mInjector.withCleanCallingIdentity(() ->
                mInjector.getDevicePolicyManagerInternal()
                        .getAllCrossProfilePackages().contains(packageName));
    }

    private boolean isCrossProfilePackageWhitelistedByDefault(String packageName) {
    private boolean isCrossProfilePackageAllowlistedByDefault(String packageName) {
        return mInjector.withCleanCallingIdentity(() ->
                mInjector.getDevicePolicyManagerInternal()
                        .getDefaultCrossProfilePackages().contains(packageName));
@@ -388,32 +390,36 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
    /**
     * See {@link android.content.pm.CrossProfileApps#setInteractAcrossProfilesAppOp(String, int)}.
     *
     * <p>Logs metrics. Use {@link #setInteractAcrossProfilesAppOpUnchecked(String, int, boolean)}
     * to avoid permission checks or to specify not to log metrics.
     * <p>Use {@link #setInteractAcrossProfilesAppOpUnchecked(String, int, int)} to avoid permission
     * checks.
     */
    @Override
    public void setInteractAcrossProfilesAppOp(String packageName, @Mode int newMode) {
        setInteractAcrossProfilesAppOp(packageName, newMode, mInjector.getCallingUserId());
    }

    private void setInteractAcrossProfilesAppOp(
            String packageName, @Mode int newMode, @UserIdInt int userId) {
        final int callingUid = mInjector.getCallingUid();
        if (!isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
                && !isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, callingUid)) {
        if (!isPermissionGranted(INTERACT_ACROSS_USERS_FULL, callingUid)
                && !isPermissionGranted(INTERACT_ACROSS_USERS, callingUid)) {
            throw new SecurityException(
                    "INTERACT_ACROSS_USERS or INTERACT_ACROSS_USERS_FULL is required to set the"
                            + " app-op for interacting across profiles.");
        }
        if (!isPermissionGranted(Manifest.permission.MANAGE_APP_OPS_MODES, callingUid)
                && !isPermissionGranted(
                        Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
        if (!isPermissionGranted(MANAGE_APP_OPS_MODES, callingUid)
                && !isPermissionGranted(CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
            throw new SecurityException(
                    "MANAGE_APP_OPS_MODES or CONFIGURE_INTERACT_ACROSS_PROFILES is required to set"
                            + " the app-op for interacting across profiles.");
        }
        setInteractAcrossProfilesAppOpUnchecked(packageName, newMode, /* logMetrics= */ true);
        setInteractAcrossProfilesAppOpUnchecked(packageName, newMode, userId);
    }

    private void setInteractAcrossProfilesAppOpUnchecked(
            String packageName, @Mode int newMode, boolean logMetrics) {
            String packageName, @Mode int newMode, @UserIdInt int userId) {
        if (newMode == AppOpsManager.MODE_ALLOWED
                && !canConfigureInteractAcrossProfiles(packageName)) {
                && !canConfigureInteractAcrossProfiles(packageName, userId)) {
            // The user should not be prompted for apps that cannot request to interact across
            // profiles. However, we return early here if required to avoid race conditions.
            Slog.e(TAG, "Tried to turn on the appop for interacting across profiles for invalid"
@@ -421,56 +427,57 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
            return;
        }
        final int[] profileIds =
                mInjector.getUserManager()
                        .getProfileIds(mInjector.getCallingUserId(), /* enabledOnly= */ false);
                mInjector.getUserManager().getProfileIds(userId, /* enabledOnly= */ false);
        for (int profileId : profileIds) {
            if (!isPackageInstalled(packageName, profileId)) {
                continue;
            }
            setInteractAcrossProfilesAppOpForUser(packageName, newMode, profileId, logMetrics);
            // Only log once per profile group by checking against the user ID.
            setInteractAcrossProfilesAppOpForProfile(
                    packageName, newMode, profileId, /* logMetrics= */ profileId == userId);
        }
    }

    /**
     * Returns whether the given package name is installed in the given user ID. The calling UID is
     * used as the filter calling UID, as described at {@link PackageManagerInternal#getPackageInfo(
     * String, int, int, int)}.
     */
    private boolean isPackageInstalled(String packageName, @UserIdInt int userId) {
        final int callingUid = mInjector.getCallingUid();
        return mInjector.withCleanCallingIdentity(() -> {
            final int flags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
            final PackageInfo info =
                    mInjector.getPackageManagerInternal()
                            .getPackageInfo(
                                    packageName,
                                    MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
                                    callingUid,
                                    userId);
                            .getPackageInfo(packageName, flags, mInjector.getCallingUid(), userId);
            return info != null;
        });
    }

    private void setInteractAcrossProfilesAppOpForUser(
            String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics) {
    private void setInteractAcrossProfilesAppOpForProfile(
            String packageName, @Mode int newMode, @UserIdInt int profileId, boolean logMetrics) {
        try {
            setInteractAcrossProfilesAppOpForUserOrThrow(packageName, newMode, userId, logMetrics);
            setInteractAcrossProfilesAppOpForProfileOrThrow(
                    packageName, newMode, profileId, logMetrics);
        } catch (PackageManager.NameNotFoundException e) {
            Slog.e(TAG, "Missing package " + packageName + " on user ID " + userId, e);
            Slog.e(TAG, "Missing package " + packageName + " on profile user ID " + profileId, e);
        }
    }

    private void setInteractAcrossProfilesAppOpForUserOrThrow(
            String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics)
    private void setInteractAcrossProfilesAppOpForProfileOrThrow(
            String packageName, @Mode int newMode, @UserIdInt int profileId, boolean logMetrics)
            throws PackageManager.NameNotFoundException {
        final int uid = mInjector.getPackageManager()
                .getPackageUidAsUser(packageName, /* flags= */ 0, userId);
                .getPackageUidAsUser(packageName, /* flags= */ 0, profileId);
        if (currentModeEquals(newMode, packageName, uid)) {
            Slog.i(TAG, "Attempt to set mode to existing value of " + newMode + " for "
                    + packageName + " on user ID " + userId);
                    + packageName + " on profile user ID " + profileId);
            return;
        }

        final boolean hadPermission = hasInteractAcrossProfilesPermission(
                packageName, uid, PermissionChecker.PID_UNKNOWN);

        final int callingUid = mInjector.getCallingUid();
        if (isPermissionGranted(
                Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
        if (isPermissionGranted(CONFIGURE_INTERACT_ACROSS_PROFILES, mInjector.getCallingUid())) {
            // Clear calling identity since the CONFIGURE_INTERACT_ACROSS_PROFILES permission allows
            // this particular app-op to be modified without the broader app-op permissions.
            mInjector.withCleanCallingIdentity(() ->
@@ -483,16 +490,15 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
        // Kill the UID before sending the broadcast to ensure that apps can be informed when
        // their app-op has been revoked.
        maybeKillUid(packageName, uid, hadPermission);
        sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(userId));
        maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, userId, logMetrics, uid);
        sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(profileId));
        maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, logMetrics, uid);
    }

    /**
     * Kills the process represented by the given UID if it has lost the permission to
     * interact across profiles.
     */
    private void maybeKillUid(
            String packageName, int uid, boolean hadPermission) {
    private void maybeKillUid(String packageName, int uid, boolean hadPermission) {
        if (!hadPermission) {
            return;
        }
@@ -503,18 +509,10 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
    }

    private void maybeLogSetInteractAcrossProfilesAppOp(
            String packageName,
            @Mode int newMode,
            @UserIdInt int userId,
            boolean logMetrics,
            int uid) {
            String packageName, @Mode int newMode, boolean logMetrics, int uid) {
        if (!logMetrics) {
            return;
        }
        if (userId != mInjector.getCallingUserId()) {
            // Only log once per profile group by checking for the calling user ID.
            return;
        }
        DevicePolicyEventLogger
                .createEvent(DevicePolicyEnums.SET_INTERACT_ACROSS_PROFILES_APP_OP)
                .setStrings(packageName)
@@ -529,8 +527,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
     * any necessary permission checks.
     */
    private boolean currentModeEquals(@Mode int otherMode, String packageName, int uid) {
        final String op =
                AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES);
        final String op = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES);
        return mInjector.withCleanCallingIdentity(() -> otherMode
                == mInjector.getAppOpsManager().unsafeCheckOpNoThrow(op, uid, packageName));
    }
@@ -562,37 +559,49 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {

    @Override
    public boolean canConfigureInteractAcrossProfiles(String packageName) {
        if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName)) {
        return canConfigureInteractAcrossProfiles(packageName, mInjector.getCallingUserId());
    }

    private boolean canConfigureInteractAcrossProfiles(String packageName, @UserIdInt int userId) {
        if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName, userId)) {
            return false;
        }
        if (!hasOtherProfileWithPackageInstalled(packageName, mInjector.getCallingUserId())) {
        if (!hasOtherProfileWithPackageInstalled(packageName, userId)) {
            return false;
        }
        if (!hasRequestedAppOpPermission(
                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) {
            return false;
        }
        return isCrossProfilePackageWhitelisted(packageName);
        return isCrossProfilePackageAllowlisted(packageName);
    }

    @Override
    public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
        final int[] profileIds = mInjector.getUserManager().getProfileIds(
                mInjector.getCallingUserId(), /* enabledOnly= */ false);
        return canUserAttemptToConfigureInteractAcrossProfiles(
                packageName, mInjector.getCallingUserId());
    }

    private boolean canUserAttemptToConfigureInteractAcrossProfiles(
            String packageName, @UserIdInt int userId) {
        final int[] profileIds =
                mInjector.getUserManager().getProfileIds(userId, /* enabledOnly= */ false);
        if (profileIds.length < 2) {
            return false;
        }
        if (isProfileOwner(packageName, profileIds)) {
            return false;
        }
        return hasRequestedAppOpPermission(
                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)
                && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
        if (!hasRequestedAppOpPermission(
                AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) {
            return false;
        }
        return !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
    }

    private boolean isPlatformSignedAppWithNonUserConfigurablePermission(
            String packageName, int[] profileIds) {
        return !isCrossProfilePackageWhitelistedByDefault(packageName)
        return !isCrossProfilePackageAllowlistedByDefault(packageName)
                && isPlatformSignedAppWithAutomaticProfilesPermission(packageName, profileIds);
    }

@@ -610,7 +619,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
            if (uid == -1) {
                continue;
            }
            if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_PROFILES, uid)) {
            if (isPermissionGranted(INTERACT_ACROSS_PROFILES, uid)) {
                return true;
            }
        }
@@ -642,7 +651,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
            return;
        }
        final String op =
                AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES);
                AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES);
        setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op));
    }

@@ -650,7 +659,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
    public void clearInteractAcrossProfilesAppOps() {
        final int defaultMode =
                AppOpsManager.opToDefaultMode(
                        AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES));
                        AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES));
        findAllPackageNames()
                .forEach(packageName -> setInteractAcrossProfilesAppOp(packageName, defaultMode));
    }
@@ -695,17 +704,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
    }

    private boolean hasInteractAcrossProfilesPermission(String packageName, int uid, int pid) {
        if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)
                || isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, uid)) {
        if (isPermissionGranted(INTERACT_ACROSS_USERS_FULL, uid)
                || isPermissionGranted(INTERACT_ACROSS_USERS, uid)) {
            return true;
        }
        return PermissionChecker.PERMISSION_GRANTED
                == PermissionChecker.checkPermissionForPreflight(
                        mContext,
                        Manifest.permission.INTERACT_ACROSS_PROFILES,
                        pid,
                        uid,
                        packageName);
                        mContext, INTERACT_ACROSS_PROFILES, pid, uid, packageName);
    }

    private boolean isProfileOwner(String packageName, int[] userIds) {
@@ -898,5 +903,12 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
        public List<UserHandle> getTargetUserProfiles(String packageName, int userId) {
            return getTargetUserProfilesUnchecked(packageName, userId);
        }

        @Override
        public void setInteractAcrossProfilesAppOp(
                String packageName, int newMode, @UserIdInt int userId) {
            CrossProfileAppsServiceImpl.this.setInteractAcrossProfilesAppOpUnchecked(
                    packageName, newMode, userId);
        }
    }
}
+23 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ import android.app.ActivityThread;
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AppOpsManager.Mode;
import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
@@ -12816,6 +12817,28 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        public ComponentName getProfileOwnerAsUser(int userHandle) {
            return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle);
        }
        @Override
        public boolean supportsResetOp(int op) {
            return op == AppOpsManager.OP_INTERACT_ACROSS_PROFILES
                    && LocalServices.getService(CrossProfileAppsInternal.class) != null;
        }
        @Override
        public void resetOp(int op, String packageName, @UserIdInt int userId) {
            if (op != AppOpsManager.OP_INTERACT_ACROSS_PROFILES) {
                throw new IllegalArgumentException("Unsupported op for DPM reset: " + op);
            }
            LocalServices.getService(CrossProfileAppsInternal.class)
                    .setInteractAcrossProfilesAppOp(
                            packageName, findInteractAcrossProfilesResetMode(packageName), userId);
        }
        private @Mode int findInteractAcrossProfilesResetMode(String packageName) {
            return getDefaultCrossProfilePackages().contains(packageName)
                    ? AppOpsManager.MODE_ALLOWED
                    : AppOpsManager.opToDefaultMode(AppOpsManager.OP_INTERACT_ACROSS_PROFILES);
        }
    }
    private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
Loading