1 package com.android.nfc; 2 3 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 4 5 import android.annotation.Nullable; 6 import android.app.ActivityManager; 7 import android.app.AppOpsManager; 8 import android.app.admin.DevicePolicyManager; 9 import android.content.Context; 10 import android.content.pm.PackageManager; 11 import android.os.Binder; 12 import android.os.UserHandle; 13 import android.os.UserManager; 14 import android.util.Log; 15 16 import java.util.List; 17 18 public class NfcPermissions { 19 20 private static final String TAG = "NfcPermissions"; 21 22 /** 23 * NFC ADMIN permission - only for system apps 24 */ 25 private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS; 26 private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required"; 27 28 /** 29 * Regular NFC permission 30 */ 31 static final String NFC_PERMISSION = android.Manifest.permission.NFC; 32 private static final String NFC_PERM_ERROR = "NFC permission required"; 33 34 /** 35 * NFC PREFERRED PAYMENT INFO permission 36 */ 37 static final String NFC_PREFERRED_PAYMENT_INFO_PERMISSION = 38 android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO; 39 private static final String NFC_PREFERRED_PAYMENT_INFO_PERM_ERROR = 40 "NFC_PREFERRED_PAYMENT_INFO permission required"; 41 42 /** 43 * NFC SET CONTROLLER ALWAYS ON permission 44 */ 45 static final String NFC_SET_CONTROLLER_ALWAYS_ON = 46 android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON; 47 private static final String NFC_SET_CONTROLLER_ALWAYS_ON_ERROR = 48 "NFC_SET_CONTROLLER_ALWAYS_ON permission required"; 49 50 private final Context mContext; 51 private final AppOpsManager mAppOpsManager; 52 53 NfcPermissions(Context context)54 public NfcPermissions(Context context) { 55 mContext = context; 56 mAppOpsManager = mContext.getSystemService(AppOpsManager.class); 57 } 58 59 validateUserId(int userId)60 public static void validateUserId(int userId) { 61 if (userId != UserHandle.getUserHandleForUid(Binder.getCallingUid()).getIdentifier()) { 62 throw new SecurityException("userId passed in is not the calling user."); 63 } 64 } 65 66 /** 67 * Validate whether the profileId belongs to current user 68 */ validateProfileId(Context context, int profileId)69 public static void validateProfileId(Context context, int profileId) { 70 // Propagate the state change to all user profiles 71 UserManager um = context.createContextAsUser( 72 UserHandle.of(ActivityManager.getCurrentUser()), /*flags=*/0) 73 .getSystemService(UserManager.class); 74 List<UserHandle> luh = um.getEnabledProfiles(); 75 76 for (UserHandle uh : luh) { 77 if (profileId == uh.getIdentifier()) { 78 return; 79 } 80 } 81 82 throw new SecurityException("profileId passed in does not belong to the calling user."); 83 } 84 enforceAdminPermissions(Context context)85 public static void enforceAdminPermissions(Context context) { 86 context.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR); 87 } 88 checkAdminPermissions(Context context)89 public static boolean checkAdminPermissions(Context context) { 90 return context.checkCallingOrSelfPermission(ADMIN_PERM) == PERMISSION_GRANTED; 91 } 92 enforceUserPermissions(Context context)93 public static void enforceUserPermissions(Context context) { 94 context.enforceCallingOrSelfPermission(NFC_PERMISSION, NFC_PERM_ERROR); 95 } 96 enforcePreferredPaymentInfoPermissions(Context context)97 public static void enforcePreferredPaymentInfoPermissions(Context context) { 98 context.enforceCallingOrSelfPermission(NFC_PREFERRED_PAYMENT_INFO_PERMISSION, 99 NFC_PREFERRED_PAYMENT_INFO_PERM_ERROR); 100 } 101 102 /** 103 * Permission check for android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON 104 */ enforceSetControllerAlwaysOnPermissions(Context context)105 public static void enforceSetControllerAlwaysOnPermissions(Context context) { 106 context.enforceCallingOrSelfPermission(NFC_SET_CONTROLLER_ALWAYS_ON, 107 NFC_SET_CONTROLLER_ALWAYS_ON_ERROR); 108 } 109 110 /** 111 * Returns the DevicePolicyManager from context 112 */ retrieveDevicePolicyManagerFromContext(Context context)113 public static DevicePolicyManager retrieveDevicePolicyManagerFromContext(Context context) { 114 DevicePolicyManager devicePolicyManager = 115 context.getSystemService(DevicePolicyManager.class); 116 if (devicePolicyManager == null 117 && context.getPackageManager().hasSystemFeature( 118 PackageManager.FEATURE_DEVICE_ADMIN)) { 119 Log.w(TAG, "retrieveDevicePolicyManagerFromContext: Error"); 120 } 121 return devicePolicyManager; 122 } 123 124 /** 125 * Returns {@code true} if the calling {@code uid} and {@code packageName} is the device owner. 126 */ isDeviceOwner(int uid, @Nullable String packageName)127 public boolean isDeviceOwner(int uid, @Nullable String packageName) { 128 // Cannot determine if the app is DO/PO if packageName is null. So, will return false to be 129 // safe. 130 if (packageName == null) { 131 Log.e(TAG, "isDeviceOwner: packageName is null, returning false"); 132 return false; 133 } 134 DevicePolicyManager devicePolicyManager = 135 retrieveDevicePolicyManagerFromUserContext(uid); 136 if (devicePolicyManager == null) return false; 137 return devicePolicyManager.isDeviceOwnerApp(packageName); 138 } 139 140 @Nullable createPackageContextAsUser(int uid)141 private Context createPackageContextAsUser(int uid) { 142 Context userContext = null; 143 try { 144 userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0, 145 UserHandle.getUserHandleForUid(uid)); 146 } catch (PackageManager.NameNotFoundException e) { 147 Log.e(TAG, "createPackageContextAsUser: Unknown package name"); 148 return null; 149 } 150 if (userContext == null) { 151 Log.e(TAG, "createPackageContextAsUser: Unable to retrieve user context for " + uid); 152 return null; 153 } 154 return userContext; 155 } 156 retrieveDevicePolicyManagerFromUserContext(int uid)157 private DevicePolicyManager retrieveDevicePolicyManagerFromUserContext(int uid) { 158 long ident = Binder.clearCallingIdentity(); 159 try { 160 Context userContext = createPackageContextAsUser(uid); 161 if (userContext == null) return null; 162 return retrieveDevicePolicyManagerFromContext(userContext); 163 } finally { 164 Binder.restoreCallingIdentity(ident); 165 } 166 } 167 168 /** 169 * Returns true if the |callingUid|/|callingPackage| is the profile owner. 170 */ isProfileOwner(int uid, @Nullable String packageName)171 public boolean isProfileOwner(int uid, @Nullable String packageName) { 172 // Cannot determine if the app is DO/PO if packageName is null. So, will return false to be 173 // safe. 174 if (packageName == null) { 175 Log.e(TAG, "isProfileOwner: packageName is null, returning false"); 176 return false; 177 } 178 DevicePolicyManager devicePolicyManager = 179 retrieveDevicePolicyManagerFromUserContext(uid); 180 if (devicePolicyManager == null) return false; 181 return devicePolicyManager.isProfileOwnerApp(packageName); 182 } 183 184 /** 185 * API to validate if a package name belongs to a UID. Throws SecurityException 186 * if pkgName does not belongs to a UID 187 * 188 * @param pkgName package name of the application requesting access 189 * @param uid The uid of the package 190 * 191 */ checkPackage(int uid, String pkgName)192 public void checkPackage(int uid, String pkgName) throws SecurityException { 193 if (pkgName == null) { 194 throw new SecurityException("Checking UID " + uid + " but Package Name is Null"); 195 } 196 mAppOpsManager.checkPackage(uid, pkgName); 197 } 198 } 199