AndroidのRuntime Permissionのフレームワーク小話


MからRuntime Permissionという概念ができたのは周知の通り。

#Runtime Permission概要
- アプリ実行時に、パーミッションの使用を許諾・拒否する仕組み
- ユーザはアプリごとにパーミッションの許諾拒否設定が可能
- アプリ開発者側は、いつでも拒否されていることを前提に設計・実装しなければいいけない

#Runtime Permissionに該当するパーミッション
- ProtectionLevelがdangerousのパーミッションすべて
- Androidフレームワークのパーミッションに加え、独自定義したカスタムパーミッションも該当

#Runtime Permission以外になにがあるのか

RuntimePermissionに対して、Install Time Permissionが存在する
- これは従来のパーミッション許諾の概念と同じで、インストール時に許諾されるとその後はアンインストール時までユーザによる拒否は不可能というもの
- これに該当するのはRuntime Permission以外のパーミッション

# Runtime Permission のフラグ
- Runtime Permissionはユーザごとに以下のxmlファイルで管理されている
- Runtime Permissionにはユーザごと、アプリごと、パーミッションごとにフラグが存在する。
- 以下xml中のflagsがそれ(com.sample.runtimepermissionsは勝手に作ったアプリ)

```xml:/data/system/users/"user_ID"/runtime-permissions.xmlより抜粋
<pkg name="com.android.chrome">
<item name="android.permission.ACCESS_FINE_LOCATION" granted="true" flags="0" />
    <item name="android.permission.ACCESS_COARSE_LOCATION" granted="true" flags="0" />
    <item name="android.permission.CAMERA" granted="true" flags="0" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="0" />
    <item name="com.android.launcher.permission.INSTALL_SHORTCUT" granted="true" flags="0" />
    <item name="android.permission.RECORD_AUDIO" granted="true" flags="0" />
  </pkg>
  
   <pkg name="com.sample.runtimepermissions">
    <item name="android.permission.ACCESS_FINE_LOCATION" granted="true" flags="0" />
    <item name="android.permission.SEND_SMS" granted="true" flags="4" />
    <item name="android.permission.CAMERA" granted="true" flags="10" />
  </pkg>
  
 <shared-user name="android.uid.phone">
    <item name="android.permission.WRITE_SETTINGS" granted="true" flags="10" />
    <item name="android.permission.READ_SMS" granted="true" flags="10" />
    <item name="android.permission.READ_CALL_LOG" granted="true" flags="10" />
 
(以下略)
```

# フラグの違いによる設定アプリからの見え方

- RuntimePermissionは、ユーザ操作によって設定からアプリごとに許諾・拒否の設定が可能だが、一部のフラグが立てられたパーミッションは、ユーザによる許諾・拒否設定変更が不可になる。
- この一部のフラグというものが、PackageManagerに定義されている以下２つ。
PackageManager.FLAG_PERMISSION_POLICY_FIXED(1 << 2)
PackageManager.FLAG_PERMISSION_SYSTEM_FIXED(1 << 4)
（他にも３つほどあるけど今のところ余り重要ではなさそう）

- 上記xmlのflags="4"というのはPOLICY_FIXED、flags="10"はSYSTEM_FIXEDがたったフラグ。


## FLAG_PERMISSION_POLICY_FIXED

- DeviceOwnerによって固定されたパーミッション。
- 具体的なメソッドは以下。パッケージ名とパーミッションに対して、grantStateを指定する。

	- DevicePolicyManager#setPermissionGrantStats(ComponentName admin, String packageName,String permission, int grantState) 


- grantStateの取り得る値は以下。
	- PERMISSION_GRANT_STATE_DENIED
	- PERMISSION_GRANT_STATE_DEFAULT
	- PERMISSION_GRANT_STATE_GRANTED


- GRANTEDが指定されると許諾状態、DENIEDが指定されると拒否状態でFIXされ、
当該アプリの設定 -> アプリ ->　許可 -> 一覧では、トグルスイッチがグレーアウトされた状態が固定される。
- DEFAULTで固定が解除される。

（TODO: キャプチャ）

## FLAG_PERMISSION_SYSTEM_FIXED

- Systemによって固定されたパーミッション
- アプリインストール時に、以下の何れかの条件を満たすアプリがAndroidManifest.xmlで要求した全RuntimePermissionに対して立てられる
	- システムパッケージ(UIDが10000未満)
	- /system/priv-appにインストールされたPersistentなアプリ

- このフラグが立つと、設定 -> アプリ ->　許可 -> 一覧 には項目そのものが存在しなくなる。
- 現時点では一部のRuntimePermissionのみFLAG_PERMISSION_SYSTEM_FIXEDを立てるということができない(多分)。
- したがって、このときにはシステムパッケージ(UIDが10000未満)、もしくは/system/priv-appにインストールされたPersistentアプリの設定 -> アプリ ->　許可そのものがグレーアウトされる。 
(このとき"許可"の項目に表示されるメッセージが"No permissions reqested"となっていて、本当に要求してないときと区別できないが、Preview版のバグだと思われる）

（TODO: キャプチャ）