在android系統中,應用程式如果想作業系統資源,往往都需要去申請權限。比如:如果想去操作攝像頭,那麼就需要去申請下面的權限
那android系統是怎麼去做這個權限的校驗呢?在了解應用程式權限校驗之前,先了解每個應用程式權限資料存儲結構、權限的解析。我們的應用在第一次安裝的時候,都是會經過PKMS來解析,然後在PKMS中會去儲存每個應用需要用的權限。
1、權限資料結構
儲存權限的相關資料結構如下圖:

應用權限資料結構
每個安裝的應用都會對應一個變量PackageSettingBase packageSetting來與之對應,而每個packageSetting都包含一個變量PermissionsState來記錄這個應用的權限資訊,而每個PermissionsState下面都會有多個PermissionData,每個permissionData來對應一個權限,而permissionData下面有一個permissionState用來直接記錄該權限是否授權、權限名稱等資訊。
2、應用權限的解析
應用安裝完後,所有的資訊會儲存在data/system/package.xml中,如下圖

應用安裝資訊
紅色框框tag是權限資訊,這部分會在PKMS啟動的時候,會調用下面的接口來解析對應權限資訊。readInstallPermissionsLPr(parser,packageSetting.getPermissionsState());這裡會将這個應用所對應的PermissionsState傳遞進去。
readInstallPermissionsLPr這個接口是在Settings.java中,接口裡面會去擷取這個權限的名稱,再根據權限的名稱向Settings.mPermissions擷取這個權限名稱所對應的BasePermission即是PKMS最前解析到的permission與UID的映射BP清單(android應用程式上層權限與底層linux的使用者組GID都是一一映射的,用來規定哪些GID的可以進行通路、操作等。映射表是在PKMS構造函數裡面解析路徑:system/etc/permissions檔案所得)
在readInstallPermissionsLPr()中最後會調用permissionsState.grantInstallPermission(bp) ——>grantPermission()來授權:

授權代碼
這裡前後各做了一個computeGids得到oldGids / newGids,再通過比較得出授權後GID是否發生了變化,如果發生變化,那就很明顯這個權限是新增的。在這兩個computeGids有兩個關鍵函數ensurePermissionData(),permissionData.grant(),其實這兩個接口,前面那個是根據權限的name來擷取到對應的PermissionData,後面那個接口隻是将其下面的變量permission标志為授權而已。
3、權限校驗
在系統服務中需要可以到看下面這段代碼mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BIND_DEVICE_ADMIN,null); 參數是各種各樣的權限名稱,這部分是做權限校驗部分

權限校驗流程
各個流程就上圖,最後會來到PKMS的checkUidPermission()

權限校驗
android原生的代碼,權限校驗部分,前面說到每個安裝的應用都會對應一個變量PackageSettingBase packageSetting來與之對應,PackageSettingBase的父類就是SettingBase,是以這裡面還是一樣先去擷取這個應用的permissionsState,檢視這個權限是否授權,再傳回值,注釋有一個special case,說明還有例外的情況。。。
另外如果沒有擷取到這個應用的LPr,則會繼續去判斷mSystemPermissions,這個變量跟前面提到的mPermissions是那麼一點點聯系,解析system/etc/permissions的時候,
上面這部分則會被解析到mPermisisons中,而tag為則會被解析到這個變量中,mSystemPermissions,原生的注釋的意思是給開發者一個更開放的開發環境。比如android開發人員想要檢視surface layout的資訊,那麼他直接可以adb shell後再運作dumpsys SurfaceFlinger,即可以看到資訊,這裡有一個權限,這個權限是在mSystemPermissions中,是以開發人員可以直接利用這個權限去調試,這是屬于高等權限之一。。。