PID 指进程ID.
PID是进程的身份标识,程序一旦运行,就会给应用分配一个独一无二的PID(ps:一个应用可能包含多个进程,每个进程有唯一的一个PID)
进程终止后PID会被系统收回,再次打开应用,会重新分配一个PID(新进程的PID一般比之前的号要大)
UID 指用户ID.
UID在Linux中就是用户的ID,表明时哪个用户运行了这个程序,主要用于权限的管理。而在Android 中又有所不同,因为android为单用户系统,这时UID 便被赋予了新的使命,数据共享,为了实现数据共享,Android init时是root权限,zygote出的系统systemserver时赋予system的uid,权限降为system权限,普通应用启动时被赋予
system 284 1 6172 1356 binder_thr f76c3430 S /system/bin/servicemanager
root 337 120 4876 1340 unix_strea f76bc430 S /system/bin/sh
root 339 120 5816 1452 __skb_recv f76c2430 S logcat
root 342 120 5816 1452 __skb_recv f76e4430 S logcat
root 346 1 1053464 74984 poll_sched f764f430 S zygote
audioserver 347 1 27488 5744 binder_thr f76dd430 S /system/bin/audioserver
cameraserver 348 1 71892 14524 binder_thr f7637430 S /system/bin/cameraserver
mediaex 349 1 47108 6896 binder_thr f7689430 S media.extractor
media 350 1 47384 7264 binder_thr f76f9430 S /system/bin/mediaserver
root 351 1 22156 2948 binder_thr f7672430 S /system/bin/netd
system 352 1 83656 3740 ep_poll f76a0430 S /system/bin/surfaceflinger
system 624 346 1214696 112084 ep_poll f764f430 S system_server
u0_a48 703 346 814300 51444 ep_poll f764f430 S com.android.inputmethod.latin
media_rw 708 84 9492 2184 inotify_re f76c6430 S /system/bin/sdcard
u0_a23 721 346 922336 140108 ep_poll f764f430 S com.android.systemui
radio 786 346 833520 64496 ep_poll f764f430 S com.android.phone
system 801 346 840676 48120 ep_poll f764f430 S com.android.settings
wifi 845 1 10024 3224 poll_sched f748b430 S /system/bin/wpa_supplicant
u0_a12 959 346 797732 40000 ep_poll f764f430 S android.ext.services
u0_a38 981 346 807800 45764 ep_poll f764f430 S com.android.deskclock
u0_a4 1024 346 799432 42172 ep_poll f764f430 S com.android.cellbroadcastreceiver
u0_a10 1058 346 804924 50732 ep_poll f764f430 S android.process.media
u0_a56 1101 346 800832 41588 ep_poll f764f430 S com.android.printspooler
system 1129 346 797848 40040 ep_poll f764f430 S com.android.keychain
u0_a14 1145 346 830128 69140 ep_poll f764f430 S com.android.launcher3
u0_a**的uid,另外还有wifi uid等。
普通的应用调用需要系统权限的方法时,一般会报出Permission Denal的SecureException,这个检查的过程是如何的?我们从一个场景进行分析,monkey检测系统应用启动有一个接口,
@Override
public void setActivityController(IActivityController controller, boolean imAMonkey) {
enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
"setActivityController()");
synchronized (this) {
mController = controller;
mControllerIsAMonkey = imAMonkey;
Watchdog.getInstance().setActivityController(controller);
}
}
这个接口在IActivityManager的Stub端ActivityManagerService的实现,普通应用通过ActivityManagerNatvie调用这个接口,第一步就会调用
enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, "setActivityController()");
来检查应用权限,我们继续看这个方法。
void enforceCallingPermission(String permission, String func) {
if (checkCallingPermission(permission)
== PackageManager.PERMISSION_GRANTED) {
return;
}
String msg = "Permission Denial: " + func + " from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
+ " requires " + permission;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
我们看到如果checkCallingPermission这个方法没有返回PERMISSION_GRANTED的话,就会抛出Permission Denial的错误。我们接着看这个方法。
int checkCallingPermission(String permission) {
return checkPermission(permission,
Binder.getCallingPid(),
UserHandle.getAppId(Binder.getCallingUid()));
}
@Override
public int checkPermission(String permission, int pid, int uid) {
if (permission == null) {
return PackageManager.PERMISSION_DENIED;
}
return checkComponentPermission(permission, pid, uid, -1, true);
}
/**
* This can be called with or without the global lock held.
*/
int checkComponentPermission(String permission, int pid, int uid,
int owningUid, boolean exported) {
if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
}
return ActivityManager.checkComponentPermission(permission, uid,
owningUid, exported);
}
首先检查是否是MY_PID,一般如果不是相同进程,这个pid是不同的。
/** @hide */
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) {
throw e.rethrowFromSystemServer();
}
}
然后调用ActivityManager.checkComponentPermission(permission, uid, owningUid, exported);方法检查。如果是root或者system的uid,直接返回PERMISSION_GRANTED。
system uid需要在manifest根节点中shareUserId中设置,并且使用目标系统的签名工具,手机厂商不同,这个签名工具一般是不同的。
return AppGlobals.getPackageManager()
.checkUidPermission(permission, uid);
最后一步检查APP的权限设置。

本文探讨了Android系统中PID和UID的概念及其区别。PID是进程标识,每次应用启动都会获得唯一PID,而UID在Android中用于权限管理和数据共享。当普通应用尝试调用需要系统权限的方法时,会遇到Permission Denial错误。这个错误通常在checkCallingPermission方法未返回PERMISSION_GRANTED时抛出。检查过程涉及比较PID、判断UID是否为root或system以及检查APP的权限设置。
3206

被折叠的 条评论
为什么被折叠?



