在Android源码的很多地方都会出现权限检查的方法checkPermission,此篇文字主要介绍Android5.1.1源码中的checkPermission方法是如何实现的,在此以WallpaperManagerService.java中的checkPermission方法为例来分析。
./base/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
........final Context mContext;
........
public WallpaperManagerService(Context context) {
mContext = context;
........
}
........
private void checkPermission(String permission) {
// 调用Context的checkCallingOrSelfPermission来检查权限
if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
throw new SecurityException("Access denied to process: " + Binder.getCallingPid()+ ", must have permission " + permission);
}
}
checkCallingOrSelfPermission中checkCallingOrSelfPermission的定义
./base/core/java/android/context/Context.java
public abstract int checkCallingOrSelfPermission(@NonNull String permission);
ContextImpl实现了Context接口,权限检查是在ContextImpl类的checkPermission方法来完成的
./base/core/java/android/app/ContextImpl.java
@Override
public int checkPermission(String permission, int pid, int uid) {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
}
try {
return ActivityManagerNative.getDefault().checkPermission(
permission, pid, uid); // 调用ActivityManagerNative的getDefault()方法来获取ActivityManagerService的对象
} catch (RemoteException e) {
return PackageManager.PERMISSION_DENIED;
}
}
........
@Override
public int checkCallingOrSelfPermission(String permission) {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
}
return checkPermission(permission, Binder.getCallingPid(),
Binder.getCallingUid()); // 调用checkPermission函数来检查权限
}
ActivityManagerNative中getDefault方法实现过程
./base/core/java/android/app/ActivityManagerNative.java
static public IActivityManager getDefault() {
return gDefault.get(); // 最终返回的是个ActivityManagerService的对象
}
ActivityManagerService中checkPermission的实现过程
./base/services/core/java/com/android/server/am/ActivityManagerService.java
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); // 调用ActivityManager的checkComponentPermission来检查权限
}
........
@Override
public int checkPermission(String permission, int pid, int uid) {
if (permission == null) {
return PackageManager.PERMISSION_DENIED;
}
// 调用checkComponentPermission函数来检查权限
}
ActivityManager中checkComponentPermission的实现过程
./base/core/java/android/app/ActivityManager.java
public static int checkComponentPermission(String permission, int uid,
int owningUid, boolean exported) {
........
try {
return AppGlobals.getPackageManager() // 调用AppGlobals的getPackageManager()函数返回IPackageManager对象
.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方法实现过程
./base/core/java/android/app/AppGlobals.java
public static IPackageManager getPackageManager() {
return ActivityThread.getPackageManager(); // 调用ActivityThread的getPackageManager()函数
}
ActivityThread的getPackageManager实现过程
./base/core/java/android/app/ActivityThread.java
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
//Slog.v("PackageManager", "returning cur default = " + sPackageManager);
return sPackageManager;
}
IBinder b = ServiceManager.getService("package");
//Slog.v("PackageManager", "default service binder = " + b);
sPackageManager = IPackageManager.Stub.asInterface(b); // 最终获取的是PackageManagerService的对象
//Slog.v("PackageManager", "default service = " + sPackageManager);
return sPackageManager;
}
PackageManagerService的checkUidPermission实现过程
./base/services/core/java/com/android/server/pm/PackageManagerService.java
@Override
public int checkUidPermission(String permName, int uid) {
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<String> perms = mSystemPermissions.get(uid);
if (perms != null && perms.contains(permName)) {
return PackageManager.PERMISSION_GRANTED;
}
}
}
return PackageManager.PERMISSION_DENIED;
}
至此权限检查就已完成