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

Commit b917306f authored by Jonathan Scott's avatar Jonathan Scott
Browse files

Fix Connected Apps on headless

Test: btest android.devicepolicy.cts.ProvisioningTest#createAndProvisionManagedProfile_setsCrossProfilePackages -si
Bug: 261834806

Change-Id: I1e611a16dc10704a386cce4fd3a1d596e1c65f36
parent ae1e35bf
Loading
Loading
Loading
Loading
+30 −10
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package android.content.pm;

import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_PERSONAL_LABEL;
import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_WORK_LABEL;

@@ -23,6 +24,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UserHandleAware;
import android.app.Activity;
import android.app.AppOpsManager.Mode;
import android.app.admin.DevicePolicyManager;
@@ -32,6 +34,7 @@ import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -167,7 +170,7 @@ public class CrossProfileApps {
     */
    @RequiresPermission(anyOf = {
            android.Manifest.permission.INTERACT_ACROSS_PROFILES,
            android.Manifest.permission.INTERACT_ACROSS_USERS})
            INTERACT_ACROSS_USERS})
    public void startActivity(
            @NonNull Intent intent,
            @NonNull UserHandle targetUser,
@@ -196,7 +199,7 @@ public class CrossProfileApps {
     */
    @RequiresPermission(anyOf = {
            android.Manifest.permission.INTERACT_ACROSS_PROFILES,
            android.Manifest.permission.INTERACT_ACROSS_USERS})
            INTERACT_ACROSS_USERS})
    public void startActivity(
            @NonNull Intent intent,
            @NonNull UserHandle targetUser,
@@ -500,10 +503,13 @@ public class CrossProfileApps {
     */
    @RequiresPermission(
            allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
                    android.Manifest.permission.INTERACT_ACROSS_USERS})
                    INTERACT_ACROSS_USERS})
    @UserHandleAware(
            enabledSinceTargetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
            requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS)
    public void setInteractAcrossProfilesAppOp(@NonNull String packageName, @Mode int newMode) {
        try {
            mService.setInteractAcrossProfilesAppOp(packageName, newMode);
            mService.setInteractAcrossProfilesAppOp(mContext.getUserId(), packageName, newMode);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
@@ -519,9 +525,12 @@ public class CrossProfileApps {
     * @hide
     */
    @TestApi
    @UserHandleAware(
            enabledSinceTargetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
            requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS)
    public boolean canConfigureInteractAcrossProfiles(@NonNull String packageName) {
        try {
            return mService.canConfigureInteractAcrossProfiles(packageName);
            return mService.canConfigureInteractAcrossProfiles(mContext.getUserId(), packageName);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
@@ -540,9 +549,13 @@ public class CrossProfileApps {
     *
     * @hide
     */
    @UserHandleAware(
            enabledSinceTargetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
            requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS)
    public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
        try {
            return mService.canUserAttemptToConfigureInteractAcrossProfiles(packageName);
            return mService.canUserAttemptToConfigureInteractAcrossProfiles(
                    mContext.getUserId(), packageName);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
@@ -569,7 +582,10 @@ public class CrossProfileApps {
     */
    @RequiresPermission(
            allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
                    android.Manifest.permission.INTERACT_ACROSS_USERS})
                    INTERACT_ACROSS_USERS})
    @UserHandleAware(
            enabledSinceTargetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
            requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS)
    public void resetInteractAcrossProfilesAppOps(
            @NonNull Collection<String> previousCrossProfilePackages,
            @NonNull Set<String> newCrossProfilePackages) {
@@ -584,7 +600,8 @@ public class CrossProfileApps {
            return;
        }
        try {
            mService.resetInteractAcrossProfilesAppOps(unsetCrossProfilePackages);
            mService.resetInteractAcrossProfilesAppOps(
                    mContext.getUserId(), unsetCrossProfilePackages);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
@@ -609,10 +626,13 @@ public class CrossProfileApps {
     */
    @RequiresPermission(
            allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
                    android.Manifest.permission.INTERACT_ACROSS_USERS})
                    INTERACT_ACROSS_USERS})
    @UserHandleAware(
            enabledSinceTargetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
            requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS)
    public void clearInteractAcrossProfilesAppOps() {
        try {
            mService.clearInteractAcrossProfilesAppOps();
            mService.clearInteractAcrossProfilesAppOps(mContext.getUserId());
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
+5 −5
Original line number Diff line number Diff line
@@ -36,9 +36,9 @@ interface ICrossProfileApps {
    List<UserHandle> getTargetUserProfiles(in String callingPackage);
    boolean canInteractAcrossProfiles(in String callingPackage);
    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);
    void clearInteractAcrossProfilesAppOps();
    void setInteractAcrossProfilesAppOp(int userId, in String packageName, int newMode);
    boolean canConfigureInteractAcrossProfiles(int userId, in String packageName);
    boolean canUserAttemptToConfigureInteractAcrossProfiles(int userId, in String packageName);
    void resetInteractAcrossProfilesAppOps(int userId, in List<String> packageNames);
    void clearInteractAcrossProfilesAppOps(int userId);
}
+25 −13
Original line number Diff line number Diff line
@@ -430,8 +430,9 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
     * checks.
     */
    @Override
    public void setInteractAcrossProfilesAppOp(String packageName, @Mode int newMode) {
        setInteractAcrossProfilesAppOp(packageName, newMode, mInjector.getCallingUserId());
    public void setInteractAcrossProfilesAppOp(
            @UserIdInt int userId, String packageName, @Mode int newMode) {
        setInteractAcrossProfilesAppOp(packageName, newMode, userId);
    }

    private void setInteractAcrossProfilesAppOp(
@@ -594,8 +595,12 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
    }

    @Override
    public boolean canConfigureInteractAcrossProfiles(String packageName) {
        return canConfigureInteractAcrossProfiles(packageName, mInjector.getCallingUserId());
    public boolean canConfigureInteractAcrossProfiles(int userId, String packageName) {
        if (mInjector.getCallingUserId() != userId) {
            mContext.checkCallingOrSelfPermission(INTERACT_ACROSS_USERS);
        }

        return canConfigureInteractAcrossProfiles(packageName, userId);
    }

    private boolean canConfigureInteractAcrossProfiles(String packageName, @UserIdInt int userId) {
@@ -613,9 +618,13 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
    }

    @Override
    public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
    public boolean canUserAttemptToConfigureInteractAcrossProfiles(int userId, String packageName) {
        if (mInjector.getCallingUserId() != userId) {
            mContext.checkCallingOrSelfPermission(INTERACT_ACROSS_USERS);
        }

        return canUserAttemptToConfigureInteractAcrossProfiles(
                packageName, mInjector.getCallingUserId());
                packageName, userId);
    }

    private boolean canUserAttemptToConfigureInteractAcrossProfiles(
@@ -676,28 +685,31 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
    }

    @Override
    public void resetInteractAcrossProfilesAppOps(List<String> packageNames) {
        packageNames.forEach(this::resetInteractAcrossProfilesAppOp);
    public void resetInteractAcrossProfilesAppOps(@UserIdInt int userId, List<String> packageNames) {
        for (String packageName : packageNames) {
            resetInteractAcrossProfilesAppOp(userId, packageName);
        }
    }

    private void resetInteractAcrossProfilesAppOp(String packageName) {
        if (canConfigureInteractAcrossProfiles(packageName)) {
    private void resetInteractAcrossProfilesAppOp(@UserIdInt int userId, String packageName) {
        if (canConfigureInteractAcrossProfiles(packageName, userId)) {
            Slog.w(TAG, "Not resetting app-op for package " + packageName
                    + " since it is still configurable by users.");
            return;
        }
        final String op =
                AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES);
        setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op));
        setInteractAcrossProfilesAppOp(userId, packageName, AppOpsManager.opToDefaultMode(op));
    }

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

    private List<String> findAllPackageNames() {
+36 −34
Original line number Diff line number Diff line
@@ -1625,8 +1625,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return LocalServices.getService(LockSettingsInternal.class);
        }
        CrossProfileApps getCrossProfileApps() {
            return mContext.getSystemService(CrossProfileApps.class);
        CrossProfileApps getCrossProfileApps(@UserIdInt int userId) {
            return mContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0)
                    .getSystemService(CrossProfileApps.class);
        }
        boolean hasUserSetupCompleted(DevicePolicyData userData) {
@@ -2412,22 +2413,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return;
        }
        final UserHandle doUserHandle = UserHandle.of(doUserId);
        for (UserInfo userInfo : mUserManager.getUsers()) {
            UserHandle userHandle = userInfo.getUserHandle();
            // Based on  CDD : https://source.android.com/compatibility/12/android-12-cdd#95_multi-user_support,
            // creation of clone profile is not allowed in case device owner is set.
            // Enforcing this restriction on setting up of device owner.
            if (!mUserManager.hasUserRestriction(
                UserManager.DISALLOW_ADD_CLONE_PROFILE, doUserHandle)) {
                    UserManager.DISALLOW_ADD_CLONE_PROFILE, userHandle)) {
                mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_CLONE_PROFILE, true,
                    doUserHandle);
                        userHandle);
            }
            // Creation of managed profile is restricted in case device owner is set, enforcing this
            // restriction by setting user level restriction at time of device owner setup.
            if (!mUserManager.hasUserRestriction(
                UserManager.DISALLOW_ADD_MANAGED_PROFILE, doUserHandle)) {
                    UserManager.DISALLOW_ADD_MANAGED_PROFILE, userHandle)) {
                mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
                    doUserHandle);
                        userHandle);
            }
        }
    }
