UserManager more consistently @UserHandleAware

Some methods in UserManager are @UserHandleAware but some are not, which
is confusing and sometimes means that no userId-version of the API
exists.

Here, we make them more consistently @UserHandleAware.

Since this is a behaviour-breaking change, we gate it by SDK version.

We introduce annotation parameters to help explain this gating and any
permission requirements that only apply when the context user differs
from the calling using.

We change the documentation to say "context user" rather than "calling
user", as is done for all @UserHandleAware methods. Note, however, that
this also applies to public APIs (which have no concept of context-based
userIds), but that is consistent with current usage.

For hidden APIs, where feasible, we do not gate.

Test: atest com.android.server.pm.UserManagerTest
Test: atest android.multiuser.cts.UserManagerTest
Bug: 183155436
Change-Id: Ief94abc321bb243ce25b9baae95e554ef015d180
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 2d28425..21004bf 100755
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -8681,15 +8681,15 @@
     method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public int getUserSwitchability();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean hasRestrictedProfiles();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean hasUserRestrictionForUser(@NonNull String, @NonNull android.os.UserHandle);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isAdminUser();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isAdminUser();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isCloneProfile();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isGuestUser();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isManagedProfile(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isMediaSharedWithParent();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isPrimaryUser();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isProfile();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile();
-    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
+    method public boolean isRestrictedProfile();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public boolean isUserNameSet();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUserOfType(@NonNull String);
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 3bee4b7..b839706 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -69,7 +69,7 @@
     String getUserAccount(int userId);
     void setUserAccount(int userId, String accountName);
     long getUserCreationTime(int userId);
-    boolean isRestricted();
+    boolean isRestricted(int userId);
     boolean canHaveRestrictedProfile(int userId);
     int getUserSerialNumber(int userId);
     int getUserHandle(int userSerialNumber);
@@ -93,10 +93,10 @@
     boolean isQuietModeEnabled(int userId);
     void setSeedAccountData(int userId, in String accountName,
             in String accountType, in PersistableBundle accountOptions, boolean persist);
-    String getSeedAccountName();
-    String getSeedAccountType();
-    PersistableBundle getSeedAccountOptions();
-    void clearSeedAccountData();
+    String getSeedAccountName(int userId);
+    String getSeedAccountType(int userId);
+    PersistableBundle getSeedAccountOptions(int userId);
+    void clearSeedAccountData(int userId);
     boolean someUserHasSeedAccount(in String accountName, in String accountType);
     boolean isProfile(int userId);
     boolean isManagedProfile(int userId);
@@ -118,7 +118,7 @@
     boolean isUserRunning(int userId);
     boolean isUserForeground(int userId);
     boolean isUserNameSet(int userId);
-    boolean hasRestrictedProfiles();
+    boolean hasRestrictedProfiles(int userId);
     boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userId, in IntentSender target, int flags);
     String getUserName();
     long getUserStartRealtime();
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 09b7aaa..da09375 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -37,6 +37,9 @@
 import android.app.ActivityManager;
 import android.app.PropertyInvalidatedCache;
 import android.app.admin.DevicePolicyManager;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -55,6 +58,7 @@
 import android.telephony.TelephonyManager;
 import android.util.AndroidException;
 import android.util.ArraySet;
+import android.util.Log;
 import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.R;
@@ -1719,6 +1723,61 @@
         }
     }
 
