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

Commit c053890f authored by Sunny Goyal's avatar Sunny Goyal Committed by android-build-merger
Browse files

Merge "Using UserManagerInternal for access control instead of UserManager"...

Merge "Using UserManagerInternal for access control instead of UserManager" into pi-dev am: 9015d243
am: b524685b

Change-Id: I27041c8a8860dfb6edada58bb61f00a854f7961f
parents f1f610d9 b524685b
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -186,4 +186,24 @@ public abstract class UserManagerInternal {
     * @return the array of user ids.
     */
    public abstract int[] getUserIds();

    /**
     * Checks if the {@code callingUserId} and {@code targetUserId} are same or in same group
     * and that the {@code callingUserId} is not a managed profile and
     * {@code targetUserId} is enabled.
     *
     * @return TRUE if the {@code callingUserId} can access {@code targetUserId}. FALSE
     * otherwise
     *
     * @throws SecurityException if the calling user and {@code targetUser} are not in the same
     * group and {@code throwSecurityException} is true, otherwise if will simply return false.
     */
    public abstract boolean isProfileAccessible(int callingUserId, int targetUserId,
            String debugMsg, boolean throwSecurityException);

    /**
     * If {@code userId} is of a managed profile, return the parent user ID. Otherwise return
     * itself.
     */
    public abstract int getProfileParentId(int userId);
}
+31 −142
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutServiceInternal;
import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -50,7 +49,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
@@ -102,7 +101,7 @@ public class LauncherAppsService extends SystemService {
        private static final boolean DEBUG = false;
        private static final String TAG = "LauncherAppsService";
        private final Context mContext;
        private final UserManager mUm;
        private final UserManagerInternal mUserManagerInternal;
        private final ActivityManagerInternal mActivityManagerInternal;
        private final ShortcutServiceInternal mShortcutServiceInternal;
        private final PackageCallbackList<IOnAppsChangedListener> mListeners
@@ -114,7 +113,8 @@ public class LauncherAppsService extends SystemService {

        public LauncherAppsImpl(Context context) {
            mContext = context;
            mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
            mUserManagerInternal = Preconditions.checkNotNull(
                    LocalServices.getService(UserManagerInternal.class));
            mActivityManagerInternal = Preconditions.checkNotNull(
                    LocalServices.getService(ActivityManagerInternal.class));
            mShortcutServiceInternal = Preconditions.checkNotNull(
@@ -222,12 +222,6 @@ public class LauncherAppsService extends SystemService {
            }
        }

        /** See {@link #canAccessProfile(String, int, String)} */
        private boolean canAccessProfile(
                String callingPackage, UserHandle targetUser, String message) {
            return canAccessProfile(callingPackage, targetUser.getIdentifier(), message);
        }

        /**
         * Checks if the calling user is in the same group as {@code targetUser}, and allowed
         * to access it.
@@ -238,30 +232,9 @@ public class LauncherAppsService extends SystemService {
         * @throws SecurityException if the calling user and {@code targetUser} are not in the same
         * group.
         */
        private boolean canAccessProfile(String callingPackage, int targetUserId, String message) {
            final int callingUserId = injectCallingUserId();

            if (targetUserId == callingUserId) return true;

            long ident = injectClearCallingIdentity();
            try {
                UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
                if (callingUserInfo.isManagedProfile()) {
                    Slog.w(TAG, message + " by " + callingPackage + " for another profile "
                            + targetUserId + " from " + callingUserId);
                    return false;
                }

                UserInfo targetUserInfo = mUm.getUserInfo(targetUserId);
                if (targetUserInfo == null
                        || targetUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
                        || targetUserInfo.profileGroupId != callingUserInfo.profileGroupId) {
                    throw new SecurityException(message + " for unrelated profile " + targetUserId);
                }
            } finally {
                injectRestoreCallingIdentity(ident);
            }
            return true;
        private boolean canAccessProfile(int targetUserId, String message) {
            return mUserManagerInternal.isProfileAccessible(injectCallingUserId(), targetUserId,
                    message, true);
        }

        @VisibleForTesting // We override it in unit tests
@@ -283,23 +256,6 @@ public class LauncherAppsService extends SystemService {
            }
        }

        /**
         * Checks if the user is enabled.
         */
        private boolean isUserEnabled(UserHandle user) {
            return isUserEnabled(user.getIdentifier());
        }

        private boolean isUserEnabled(int userId) {
            long ident = injectClearCallingIdentity();
            try {
                UserInfo targetUserInfo = mUm.getUserInfo(userId);
                return targetUserInfo != null && targetUserInfo.isEnabled();
            } finally {
                injectRestoreCallingIdentity(ident);
            }
        }

        @Override
        public ParceledListSlice<ResolveInfo> getLauncherActivities(String callingPackage,
                String packageName, UserHandle user)
@@ -315,10 +271,7 @@ public class LauncherAppsService extends SystemService {
        public ActivityInfo resolveActivity(
                String callingPackage, ComponentName component, UserHandle user)
                throws RemoteException {
            if (!canAccessProfile(callingPackage, user, "Cannot resolve activity")) {
                return null;
            }
            if (!isUserEnabled(user)) {
            if (!canAccessProfile(user.getIdentifier(), "Cannot resolve activity")) {
                return null;
            }

@@ -346,10 +299,7 @@ public class LauncherAppsService extends SystemService {

        private ParceledListSlice<ResolveInfo> queryActivitiesForUser(String callingPackage,
                Intent intent, UserHandle user) {
            if (!canAccessProfile(callingPackage, user, "Cannot retrieve activities")) {
                return null;
            }
            if (!isUserEnabled(user)) {
            if (!canAccessProfile(user.getIdentifier(), "Cannot retrieve activities")) {
                return null;
            }

@@ -372,11 +322,10 @@ public class LauncherAppsService extends SystemService {
        public IntentSender getShortcutConfigActivityIntent(String callingPackage,
                ComponentName component, UserHandle user) throws RemoteException {
            ensureShortcutPermission(callingPackage);
            if (!canAccessProfile(callingPackage, user, "Cannot check package")) {
            if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
                return null;
            }
            Preconditions.checkNotNull(component);
            Preconditions.checkArgument(isUserEnabled(user), "User not enabled");

            // All right, create the sender.
            Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(component);
@@ -395,10 +344,7 @@ public class LauncherAppsService extends SystemService {
        @Override
        public boolean isPackageEnabled(String callingPackage, String packageName, UserHandle user)
                throws RemoteException {
            if (!canAccessProfile(callingPackage, user, "Cannot check package")) {
                return false;
            }
            if (!isUserEnabled(user)) {
            if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
                return false;
            }

@@ -421,10 +367,7 @@ public class LauncherAppsService extends SystemService {
        public ApplicationInfo getApplicationInfo(
                String callingPackage, String packageName, int flags, UserHandle user)
                throws RemoteException {
            if (!canAccessProfile(callingPackage, user, "Cannot check package")) {
                return null;
            }
            if (!isUserEnabled(user)) {
            if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
                return null;
            }

@@ -454,8 +397,7 @@ public class LauncherAppsService extends SystemService {
                String packageName, List shortcutIds, ComponentName componentName, int flags,
                UserHandle targetUser) {
            ensureShortcutPermission(callingPackage);
            if (!canAccessProfile(callingPackage, targetUser, "Cannot get shortcuts")
                    || !isUserEnabled(targetUser)) {
            if (!canAccessProfile(targetUser.getIdentifier(), "Cannot get shortcuts")) {
                return new ParceledListSlice<>(Collections.EMPTY_LIST);
            }
            if (shortcutIds != null && packageName == null) {
@@ -475,13 +417,9 @@ public class LauncherAppsService extends SystemService {
        public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
                UserHandle targetUser) {
            ensureShortcutPermission(callingPackage);
            if (!canAccessProfile(callingPackage, targetUser, "Cannot pin shortcuts")) {
            if (!canAccessProfile(targetUser.getIdentifier(), "Cannot pin shortcuts")) {
                return;
            }
            if (!isUserEnabled(targetUser)) {
                throw new IllegalStateException("Cannot pin shortcuts for disabled profile "
                        + targetUser);
            }

            mShortcutServiceInternal.pinShortcuts(getCallingUserId(),
                    callingPackage, packageName, ids, targetUser.getIdentifier());
@@ -491,10 +429,7 @@ public class LauncherAppsService extends SystemService {
        public int getShortcutIconResId(String callingPackage, String packageName, String id,
                int targetUserId) {
            ensureShortcutPermission(callingPackage);
            if (!canAccessProfile(callingPackage, targetUserId, "Cannot access shortcuts")) {
                return 0;
            }
            if (!isUserEnabled(targetUserId)) {
            if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
                return 0;
            }

@@ -506,10 +441,7 @@ public class LauncherAppsService extends SystemService {
        public ParcelFileDescriptor getShortcutIconFd(String callingPackage,
                String packageName, String id, int targetUserId) {
            ensureShortcutPermission(callingPackage);
            if (!canAccessProfile(callingPackage, targetUserId, "Cannot access shortcuts")) {
                return null;
            }
            if (!isUserEnabled(targetUserId)) {
            if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
                return null;
            }

@@ -528,13 +460,9 @@ public class LauncherAppsService extends SystemService {
        public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
                Rect sourceBounds, Bundle startActivityOptions, int targetUserId) {
            verifyCallingPackage(callingPackage);
            if (!canAccessProfile(callingPackage, targetUserId, "Cannot start activity")) {
            if (!canAccessProfile(targetUserId, "Cannot start activity")) {
                return false;
            }
            if (!isUserEnabled(targetUserId)) {
                throw new IllegalStateException("Cannot start a shortcut for disabled profile "
                        + targetUserId);
            }

            // Even without the permission, pinned shortcuts are always launchable.
            if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
@@ -581,10 +509,7 @@ public class LauncherAppsService extends SystemService {
        public boolean isActivityEnabled(
                String callingPackage, ComponentName component, UserHandle user)
                throws RemoteException {
            if (!canAccessProfile(callingPackage , user, "Cannot check component")) {
                return false;
            }
            if (!isUserEnabled(user)) {
            if (!canAccessProfile(user.getIdentifier(), "Cannot check component")) {
                return false;
            }

@@ -607,12 +532,9 @@ public class LauncherAppsService extends SystemService {
        public void startActivityAsUser(String callingPackage,
                ComponentName component, Rect sourceBounds,
                Bundle opts, UserHandle user) throws RemoteException {
            if (!canAccessProfile(callingPackage, user, "Cannot start activity")) {
            if (!canAccessProfile(user.getIdentifier(), "Cannot start activity")) {
                return;
            }
            if (!isUserEnabled(user)) {
                throw new IllegalStateException("Cannot start activity for disabled profile "  + user);
            }

            Intent launchIntent = new Intent(Intent.ACTION_MAIN);
            launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
@@ -665,13 +587,9 @@ public class LauncherAppsService extends SystemService {
        @Override
        public void showAppDetailsAsUser(String callingPackage, ComponentName component,
                Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException {
            if (!canAccessProfile(callingPackage, user, "Cannot show app details")) {
            if (!canAccessProfile(user.getIdentifier(), "Cannot show app details")) {
                return;
            }
            if (!isUserEnabled(user)) {
                throw new IllegalStateException("Cannot show app details for disabled profile "
                        + user);
            }

            long ident = Binder.clearCallingIdentity();
            try {
@@ -688,39 +606,10 @@ public class LauncherAppsService extends SystemService {

        /** Checks if user is a profile of or same as listeningUser.
         * and the user is enabled. */
        private boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser,
        private boolean isEnabledProfileOf(UserHandle listeningUser, UserHandle user,
                String debugMsg) {
            if (user.getIdentifier() == listeningUser.getIdentifier()) {
                if (DEBUG) Log.d(TAG, "Delivering msg to same user: " + debugMsg);
                return true;
            }
            if (mUm.isManagedProfile(listeningUser.getIdentifier())) {
                if (DEBUG) Log.d(TAG, "Managed profile can't see other profiles: " + debugMsg);
                return false;
            }
            long ident = injectClearCallingIdentity();
            try {
                UserInfo userInfo = mUm.getUserInfo(user.getIdentifier());
                UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier());
                if (userInfo == null || listeningUserInfo == null
                        || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
                        || userInfo.profileGroupId != listeningUserInfo.profileGroupId
                        || !userInfo.isEnabled()) {
                    if (DEBUG) {
                        Log.d(TAG, "Not delivering msg from " + user + " to " + listeningUser + ":"
                                + debugMsg);
                    }
                    return false;
                } else {
                    if (DEBUG) {
                        Log.d(TAG, "Delivering msg from " + user + " to " + listeningUser + ":"
                                + debugMsg);
                    }
                    return true;
                }
            } finally {
                injectRestoreCallingIdentity(ident);
            }
            return mUserManagerInternal.isProfileAccessible(listeningUser.getIdentifier(),
                    user.getIdentifier(), debugMsg, false);
        }

        @VisibleForTesting
@@ -740,7 +629,7 @@ public class LauncherAppsService extends SystemService {
                    for (int i = 0; i < n; i++) {
                        IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
                        BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
                        if (!isEnabledProfileOf(user, cookie.user, "onPackageAdded")) continue;
                        if (!isEnabledProfileOf(cookie.user, user, "onPackageAdded")) continue;
                        try {
                            listener.onPackageAdded(user, packageName);
                        } catch (RemoteException re) {
@@ -762,7 +651,7 @@ public class LauncherAppsService extends SystemService {
                    for (int i = 0; i < n; i++) {
                        IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
                        BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
                        if (!isEnabledProfileOf(user, cookie.user, "onPackageRemoved")) continue;
                        if (!isEnabledProfileOf(cookie.user, user, "onPackageRemoved")) continue;
                        try {
                            listener.onPackageRemoved(user, packageName);
                        } catch (RemoteException re) {
@@ -784,7 +673,7 @@ public class LauncherAppsService extends SystemService {
                    for (int i = 0; i < n; i++) {
                        IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
                        BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
                        if (!isEnabledProfileOf(user, cookie.user, "onPackageModified")) continue;
                        if (!isEnabledProfileOf(cookie.user, user, "onPackageModified")) continue;
                        try {
                            listener.onPackageChanged(user, packageName);
                        } catch (RemoteException re) {
@@ -806,7 +695,7 @@ public class LauncherAppsService extends SystemService {
                    for (int i = 0; i < n; i++) {
                        IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
                        BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
                        if (!isEnabledProfileOf(user, cookie.user, "onPackagesAvailable")) continue;
                        if (!isEnabledProfileOf(cookie.user, user, "onPackagesAvailable")) continue;
                        try {
                            listener.onPackagesAvailable(user, packages, isReplacing());
                        } catch (RemoteException re) {
@@ -828,7 +717,7 @@ public class LauncherAppsService extends SystemService {
                    for (int i = 0; i < n; i++) {
                        IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
                        BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
                        if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnavailable")) continue;
                        if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnavailable")) continue;
                        try {
                            listener.onPackagesUnavailable(user, packages, isReplacing());
                        } catch (RemoteException re) {
@@ -850,7 +739,7 @@ public class LauncherAppsService extends SystemService {
                    for (int i = 0; i < n; i++) {
                        IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
                        BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
                        if (!isEnabledProfileOf(user, cookie.user, "onPackagesSuspended")) continue;
                        if (!isEnabledProfileOf(cookie.user, user, "onPackagesSuspended")) continue;
                        try {
                            listener.onPackagesSuspended(user, packages);
                        } catch (RemoteException re) {
@@ -872,7 +761,7 @@ public class LauncherAppsService extends SystemService {
                    for (int i = 0; i < n; i++) {
                        IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
                        BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
                        if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnsuspended")) continue;
                        if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnsuspended")) continue;
                        try {
                            listener.onPackagesUnsuspended(user, packages);
                        } catch (RemoteException re) {
@@ -901,7 +790,7 @@ public class LauncherAppsService extends SystemService {
                    for (int i = 0; i < n; i++) {
                        IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
                        BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
                        if (!isEnabledProfileOf(user, cookie.user, "onShortcutChanged")) continue;
                        if (!isEnabledProfileOf(cookie.user, user, "onShortcutChanged")) continue;

                        final int launcherUserId = cookie.user.getIdentifier();

+6 −16
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.ArraySet;
@@ -315,7 +315,7 @@ public class ShortcutService extends IShortcutService.Stub {

    private final IPackageManager mIPackageManager;
    private final PackageManagerInternal mPackageManagerInternal;
    private final UserManager mUserManager;
    private final UserManagerInternal mUserManagerInternal;
    private final UsageStatsManagerInternal mUsageStatsManagerInternal;
    private final ActivityManagerInternal mActivityManagerInternal;

@@ -430,7 +430,8 @@ public class ShortcutService extends IShortcutService.Stub {
        mIPackageManager = AppGlobals.getPackageManager();
        mPackageManagerInternal = Preconditions.checkNotNull(
                LocalServices.getService(PackageManagerInternal.class));
        mUserManager = Preconditions.checkNotNull(context.getSystemService(UserManager.class));
        mUserManagerInternal = Preconditions.checkNotNull(
                LocalServices.getService(UserManagerInternal.class));
        mUsageStatsManagerInternal = Preconditions.checkNotNull(
                LocalServices.getService(UsageStatsManagerInternal.class));
        mActivityManagerInternal = Preconditions.checkNotNull(
@@ -1176,12 +1177,7 @@ public class ShortcutService extends IShortcutService.Stub {
        // the user might just have been unlocked.
        // Note we just don't use isUserUnlockingOrUnlocked() here, because it'll return false
        // when the user is STOPPING, which we still want to consider as "unlocked".
        final long token = injectClearCallingIdentity();
        try {
            return mUserManager.isUserUnlockingOrUnlocked(userId);
        } finally {
            injectRestoreCallingIdentity(token);
        }
        return mUserManagerInternal.isUserUnlockingOrUnlocked(userId);
    }

    // Requires mLock held, but "Locked" prefix would look weired so we jsut say "L".
@@ -3493,13 +3489,7 @@ public class ShortcutService extends IShortcutService.Stub {
     * itself.
     */
    int getParentOrSelfUserId(int userId) {
        final long token = injectClearCallingIdentity();
        try {
            final UserInfo parent = mUserManager.getProfileParent(userId);
            return (parent != null) ? parent.id : userId;
        } finally {
            injectRestoreCallingIdentity(token);
        }
        return mUserManagerInternal.getProfileParentId(userId);
    }

    void injectSendIntentSender(IntentSender intentSender, Intent extras) {
+51 −8
Original line number Diff line number Diff line
@@ -781,14 +781,7 @@ public class UserManagerService extends IUserManager.Stub {
    @Override
    public int getProfileParentId(int userHandle) {
        checkManageUsersPermission("get the profile parent");
        synchronized (mUsersLock) {
            UserInfo profileParent = getProfileParentLU(userHandle);
            if (profileParent == null) {
                return userHandle;
            }

            return profileParent.id;
        }
        return mLocalService.getProfileParentId(userHandle);
    }

    private UserInfo getProfileParentLU(int userHandle) {
@@ -3928,6 +3921,56 @@ public class UserManagerService extends IUserManager.Stub {
        public boolean exists(int userId) {
            return getUserInfoNoChecks(userId) != null;
        }

        @Override
        public boolean isProfileAccessible(int callingUserId, int targetUserId, String debugMsg,
                boolean throwSecurityException) {
            if (targetUserId == callingUserId) {
                return true;
            }
            synchronized (mUsersLock) {
                UserInfo callingUserInfo = getUserInfoLU(callingUserId);
                if (callingUserInfo == null || callingUserInfo.isManagedProfile()) {
                    if (throwSecurityException) {
                        throw new SecurityException(
                                debugMsg + " for another profile "
                                        + targetUserId + " from " + callingUserId);
                    }
                }

                UserInfo targetUserInfo = getUserInfoLU(targetUserId);
                if (targetUserInfo == null || !targetUserInfo.isEnabled()) {
                    // Do not throw any exception here as this could happen due to race conditions
                    // between the system updating its state and the client getting notified.
                    if (throwSecurityException) {
                        Slog.w(LOG_TAG, debugMsg + " for disabled profile "
                                + targetUserId + " from " + callingUserId);
                    }
                    return false;
                }

                if (targetUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID ||
                        targetUserInfo.profileGroupId != callingUserInfo.profileGroupId) {
                    if (throwSecurityException) {
                        throw new SecurityException(
                                debugMsg + " for unrelated profile " + targetUserId);
                    }
                    return false;
                }
            }
            return true;
        }

        @Override
        public int getProfileParentId(int userId) {
            synchronized (mUsersLock) {
                UserInfo profileParent = getProfileParentLU(userId);
                if (profileParent == null) {
                    return userId;
                }
                return profileParent.id;
            }
        }
    }

    /* Remove all the users except of the system one. */