? ? ? ? 在android系統(tǒng)中缩多,應(yīng)用程序如果想操作系統(tǒng)資源,往往都需要去申請(qǐng)權(quán)限。比如:如果想去操作攝像頭第献,那么就需要去申請(qǐng)下面的權(quán)限<uses-permission android:name="andorid.permission.CAMERA">
? ? ? ? 那android系統(tǒng)是怎么去做這個(gè)權(quán)限的校驗(yàn)?zāi)兀吭诹私鈶?yīng)用程序權(quán)限校驗(yàn)之前兔港,先了解每個(gè)應(yīng)用程序權(quán)限數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)庸毫、權(quán)限的解析。我們的應(yīng)用在第一次安裝的時(shí)候衫樊,都是會(huì)經(jīng)過PKMS來解析飒赃,然后在PKMS中會(huì)去保存每個(gè)應(yīng)用需要用的權(quán)限。
? ? ? ? 1科侈、權(quán)限數(shù)據(jù)結(jié)構(gòu)
? ? ? ? 保存權(quán)限的相關(guān)數(shù)據(jù)結(jié)構(gòu)如下圖:
? ? ? ? 每個(gè)安裝的應(yīng)用都會(huì)對(duì)應(yīng)一個(gè)變量PackageSettingBase? packageSetting來與之對(duì)應(yīng),而每個(gè)packageSetting都包含一個(gè)變量PermissionsState來記錄這個(gè)應(yīng)用的權(quán)限信息盒揉,而每個(gè)PermissionsState下面都會(huì)有多個(gè)PermissionData,每個(gè)permissionData來對(duì)應(yīng)一個(gè)權(quán)限兑徘,而permissionData下面有一個(gè)permissionState用來直接記錄該權(quán)限是否授權(quán)刚盈、權(quán)限名稱等信息。
? ? ? ? 2挂脑、應(yīng)用權(quán)限的解析
? ? ? ? 應(yīng)用安裝完后藕漱,所有的信息會(huì)保存在data/system/package.xml中欲侮,如下圖
? ? ? ? 紅色框框tag是權(quán)限信息,這部分會(huì)在PKMS啟動(dòng)的時(shí)候肋联,會(huì)調(diào)用下面的接口來解析對(duì)應(yīng)權(quán)限信息威蕉。readInstallPermissionsLPr(parser,packageSetting.getPermissionsState());這里會(huì)將這個(gè)應(yīng)用所對(duì)應(yīng)的PermissionsState傳遞進(jìn)去。
? ? ? ? readInstallPermissionsLPr這個(gè)接口是在Settings.java中橄仍,接口里面會(huì)去獲取這個(gè)權(quán)限的名稱韧涨,再根據(jù)權(quán)限的名稱向Settings.mPermissions獲取這個(gè)權(quán)限名稱所對(duì)應(yīng)的BasePermission 即是PKMS最前解析到的permission與UID的映射BP列表(android應(yīng)用程序上層權(quán)限與底層linux的用戶組GID都是一一映射的,用來規(guī)定哪些GID的可以進(jìn)行訪問侮繁、操作等虑粥。映射表是在PKMS構(gòu)造函數(shù)里面解析路徑:system/etc/permissions文件所得)
? ? ? ? 在readInstallPermissionsLPr()中最后會(huì)調(diào)用permissionsState.grantInstallPermission(bp) ——>grantPermission()來授權(quán):
? ? ? ? 這里前后各做了一個(gè)computeGids得到oldGids / newGids,再通過比較得出授權(quán)后GID是否發(fā)生了變化宪哩,如果發(fā)生變化娩贷,那就很明顯這個(gè)權(quán)限是新增的。在這兩個(gè)computeGids有兩個(gè)關(guān)鍵函數(shù)ensurePermissionData()锁孟,permissionData.grant()彬祖,其實(shí)這兩個(gè)接口,前面那個(gè)是根據(jù)權(quán)限的name來獲取到對(duì)應(yīng)的PermissionData品抽,后面那個(gè)接口只是將其下面的變量permission標(biāo)志為授權(quán)而已储笑。
? ? ? ? 3、權(quán)限校驗(yàn)
? ? ? ? 在系統(tǒng)服務(wù)中需要可以到看下面這段代碼mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_DEVICE_ADMIN,null); 參數(shù)是各種各樣的權(quán)限名稱圆恤,這部分是做權(quán)限校驗(yàn)部分
? ? ? ? 各個(gè)流程就上圖南蓬,最后會(huì)來到PKMS的checkUidPermission()
? ? ? ? android原生的代碼,權(quán)限校驗(yàn)部分哑了,前面說到每個(gè)安裝的應(yīng)用都會(huì)對(duì)應(yīng)一個(gè)變量PackageSettingBase? packageSetting來與之對(duì)應(yīng)赘方,PackageSettingBase的父類就是SettingBase,所以這里面還是一樣先去獲取這個(gè)應(yīng)用的permissionsState弱左,查看這個(gè)權(quán)限是否授權(quán)窄陡,再返回值,注釋有一個(gè)special case拆火,說明還有例外的情況跳夭。。们镜。
? ? ? ? 另外如果沒有獲取到這個(gè)應(yīng)用的LPr币叹,則會(huì)繼續(xù)去判斷mSystemPermissions,這個(gè)變量跟前面提到的mPermissions是那么一點(diǎn)點(diǎn)聯(lián)系模狭,解析system/etc/permissions的時(shí)候颈抚,<permission name ="android.permission.BLUETOOTH">
<group gid="net-bt"/>
</permission>
? ? ? ? ?上面這部分則會(huì)被解析到mPermisisons中,而tag為<assign-permissino ...>則會(huì)被解析到這個(gè)變量中嚼鹉,mSystemPermissions贩汉,原生的注釋的意思是給開發(fā)者一個(gè)更開放的開發(fā)環(huán)境驱富。比如android開發(fā)人員想要查看surface layout的信息,那么他直接可以adb shell后再運(yùn)行dumpsys SurfaceFlinger匹舞,即可以看到信息褐鸥,這里有一個(gè)權(quán)限<assign-permission? name ="android.permisison.ACCESS_SURFACE_FLIGNER">,這個(gè)權(quán)限是在mSystemPermissions中赐稽,所以開發(fā)人員可以直接利用這個(gè)權(quán)限去調(diào)試叫榕,這是屬于高等權(quán)限之一笛谦。叹哭。。