+    /**
+     * For apps targeting {@link Build.VERSION_CODES#TIRAMISU} and above, any UserManager API marked
+     * as {@link  android.annotation.UserHandleAware @UserHandleAware} will use the context user
+     * (rather than the calling user).
+     * For apps targeting an SDK version <em>below</em> this, the behaviour
+     * depends on the particular method and when it was first introduced:
+     * <ul>
+     *     <li>
+     *         if the {@literal @}UserHandleAware specifies a
+     *         {@link  android.annotation.UserHandleAware#enabledSinceTargetSdkVersion} of
+     *         {@link Build.VERSION_CODES#TIRAMISU} the <em>calling</em> user is used.
+     *     </li>
+     *     <li>
+     *         if the {@literal @}UserHandleAware doesn't specify a
+     *         {@link  android.annotation.UserHandleAware#enabledSinceTargetSdkVersion}, the
+     *         <em>context</em> user is used.
+     *     </li>
+     *     <li>there should currently be no other values used by UserManager for
+     *         {@link  android.annotation.UserHandleAware#enabledSinceTargetSdkVersion}, since all
+     *         old implicitly user-dependant APIs were updated in that version and anything
+     *         introduced more recently should already be {@literal @}UserHandleAware.
+     *     </li>
+     * </ul>
+     *
+     * Note that when an API marked with
+     * {@link  android.annotation.UserHandleAware#enabledSinceTargetSdkVersion} is run
+     * on a device whose OS predates that version, the calling user will be used, since on such a
+     * device, the API is not {@literal @}UserHandleAware yet.
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+    public static final long ALWAYS_USE_CONTEXT_USER = 183155436L;
+
+    /**
+     * Returns the context user or the calling user, depending on the target SDK.
+     * New APIs do not require such gating and therefore should always use mUserId instead.
+     * @see #ALWAYS_USE_CONTEXT_USER
+     */
+    private @UserIdInt int getContextUserIfAppropriate() {
+        if (CompatChanges.isChangeEnabled(ALWAYS_USE_CONTEXT_USER)) {
+            return mUserId;
+        } else {
+            final int callingUser = UserHandle.myUserId();
+            if (callingUser != mUserId) {
+                Log.w(TAG, "Using the calling user " + callingUser
+                        + ", rather than the specified context user " + mUserId
+                        + ", because API is only UserHandleAware on higher targetSdkVersions.",
+                        new Throwable());
+            }
+            return callingUser;
+        }
+    }
+
     /** @hide */
     @UnsupportedAppUsage
     public static UserManager get(Context context) {
@@ -1784,7 +1843,12 @@
      * @hide
      */
     @Deprecated
+    @RequiresPermission(allOf = {
+            Manifest.permission.READ_PHONE_STATE,
+            Manifest.permission.MANAGE_USERS}, // Can be INTERACT_ACROSS_USERS instead.
+            conditional = true)
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    @UserHandleAware()
     public boolean canSwitchUsers() {
         boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
                 mContext.getContentResolver(),
@@ -1795,14 +1859,13 @@
         if (telephonyManager != null) {
             inCall = telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE;
         }
-        boolean isUserSwitchDisallowed = hasUserRestriction(DISALLOW_USER_SWITCH);
+        boolean isUserSwitchDisallowed = hasUserRestrictionForUser(DISALLOW_USER_SWITCH, mUserId);
         return (allowUserSwitchingWhenSystemUserLocked || isSystemUserUnlocked) && !inCall
                 && !isUserSwitchDisallowed;
     }
 
     /**
-     * Returns whether switching users is currently allowed for the user this process is running
-     * under.
+     * Returns whether switching users is currently allowed for the context user.
      * <p>
      * Switching users is not allowed in the following cases:
      * <li>the user is in a phone call</li>
@@ -1816,8 +1879,9 @@
     @RequiresPermission(allOf = {Manifest.permission.READ_PHONE_STATE,
             android.Manifest.permission.MANAGE_USERS,
             android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public @UserSwitchabilityResult int getUserSwitchability() {
-        return getUserSwitchability(Process.myUserHandle());
+        return getUserSwitchability(UserHandle.of(getContextUserIfAppropriate()));
     }
 
     /**
@@ -1842,7 +1906,7 @@
         if (tm.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
             flags |= SWITCHABILITY_STATUS_USER_IN_CALL;
         }
-        if (hasUserRestriction(DISALLOW_USER_SWITCH, userHandle)) {
+        if (hasUserRestrictionForUser(DISALLOW_USER_SWITCH, userHandle)) {
             flags |= SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED;
         }
 
@@ -1862,14 +1926,16 @@
     }
 
     /**
-     * Returns the user handle for the user that this process is running under.
+     * Returns the userId for the context user.
      *
-     * @return the user handle of this process.
+     * @return the userId of the context user.
      * @hide
      */
     @UnsupportedAppUsage
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+    // *** Do NOT use this in UserManager. Instead always use mUserId. ***
     public @UserIdInt int getUserHandle() {
-        return UserHandle.myUserId();
+        return getContextUserIfAppropriate();
     }
 
     /**
@@ -1877,9 +1943,9 @@
      * @hide
      */
     @TestApi
-    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
-            android.Manifest.permission.CREATE_USERS
-    })
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS})
     @UserHandleAware
     public @NonNull String getUserType() {
         UserInfo userInfo = getUserInfo(mUserId);
@@ -1919,9 +1985,10 @@
     @SystemApi
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.GET_ACCOUNTS_PRIVILEGED})
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public boolean isUserNameSet() {
         try {
-            return mService.isUserNameSet(getUserHandle());
+            return mService.isUserNameSet(getContextUserIfAppropriate());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -1939,52 +2006,60 @@
      *
      * @return Returns whether the user making this call is a goat.
      */
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public boolean isUserAGoat() {
         if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R) {
             return false;
         }
+        // Caution: This is NOT @UserHandleAware (because mContext is getApplicationContext and
+        // holds a different userId), but for R+ it returns false, so it doesn't matter anyway.
         return mContext.getPackageManager()
                 .isPackageAvailable("com.coffeestainstudios.goatsimulator");
     }
 
     /**
-     * Used to check if this process is running under the primary user. The primary user
+     * Used to check if the context user is the primary user. The primary user
      * is the first human user on a device. This is not supported in headless system user mode.
      *
-     * @return whether this process is running under the primary user.
+     * @return whether the context user is the primary user.
      * @hide
      */
     @SystemApi
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS})
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public boolean isPrimaryUser() {
-        UserInfo user = getUserInfo(UserHandle.myUserId());
+        final UserInfo user = getUserInfo(getContextUserIfAppropriate());
         return user != null && user.isPrimary();
     }
 
     /**
-     * Used to check if this process is running under the system user. The system user
+     * Used to check if the context user is the system user. The system user
      * is the initial user that is implicitly created on first boot and hosts most of the
      * system services.
      *
-     * @return whether this process is running under the system user.
+     * @return whether the context user is the system user.
      */
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public boolean isSystemUser() {
-        return UserHandle.myUserId() == UserHandle.USER_SYSTEM;
+        return getContextUserIfAppropriate() == UserHandle.USER_SYSTEM;
     }
 
     /**
-     * Used to check if this process is running as an admin user. An admin user is allowed to
+     * Used to check if the context user is an admin user. An admin user is allowed to
      * modify or configure certain settings that aren't available to non-admin users,
      * create and delete additional users, etc. There can be more than one admin users.
      *
-     * @return whether this process is running under an admin user.
+     * @return whether the context user is an admin user.
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            Manifest.permission.MANAGE_USERS,
+            Manifest.permission.CREATE_USERS})
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public boolean isAdminUser() {
-        return isUserAdmin(UserHandle.myUserId());
+        return isUserAdmin(getContextUserIfAppropriate());
     }
 
     /**
@@ -2099,22 +2174,33 @@
      */
     @UnsupportedAppUsage
     @Deprecated