@@ -18645,7 +18647,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                        "Error creating profile, createProfileForUserEvenWhenDisallowed "
                                + "returned null.");
            }
            resetInteractAcrossProfilesAppOps();
            resetInteractAcrossProfilesAppOps(caller.getUserId());
            logEventDuration(
                    DevicePolicyEnums.PLATFORM_PROVISIONING_CREATE_PROFILE_MS,
                    startTime,
@@ -18797,37 +18799,37 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        return caller.getPackageName().equals(devicePolicyManagementRoleHolderPackageName);
    }
    private void resetInteractAcrossProfilesAppOps() {
        mInjector.getCrossProfileApps().clearInteractAcrossProfilesAppOps();
        pregrantDefaultInteractAcrossProfilesAppOps();
    private void resetInteractAcrossProfilesAppOps(@UserIdInt int userId) {
        mInjector.getCrossProfileApps(userId).clearInteractAcrossProfilesAppOps();
        pregrantDefaultInteractAcrossProfilesAppOps(userId);
    }
    private void pregrantDefaultInteractAcrossProfilesAppOps() {
    private void pregrantDefaultInteractAcrossProfilesAppOps(@UserIdInt int userId) {
        final String op =
                AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES);
        for (String packageName : getConfigurableDefaultCrossProfilePackages()) {
            if (appOpIsChangedFromDefault(op, packageName)) {
        for (String packageName : getConfigurableDefaultCrossProfilePackages(userId)) {
            if (!appOpIsDefaultOrAllowed(userId, op, packageName)) {
                continue;
            }
            mInjector.getCrossProfileApps().setInteractAcrossProfilesAppOp(
            mInjector.getCrossProfileApps(userId).setInteractAcrossProfilesAppOp(
                    packageName, MODE_ALLOWED);
        }
    }
    private Set<String> getConfigurableDefaultCrossProfilePackages() {
    private Set<String> getConfigurableDefaultCrossProfilePackages(@UserIdInt int userId) {
        List<String> defaultPackages = getDefaultCrossProfilePackages();
        return defaultPackages.stream().filter(
                mInjector.getCrossProfileApps()::canConfigureInteractAcrossProfiles).collect(
                mInjector.getCrossProfileApps(userId)::canConfigureInteractAcrossProfiles).collect(
                Collectors.toSet());
    }
    private boolean appOpIsChangedFromDefault(String op, String packageName) {
    private boolean appOpIsDefaultOrAllowed(@UserIdInt int userId, String op, String packageName) {
        try {
            final int uid = mContext.getPackageManager().getPackageUid(
                    packageName, /* flags= */ 0);
            return mInjector.getAppOpsManager().unsafeCheckOpNoThrow(
                    op, uid, packageName)
                    != AppOpsManager.MODE_DEFAULT;
            final int uid = mContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0).
                    getPackageManager().getPackageUid(packageName, /* flags= */ 0);
            int mode = mInjector.getAppOpsManager().unsafeCheckOpNoThrow(
                    op, uid, packageName);
            return mode == MODE_ALLOWED || mode == MODE_DEFAULT;
        } catch (NameNotFoundException e) {
            return false;
        }
+44 −32

File changed.

Preview size limit exceeded, changes collapsed.