标签:
1、什么是protectionlevel呢?
我们经常在AndroidManifest中使用权限,如果我们想让应用程序可以发短信,那么应该这样写:
<uses-permission android:name="android.permission.SEND_SMS" />
frameworks/base/core/res/AndroidManifest.xml
<permission android:name="android.permission.SEND_SMS" android:permissionGroup="android.permission-group.COST_MONEY" android:protectionLevel="dangerous" android:label="@string/permlab_sendSms" android:description="@string/permdesc_sendSms" />这个xml可以认为是系统apk使用的AndroidManifest.xml,该apk使用系统的私钥进行签名。
name:权限的名字,uses-permisson使用的。
permissionGroup:权限的分类,在提示用户安装时会把某些功能差不多的权限放到一类。
protectionLevel:分为Normal、Dangerous、Signature、SignatureOrSystem,我们后面会着重讲这个。
label:提示给用户的权限名。
description:提示给用户的权限描述。
2、protectionLevel
(1)Normal
权限被声明为Normal级别,任何应用都可以申请,在安装应用时,不会直接提示给用户,点击全部才会展示。
(2)Dangerous
权限被声明为Dangerous级别,任何应用都可以申请,在安装应用时,会直接提示给用户。
(3)Signature
权限被声明为Signature级别,只有和该apk(定义了这个权限的apk)用相同的私钥签名的应用才可以申请该权限。
frameworks/base/core/res/AndroidManifest.xml声明的权限为Signature级别,那么只有Android官方使用相同私钥签名的应用才可以申请该权限。
(4)SignatureOrSystem
权限被声明为SignatureOrSystem级别,有两种应用可以申请该权限。
1)和该apk(定义了这个权限的apk)用相同的私钥签名的应用
2)在/system/app目录下的应用
3、举个例子
比如百度地图apk的AndroidManifest.xml里面声明了一个权限,
(1)、权限定义为Dangerous,那么任何其他应用都可以使用。
(2)、权限定义为Signature,那么只有使用同样私钥签名的apk,例如百度网盘,可以使用这个权限。
(3)、权限定义为SignatureOrSystem,那么使用同样私钥签名的apk,例如百度网盘,可以使用这个权限。在/system/app下的应用也可以使用这个权限。
4、我们自然想到一个问题,申请了某个权限与否,在代码中是怎么控制是否可以访问某个资源呢?
(1)、Android系统独有的权限,在代码中是怎么控制是否可以访问某个资源呢?我们看一个实际的例子。
Client端:
void startDockOrHome(){ awakenDreams(); ...... } private static void awakenDreams(){ IDreamManager dreamManager = getDreamManager(); if(dreamManager != null){ try{ dreamManager.awaken();//调用Server端的awaken } catch(RemoteException e){ //fine, stay asleep then } }Server端:
@Override // Binder call public void awaken() { checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); final long ident = Binder.clearCallingIdentity(); try { requestAwakenInternal(); } finally { Binder.restoreCallingIdentity(ident); } } private void checkPermission(String permission) { if (mContext.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Access denied to process: " + Binder.getCallingPid() + ", must have permission " + permission); } }Client端和Server端通过Binder进程间通信机制来通信。在Server端通过checkPermission来检查Client端是否申明了此权限。
(2)、对于非Android特有的Service(底层平台已经提供,如File访问,TCPIP数据收发等),多个入口访问:Android API,Java API,NDK C API,shell都可以访问。这样权限控制就聚口在底层,所以在底层统一控制。这个底层统一控制其实就是传统的Linux文件读写执行权限(rwx)。
例如在应用中申请了写SD卡的权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />我们需要把Android空间的Permission Mapping到OS的GID。
我们看一个重要的类,frameworks\base\data\etc\Platform.xml
<permission name="android.permission.WRITE_EXTERNAL_STORAGE" > <group gid="sdcard_rw" /> </permission>
对于申请了WRITE_EXTERNAL_STORAGE特权的应用,该应用的进程的gids就包含了sdcard_r,就可以对sd卡中的文件进行操作了。
再看Android_filesystem_config.h的源码:
#define AID_SDCARD_RW 1015 /* external storage write access */
也就是说这个权限映射到1015的gid,我们再来看一张图:
我们查看com.android.phone这个进程,该应用申请了写外部内存卡的权限。首先使用ps查看该进程的进程号是1038,然后采用如下命令:
我们看到这个进程的Groups里面有gid为1015,1015就是对应sdcard_r。
5、除了我们在AndroidManifest.xml里面申请权限外,我们还可以在frameworks\base\data\etc\Platform.xml,assign权限,如下:
<assign-permission name="android.permission.WRITE_EXTERNAL_STORAGE" uid="shell" /> <assign-permission name="android.permission.SEND_SMS" uid="shell" /> <assign-permission name="android.permission.CALL_PHONE" uid="shell" /> <assign-permission name="android.permission.READ_CONTACTS" uid="shell" /> <assign-permission name="android.permission.WRITE_CONTACTS" uid="shell" /> <assign-permission name="android.permission.READ_CALENDAR" uid="shell" /> <assign-permission name="android.permission.WRITE_CALENDAR" uid="shell" /> <assign-permission name="android.permission.READ_USER_DICTIONARY" uid="shell" /> <assign-permission name="android.permission.WRITE_USER_DICTIONARY" uid="shell" /> <assign-permission name="android.permission.ACCESS_FINE_LOCATION" uid="shell" /> <assign-permission name="android.permission.ACCESS_COARSE_LOCATION" uid="shell" /> <assign-permission name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" uid="shell" /> <assign-permission name="android.permission.ACCESS_NETWORK_STATE" uid="shell" /> <assign-permission name="android.permission.ACCESS_WIFI_STATE" uid="shell" /> <assign-permission name="android.permission.BLUETOOTH" uid="shell" /> <!-- System tool permissions granted to the shell. --> <assign-permission name="android.permission.GET_TASKS" uid="shell" /> <assign-permission name="android.permission.CHANGE_CONFIGURATION" uid="shell" /> <assign-permission name="android.permission.REORDER_TASKS" uid="shell" /> <assign-permission name="android.permission.SET_ANIMATION_SCALE" uid="shell" /> <assign-permission name="android.permission.SET_PREFERRED_APPLICATIONS" uid="shell" /> <assign-permission name="android.permission.WRITE_SETTINGS" uid="shell" /> <assign-permission name="android.permission.WRITE_SECURE_SETTINGS" uid="shell" /> <assign-permission name="android.permission.BROADCAST_STICKY" uid="shell" /> <!-- Development tool permissions granted to the shell. --> <assign-permission name="android.permission.SET_DEBUG_APP" uid="shell" /> <assign-permission name="android.permission.SET_PROCESS_LIMIT" uid="shell" /> <assign-permission name="android.permission.SET_ALWAYS_FINISH" uid="shell" /> <assign-permission name="android.permission.DUMP" uid="shell" /> <assign-permission name="android.permission.SIGNAL_PERSISTENT_PROCESSES" uid="shell" /> <!-- Internal permissions granted to the shell. --> <assign-permission name="android.permission.FORCE_BACK" uid="shell" /> <assign-permission name="android.permission.BATTERY_STATS" uid="shell" /> <assign-permission name="android.permission.INTERNAL_SYSTEM_WINDOW" uid="shell" /> <assign-permission name="android.permission.INJECT_EVENTS" uid="shell" /> <assign-permission name="android.permission.SET_ACTIVITY_WATCHER" uid="shell" /> <assign-permission name="android.permission.READ_INPUT_STATE" uid="shell" /> <assign-permission name="android.permission.SET_ORIENTATION" uid="shell" /> <assign-permission name="android.permission.INSTALL_PACKAGES" uid="shell" /> <assign-permission name="android.permission.CLEAR_APP_USER_DATA" uid="shell" /> <assign-permission name="android.permission.DELETE_CACHE_FILES" uid="shell" /> <assign-permission name="android.permission.DELETE_PACKAGES" uid="shell" /> <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="shell" /> <assign-permission name="android.permission.READ_FRAME_BUFFER" uid="shell" /> <assign-permission name="android.permission.DEVICE_POWER" uid="shell" /> <assign-permission name="android.permission.INSTALL_LOCATION_PROVIDER" uid="shell" /> <assign-permission name="android.permission.BACKUP" uid="shell" /> <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" /> <assign-permission name="android.permission.ACCESS_DRM" uid="media" /> <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" /> <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />shell进程的权限我们在Android中的权限管理(基于uid gid gids setUid),已经看到过其申请的权限对应的gids。那时候没有讲shell进程是怎么样申请的这个权限,这里解决了我们的疑问。
由于platform.xml只有root用户可以操作,避免了安全问题。
版权声明:本文为博主原创文章,未经博主允许不得转载。
Android中的权限管理(基于Permission ProtectionLevel)
标签:
原文地址:http://blog.csdn.net/jltxgcy/article/details/48288467