+    @UserHandleAware(
+            enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+            requiresAnyOfPermissionsIfNotCaller = {
+                    android.Manifest.permission.MANAGE_USERS,
+                    android.Manifest.permission.CREATE_USERS}
+    )
     public boolean isLinkedUser() {
         return isRestrictedProfile();
     }
 
     /**
-     * Used to check if this process is running under a restricted profile. Restricted profiles
+     * Used to check if the context user is a restricted profile. Restricted profiles
      * may have a reduced number of available apps, app restrictions, and account restrictions.
      *
-     * @return whether this process is running under a restricted profile.
+     * @return whether the context user is a restricted profile.
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @UserHandleAware(
+            enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+            requiresAnyOfPermissionsIfNotCaller = {
+                    android.Manifest.permission.MANAGE_USERS,
+                    android.Manifest.permission.CREATE_USERS}
+    )
     public boolean isRestrictedProfile() {
         try {
-            return mService.isRestricted();
+            return mService.isRestricted(getContextUserIfAppropriate());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -2129,11 +2215,13 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
-            Manifest.permission.CREATE_USERS})
+    @RequiresPermission(anyOf = {
+            Manifest.permission.MANAGE_USERS,
+            Manifest.permission.CREATE_USERS},
+            conditional = true)
     public boolean isRestrictedProfile(@NonNull UserHandle user) {
         try {
-            return mService.getUserInfo(user.getIdentifier()).isRestricted();
+            return mService.isRestricted(user.getIdentifier());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -2156,15 +2244,16 @@
     }
 
     /**
-     * Returns whether the calling user has at least one restricted profile associated with it.
-     * @return
+     * Returns whether the context user has at least one restricted profile associated with it.
+     * @return whether the user has a restricted profile associated with it
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public boolean hasRestrictedProfiles() {
         try {
-            return mService.hasRestrictedProfiles();
+            return mService.hasRestrictedProfiles(getContextUserIfAppropriate());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -2203,29 +2292,34 @@
     }
 
     /**
-     * Used to check if this process is running under a guest user. A guest user may be transient.
+     * Used to check if the context user is a guest user. A guest user may be transient.
      *
-     * @return whether this process is running under a guest user.
+     * @return whether the context user is a guest user.
      * @hide
      */
     @SystemApi
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS})
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public boolean isGuestUser() {
-        UserInfo user = getUserInfo(UserHandle.myUserId());
+        UserInfo user = getUserInfo(getContextUserIfAppropriate());
         return user != null && user.isGuest();
     }
 
 
     /**
-     * Checks if the calling app is running in a demo user. When running in a demo user,
+     * Checks if the context user is a demo user. When running in a demo user,
      * apps can be more helpful to the user, or explain their features in more detail.
      *
-     * @return whether the caller is a demo user.
+     * @return whether the context user is a demo user.
      */
