Add permission check to UsageStatsManager#isAppInactive

UsageStatsManager#isAppInactive provides usage information that is
usually gated by the PACKAGE_USAGE_STATS permission in similar API.
This updates isAppInactive to also check for the PACKAGE_USAGE_STATS
permission.

Test: atest android.app.usage.cts android.app.usage.cts.UsageStatsTest#testIsAppInactive
Fixes: 148991455

Change-Id: I8ff8eb5d2e887bc164095f38d374e3992808fe79
This commit is contained in:
Michael Wachenschwanz
2020-04-01 16:28:46 -07:00
parent 969e1e2759
commit d2b132fac4
4 changed files with 24 additions and 7 deletions

View File

@@ -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);

View File

@@ -601,12 +601,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.
* <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} to query the
* inactive state of other apps</p>
*
* @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
}

View File

@@ -2493,7 +2493,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;
}

View File

@@ -1578,15 +1578,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(