Android账户uid和App的uid的含义

总结:
这篇文章你会学到: PackageManagerSercive UserManagerService UserHandle是一个工具类

Android系统中,每个用户都有自己的一套权限和资源,因此需要将系统中的各种资源进行隔离和分配.Android系统给每个用户分配的资源范围是 100000. 每个用户预留了 100000个UID号.比如 第一个用户的UID=0 那么他的资源就是 0 - 999999 . 如果第二个账户UID=1. 那么他的资源范围就是 100000 - 199999. 为什么要这么干因为每个app都有唯一一个UID号.
在App启动的时候,第一个判断就是判断当期要启动的app是不是属于这个用户的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class ActivityTaskManagerService{
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
@Nullable String callingFeatureId, Intent intent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
// 判断 这个包是不是这个用户的
assertPackageMatchesCallingUid(callingPackage);
enforceNotIsolatedCaller("startActivityAsUser");

userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

// TODO: Switch to user app stacks here.
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setCallingFeatureId(callingFeatureId)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setUserId(userId)
.execute();

}
}
1
2
3
4
5
6
7
8
9
10
11
void assertPackageMatchesCallingUid(@Nullable String packageName) {
// 获取当期app的uid 比如是10106 每个app安装的时候就会被固定分配一个值
final int callingUid = Binder.getCallingUid();
if (isSameApp(callingUid, packageName)) {
return;
}
final String msg = "Permission Denial: package=" + packageName
+ " does not belong to uid=" + callingUid;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private boolean isSameApp(int callingUid, @Nullable String packageName) {
try {
//SYSTEM_UID 超级管理员是1000
if (callingUid != 0 && callingUid != SYSTEM_UID) {
if (packageName == null) {
return false;
}
//通过包名获取用户的uid
final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
UserHandle.getUserId(callingUid));
// 最终步骤
return UserHandle.isSameApp(callingUid, uid);
}
} catch (RemoteException e) {
// Should not happen
}
return true;
}

这里就涉及到了另外一个系统级别的服务PackageManagerService

1
2
3
4
5
6
7
8
9
10
11
12
class PackageManagerSercice{
// 找到对应的用户id 一般就0 1 2 这么小的值
public int getPackageUid(String packageName, int flags, int userId) {
//通过系统级别服务判断这个用户存在不
if (!mUserManager.exists(userId)) return -1;
final int callingUid = Binder.getCallingUid();
flags = updateFlagsForPackage(flags, userId);
enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
false /*checkShell*/, "getPackageUid");
return getPackageUidInternal(packageName, flags, userId, callingUid);
}
}

这里又涉及到了另外一个服务UserManagerSercice,用户判断用户是否存在.

这里就不开枝散叶了,直接看回最终步骤:

1
2
3
4
5
6
7
8
9
UserHandle.isSameApp(callingUid, uid);

public static boolean isSameApp(int uid1, int uid2) {
return getAppId(uid1) == getAppId(uid2);
}

public static @AppIdInt int getAppId(int uid) {
return uid % PER_USER_RANGE;//100000
}