From b6aaed1bfc5375f51c3ffeb5ef88bc2f3da5d254 Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Mon, 27 Jan 2020 15:15:02 -0800 Subject: [PATCH] Link PACKAGE_USAGE_STATS with LOADER_USAGE_STATS Bug: 148374455 Test: Manual Test: Create three packages; 1) only request PACKAGE_USAGE_STATS, 2) only request LOADER_USAGE_STATS, 3) request both Test: Go to Settings -> Apps & Notifications -> Special app access Test: See that there is only a single entry for "Usage access" Test: Under "Usage access", see all three test apps appear Test: Disable access for each application and verify that only the appop for the declared permisson is flipped using Test: adb shell cmd appops get <> Change-Id: I7741a703fd4494832347e51e113adf974cc31d2b --- .../applications/AppStateAppOpsBridge.java | 12 ++++++++- .../applications/AppStateUsageBridge.java | 15 ++++++++--- .../applications/UsageAccessDetails.java | 26 +++++++++++++++++-- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/com/android/settings/applications/AppStateAppOpsBridge.java b/src/com/android/settings/applications/AppStateAppOpsBridge.java index 3dbdbe99598..8c001d841f1 100755 --- a/src/com/android/settings/applications/AppStateAppOpsBridge.java +++ b/src/com/android/settings/applications/AppStateAppOpsBridge.java @@ -61,17 +61,27 @@ public abstract class AppStateAppOpsBridge extends AppStateBaseBridge { this(context, appState, callback, appOpsOpCode, permissions, AppGlobals.getPackageManager()); } + AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback, + int[] appOpsOpCodes, String[] permissions) { + this(context, appState, callback, appOpsOpCodes, permissions, + AppGlobals.getPackageManager()); + } @VisibleForTesting AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback, int appOpsOpCode, String[] permissions, IPackageManager packageManager) { + this(context, appState, callback, new int[] {appOpsOpCode}, permissions, + packageManager); + } + AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback, + int[] appOpsOpCodes, String[] permissions, IPackageManager packageManager) { super(appState, callback); mContext = context; mIPackageManager = packageManager; mUserManager = UserManager.get(context); mProfiles = mUserManager.getUserProfiles(); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - mAppOpsOpCodes = new int[] {appOpsOpCode}; + mAppOpsOpCodes = appOpsOpCodes; mPermissions = permissions; } diff --git a/src/com/android/settings/applications/AppStateUsageBridge.java b/src/com/android/settings/applications/AppStateUsageBridge.java index f84ef3e2923..c1c861fbe4e 100644 --- a/src/com/android/settings/applications/AppStateUsageBridge.java +++ b/src/com/android/settings/applications/AppStateUsageBridge.java @@ -33,13 +33,20 @@ public class AppStateUsageBridge extends AppStateAppOpsBridge { private static final String TAG = "AppStateUsageBridge"; private static final String PM_USAGE_STATS = Manifest.permission.PACKAGE_USAGE_STATS; - private static final int APP_OPS_OP_CODE = AppOpsManager.OP_GET_USAGE_STATS; - private static final String[] PM_PERMISSION = { - PM_USAGE_STATS + private static final String PM_LOADER_STATS = Manifest.permission.LOADER_USAGE_STATS; + private static final int APP_OPS_USAGE_STATS = AppOpsManager.OP_GET_USAGE_STATS; + private static final int APP_OPS_LOADER_STATS = AppOpsManager.OP_LOADER_USAGE_STATS; + private static final int[] APP_OPS_OP_CODES = { + APP_OPS_USAGE_STATS, + APP_OPS_LOADER_STATS, + }; + private static final String[] PM_PERMISSIONS = { + PM_USAGE_STATS, + PM_LOADER_STATS, }; public AppStateUsageBridge(Context context, ApplicationsState appState, Callback callback) { - super(context, appState, callback, APP_OPS_OP_CODE, PM_PERMISSION); + super(context, appState, callback, APP_OPS_OP_CODES, PM_PERMISSIONS); } @Override diff --git a/src/com/android/settings/applications/UsageAccessDetails.java b/src/com/android/settings/applications/UsageAccessDetails.java index 58dff7c2e02..cddacb3b280 100644 --- a/src/com/android/settings/applications/UsageAccessDetails.java +++ b/src/com/android/settings/applications/UsageAccessDetails.java @@ -15,6 +15,10 @@ */ package com.android.settings.applications; +import static android.app.AppOpsManager.OP_GET_USAGE_STATS; +import static android.app.AppOpsManager.OP_LOADER_USAGE_STATS; + +import android.Manifest; import android.app.AppOpsManager; import android.app.admin.DevicePolicyManager; import android.app.settings.SettingsEnums; @@ -104,10 +108,28 @@ public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenc return false; } + private static boolean doesAnyPermissionMatch(String permissionToMatch, String[] permissions) { + for (String permission : permissions) { + if (permissionToMatch.equals(permission)) { + return true; + } + } + return false; + } + private void setHasAccess(boolean newState) { logSpecialPermissionChange(newState, mPackageName); - mAppOpsManager.setMode(AppOpsManager.OP_GET_USAGE_STATS, mPackageInfo.applicationInfo.uid, - mPackageName, newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); + + final int newAppOpMode = newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED; + final int uid = mPackageInfo.applicationInfo.uid; + if (doesAnyPermissionMatch(Manifest.permission.PACKAGE_USAGE_STATS, + mUsageState.packageInfo.requestedPermissions)) { + mAppOpsManager.setMode(OP_GET_USAGE_STATS, uid, mPackageName, newAppOpMode); + } + if (doesAnyPermissionMatch(Manifest.permission.LOADER_USAGE_STATS, + mUsageState.packageInfo.requestedPermissions)) { + mAppOpsManager.setMode(OP_LOADER_USAGE_STATS, uid, mPackageName, newAppOpMode); + } } @VisibleForTesting