[Android][Lollipop]UsageStatsManagerの権限状態の確認方法


# UsageStatsManagerの権限確認

UsageStatsManagerは、Lollipop以降でActivityManagerのgetRunningTasksなどの各種メソッドの代替として提供されているAPIです。

* [【Android】getRunningTasksが使えなくなったLollipopでアプリ使用状況を取得する](http://qiita.com/kgmyshin/items/35b002e42df2027fb56e)
* [[Android][Lollipop]UsageStatsManagerを使ってみた](http://qiita.com/wasnot/items/6074dbcdd49141f8e7d8)

Manifestへに権限(android.permission.PACKAGE_USAGE_STATS)を定義する他に、ユーザによる権限付与が必要なのですが、その確認方法をメモしておきます。

```java:
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static boolean checkPermission(Context context) {
        // Lollipop以前は使えないAPIが含まれています。
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
            return false;
        // AppOpsManagerを取得
        AppOpsManager aom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        // GET_USAGE_STATSのステータスを取得
        int mode = aom.checkOp(AppOpsManager.OPSTR_GET_USAGE_STATS, Process.myUid(),
                context.getPackageName());
        LogUtil.d(TAG, "check:" + mode);
        if (mode == AppOpsManager.MODE_DEFAULT) {
            // AppOpsの状態がデフォルトなら通常のpermissionチェックを行う。
            // 普通のアプリならfalse
            return context.checkPermission("android.permission.PACKAGE_USAGE_STATS",
                    Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED;
        }
        // AppOpsの状態がデフォルトでないならallowedのみtrue
        return mode == AppOpsManager.MODE_ALLOWED;
    }
```

調べたのはUsageStatsManagerの実装部分のUsageStatsServiceのメソッドです。

[UsageStatsService.BinderService.hasPermission](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.0.0_r1/com/android/server/usage/UsageStatsService.java#UsageStatsService.BinderService.hasPermission%28java.lang.String%29)

AppOpsManagaer自体はAPI19からアクセス可能みたいです。
Runtime-Permissionと別に管理されているようですね。

上記確認方法はAndroid 6.0 Preview(MPA44G)でも使用可能でした。

#おまけ：ActivityManager.getRunningAppProcessesなどの現状

## Lollipop以前と以後

Android5.0以前ではActivityのスタックの状況やプロセスなど、ActivityManagerの[getRunningTasks](http://developer.android.com/reference/android/app/ActivityManager.html#getRunningTasks(int))や[getRecentTasks](http://developer.android.com/reference/android/app/ActivityManager.html#getRecentTasks(int,%20int))、[getRunningAppProcesses](http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses%28%29)で取得することができました。
しかもgetRunningAppProcessesなどは特に権限が入らなかったりしました。
getRunningTaskは[GET_TASKS](http://developer.android.com/reference/android/Manifest.permission.html#GET_TASKS)の権限が必要でした。

しかし、Android5.0からはgetRunningTasksとgetRecentTasksはDeprecatedになり、GET_TASKS権限はREAL_GET_TASKSに隠蔽されて通常のアプリでは使えなくなりました。

## getRunningTasks,getRecentTasksの挙動

Deprecatedになりましたが、呼ぶことはできます。
Homeアプリと自アプリ以外のtaskは取得できなくなったようです。

## getRunningAppProcessesの挙動

getRunningAppProcessesなどの多くのメソッドにも注記が追加されました。

```
Note: this method is only intended for debugging or building a user-facing process management UI.
// このメソッドはデバッグやユーザがプロセス管理を行うUIを作るためのものです。
```

意味がちょっとわからなかったのですが、getRunningAppProcessesでもLollipopのアップデートによって徐々に挙動が変化しました。

[caller ***** does not hold REAL_GET_TASKS; limiting output エラー](http://qiita.com/tac0x2a/items/1084c4d8283dd2821837)
[Issue 2347: 	ActivityManager getRunningAppProcesses not woking](https://code.google.com/p/android-developer-preview/issues/detail?id=2347)

具体的には、今まではすべての動作プロセスの情報が取得できましたが、Lollipopの特定ビルド(Nexus5/6ではLMY48I)以降では、自分のアプリ（正確に自分と同一のユーザグループのアプリ）のプロセスの情報のみ取得できるようになりました。

つまり、[getRunningServices](http://developer.android.com/reference/android/app/ActivityManager.html#getRunningServices(int))などで自分のアプリのサービスが起動済みかどうかなど、確認する用途で使っている場合には影響はなさそうです。

## getProcessMemoryInfo

未確認ですが、プロセスリストが取得できないのでpidがわからず、memoryの使用状況などわからなくなりそうな気がします。。