+    @UserHandleAware(
+            enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+            requiresPermissionIfNotCaller = android.Manifest.permission.MANAGE_USERS
+    )
     public boolean isDemoUser() {
         try {
-            return mService.isDemoUser(UserHandle.myUserId());
+            return mService.isDemoUser(getContextUserIfAppropriate());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -2250,14 +2344,14 @@
     }
 
     private boolean isProfile(@UserIdInt int userId) {
-        if (userId == UserHandle.myUserId()) {
+        if (userId == mUserId) {
             // No need for synchronization.  Once it becomes non-null, it'll be non-null forever.
             // Worst case we might end up calling the AIDL method multiple times but that's fine.
             if (mIsProfileCached != null) {
                 return mIsProfileCached;
             }
             try {
-                mIsProfileCached = mService.isProfile(userId);
+                mIsProfileCached = mService.isProfile(mUserId);
                 return mIsProfileCached;
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
@@ -2272,22 +2366,18 @@
     }
 
     /**
-     * Checks if the calling app is running in a managed profile.
+     * Checks if the context user is a managed profile.
      *
-     * @return whether the caller is in a managed profile.
+     * @return whether the context user is a managed profile.
      */
+    @UserHandleAware(
+            enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+            requiresAnyOfPermissionsIfNotCallerProfileGroup = {
+                    android.Manifest.permission.MANAGE_USERS,
+                    android.Manifest.permission.INTERACT_ACROSS_USERS}
+    )
     public boolean isManagedProfile() {
-        // No need for synchronization.  Once it becomes non-null, it'll be non-null forever.
-        // Worst case we might end up calling the AIDL method multiple times but that's fine.
-        if (mIsManagedProfileCached != null) {
-            return mIsManagedProfileCached;
-        }
-        try {
-            mIsManagedProfileCached = mService.isManagedProfile(UserHandle.myUserId());
-            return mIsManagedProfileCached;
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
+        return isManagedProfile(getContextUserIfAppropriate());
     }
 
     /**
@@ -2303,13 +2393,24 @@
     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
             Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
     public boolean isManagedProfile(@UserIdInt int userId) {
-        if (userId == UserHandle.myUserId()) {
-            return isManagedProfile();
-        }
-        try {
-            return mService.isManagedProfile(userId);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
+        if (userId == mUserId) {
+            // No need for synchronization.  Once it becomes non-null, it'll be non-null forever.
+            // Worst case we might end up calling the AIDL method multiple times but that's fine.
+            if (mIsManagedProfileCached != null) {
+                return mIsManagedProfileCached;
+            }
+            try {
+                mIsManagedProfileCached = mService.isManagedProfile(mUserId);
+                return mIsManagedProfileCached;
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        } else {
+            try {
+                return mService.isManagedProfile(userId);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
         }
     }
 
@@ -2339,15 +2440,16 @@
     }
 
     /**
-     * Checks if the calling app is running as an ephemeral user.
+     * Checks if the context user is an ephemeral user.
      *
-     * @return whether the caller is an ephemeral user.
+     * @return whether the context user is an ephemeral user.
      * @hide
      */
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS})
+    @UserHandleAware()
     public boolean isEphemeralUser() {
-        return isUserEphemeral(UserHandle.myUserId());
+        return isUserEphemeral(mUserId);
     }
 
     /**
@@ -2436,7 +2538,7 @@
     }
 
     /**
-     * Return whether the calling user is running in an "unlocked" state.
+     * Return whether the context user is running in an "unlocked" state.
      * <p>
      * On devices with direct boot, a user is unlocked only after they've
      * entered their credentials (such as a lock pattern or PIN). On devices
@@ -2449,8 +2551,14 @@
      * @see Intent#ACTION_USER_UNLOCKED
      * @see Context#createDeviceProtectedStorageContext()
      */
+    @UserHandleAware(
+            enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+            requiresAnyOfPermissionsIfNotCallerProfileGroup = {
+                    android.Manifest.permission.MANAGE_USERS,
+                    android.Manifest.permission.INTERACT_ACROSS_USERS}
+    )
     public boolean isUserUnlocked() {
-        return isUserUnlocked(Process.myUserHandle());
+        return isUserUnlocked(getContextUserIfAppropriate());
     }
 
     /**
@@ -2573,7 +2681,14 @@
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    // NOT @UserHandleAware
     public long getUserStartRealtime() {
+        if (getContextUserIfAppropriate() != UserHandle.myUserId()) {
+            // Note: If we want to support this in the future, also annotate with
+            //       @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+            throw new IllegalArgumentException("Calling from a context differing from the calling "
+                    + "user is not currently supported.");
+        }
         try {
             return mService.getUserStartRealtime();
         } catch (RemoteException re) {
@@ -2582,13 +2697,20 @@
     }
 
     /**
-     * Return the time when the calling user was unlocked elapsed milliseconds since boot,
+     * Return the time when the context user was unlocked elapsed milliseconds since boot,
      * or 0 if not unlocked.
      *
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    // NOT @UserHandleAware
     public long getUserUnlockRealtime() {
+        if (getContextUserIfAppropriate() != UserHandle.myUserId()) {
+            // Note: If we want to support this in the future, also annotate with
+            //       @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+            throw new IllegalArgumentException("Calling from a context differing from the calling "
+                    + "user is not currently supported.");
+        }
         try {
             return mService.getUserUnlockRealtime();
         } catch (RemoteException re) {
@@ -2657,11 +2779,21 @@
     }
 
     /**
-     * Returns the user-wide restrictions imposed on this user.
+     * Returns the user-wide restrictions imposed on the context user.
      * @return a Bundle containing all the restrictions.
      */
+    @UserHandleAware(
+            enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+            requiresAnyOfPermissionsIfNotCallerProfileGroup = {
+                    android.Manifest.permission.MANAGE_USERS,
+                    android.Manifest.permission.INTERACT_ACROSS_USERS}
+    )
     public Bundle getUserRestrictions() {
-        return getUserRestrictions(Process.myUserHandle());
+        try {
+            return mService.getUserRestrictions(getContextUserIfAppropriate());
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -2727,7 +2859,7 @@
     }
 
     /**
-     * Sets the value of a specific restriction.
+     * Sets the value of a specific restriction on the context user.
      * Requires the MANAGE_USERS permission.
      * @param key the key of the restriction
      * @param value the value for the restriction
@@ -2738,8 +2870,13 @@
      */
     @Deprecated
     @RequiresPermission(Manifest.permission.MANAGE_USERS)
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public void setUserRestriction(String key, boolean value) {
-        setUserRestriction(key, value, Process.myUserHandle());
+        try {
+            mService.setUserRestriction(key, value, getContextUserIfAppropriate());
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -2764,14 +2901,20 @@
     }
 
     /**
-     * Returns whether the current user has been disallowed from performing certain actions
+     * Returns whether the context user has been disallowed from performing certain actions
      * or setting certain settings.
      *
      * @param restrictionKey The string key representing the restriction.
-     * @return {@code true} if the current user has the given restriction, {@code false} otherwise.
+     * @return {@code true} if the context user has the given restriction, {@code false} otherwise.
      */
+    @UserHandleAware(
+            enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+            requiresAnyOfPermissionsIfNotCallerProfileGroup = {
+                    android.Manifest.permission.MANAGE_USERS,
+                    android.Manifest.permission.INTERACT_ACROSS_USERS}
+    )
     public boolean hasUserRestriction(@UserRestrictionKey String restrictionKey) {
-        return hasUserRestrictionForUser(restrictionKey, Process.myUserHandle());
+        return hasUserRestrictionForUser(restrictionKey, getContextUserIfAppropriate());
     }
 
     /**
@@ -2780,8 +2923,13 @@
      * or setting certain settings.
      * @param restrictionKey the string key representing the restriction
      * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
+     * @deprecated Use {@link #hasUserRestrictionForUser(String, UserHandle)} instead.
      */
     @UnsupportedAppUsage
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+    @Deprecated
     public boolean hasUserRestriction(@UserRestrictionKey String restrictionKey,
             UserHandle userHandle) {
         return hasUserRestrictionForUser(restrictionKey, userHandle);
@@ -2805,8 +2953,16 @@
             android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
     public boolean hasUserRestrictionForUser(@NonNull @UserRestrictionKey String restrictionKey,
             @NonNull UserHandle userHandle) {
+        return hasUserRestrictionForUser(restrictionKey, userHandle.getIdentifier());
+    }
+
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+    private boolean hasUserRestrictionForUser(@NonNull @UserRestrictionKey String restrictionKey,
+            @UserIdInt int userId) {
         try {
-            return mService.hasUserRestriction(restrictionKey, userHandle.getIdentifier());
+            return mService.hasUserRestriction(restrictionKey, userId);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -3148,7 +3304,7 @@
 
     /**
      * Creates a restricted profile with the specified name. This method also sets necessary
-     * restrictions and adds shared accounts.
+     * restrictions and adds shared accounts (with the context user).
      *
      * @param name profile's name
      * @return the {@link UserInfo} object for the created user, or {@code null} if the user
@@ -3159,16 +3315,17 @@
     @TestApi
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS})
+    @UserHandleAware()
     public @Nullable UserInfo createRestrictedProfile(@Nullable String name) {
         try {
-            UserHandle parentUserHandle = Process.myUserHandle();
-            UserInfo user = mService.createRestrictedProfileWithThrow(name,
-                    parentUserHandle.getIdentifier());
-            if (user != null) {
+            final int parentUserId = mUserId;
+            final UserInfo profile = mService.createRestrictedProfileWithThrow(name, parentUserId);
+            if (profile != null) {
+                final UserHandle parentUserHandle = UserHandle.of(parentUserId);
                 AccountManager.get(mContext).addSharedAccountsFromParentUser(parentUserHandle,
-                        UserHandle.of(user.id));
+                        UserHandle.of(profile.id));
             }
-            return user;
+            return profile;
         } catch (ServiceSpecificException e) {
             return null;
         } catch (RemoteException re) {
@@ -3260,13 +3417,14 @@
     /**
      * @hide
      *
-     * Returns the preferred account name for user creation.
+     * Returns the preferred account name for the context user's creation.
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public String getSeedAccountName() {
         try {
-            return mService.getSeedAccountName();
+            return mService.getSeedAccountName(getContextUserIfAppropriate());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -3275,13 +3433,14 @@
     /**
      * @hide
      *
-     * Returns the preferred account type for user creation.
+     * Returns the preferred account type for the context user's creation.
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public String getSeedAccountType() {
         try {
-            return mService.getSeedAccountType();
+            return mService.getSeedAccountType(getContextUserIfAppropriate());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -3291,13 +3450,14 @@
      * @hide
      *
      * Returns the preferred account's options bundle for user creation.
-     * @return Any options set by the requestor that created the user.
+     * @return Any options set by the requestor that created the context user.
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public PersistableBundle getSeedAccountOptions() {
         try {
-            return mService.getSeedAccountOptions();
+            return mService.getSeedAccountOptions(getContextUserIfAppropriate());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -3327,13 +3487,14 @@
 
     /**
      * @hide
-     * Clears the seed information used to create this user.
+     * Clears the seed information used to create the context user.
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public void clearSeedAccountData() {
         try {
-            mService.clearSeedAccountData();
+            mService.clearSeedAccountData(getContextUserIfAppropriate());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -3657,8 +3818,8 @@
      * {@link #getEnabledProfiles(int)} if you need only the enabled ones.
      * <p>Note that this includes all profile types (not including Restricted profiles).
      *
-     * <p>Requires {@link android.Manifest.permission#MANAGE_USERS}.
-     * {@link android.Manifest.permission#CREATE_USERS} suffices if userId is the calling user.
+     * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} or
+     * {@link android.Manifest.permission#CREATE_USERS} if userId is not the calling user.
      * @param userId profiles of this user will be returned.
      * @return the list of profiles.
      * @hide
@@ -3710,8 +3871,8 @@
      * Note that this returns only enabled.
      * <p>Note that this includes all profile types (not including Restricted profiles).
      *
-     * <p>Requires {@link android.Manifest.permission#MANAGE_USERS}.
-     * {@link android.Manifest.permission#CREATE_USERS} suffices if userId is the calling user.
+     * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} or
+     * {@link android.Manifest.permission#CREATE_USERS} if userId is not the calling user.
      * @param userId profiles of this user will be returned.
      * @return the list of profiles.
      * @hide
@@ -3728,19 +3889,21 @@
     }
 
     /**
-     * Returns a list of UserHandles for profiles associated with the user that the calling process
-     * is running on, including the user itself.
+     * Returns a list of UserHandles for profiles associated with the context user, including the
+     * user itself.
      * <p>Note that this includes all profile types (not including Restricted profiles).
      *
-     * @return A non-empty list of UserHandles associated with the calling user.
+     * @return A non-empty list of UserHandles associated with the context user.
      */
+    @UserHandleAware(
+            enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU,
+            requiresAnyOfPermissionsIfNotCaller = {
+                    Manifest.permission.MANAGE_USERS,
+                    Manifest.permission.CREATE_USERS}
+    )
     public List<UserHandle> getUserProfiles() {
-        int[] userIds = getProfileIds(UserHandle.myUserId(), true /* enabledOnly */);
-        List<UserHandle> result = new ArrayList<>(userIds.length);
-        for (int userId : userIds) {
-            result.add(UserHandle.of(userId));
-        }
-        return result;
+        int[] userIds = getProfileIds(getContextUserIfAppropriate(), true /* enabledOnly */);
+        return convertUserIdsToUserHandles(userIds);
     }
 
     /**
@@ -3748,7 +3911,7 @@
      * user itself.
      * <p>Note that this includes all profile types (not including Restricted profiles).
      *
-     * @return A non-empty list of UserHandles associated with the calling user.
+     * @return A non-empty list of UserHandles associated with the context user.
      * @hide
      */
     @SystemApi
@@ -3764,7 +3927,7 @@
      * itself.
      * <p>Note that this includes all profile types (not including Restricted profiles).
      *
-     * @return A non-empty list of UserHandles associated with the calling user.
+     * @return A non-empty list of UserHandles associated with the context user.
      * @hide
      */
     @SystemApi
@@ -3781,13 +3944,18 @@
      * <p>Note that this includes all profile types (not including Restricted profiles).
      *
      * @param enabledOnly whether to return only {@link UserInfo#isEnabled() enabled} profiles
-     * @return A non-empty list of UserHandles associated with the calling user.
+     * @return A non-empty list of UserHandles associated with the context user.
      */
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS}, conditional = true)
     @UserHandleAware
     private @NonNull List<UserHandle> getProfiles(boolean enabledOnly) {
         final int[] userIds = getProfileIds(mUserId, enabledOnly);
+        return convertUserIdsToUserHandles(userIds);
+    }
+
+    /** Converts the given array of userIds to a List of UserHandles. */
+    private @NonNull List<UserHandle> convertUserIdsToUserHandles(@NonNull int[] userIds) {
         final List<UserHandle> result = new ArrayList<>(userIds.length);
         for (int userId : userIds) {
             result.add(UserHandle.of(userId));
@@ -4433,6 +4601,11 @@
      * @return true if user switcher is enabled
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS // And INTERACT_ if diff profile group
+    })
+    @UserHandleAware()
     public boolean isUserSwitcherEnabled() {
         return isUserSwitcherEnabled(true);
     }
@@ -4445,11 +4618,16 @@
      * @return true if user switcher should be shown.
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS // And INTERACT_ if diff profile group
+    })
+    @UserHandleAware()
     public boolean isUserSwitcherEnabled(boolean showEvenIfNotActionable) {
         if (!supportsMultipleUsers()) {
             return false;
         }
-        if (hasUserRestriction(DISALLOW_USER_SWITCH)) {
+        if (hasUserRestrictionForUser(DISALLOW_USER_SWITCH, mUserId)) {
             return false;
         }
         // If Demo Mode is on, don't show user switcher
@@ -4468,10 +4646,14 @@
         // The feature is enabled. But is it worth showing?
         return showEvenIfNotActionable
                 || areThereUsersToWhichToSwitch() // There are switchable users.
-                || !hasUserRestriction(UserManager.DISALLOW_ADD_USER); // New users can be added.
+                || !hasUserRestrictionForUser(DISALLOW_ADD_USER, mUserId); // New users can be added
     }
 
     /** Returns whether there are any users (other than the current user) to which to switch. */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
     private boolean areThereUsersToWhichToSwitch() {
         final List<UserInfo> users = getAliveUsers();
         if (users == null) {
@@ -4530,8 +4712,8 @@
     }
 
     /**
-     * Returns a {@link Bundle} containing any saved application restrictions for this user, for the
-     * given package name. Only an application with this package name can call this method.
+     * Returns a {@link Bundle} containing any saved application restrictions for the context user,
+     * for the given package name. Only an application with this package name can call this method.
      *
      * <p>The returned {@link Bundle} consists of key-value pairs, as defined by the application,
      * where the types of values may be:
@@ -4551,9 +4733,11 @@
      * @see #KEY_RESTRICTIONS_PENDING
      */
     @WorkerThread
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public Bundle getApplicationRestrictions(String packageName) {
         try {
-            return mService.getApplicationRestrictions(packageName);
+            return mService.getApplicationRestrictionsForUser(packageName,
+                    getContextUserIfAppropriate());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e8182e0..eb94fc4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -858,11 +858,12 @@
 
     @Override
     public List<UserInfo> getProfiles(@UserIdInt int userId, boolean enabledOnly) {
-        boolean returnFullInfo = true;
+        boolean returnFullInfo;
         if (userId != UserHandle.getCallingUserId()) {
             checkManageOrCreateUsersPermission("getting profiles related to user " + userId);
+            returnFullInfo = true;
         } else {
-            returnFullInfo = hasManageUsersPermission();
+            returnFullInfo = hasManageOrCreateUsersPermission();
         }
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -1659,9 +1660,13 @@
     }
 
     @Override
-    public boolean isRestricted() {
+    public boolean isRestricted(@UserIdInt int userId) {
+        if (userId != UserHandle.getCallingUserId()) {
+            checkManageOrCreateUsersPermission("query isRestricted for user " + userId);
+        }
         synchronized (mUsersLock) {
-            return getUserInfoLU(UserHandle.getCallingUserId()).isRestricted();
+            final UserInfo userInfo = getUserInfoLU(userId);
+            return userInfo == null ? false : userInfo.isRestricted();
         }
     }
 
@@ -1682,15 +1687,14 @@
     }
 
     @Override
-    public boolean hasRestrictedProfiles() {
+    public boolean hasRestrictedProfiles(@UserIdInt int userId) {
         checkManageUsersPermission("hasRestrictedProfiles");
-        final int callingUserId = UserHandle.getCallingUserId();
         synchronized (mUsersLock) {
             final int userSize = mUsers.size();
             for (int i = 0; i < userSize; i++) {
                 UserInfo profile = mUsers.valueAt(i).info;
-                if (callingUserId != profile.id
-                        && profile.restrictedProfileParentId == callingUserId) {
+                if (userId != profile.id
+                        && profile.restrictedProfileParentId == userId) {
                     return true;
                 }
             }
@@ -2541,6 +2545,14 @@
      */
     private static final boolean hasManageUsersPermission() {
         final int callingUid = Binder.getCallingUid();
+        return hasManageUsersPermission(callingUid);
+    }
+
+    /**
+     * @return whether the given UID is system UID or root's UID or the has the permission
+     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}.
+     */
+    private static boolean hasManageUsersPermission(int callingUid) {
         return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
                 || callingUid == Process.ROOT_UID
                 || hasPermissionGranted(android.Manifest.permission.MANAGE_USERS, callingUid);
@@ -2552,9 +2564,7 @@
      */
     private static final boolean hasManageUsersOrPermission(String alternativePermission) {
         final int callingUid = Binder.getCallingUid();
-        return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
-                || callingUid == Process.ROOT_UID
-                || hasPermissionGranted(android.Manifest.permission.MANAGE_USERS, callingUid)
+        return hasManageUsersPermission(callingUid)
                 || hasPermissionGranted(alternativePermission, callingUid);
     }
 
@@ -4939,39 +4949,39 @@
     }
 
     @Override
-    public String getSeedAccountName() throws RemoteException {
+    public String getSeedAccountName(@UserIdInt int userId) throws RemoteException {
         checkManageUsersPermission("Cannot get seed account information");
         synchronized (mUsersLock) {
-            UserData userData = getUserDataLU(UserHandle.getCallingUserId());
-            return userData.seedAccountName;
+            final UserData userData = getUserDataLU(userId);
+            return userData == null ? null : userData.seedAccountName;
         }
     }
 
     @Override
-    public String getSeedAccountType() throws RemoteException {
+    public String getSeedAccountType(@UserIdInt int userId) throws RemoteException {
         checkManageUsersPermission("Cannot get seed account information");
         synchronized (mUsersLock) {
-            UserData userData = getUserDataLU(UserHandle.getCallingUserId());
-            return userData.seedAccountType;
+            final UserData userData = getUserDataLU(userId);
+            return userData == null ? null : userData.seedAccountType;
         }
     }
 
     @Override
-    public PersistableBundle getSeedAccountOptions() throws RemoteException {
+    public PersistableBundle getSeedAccountOptions(@UserIdInt int userId) throws RemoteException {
         checkManageUsersPermission("Cannot get seed account information");
         synchronized (mUsersLock) {
-            UserData userData = getUserDataLU(UserHandle.getCallingUserId());
-            return userData.seedAccountOptions;
+            final UserData userData = getUserDataLU(userId);
+            return userData == null ? null : userData.seedAccountOptions;
         }
     }
 
     @Override
-    public void clearSeedAccountData() throws RemoteException {
+    public void clearSeedAccountData(@UserIdInt int userId) throws RemoteException {
         checkManageUsersPermission("Cannot clear seed account information");
         synchronized (mPackagesLock) {
             UserData userData;
             synchronized (mUsersLock) {
-                userData = getUserDataLU(UserHandle.getCallingUserId());
+                userData = getUserDataLU(userId);
                 if (userData == null) return;
                 userData.clearSeedAccountData();
             }