summaryrefslogtreecommitdiffstats
path: root/services/usage
diff options
context:
space:
mode:
Diffstat (limited to 'services/usage')
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java100
-rw-r--r--services/usage/java/com/android/server/usage/UserUsageStatsService.java11
2 files changed, 111 insertions, 0 deletions
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 3d54dfb..edeeaba 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -17,7 +17,10 @@
package com.android.server.usage;
import android.Manifest;
+import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.admin.DevicePolicyManager;
import android.app.usage.ConfigurationStats;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
@@ -30,6 +33,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
@@ -82,6 +86,7 @@ public class UsageStatsService extends SystemService implements
static final int MSG_FLUSH_TO_DISK = 1;
static final int MSG_REMOVE_USER = 2;
static final int MSG_INFORM_LISTENERS = 3;
+ static final int MSG_RESET_LAST_TIMESTAMP = 4;
private final Object mLock = new Object();
Handler mHandler;
@@ -279,6 +284,29 @@ public class UsageStatsService extends SystemService implements
}
/**
+ * Forces the app's timestamp to reflect idle or active. If idle, then it rolls back the
+ * last used timestamp to a point in time thats behind the threshold for idle.
+ */
+ void resetLastTimestamp(String packageName, int userId, boolean idle) {
+ synchronized (mLock) {
+ final long timeNow = checkAndGetTimeLocked();
+ final long lastTimestamp = timeNow - (idle ? mAppIdleDurationMillis : 0);
+
+ final UserUsageStatsService service =
+ getUserDataAndInitializeIfNeededLocked(userId, timeNow);
+ final long lastUsed = service.getLastPackageAccessTime(packageName);
+ final boolean previouslyIdle = hasPassedIdleDuration(lastUsed);
+ service.setLastTimestamp(packageName, lastTimestamp);
+ // Inform listeners if necessary
+ if (previouslyIdle != idle) {
+ // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
+ /* idle = */ idle ? 1 : 0, packageName));
+ }
+ }
+ }
+
+ /**
* Called by the Binder stub.
*/
void flushToDisk() {
@@ -384,13 +412,41 @@ public class UsageStatsService extends SystemService implements
}
boolean isAppIdle(String packageName, int userId) {
+ if (packageName == null) return false;
if (SystemConfig.getInstance().getAllowInPowerSave().contains(packageName)) {
return false;
}
+ if (isActiveDeviceAdmin(packageName, userId)) {
+ return false;
+ }
+
final long lastUsed = getLastPackageAccessTime(packageName, userId);
return hasPassedIdleDuration(lastUsed);
}
+ void setAppIdle(String packageName, boolean idle, int userId) {
+ if (packageName == null) return;
+
+ mHandler.obtainMessage(MSG_RESET_LAST_TIMESTAMP, userId, idle ? 1 : 0, packageName)
+ .sendToTarget();
+ }
+
+ private boolean isActiveDeviceAdmin(String packageName, int userId) {
+ DevicePolicyManager dpm = getContext().getSystemService(DevicePolicyManager.class);
+ if (dpm == null) return false;
+ List<ComponentName> components = dpm.getActiveAdminsAsUser(userId);
+ if (components == null) {
+ return false;
+ }
+ final int size = components.size();
+ for (int i = 0; i < size; i++) {
+ if (components.get(i).getPackageName().equals(packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void informListeners(String packageName, int userId, boolean isIdle) {
for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
listener.onAppIdleStateChanged(packageName, userId, isIdle);
@@ -459,6 +515,10 @@ public class UsageStatsService extends SystemService implements
informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1);
break;
+ case MSG_RESET_LAST_TIMESTAMP:
+ resetLastTimestamp((String) msg.obj, msg.arg1, msg.arg2 == 1);
+ break;
+
default:
super.handleMessage(msg);
break;
@@ -566,6 +626,46 @@ public class UsageStatsService extends SystemService implements
}
@Override
+ public boolean isAppIdle(String packageName, int userId) {
+ try {
+ userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, true, "isAppIdle", null);
+ } catch (RemoteException re) {
+ return false;
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return UsageStatsService.this.isAppIdle(packageName, userId);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void setAppIdle(String packageName, boolean idle, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ try {
+ userId = ActivityManagerNative.getDefault().handleIncomingUser(
+ Binder.getCallingPid(), callingUid, userId, false, true,
+ "setAppIdle", null);
+ } catch (RemoteException re) {
+ return;
+ }
+ getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
+ "No permission to change app idle state");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ PackageInfo pi = AppGlobals.getPackageManager()
+ .getPackageInfo(packageName, 0, userId);
+ if (pi == null) return;
+ UsageStatsService.this.setAppIdle(packageName, idle, userId);
+ } catch (RemoteException re) {
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 0a9481a..d94759d 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -211,6 +211,17 @@ class UserUsageStatsService {
notifyStatsChanged();
}
+ /**
+ * Sets the last timestamp for each of the intervals.
+ * @param lastTimestamp
+ */
+ void setLastTimestamp(String packageName, long lastTimestamp) {
+ for (IntervalStats stats : mCurrentStats) {
+ stats.update(packageName, lastTimestamp, UsageEvents.Event.NONE);
+ }
+ notifyStatsChanged();
+ }
+
private static final StatCombiner<UsageStats> sUsageStatsCombiner =
new StatCombiner<UsageStats>() {
@Override