diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl index 1211c731e2e1d..ed6ba0c5efa47 100644 --- a/core/java/android/app/usage/IUsageStatsManager.aidl +++ b/core/java/android/app/usage/IUsageStatsManager.aidl @@ -43,7 +43,7 @@ interface IUsageStatsManager { @UnsupportedAppUsage void setAppInactive(String packageName, boolean inactive, int userId); @UnsupportedAppUsage - boolean isAppInactive(String packageName, int userId); + boolean isAppInactive(String packageName, int userId, String callingPackage); void onCarrierPrivilegedAppsChanged(); void reportChooserSelection(String packageName, int userId, String contentType, in String[] annotations, String action); diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index 0a67802fe92bf..2ce6a86753a6e 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -622,12 +622,17 @@ public final class UsageStatsManager { * app hasn't been used directly or indirectly for a period of time defined by the system. This * could be of the order of several hours or days. Apps are not considered inactive when the * device is charging. + *
The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} to query the + * inactive state of other apps
+ * * @param packageName The package name of the app to query - * @return whether the app is currently considered inactive + * @return whether the app is currently considered inactive or false if querying another app + * without {@link android.Manifest.permission#PACKAGE_USAGE_STATS} */ public boolean isAppInactive(String packageName) { try { - return mService.isAppInactive(packageName, mContext.getUserId()); + return mService.isAppInactive(packageName, mContext.getUserId(), + mContext.getOpPackageName()); } catch (RemoteException e) { // fall through and return default } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 8f5fbf7431e11..149e3baa90e7a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -2504,7 +2504,7 @@ final class ActivityManagerShellCommand extends ShellCommand { IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService( Context.USAGE_STATS_SERVICE)); - boolean isIdle = usm.isAppInactive(packageName, userId); + boolean isIdle = usm.isAppInactive(packageName, userId, SHELL_PACKAGE_NAME); pw.println("Idle=" + isIdle); return 0; } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index bbe9851520a10..5b5d57bf2f51c 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -1577,15 +1577,27 @@ public class UsageStatsService extends SystemService implements } @Override - public boolean isAppInactive(String packageName, int userId) { + public boolean isAppInactive(String packageName, int userId, String callingPackage) { + final int callingUid = Binder.getCallingUid(); try { userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(), - Binder.getCallingUid(), userId, false, false, "isAppInactive", null); + callingUid, userId, false, false, "isAppInactive", null); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } + + // If the calling app is asking about itself, continue, else check for permission. + if (packageName.equals(callingPackage)) { + final int actualCallingUid = mPackageManagerInternal.getPackageUidInternal( + callingPackage, 0, userId); + if (actualCallingUid != callingUid) { + return false; + } + } else if (!hasPermission(callingPackage)) { + return false; + } final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( - Binder.getCallingUid(), userId); + callingUid, userId); final long token = Binder.clearCallingIdentity(); try { return mAppStandby.isAppIdleFiltered(