Allow callers holding PACKAGE_USAGE_STATS permission to call ActivityManager#getPackageImportance()

Bug:22055550
Change-Id: I1e732e95698daf44bcb223cafde3d3c22746d232
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 69ba27c..13fda59 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -1688,7 +1688,7 @@
     private void runPackageImportance() throws Exception {
         String packageName = nextArgRequired();
         try {
-            int procState = mAm.getPackageProcessState(packageName);
+            int procState = mAm.getPackageProcessState(packageName, "com.android.shell");
             System.out.println(
                     ActivityManager.RunningAppProcessInfo.procStateToImportance(procState));
         } catch (RemoteException e) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b65593d..9ca206a 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2345,7 +2345,8 @@
     @SystemApi
     public int getPackageImportance(String packageName) {
         try {
-            int procState = ActivityManagerNative.getDefault().getPackageProcessState(packageName);
+            int procState = ActivityManagerNative.getDefault().getPackageProcessState(packageName,
+                    mContext.getOpPackageName());
             return RunningAppProcessInfo.procStateToImportance(procState);
         } catch (RemoteException e) {
             return RunningAppProcessInfo.IMPORTANCE_GONE;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 680feae..3035e3d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2539,7 +2539,8 @@
         case GET_PACKAGE_PROCESS_STATE_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String pkg = data.readString();
-            int res = getPackageProcessState(pkg);
+            String callingPackage = data.readString();
+            int res = getPackageProcessState(pkg, callingPackage);
             reply.writeNoException();
             reply.writeInt(res);
             return true;
@@ -5868,11 +5869,13 @@
     }
 
     @Override
-    public int getPackageProcessState(String packageName) throws RemoteException {
+    public int getPackageProcessState(String packageName, String callingPackage)
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(packageName);
+        data.writeString(callingPackage);
         mRemote.transact(GET_PACKAGE_PROCESS_STATE_TRANSACTION, data, reply, 0);
         reply.readException();
         int res = reply.readInt();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index e7f7e13..0328708 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -503,7 +503,8 @@
     public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;
     public void updateDeviceOwner(String packageName) throws RemoteException;
 
-    public int getPackageProcessState(String packageName) throws RemoteException;
+    public int getPackageProcessState(String packageName, String callingPackage)
+            throws RemoteException;
 
     public boolean setProcessMemoryTrimLevel(String process, int uid, int level)
             throws RemoteException;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1ef1375..f031694 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3583,10 +3583,23 @@
         }
     }
 
+    private boolean hasUsageStatsPermission(String callingPackage) {
+        final int mode = mAppOpsService.checkOperation(AppOpsManager.OP_GET_USAGE_STATS,
+                Binder.getCallingUid(), callingPackage);
+        if (mode == AppOpsManager.MODE_DEFAULT) {
+            return checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+                    == PackageManager.PERMISSION_GRANTED;
+        }
+        return mode == AppOpsManager.MODE_ALLOWED;
+    }
+
     @Override
-    public int getPackageProcessState(String packageName) {
-        enforceCallingPermission(android.Manifest.permission.GET_PACKAGE_IMPORTANCE,
-                "getPackageProcessState");
+    public int getPackageProcessState(String packageName, String callingPackage) {
+        if (!hasUsageStatsPermission(callingPackage)) {
+            enforceCallingPermission(android.Manifest.permission.GET_PACKAGE_IMPORTANCE,
+                    "getPackageProcessState");
+        }
+
         int procState = ActivityManager.PROCESS_STATE_NONEXISTENT;
         synchronized (this) {
             for (int i=mLruProcesses.size()-1; i>=0; i--) {