Android MのRuntime Permissionsを見据えてprotectionlevelを調べたよ


周知の通りこれ。
http://developer.android.com/preview/features/runtime-permissions.html

ProtectionLevelがNORMALやSignatureのパーミッションは影響を受けない[^1]ということなので、じゃあ影響を受けるパーミッションは何で受けないのは何かという問題。

ユーザ操作で任意に付与・剥奪が許されているパーミッションは、
[ここ](http://developer.android.com/preview/features/runtime-permissions.html)のTable1のgroupedなものと、それ以外（dangerousかつungroupedなパーミッション）。
それ以外っていうのは、M Developer PreviewではApp->PermissionのShowLegacyで表示されるパーミッション。frameworkが宣言してるパーミッションでは10個くらいあったと思う。

これらは、pmコマンドで容易に確認できる。

```Bash
grouped
$adb shell pm list permissions -g`

dangerous
$adb shell pm list permissions -d

全部
$adb shell pm list permissions -f
```

pmコマンドでもいいけど、frameworkが宣言しているパーミッション[^2]について、protection levelがどうなってるか調べてみた。

[公式サイト](http://developer.android.com/preview/features/runtime-permissions.html)には、`internet`と`alarm clock`は`normal`になったよと書いてる。

[internetはLではdangerous](http://tools.oesf.biz/android-5.1.1_r1.0/xref/frameworks/base/core/res/AndroidManifest.xml#803)だったのが、Mではnormalに変更さているが、alarm clockはSET_ALARMのことだろうか。
[Lでもnormalのような気がする](http://tools.oesf.biz/android-5.1.1_r1.0/xref/frameworks/base/core/res/AndroidManifest.xml#670)ががが。

まぁ、いいか。

とりあえず、frameworkの全permissionのprotection levelを調べるコードを貼っておく。

```Java
public class MainActivity extends Activity {

    private static final String TAG = "PERMISSION_INFO";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        PackageInfo packageInfo = null;
        try {
            packageInfo = getPackageManager().getPackageInfo("android", PackageManager.GET_PERMISSIONS);
        } catch (...) {...}

        if (packageInfo == null) return;

        for (PermissionInfo p : packageInfo.permissions) {
            Log.d(TAG, p.name + ", " + getProtectionLevel(p));
        }

    }

    private static String getProtectionLevel(PermissionInfo pi) {

        StringBuffer protectionLevel = new StringBuffer();
        int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
        int flag = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_FLAGS;

        if (base == PermissionInfo.PROTECTION_NORMAL) {
            protectionLevel.append("NORMAL | ");
        } else if (base == PermissionInfo.PROTECTION_DANGEROUS) {
            protectionLevel.append("DANGEROUS | ");
        } else if (base == PermissionInfo.PROTECTION_SIGNATURE) {
            protectionLevel.append("SIGNATURE | ");
        } else if (base == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
            protectionLevel.append("SIGNATURE_OR_SYSTEM | ");
        } else {
            protectionLevel.append("BASE_UNKNOWN | ");
        }

        if ((flag & PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
            protectionLevel.append("APPOP | ");
        }
        if ((flag & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
            protectionLevel.append("DEVELOPMENT | ");
        }
        if ((flag & PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
            protectionLevel.append("SYSTEM");
        }

        return protectionLevel.toString();
    }
}
```

[^1]: インストール時自動付与、かつインストール後にユーザによるパーミッション剥奪不可

[^2]: つまりパッケージ名が"android"のやつら(frameworks/base/core/res/AndroidManifest.xmlで宣言されてるやつ)