summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2015-05-12 13:04:29 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-05-12 13:04:31 +0000
commitbb9d9278aa6fe3ba3d4c21b03d3e3da4543a974c (patch)
treee184b253d316feec89eb65c151bc8b0b4eaea522 /services
parent6959865fb0de965b5a2c7a797bf26b8bf9d10228 (diff)
parent06bf824628c118fbd5ad6756913d7fd63a6f4ce5 (diff)
downloadframeworks_base-bb9d9278aa6fe3ba3d4c21b03d3e3da4543a974c.zip
frameworks_base-bb9d9278aa6fe3ba3d4c21b03d3e3da4543a974c.tar.gz
frameworks_base-bb9d9278aa6fe3ba3d4c21b03d3e3da4543a974c.tar.bz2
Merge "Idle timebase" into mnc-dev
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java11
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java4
-rw-r--r--services/usage/java/com/android/server/usage/IntervalStats.java12
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java200
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsXmlV1.java8
-rw-r--r--services/usage/java/com/android/server/usage/UserUsageStatsService.java35
7 files changed, 206 insertions, 66 deletions
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 76465d4..0b33812 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -313,6 +313,10 @@ public class DeviceIdleController extends SystemService {
return getAppIdWhitelistInternal();
}
+ @Override public boolean isPowerSaveWhitelistApp(String name) {
+ return isPowerSaveWhitelistAppInternal(name);
+ }
+
@Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
DeviceIdleController.this.dump(fd, pw, args);
}
@@ -452,6 +456,13 @@ public class DeviceIdleController extends SystemService {
}
}
+ public boolean isPowerSaveWhitelistAppInternal(String packageName) {
+ synchronized (this) {
+ return mPowerSaveWhitelistApps.containsKey(packageName)
+ || mPowerSaveWhitelistUserApps.containsKey(packageName);
+ }
+ }
+
public int[] getAppIdWhitelistInternal() {
synchronized (this) {
return mPowerSaveWhitelistAppIdArray;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 76ee3bc..d035c92 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19490,7 +19490,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mStackSupervisor.resumeTopActivitiesLocked();
}
EventLogTags.writeAmSwitchUser(newUserId);
- getUserManagerLocked().userForeground(newUserId);
+ getUserManagerLocked().onUserForeground(newUserId);
sendUserSwitchBroadcastsLocked(oldUserId, newUserId);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 8dccfdf..e463fad 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -241,7 +241,7 @@ public class UserManagerService extends IUserManager.Stub {
}
}
}
- userForeground(UserHandle.USER_OWNER);
+ onUserForeground(UserHandle.USER_OWNER);
mAppOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
for (int i = 0; i < mUserIds.length; ++i) {
@@ -1784,7 +1784,7 @@ public class UserManagerService extends IUserManager.Stub {
* Make a note of the last started time of a user and do some cleanup.
* @param userId the user that was just foregrounded
*/
- public void userForeground(int userId) {
+ public void onUserForeground(int userId) {
synchronized (mPackagesLock) {
UserInfo user = mUsers.get(userId);
long now = System.currentTimeMillis();
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 869d6e1..d6ff475 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -48,6 +48,7 @@ class IntervalStats {
usageStats.mPackageName = getCachedStringRef(packageName);
usageStats.mBeginTimeStamp = beginTime;
usageStats.mEndTimeStamp = endTime;
+ usageStats.mBeginIdleTime = endTime;
packageStats.put(usageStats.mPackageName, usageStats);
}
return usageStats;
@@ -119,6 +120,17 @@ class IntervalStats {
endTime = timeStamp;
}
+ /**
+ * Updates the last active time for the package. The timestamp uses a timebase that
+ * tracks the device usage time.
+ * @param packageName
+ * @param timeStamp
+ */
+ void updateBeginIdleTime(String packageName, long timeStamp) {
+ UsageStats usageStats = getOrCreateUsageStats(packageName);
+ usageStats.mBeginIdleTime = timeStamp;
+ }
+
void updateConfigurationStats(Configuration config, long timeStamp) {
if (activeConfiguration != null) {
ConfigurationStats activeStats = configurations.get(activeConfiguration);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 48b127a..197daed 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -40,31 +40,39 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.database.ContentObserver;
+import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
+import android.os.IDeviceIdleController;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.ArraySet;
+import android.util.AtomicFile;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.Display;
-import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.SystemConfig;
+import com.android.server.DeviceIdleController;
import com.android.server.SystemService;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -76,6 +84,7 @@ import java.util.List;
*/
public class UsageStatsService extends SystemService implements
UserUsageStatsService.StatsUpdatedListener {
+
static final String TAG = "UsageStatsService";
static final boolean DEBUG = false;
@@ -91,7 +100,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;
+ static final int MSG_FORCE_IDLE_STATE = 4;
static final int MSG_CHECK_IDLE_STATES = 5;
private final Object mLock = new Object();
@@ -99,16 +108,20 @@ public class UsageStatsService extends SystemService implements
AppOpsManager mAppOps;
UserManager mUserManager;
AppWidgetManager mAppWidgetManager;
+ IDeviceIdleController mDeviceIdleController;
+ private DisplayManager mDisplayManager;
private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
private File mUsageStatsDir;
long mRealTimeSnapshot;
long mSystemTimeSnapshot;
boolean mAppIdleParoled;
+ private boolean mScreenOn;
long mAppIdleDurationMillis;
-
long mCheckIdleIntervalMillis = DEFAULT_CHECK_IDLE_INTERVAL;
+ long mScreenOnTime;
+ long mScreenOnSystemTimeSnapshot;
private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
mPackageAccessListeners = new ArrayList<>();
@@ -162,6 +175,18 @@ public class UsageStatsService extends SystemService implements
// Observe changes to the threshold
new SettingsObserver(mHandler).registerObserver();
mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class);
+ mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(DeviceIdleController.SERVICE_NAME));
+ mDisplayManager = (DisplayManager) getContext().getSystemService(
+ Context.DISPLAY_SERVICE);
+ mScreenOnSystemTimeSnapshot = System.currentTimeMillis();
+ synchronized (this) {
+ mScreenOnTime = readScreenOnTimeLocked();
+ }
+ mDisplayManager.registerDisplayListener(mDisplayListener, null);
+ synchronized (this) {
+ updateDisplayLocked();
+ }
} else if (phase == PHASE_BOOT_COMPLETED) {
setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
}
@@ -195,6 +220,24 @@ public class UsageStatsService extends SystemService implements
}
}
+ private final DisplayManager.DisplayListener mDisplayListener
+ = new DisplayManager.DisplayListener() {
+
+ @Override public void onDisplayAdded(int displayId) {
+ }
+
+ @Override public void onDisplayRemoved(int displayId) {
+ }
+
+ @Override public void onDisplayChanged(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ synchronized (UsageStatsService.this.mLock) {
+ updateDisplayLocked();
+ }
+ }
+ }
+ };
+
@Override
public void onStatsUpdated() {
mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL);
@@ -261,7 +304,7 @@ public class UsageStatsService extends SystemService implements
final int packageCount = packages.size();
for (int p = 0; p < packageCount; p++) {
final String packageName = packages.get(p).packageName;
- final boolean isIdle = isAppIdle(packageName, userId);
+ final boolean isIdle = isAppIdleFiltered(packageName, userId);
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
userId, isIdle ? 1 : 0, packageName));
}
@@ -270,6 +313,61 @@ public class UsageStatsService extends SystemService implements
mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis);
}
+ void updateDisplayLocked() {
+ boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState()
+ != Display.STATE_OFF;
+ if (screenOn == mScreenOn) return;
+
+ mScreenOn = screenOn;
+ long now = System.currentTimeMillis();
+ if (mScreenOn) {
+ mScreenOnSystemTimeSnapshot = now;
+ } else {
+ mScreenOnTime += now - mScreenOnSystemTimeSnapshot;
+ writeScreenOnTimeLocked(mScreenOnTime);
+ }
+ }
+
+ private long getScreenOnTimeLocked(long now) {
+ if (mScreenOn) {
+ return now - mScreenOnSystemTimeSnapshot + mScreenOnTime;
+ } else {
+ return mScreenOnTime;
+ }
+ }
+
+ private File getScreenOnTimeFile() {
+ return new File(mUsageStatsDir, UserHandle.USER_OWNER + "/screen_on_time");
+ }
+
+ private long readScreenOnTimeLocked() {
+ long screenOnTime = 0;
+ File screenOnTimeFile = getScreenOnTimeFile();
+ if (screenOnTimeFile.exists()) {
+ try {
+ BufferedReader reader = new BufferedReader(new FileReader(screenOnTimeFile));
+ screenOnTime = Long.parseLong(reader.readLine());
+ reader.close();
+ } catch (IOException | NumberFormatException e) {
+ }
+ } else {
+ writeScreenOnTimeLocked(screenOnTime);
+ }
+ return screenOnTime;
+ }
+
+ private void writeScreenOnTimeLocked(long screenOnTime) {
+ AtomicFile screenOnTimeFile = new AtomicFile(getScreenOnTimeFile());
+ FileOutputStream fos = null;
+ try {
+ fos = screenOnTimeFile.startWrite();
+ fos.write(Long.toString(screenOnTime).getBytes());
+ screenOnTimeFile.finishWrite(fos);
+ } catch (IOException ioe) {
+ screenOnTimeFile.failWrite(fos);
+ }
+ }
+
private static void deleteRecursively(File f) {
File[] files = f.listFiles();
if (files != null) {
@@ -289,7 +387,7 @@ public class UsageStatsService extends SystemService implements
if (service == null) {
service = new UserUsageStatsService(getContext(), userId,
new File(mUsageStatsDir, Integer.toString(userId)), this);
- service.init(currentTimeMillis);
+ service.init(currentTimeMillis, getScreenOnTimeLocked(currentTimeMillis));
mUserState.put(userId, service);
}
return service;
@@ -343,9 +441,10 @@ public class UsageStatsService extends SystemService implements
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- final long lastUsed = service.getLastPackageAccessTime(event.mPackage);
- final boolean previouslyIdle = hasPassedIdleDuration(lastUsed);
- service.reportEvent(event);
+ final long lastUsed = service.getBeginIdleTime(event.mPackage);
+ final long screenOnTime = getScreenOnTimeLocked(timeNow);
+ final boolean previouslyIdle = hasPassedIdleTimeout(lastUsed, screenOnTime);
+ service.reportEvent(event, screenOnTime);
// Inform listeners if necessary
if ((event.mEventType == Event.MOVE_TO_FOREGROUND
|| event.mEventType == Event.MOVE_TO_BACKGROUND
@@ -360,19 +459,21 @@ 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.
+ * Forces the app's beginIdleTime to reflect idle or active. If idle, then it rolls back the
+ * beginIdleTime to a point in time thats behind the threshold for idle.
*/
- void resetLastTimestamp(String packageName, int userId, boolean idle) {
+ void forceIdleState(String packageName, int userId, boolean idle) {
synchronized (mLock) {
final long timeNow = checkAndGetTimeLocked();
- final long lastTimestamp = timeNow - (idle ? mAppIdleDurationMillis : 0) - 5000;
+ final long screenOnTime = getScreenOnTimeLocked(timeNow);
+ final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000;
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- final long lastUsed = service.getLastPackageAccessTime(packageName);
- final boolean previouslyIdle = hasPassedIdleDuration(lastUsed);
- service.setLastTimestamp(packageName, lastTimestamp);
+ final long lastUsed = service.getBeginIdleTime(packageName);
+ final boolean previouslyIdle = hasPassedIdleTimeout(lastUsed,
+ getScreenOnTimeLocked(timeNow));
+ service.setBeginIdleTime(packageName, deviceUsageTime);
// Inform listeners if necessary
if (previouslyIdle != idle) {
// Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
@@ -451,23 +552,25 @@ public class UsageStatsService extends SystemService implements
}
}
- /**
- * Called by LocalService stub.
- */
- long getLastPackageAccessTime(String packageName, int userId) {
+ private boolean isAppIdleUnfiltered(String packageName, int userId) {
synchronized (mLock) {
final long timeNow = checkAndGetTimeLocked();
- // android package is always considered non-idle.
- // TODO: Add a generic whitelisting mechanism
- if (packageName.equals("android")) {
- return timeNow;
- }
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- return service.getLastPackageAccessTime(packageName);
+ long beginIdleTime = service.getBeginIdleTime(packageName);
+ return hasPassedIdleTimeout(beginIdleTime, getScreenOnTimeLocked(timeNow));
}
}
+ /**
+ * @param timestamp when the app was last used in device usage timebase
+ * @param currentTime current time in device usage timebase
+ * @return whether it's been used far enough in the past to be considered inactive
+ */
+ boolean hasPassedIdleTimeout(long timestamp, long currentTime) {
+ return timestamp <= currentTime - mAppIdleDurationMillis;
+ }
+
void addListener(AppIdleStateChangeListener listener) {
synchronized (mLock) {
if (!mPackageAccessListeners.contains(listener)) {
@@ -482,12 +585,13 @@ public class UsageStatsService extends SystemService implements
}
}
- private boolean hasPassedIdleDuration(long lastUsed) {
- final long now = System.currentTimeMillis();
- return lastUsed <= now - mAppIdleDurationMillis;
- }
-
- boolean isAppIdle(String packageName, int userId) {
+ /**
+ * Checks if an app has been idle for a while and filters out apps that are excluded.
+ * It returns false if the current system state allows all apps to be considered active.
+ * This happens if the device is plugged in or temporarily allowed to make exceptions.
+ * Called by interface impls.
+ */
+ boolean isAppIdleFiltered(String packageName, int userId) {
if (packageName == null) return false;
synchronized (mLock) {
// Temporary exemption, probably due to device charging or occasional allowance to
@@ -496,8 +600,12 @@ public class UsageStatsService extends SystemService implements
return false;
}
}
- if (SystemConfig.getInstance().getAllowInPowerSave().contains(packageName)) {
- return false;
+ if (packageName.equals("android")) return false;
+ try {
+ if (mDeviceIdleController.isPowerSaveWhitelistApp(packageName)) {
+ return false;
+ }
+ } catch (RemoteException re) {
}
// TODO: Optimize this check
if (isActiveDeviceAdmin(packageName, userId)) {
@@ -509,14 +617,13 @@ public class UsageStatsService extends SystemService implements
return false;
}
- final long lastUsed = getLastPackageAccessTime(packageName, userId);
- return hasPassedIdleDuration(lastUsed);
+ return isAppIdleUnfiltered(packageName, userId);
}
void setAppIdle(String packageName, boolean idle, int userId) {
if (packageName == null) return;
- mHandler.obtainMessage(MSG_RESET_LAST_TIMESTAMP, userId, idle ? 1 : 0, packageName)
+ mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
.sendToTarget();
}
@@ -559,6 +666,7 @@ public class UsageStatsService extends SystemService implements
*/
void dump(String[] args, PrintWriter pw) {
synchronized (mLock) {
+ final long screenOnTime = getScreenOnTimeLocked(checkAndGetTimeLocked());
IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " ");
ArraySet<String> argSet = new ArraySet<>();
argSet.addAll(Arrays.asList(args));
@@ -569,12 +677,13 @@ public class UsageStatsService extends SystemService implements
idpw.println();
idpw.increaseIndent();
if (argSet.contains("--checkin")) {
- mUserState.valueAt(i).checkin(idpw);
+ mUserState.valueAt(i).checkin(idpw, screenOnTime);
} else {
- mUserState.valueAt(i).dump(idpw);
+ mUserState.valueAt(i).dump(idpw, screenOnTime);
}
idpw.decreaseIndent();
}
+ pw.write("Screen On Timestamp:" + mScreenOnTime + "\n");
}
}
@@ -602,8 +711,8 @@ 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);
+ case MSG_FORCE_IDLE_STATE:
+ forceIdleState((String) msg.obj, msg.arg1, msg.arg2 == 1);
break;
case MSG_CHECK_IDLE_STATES:
@@ -727,7 +836,7 @@ public class UsageStatsService extends SystemService implements
}
final long token = Binder.clearCallingIdentity();
try {
- return UsageStatsService.this.isAppIdle(packageName, userId);
+ return UsageStatsService.this.isAppIdleFiltered(packageName, userId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -832,12 +941,7 @@ public class UsageStatsService extends SystemService implements
@Override
public boolean isAppIdle(String packageName, int userId) {
- return UsageStatsService.this.isAppIdle(packageName, userId);
- }
-
- @Override
- public long getLastPackageAccessTime(String packageName, int userId) {
- return UsageStatsService.this.getLastPackageAccessTime(packageName, userId);
+ return UsageStatsService.this.isAppIdleFiltered(packageName, userId);
}
@Override
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index bfb71c5..0111201 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -26,6 +26,7 @@ import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
import android.content.res.Configuration;
+import android.text.TextUtils;
import java.io.IOException;
import java.net.ProtocolException;
@@ -54,6 +55,7 @@ final class UsageStatsXmlV1 {
// Time attributes stored as an offset of the beginTime.
private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+ private static final String BEGIN_IDLE_TIME_ATTR = "beginIdleTime";
private static final String END_TIME_ATTR = "endTime";
private static final String TIME_ATTR = "time";
@@ -69,7 +71,10 @@ final class UsageStatsXmlV1 {
// Apply the offset to the beginTime to find the absolute time.
stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
parser, LAST_TIME_ACTIVE_ATTR);
-
+ final String beginIdleTime = parser.getAttributeValue(null, BEGIN_IDLE_TIME_ATTR);
+ if (!TextUtils.isEmpty(beginIdleTime)) {
+ stats.mBeginIdleTime = Long.parseLong(beginIdleTime);
+ }
stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR);
}
@@ -129,6 +134,7 @@ final class UsageStatsXmlV1 {
XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent);
+ XmlUtils.writeLongAttribute(xml, BEGIN_IDLE_TIME_ATTR, usageStats.mBeginIdleTime);
xml.endTag(null, PACKAGE_TAG);
}
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index d94759d..b638c8e 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -80,7 +80,7 @@ class UserUsageStatsService {
mUserId = userId;
}
- void init(final long currentTimeMillis) {
+ void init(final long currentTimeMillis, final long deviceUsageTime) {
mDatabase.init(currentTimeMillis);
int nullCount = 0;
@@ -135,7 +135,8 @@ class UserUsageStatsService {
}
if (mDatabase.isNewUpdate()) {
- initializeDefaultsForApps(currentTimeMillis, mDatabase.isFirstUpdate());
+ initializeDefaultsForApps(currentTimeMillis, deviceUsageTime,
+ mDatabase.isFirstUpdate());
}
}
@@ -145,7 +146,8 @@ class UserUsageStatsService {
* @param firstUpdate if it is the first update, touch all installed apps, otherwise only
* touch the system apps
*/
- private void initializeDefaultsForApps(long currentTimeMillis, boolean firstUpdate) {
+ private void initializeDefaultsForApps(long currentTimeMillis, long deviceUsageTime,
+ boolean firstUpdate) {
PackageManager pm = mContext.getPackageManager();
List<PackageInfo> packages = pm.getInstalledPackages(0, mUserId);
final int packageCount = packages.size();
@@ -153,9 +155,10 @@ class UserUsageStatsService {
final PackageInfo pi = packages.get(i);
String packageName = pi.packageName;
if (pi.applicationInfo != null && (firstUpdate || pi.applicationInfo.isSystemApp())
- && getLastPackageAccessTime(packageName) == -1) {
+ && getBeginIdleTime(packageName) == -1) {
for (IntervalStats stats : mCurrentStats) {
stats.update(packageName, currentTimeMillis, Event.INTERACTION);
+ stats.updateBeginIdleTime(packageName, deviceUsageTime);
mStatsChanged = true;
}
}
@@ -170,7 +173,7 @@ class UserUsageStatsService {
loadActiveStats(newTime, true);
}
- void reportEvent(UsageEvents.Event event) {
+ void reportEvent(UsageEvents.Event event, long deviceUsageTime) {
if (DEBUG) {
Slog.d(TAG, mLogPrefix + "Got usage event for " + event.mPackage
+ "[" + event.mTimeStamp + "]: "
@@ -205,6 +208,7 @@ class UserUsageStatsService {
stats.updateConfigurationStats(newFullConfig, event.mTimeStamp);
} else {
stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+ stats.updateBeginIdleTime(event.mPackage, deviceUsageTime);
}
}
@@ -215,9 +219,9 @@ class UserUsageStatsService {
* Sets the last timestamp for each of the intervals.
* @param lastTimestamp
*/
- void setLastTimestamp(String packageName, long lastTimestamp) {
+ void setBeginIdleTime(String packageName, long deviceUsageTime) {
for (IntervalStats stats : mCurrentStats) {
- stats.update(packageName, lastTimestamp, UsageEvents.Event.NONE);
+ stats.updateBeginIdleTime(packageName, deviceUsageTime);
}
notifyStatsChanged();
}
@@ -376,13 +380,13 @@ class UserUsageStatsService {
return new UsageEvents(results, table);
}
- long getLastPackageAccessTime(String packageName) {
+ long getBeginIdleTime(String packageName) {
final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY];
UsageStats packageUsage;
if ((packageUsage = yearly.packageStats.get(packageName)) == null) {
return -1;
} else {
- return packageUsage.getLastTimeUsed();
+ return packageUsage.getBeginIdleTime();
}
}
@@ -506,23 +510,23 @@ class UserUsageStatsService {
// -- DUMP related methods --
//
- void checkin(final IndentingPrintWriter pw) {
+ void checkin(final IndentingPrintWriter pw, final long screenOnTime) {
mDatabase.checkinDailyFiles(new UsageStatsDatabase.CheckinAction() {
@Override
public boolean checkin(IntervalStats stats) {
- printIntervalStats(pw, stats, false);
+ printIntervalStats(pw, stats, screenOnTime, false);
return true;
}
});
}
- void dump(IndentingPrintWriter pw) {
+ void dump(IndentingPrintWriter pw, final long screenOnTime) {
// This is not a check-in, only dump in-memory stats.
for (int interval = 0; interval < mCurrentStats.length; interval++) {
pw.print("In-memory ");
pw.print(intervalToString(interval));
pw.println(" stats");
- printIntervalStats(pw, mCurrentStats[interval], true);
+ printIntervalStats(pw, mCurrentStats[interval], screenOnTime, true);
}
}
@@ -540,7 +544,8 @@ class UserUsageStatsService {
return Long.toString(elapsedTime);
}
- void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats, boolean prettyDates) {
+ void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats, long screenOnTime,
+ boolean prettyDates) {
if (prettyDates) {
pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext,
stats.beginTime, stats.endTime, sDateFormatFlags) + "\"");
@@ -559,6 +564,8 @@ class UserUsageStatsService {
pw.printPair("package", usageStats.mPackageName);
pw.printPair("totalTime", formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates));
pw.printPair("lastTime", formatDateTime(usageStats.mLastTimeUsed, prettyDates));
+ pw.printPair("inactiveTime",
+ formatElapsedTime(screenOnTime - usageStats.mBeginIdleTime, prettyDates));
pw.println();
}
pw.decreaseIndent();