mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET, null);
大家经常会看到上面这句话在runtime是check 权限,具体是怎么实现的呢?
xref: /frameworks/base/core/java/android/app/ContextImpl.java
1568 public void enforceCallingOrSelfPermission(
1569 String permission, String message) {
1570 enforce(permission,
1571 checkCallingOrSelfPermission(permission),
1572 true,
1573 Binder.getCallingUid(),
1574 message);
1575 }
1537 private void enforce(
1538 String permission, int resultOfCheck,
1539 boolean selfToo, int uid, String message) {
1540 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1541 throw new SecurityException(
1542 (message != null ? (message + ": ") : "") +
1543 (selfToo
1544 ? "Neither user " + uid + " nor current process has "
1545 : "uid " + uid + " does not have ") +
1546 permission +
1547 ".");
1548 }
1549 }
resultOfCheck=checkCallingOrSelfPermission(permission)
只要resultOfCheck 等于PackageManager.PERMISSION_GRANTED 就表示有权限,我们在来看看checkCallingOrSelfPermission的实现。
1528 public int checkCallingOrSelfPermission(String permission) {
1529 if (permission == null) {
1530 throw new IllegalArgumentException("permission is null");
1531 }
1532
1533 return checkPermission(permission, Binder.getCallingPid(),
1534 Binder.getCallingUid());
1535 }
checkCallingOrSelfPermission 在判断permission 不能为空后,继续调用checkPermission
1501 public int checkPermission(String permission, int pid, int uid) {
1502 if (permission == null) {
1503 throw new IllegalArgumentException("permission is null");
1504 }
1505
1506 try {
1507 return ActivityManagerNative.getDefault().checkPermission(
1508 permission, pid, uid);
1509 } catch (RemoteException e) {
1510 return PackageManager.PERMISSION_DENIED;
1511 }
1512 }
第1507行可知最后是调用到ActivityManagerService 那边
/server/am/ActivityManagerService.java
@Override
public int checkPermission(String permission, int pid, int uid) {
if (permission == null) {
return PackageManager.PERMISSION_DENIED;
}
return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);
}
继续调用checkComponentPermission
int checkComponentPermission(String permission, int pid, int uid,
int owningUid, boolean exported) {
// We might be performing an operation on behalf of an indirect binder
// invocation, e.g. via {@link #openContentUri}. Check and adjust the
// client identity accordingly before proceeding.
Identity tlsIdentity = sCallerIdentity.get();
if (tlsIdentity != null) {
Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
+ tlsIdentity.pid + "," + tlsIdentity.uid + "}");
uid = tlsIdentity.uid;
pid = tlsIdentity.pid;
}
if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
}
return ActivityManager.checkComponentPermission(permission, uid,
owningUid, exported);
}
android/app/ActivityManager.java
调用activitymanager 的checkComponentPermission
public static int checkComponentPermission(String permission, int uid,
int owningUid, boolean exported) {
// Root, system server get to do everything.
final int appId = UserHandle.getAppId(uid);
if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
return PackageManager.PERMISSION_GRANTED;
}
// Isolated processes don't get any permissions.
if (UserHandle.isIsolated(uid)) {
return PackageManager.PERMISSION_DENIED;
}
// If there is a uid that owns whatever is being accessed, it has
// blanket access to it regardless of the permissions it requires.
if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) {
return PackageManager.PERMISSION_GRANTED;
}
// If the target is not exported, then nobody else can get to it.
if (!exported) {
/*
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid,
here);
*/
return PackageManager.PERMISSION_DENIED;
}
if (permission == null) {
return PackageManager.PERMISSION_GRANTED;
}
try {
return AppGlobals.getPackageManager()
.checkUidPermission(permission, uid);
} catch (RemoteException e) {
// Should never happen, but if it does... deny!
Slog.e(TAG, "PackageManager is dead?!?", e);
}
return PackageManager.PERMISSION_DENIED;
}
这个函数最关键的一句AppGlobals.getPackageManager().checkUidPermission(permission, uid);
最后还是调用packagemanagerservice的checkUiPermission函数。
public int checkUidPermission(String permName, int uid) {
final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
synchronized (mPackages) {
Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
if (obj != null) {
GrantedPermissions gp = (GrantedPermissions)obj;
if (gp.grantedPermissions.contains(permName)) {
return PackageManager.PERMISSION_GRANTED;
}
} else {
HashSet perms = mSystemPermissions.get(uid);
if (perms != null && perms.contains(permName)) {
return PackageManager.PERMISSION_GRANTED;
}
}
if (!isPermissionEnforcedLocked(permName, enforcedDefault)) {
return PackageManager.PERMISSION_GRANTED;
}
}
return PackageManager.PERMISSION_DENIED;
}
分两种情况,分别查mSettings 里面和 mSystemPermissions 这个hashset里面是否有权限.