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