Merge commit '5142a2d5b3f70c2017792ce04d3f254221ab3d21' into manual_merge_5142a2d5b3
Change-Id: I6681b0e132e95bd7e861e183e7369b4da07738eb
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 0fce4e2..a88aa3125 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -165,14 +165,18 @@
mPackageName + "' with UsageStats for package '" + right.mPackageName + "'.");
}
- if (right.mEndTimeStamp > mEndTimeStamp) {
+ if (right.mBeginTimeStamp > mBeginTimeStamp) {
+ // The incoming UsageStat begins after this one, so use its last time used fields
+ // as the source of truth.
+ // We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with
+ // regards to their mEndTimeStamp.
mLastEvent = right.mLastEvent;
- mEndTimeStamp = right.mEndTimeStamp;
mLastTimeUsed = right.mLastTimeUsed;
mBeginIdleTime = right.mBeginIdleTime;
mLastTimeSystemUsed = right.mLastTimeSystemUsed;
}
mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
+ mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
mTotalTimeInForeground += right.mTotalTimeInForeground;
mLaunchCount += right.mLaunchCount;
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 81031da..bfdac7e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -123,6 +123,7 @@
static final int MSG_PAROLE_END_TIMEOUT = 7;
static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
static final int MSG_PAROLE_STATE_CHANGED = 9;
+ static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
private final Object mLock = new Object();
Handler mHandler;
@@ -145,7 +146,7 @@
private long mLastAppIdleParoledTime;
long mScreenOnTime;
- long mScreenOnSystemTimeSnapshot;
+ long mLastScreenOnEventRealtime;
@GuardedBy("mLock")
private AppIdleHistory mAppIdleHistory = new AppIdleHistory();
@@ -188,6 +189,8 @@
synchronized (mLock) {
cleanUpRemovedUsersLocked();
+ mLastScreenOnEventRealtime = SystemClock.elapsedRealtime();
+ mScreenOnTime = readScreenOnTimeLocked();
}
mRealTimeSnapshot = SystemClock.elapsedRealtime();
@@ -214,10 +217,6 @@
Context.DISPLAY_SERVICE);
mPowerManager = getContext().getSystemService(PowerManager.class);
- mScreenOnSystemTimeSnapshot = System.currentTimeMillis();
- synchronized (mLock) {
- mScreenOnTime = readScreenOnTimeLocked();
- }
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
synchronized (mLock) {
updateDisplayLocked();
@@ -281,6 +280,11 @@
}
@Override
+ public void onStatsReloaded() {
+ postOneTimeCheckIdleStates();
+ }
+
+ @Override
public long getAppIdleRollingWindowDurationMillis() {
return mAppIdleWallclockThresholdMillis * 2;
}
@@ -359,6 +363,14 @@
mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
}
+ /**
+ * We send a different message to check idle states once, otherwise we would end up
+ * scheduling a series of repeating checkIdleStates each time we fired off one.
+ */
+ void postOneTimeCheckIdleStates() {
+ mHandler.sendEmptyMessage(MSG_ONE_TIME_CHECK_IDLE_STATES);
+ }
+
/** Check all running users' or specified user's apps to see if they enter an idle state. */
void checkIdleStates(int checkUserId) {
if (!mAppIdleEnabled) {
@@ -385,7 +397,7 @@
userId);
synchronized (mLock) {
final long timeNow = checkAndGetTimeLocked();
- final long screenOnTime = getScreenOnTimeLocked(timeNow);
+ final long screenOnTime = getScreenOnTimeLocked();
UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId,
timeNow);
final int packageCount = packages.size();
@@ -401,8 +413,6 @@
}
}
}
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0),
- mCheckIdleIntervalMillis);
}
/** Check if it's been a while since last parole and let idle apps do some work */
@@ -443,21 +453,21 @@
if (screenOn == mScreenOn) return;
mScreenOn = screenOn;
- long now = System.currentTimeMillis();
+ long now = SystemClock.elapsedRealtime();
if (mScreenOn) {
- mScreenOnSystemTimeSnapshot = now;
+ mLastScreenOnEventRealtime = now;
} else {
- mScreenOnTime += now - mScreenOnSystemTimeSnapshot;
+ mScreenOnTime += now - mLastScreenOnEventRealtime;
writeScreenOnTimeLocked(mScreenOnTime);
}
}
- private long getScreenOnTimeLocked(long now) {
+ long getScreenOnTimeLocked() {
+ long screenOnTime = mScreenOnTime;
if (mScreenOn) {
- return now - mScreenOnSystemTimeSnapshot + mScreenOnTime;
- } else {
- return mScreenOnTime;
+ screenOnTime += SystemClock.elapsedRealtime() - mLastScreenOnEventRealtime;
}
+ return screenOnTime;
}
private File getScreenOnTimeFile() {
@@ -527,7 +537,7 @@
if (service == null) {
service = new UserUsageStatsService(getContext(), userId,
new File(mUsageStatsDir, Integer.toString(userId)), this);
- service.init(currentTimeMillis, getScreenOnTimeLocked(currentTimeMillis));
+ service.init(currentTimeMillis, getScreenOnTimeLocked());
mUserState.put(userId, service);
}
return service;
@@ -540,25 +550,18 @@
final long actualSystemTime = System.currentTimeMillis();
final long actualRealtime = SystemClock.elapsedRealtime();
final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
- boolean resetBeginIdleTime = false;
- if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
+ final long diffSystemTime = actualSystemTime - expectedSystemTime;
+ if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
// The time has changed.
-
- // Check if it's severe enough a change to reset screenOnTime
- if (Math.abs(actualSystemTime - expectedSystemTime) > mAppIdleDurationMillis) {
- mScreenOnSystemTimeSnapshot = actualSystemTime;
- mScreenOnTime = 0;
- resetBeginIdleTime = true;
- }
+ Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds");
final int userCount = mUserState.size();
for (int i = 0; i < userCount; i++) {
final UserUsageStatsService service = mUserState.valueAt(i);
- service.onTimeChanged(expectedSystemTime, actualSystemTime, mScreenOnTime,
- resetBeginIdleTime);
+ service.onTimeChanged(expectedSystemTime, actualSystemTime, getScreenOnTimeLocked(),
+ false);
}
mRealTimeSnapshot = actualRealtime;
mSystemTimeSnapshot = actualSystemTime;
- postCheckIdleStates(UserHandle.USER_ALL);
}
return actualSystemTime;
}
@@ -587,7 +590,7 @@
void reportEvent(UsageEvents.Event event, int userId) {
synchronized (mLock) {
final long timeNow = checkAndGetTimeLocked();
- final long screenOnTime = getScreenOnTimeLocked(timeNow);
+ final long screenOnTime = getScreenOnTimeLocked();
convertToSystemTimeLocked(event);
final UserUsageStatsService service =
@@ -603,7 +606,6 @@
|| event.mEventType == Event.SYSTEM_INTERACTION
|| event.mEventType == Event.USER_INTERACTION)) {
if (previouslyIdle) {
- //Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
/* idle = */ 0, event.mPackage));
notifyBatteryStats(event.mPackage, userId, false);
@@ -643,7 +645,7 @@
void forceIdleState(String packageName, int userId, boolean idle) {
synchronized (mLock) {
final long timeNow = checkAndGetTimeLocked();
- final long screenOnTime = getScreenOnTimeLocked(timeNow);
+ final long screenOnTime = getScreenOnTimeLocked();
final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000;
final UserUsageStatsService service =
@@ -657,7 +659,6 @@
timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000);
// Inform listeners if necessary
if (previouslyIdle != idle) {
- // Slog.d(TAG, "Informing listeners of out-of-idle " + packageName);
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
/* idle = */ idle ? 1 : 0, packageName));
if (!idle) {
@@ -796,7 +797,7 @@
timeNow = checkAndGetTimeLocked();
}
userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- screenOnTime = getScreenOnTimeLocked(timeNow);
+ screenOnTime = getScreenOnTimeLocked();
}
return isAppIdleFiltered(packageName, UserHandle.getAppId(uidForAppId), userId,
userService, timeNow, screenOnTime);
@@ -865,7 +866,7 @@
synchronized (mLock) {
timeNow = checkAndGetTimeLocked();
userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- screenOnTime = getScreenOnTimeLocked(timeNow);
+ screenOnTime = getScreenOnTimeLocked();
}
List<ApplicationInfo> apps;
@@ -987,7 +988,7 @@
*/
void dump(String[] args, PrintWriter pw) {
synchronized (mLock) {
- final long screenOnTime = getScreenOnTimeLocked(checkAndGetTimeLocked());
+ final long screenOnTime = getScreenOnTimeLocked();
IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " ");
ArraySet<String> argSet = new ArraySet<>();
argSet.addAll(Arrays.asList(args));
@@ -1008,7 +1009,11 @@
}
idpw.decreaseIndent();
}
- pw.println("Screen On Timebase:" + mScreenOnTime);
+ pw.print("Screen On Timebase: ");
+ pw.print(screenOnTime);
+ pw.print(" (");
+ TimeUtils.formatDuration(screenOnTime, pw);
+ pw.println(")");
pw.println();
pw.println("Settings:");
@@ -1042,8 +1047,8 @@
pw.println();
pw.print("mScreenOnTime="); TimeUtils.formatDuration(mScreenOnTime, pw);
pw.println();
- pw.print("mScreenOnSystemTimeSnapshot=");
- TimeUtils.formatDuration(mScreenOnSystemTimeSnapshot, pw);
+ pw.print("mLastScreenOnEventRealtime=");
+ TimeUtils.formatDuration(mLastScreenOnEventRealtime, pw);
pw.println();
}
}
@@ -1078,6 +1083,14 @@
case MSG_CHECK_IDLE_STATES:
checkIdleStates(msg.arg1);
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(
+ MSG_CHECK_IDLE_STATES, msg.arg1, 0),
+ mCheckIdleIntervalMillis);
+ break;
+
+ case MSG_ONE_TIME_CHECK_IDLE_STATES:
+ mHandler.removeMessages(MSG_ONE_TIME_CHECK_IDLE_STATES);
+ checkIdleStates(UserHandle.USER_ALL);
break;
case MSG_CHECK_PAROLE_TIMEOUT:
@@ -1138,7 +1151,7 @@
@Override
public void onChange(boolean selfChange) {
updateSettings();
- postCheckIdleStates(UserHandle.USER_ALL);
+ postOneTimeCheckIdleStates();
}
void updateSettings() {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index aa2cf77..f2045d3 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -73,6 +73,7 @@
interface StatsUpdatedListener {
void onStatsUpdated();
+ void onStatsReloaded();
long getAppIdleRollingWindowDurationMillis();
}
@@ -523,6 +524,9 @@
mStatsChanged = false;
updateRolloverDeadline();
+
+ // Tell the listener that the stats reloaded, which may have changed idle states.
+ mListener.onStatsReloaded();
}
private void updateRolloverDeadline() {