BasePermission
系统权限的基本表示单元是BasePermission,Settings中维护了一个总的权限映射表mPermissions,所有权限都会添加到mPermissions列表中,其中key是权限的名字,value是具体的BasePermission实例。
[/frameworks/base/services/core/java/com/android/server/pm/Settings.java]
// Mapping from permission names to info about them.
final ArrayMap<String, BasePermission> mPermissions = new ArrayMap<String, BasePermission>();
我们都知道绝大部分权限已经在系统中定义好,如READ_EXTERNAL_STORAGE读写外部存储权限、READ_PHONE_STATE读取手机状态信息权限等,这些权限的定义都在framework-res.apk中,在扫描framework-res.apk过程中解析并添加到mPermissions映射表中。系统权限的定义:
[/frameworks/base/core/res/AndroidManifest.xml]
<!-- Allows an application to send SMS messages. -->
<permission android:name="android.permission.SEND_SMS"
android:permissionGroup="android.permission-group.MESSAGES"
android:protectionLevel="dangerous"
android:permissionFlags="costsMoney"
android:label="@string/permlab_sendSms"
android:description="@string/permdesc_sendSms" />
绝大部分的权限定义都在上面的AndroidManifest.xml文件中,最终会打包进framework-res.apk中并经过解析保存到Settings的mPermissions映射表中。
final class BasePermission {
final static int TYPE_NORMAL = 0;
final static int TYPE_BUILTIN = 1;//构建类型
final static int TYPE_DYNAMIC = 2;//动态类型
final String name;
String sourcePackage;
PackageSettingBase packageSetting;
final int type;
int protectionLevel;
PackageParser.Permission perm;
PermissionInfo pendingInfo;
/** UID that owns the definition of this permission */
int uid;//拥有此权限定义的UID
/** Additional GIDs given to apps granted this permission */
private int[] gids;//授予应用程序这个权限的附加GIDs
/**
* Flag indicating that {@link #gids} should be adjusted based on the
* {@link UserHandle} the granted app is running as.表示gids应该基于UserHandle授予的应用程序进行调整的标志
*/
private boolean perUser;
BasePermission(String _name, String _sourcePackage, int _type) {
name = _name;
sourcePackage = _sourcePackage;
type = _type;
// Default to most conservative protection level.默认为最保守的保护级别
protectionLevel = PermissionInfo.PROTECTION_SIGNATURE;
}
@Override
public String toString() {
return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " " + name
+ "}";//identityHashCode返回给定对象的哈希码
}
public void setGids(int[] gids, boolean perUser) {
this.gids = gids;
this.perUser = perUser;
}
public int[] computeGids(int userId) {
if (perUser) {
final int[] userGids = new int[gids.length];
for (int i = 0; i < gids.length; i++) {
userGids[i] = UserHandle.getUid(userId, gids[i]);
}
return userGids;
} else {
return gids;
}
}
public boolean isRuntime() {
return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)//保护级别的标志:基本的保护类型
== PermissionInfo.PROTECTION_DANGEROUS;//危险级别
}
public boolean isDevelopment() {
return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
== PermissionInfo.PROTECTION_SIGNATURE//对应于签名的保护级别,系统级的保护级别。
&& (protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0;//对于development的附加标志
}
public boolean isInstant() {
return (protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0;
}
public boolean isRuntimeOnly() {
return (protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0;
}
}
PackageParser.Permission
PackageParser.Permission使用PackageParser解析apk的AndroidManifest.xml文件中的<permission>标签后得到的权限表示。PackageParser.Permission中包含一个对应的PermissionInfo。
public final static class Permission extends Component<IntentInfo> implements Parcelable {
public final PermissionInfo info;
public boolean tree;
public PermissionGroup group;
public Permission(Package _owner) {
super(_owner);
info = new PermissionInfo();
}
public Permission(Package _owner, PermissionInfo _info) {
super(_owner);
info = _info;
}
public void setPackageName(String packageName) {
super.setPackageName(packageName);
info.packageName = packageName;
}
public String toString() {
return "Permission{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + info.name + "}";
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeParcelable(info, flags);
dest.writeInt(tree ? 1 : 0);
dest.writeParcelable(group, flags);
}
private Permission(Parcel in) {
super(in);
final ClassLoader boot = Object.class.getClassLoader();
info = in.readParcelable(boot);
if (info.group != null) {
info.group = info.group.intern();
}
tree = (in.readInt() == 1);
g