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 <<PACKAGE_NAME>>
Change-Id: I7741a703fd4494832347e51e113adf974cc31d2b
diff --git a/src/com/android/settings/applications/AppStateAppOpsBridge.java b/src/com/android/settings/applications/AppStateAppOpsBridge.java
index 3dbdbe9..8c001d8 100755
--- a/src/com/android/settings/applications/AppStateAppOpsBridge.java
+++ b/src/com/android/settings/applications/AppStateAppOpsBridge.java
@@ -61,17 +61,27 @@
         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 f84ef3e..c1c861f 100644
--- a/src/com/android/settings/applications/AppStateUsageBridge.java
+++ b/src/com/android/settings/applications/AppStateUsageBridge.java
@@ -33,13 +33,20 @@
     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 58dff7c..cddacb3 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 @@
         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