• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.permission.util;
18 
19 import android.annotation.NonNull;
20 import android.annotation.UserIdInt;
21 import android.content.Context;
22 import android.os.Binder;
23 import android.os.Process;
24 import android.os.UserHandle;
25 import android.os.UserManager;
26 
27 import com.android.internal.util.Preconditions;
28 import com.android.permission.compat.UserHandleCompat;
29 
30 import java.util.List;
31 
32 /** Utility class to deal with Android users. */
33 public final class UserUtils {
34 
UserUtils()35     private UserUtils() {}
36 
37     /** Enforces cross user permission for the calling UID and the given {@code userId}. */
enforceCrossUserPermission( @serIdInt int userId, boolean allowAll, @NonNull String message, @NonNull Context context)38     public static void enforceCrossUserPermission(
39             @UserIdInt int userId,
40             boolean allowAll,
41             @NonNull String message,
42             @NonNull Context context) {
43         final int callingUid = Binder.getCallingUid();
44         final int callingUserId = UserHandleCompat.getUserId(callingUid);
45         if (userId == callingUserId) {
46             return;
47         }
48         Preconditions.checkArgument(
49                 userId >= UserHandleCompat.USER_SYSTEM
50                         || (allowAll && userId == UserHandleCompat.USER_ALL),
51                 "Invalid user " + userId);
52         context.enforceCallingOrSelfPermission(
53                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
54         if (callingUid != Process.SHELL_UID || userId < UserHandleCompat.USER_SYSTEM) {
55             return;
56         }
57         UserManager userManager = context.getSystemService(UserManager.class);
58         if (userManager.hasUserRestrictionForUser(
59                 UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.of(userId))) {
60             throw new SecurityException("Shell does not have permission to access user " + userId);
61         }
62     }
63 
64     /** Returns whether a given {@code userId} corresponds to an existing user. */
isUserExistent(@serIdInt int userId, @NonNull Context context)65     public static boolean isUserExistent(@UserIdInt int userId, @NonNull Context context) {
66         return getUserHandles(context).contains(UserHandle.of(userId));
67     }
68 
69     /** Returns all the alive users on the device. */
70     @NonNull
getUserHandles(@onNull Context context)71     public static List<UserHandle> getUserHandles(@NonNull Context context) {
72         UserManager userManager = context.getSystemService(UserManager.class);
73         // This call requires the MANAGE_USERS permission.
74         final long identity = Binder.clearCallingIdentity();
75         try {
76             return userManager.getUserHandles(true);
77         } finally {
78             Binder.restoreCallingIdentity(identity);
79         }
80     }
81 
82     /** Returns whether a given {@code userId} corresponds to a managed profile. */
isManagedProfile(@serIdInt int userId, @NonNull Context context)83     public static boolean isManagedProfile(@UserIdInt int userId, @NonNull Context context) {
84         UserManager userManager = context.getSystemService(UserManager.class);
85         // This call requires the QUERY_USERS permission.
86         final long identity = Binder.clearCallingIdentity();
87         try {
88             return userManager.isManagedProfile(userId);
89         } finally {
90             Binder.restoreCallingIdentity(identity);
91         }
92     }
93 
94     /**
95      * Returns whether a given {@code userId} corresponds to a running managed profile, i.e. the
96      * user is running and the quiet mode is not enabled.
97      */
isProfileRunning(@serIdInt int userId, @NonNull Context context)98     public static boolean isProfileRunning(@UserIdInt int userId, @NonNull Context context) {
99         UserManager userManager = context.getSystemService(UserManager.class);
100         // This call requires the QUERY_USERS permission
101         final long identity = Binder.clearCallingIdentity();
102         try {
103             return userManager.isUserRunning(UserHandle.of(userId))
104                     && !userManager.isQuietModeEnabled(UserHandle.of(userId));
105         } finally {
106             Binder.restoreCallingIdentity(identity);
107         }
108     }
109 }
110