summaryrefslogtreecommitdiff
path: root/services/usage/java
diff options
context:
space:
mode:
author Amith Yamasani <yamasani@google.com> 2017-02-24 11:02:07 -0800
committer Amith Yamasani <yamasani@google.com> 2017-02-24 14:54:36 -0800
commit61d5fd7fee3250bdf4b6ddfbccbd6bceae9436c6 (patch)
treedb8b24f056ec037931c11f1f864a2a096e21cb54 /services/usage/java
parent2140cd6431266bdb17024c66bb93cf88ff7cc407 (diff)
Reduce screen on delay during UsageStats rollover
Decoupled the app idle book-keeping from usage stats lock, by introducing an mAppIdleLock. This is used for all state related to app idle. In some cases, the locks will be nested, with mLock being acquired first and then mAppIdleLock. This should fix the situation where a rollover, which writes to disk and could take several seconds when the system is swamped, like when the device just came out of idle and the screen was turned on (like this run-on sentence), causes calls from other services for app-idle status to be blocked. This was resulting in a long time to turn on the screen. Also fixed a dump indentation issue. Bug: 34627115 Bug: 34961340 Test: Manual, force into idle, increased rollover frequency, and tested screen on time. Change-Id: Ie8b44e6f07f82d8a31f1b733a403dd9b6dc310f6
Diffstat (limited to 'services/usage/java')
-rw-r--r--services/usage/java/com/android/server/usage/AppIdleHistory.java87
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java218
-rw-r--r--services/usage/java/com/android/server/usage/UserUsageStatsService.java2
3 files changed, 174 insertions, 133 deletions
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index f69dae44a316..f2985597573f 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -18,7 +18,6 @@ package com.android.server.usage;
import android.os.Environment;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Slog;
@@ -101,7 +100,7 @@ public class AppIdleHistory {
mElapsedSnapshot = elapsedRealtime;
mScreenOnSnapshot = elapsedRealtime;
mStorageDir = storageDir;
- readScreenOnTimeLocked();
+ readScreenOnTime();
}
public void setThresholds(long elapsedTimeThreshold, long screenOnTimeThreshold) {
@@ -109,7 +108,7 @@ public class AppIdleHistory {
mScreenOnTimeThreshold = screenOnTimeThreshold;
}
- public void updateDisplayLocked(boolean screenOn, long elapsedRealtime) {
+ public void updateDisplay(boolean screenOn, long elapsedRealtime) {
if (screenOn == mScreenOn) return;
mScreenOn = screenOn;
@@ -122,7 +121,7 @@ public class AppIdleHistory {
}
}
- public long getScreenOnTimeLocked(long elapsedRealtime) {
+ public long getScreenOnTime(long elapsedRealtime) {
long screenOnTime = mScreenOnDuration;
if (mScreenOn) {
screenOnTime += elapsedRealtime - mScreenOnSnapshot;
@@ -135,7 +134,7 @@ public class AppIdleHistory {
return new File(mStorageDir, "screen_on_time");
}
- private void readScreenOnTimeLocked() {
+ private void readScreenOnTime() {
File screenOnTimeFile = getScreenOnTimeFile();
if (screenOnTimeFile.exists()) {
try {
@@ -146,11 +145,11 @@ public class AppIdleHistory {
} catch (IOException | NumberFormatException e) {
}
} else {
- writeScreenOnTimeLocked();
+ writeScreenOnTime();
}
}
- private void writeScreenOnTimeLocked() {
+ private void writeScreenOnTime() {
AtomicFile screenOnTimeFile = new AtomicFile(getScreenOnTimeFile());
FileOutputStream fos = null;
try {
@@ -166,30 +165,30 @@ public class AppIdleHistory {
/**
* To be called periodically to keep track of elapsed time when app idle times are written
*/
- public void writeAppIdleDurationsLocked() {
+ public void writeAppIdleDurations() {
final long elapsedRealtime = SystemClock.elapsedRealtime();
// Only bump up and snapshot the elapsed time. Don't change screen on duration.
mElapsedDuration += elapsedRealtime - mElapsedSnapshot;
mElapsedSnapshot = elapsedRealtime;
- writeScreenOnTimeLocked();
+ writeScreenOnTime();
}
- public void reportUsageLocked(String packageName, int userId, long elapsedRealtime) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
- PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+ public void reportUsage(String packageName, int userId, long elapsedRealtime) {
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
+ PackageHistory packageHistory = getPackageHistory(userHistory, packageName,
elapsedRealtime);
shiftHistoryToNow(userHistory, elapsedRealtime);
packageHistory.lastUsedElapsedTime = mElapsedDuration
+ (elapsedRealtime - mElapsedSnapshot);
- packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime);
+ packageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
packageHistory.recent[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
}
public void setIdle(String packageName, int userId, long elapsedRealtime) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
- PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
+ PackageHistory packageHistory = getPackageHistory(userHistory, packageName,
elapsedRealtime);
shiftHistoryToNow(userHistory, elapsedRealtime);
@@ -222,23 +221,23 @@ public class AppIdleHistory {
mLastPeriod = thisPeriod;
}
- private ArrayMap<String, PackageHistory> getUserHistoryLocked(int userId) {
+ private ArrayMap<String, PackageHistory> getUserHistory(int userId) {
ArrayMap<String, PackageHistory> userHistory = mIdleHistory.get(userId);
if (userHistory == null) {
userHistory = new ArrayMap<>();
mIdleHistory.put(userId, userHistory);
- readAppIdleTimesLocked(userId, userHistory);
+ readAppIdleTimes(userId, userHistory);
}
return userHistory;
}
- private PackageHistory getPackageHistoryLocked(ArrayMap<String, PackageHistory> userHistory,
+ private PackageHistory getPackageHistory(ArrayMap<String, PackageHistory> userHistory,
String packageName, long elapsedRealtime) {
PackageHistory packageHistory = userHistory.get(packageName);
if (packageHistory == null) {
packageHistory = new PackageHistory();
- packageHistory.lastUsedElapsedTime = getElapsedTimeLocked(elapsedRealtime);
- packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime);
+ packageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime);
+ packageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
userHistory.put(packageName, packageHistory);
}
return packageHistory;
@@ -248,41 +247,41 @@ public class AppIdleHistory {
mIdleHistory.remove(userId);
}
- public boolean isIdleLocked(String packageName, int userId, long elapsedRealtime) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+ public boolean isIdle(String packageName, int userId, long elapsedRealtime) {
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
PackageHistory packageHistory =
- getPackageHistoryLocked(userHistory, packageName, elapsedRealtime);
+ getPackageHistory(userHistory, packageName, elapsedRealtime);
if (packageHistory == null) {
return false; // Default to not idle
} else {
- return hasPassedThresholdsLocked(packageHistory, elapsedRealtime);
+ return hasPassedThresholds(packageHistory, elapsedRealtime);
}
}
- private long getElapsedTimeLocked(long elapsedRealtime) {
+ private long getElapsedTime(long elapsedRealtime) {
return (elapsedRealtime - mElapsedSnapshot + mElapsedDuration);
}
- public void setIdleLocked(String packageName, int userId, boolean idle, long elapsedRealtime) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
- PackageHistory packageHistory = getPackageHistoryLocked(userHistory, packageName,
+ public void setIdle(String packageName, int userId, boolean idle, long elapsedRealtime) {
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
+ PackageHistory packageHistory = getPackageHistory(userHistory, packageName,
elapsedRealtime);
- packageHistory.lastUsedElapsedTime = getElapsedTimeLocked(elapsedRealtime)
+ packageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime)
- mElapsedTimeThreshold;
- packageHistory.lastUsedScreenTime = getScreenOnTimeLocked(elapsedRealtime)
+ packageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime)
- (idle ? mScreenOnTimeThreshold : 0) - 1000 /* just a second more */;
}
- public void clearUsageLocked(String packageName, int userId) {
- ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+ public void clearUsage(String packageName, int userId) {
+ ArrayMap<String, PackageHistory> userHistory = getUserHistory(userId);
userHistory.remove(packageName);
}
- private boolean hasPassedThresholdsLocked(PackageHistory packageHistory, long elapsedRealtime) {
+ private boolean hasPassedThresholds(PackageHistory packageHistory, long elapsedRealtime) {
return (packageHistory.lastUsedScreenTime
- <= getScreenOnTimeLocked(elapsedRealtime) - mScreenOnTimeThreshold)
+ <= getScreenOnTime(elapsedRealtime) - mScreenOnTimeThreshold)
&& (packageHistory.lastUsedElapsedTime
- <= getElapsedTimeLocked(elapsedRealtime) - mElapsedTimeThreshold);
+ <= getElapsedTime(elapsedRealtime) - mElapsedTimeThreshold);
}
private File getUserFile(int userId) {
@@ -290,7 +289,7 @@ public class AppIdleHistory {
Integer.toString(userId)), APP_IDLE_FILENAME);
}
- private void readAppIdleTimesLocked(int userId, ArrayMap<String, PackageHistory> userHistory) {
+ private void readAppIdleTimes(int userId, ArrayMap<String, PackageHistory> userHistory) {
FileInputStream fis = null;
try {
AtomicFile appIdleFile = new AtomicFile(getUserFile(userId));
@@ -332,7 +331,7 @@ public class AppIdleHistory {
}
}
- public void writeAppIdleTimesLocked(int userId) {
+ public void writeAppIdleTimes(int userId) {
FileOutputStream fos = null;
AtomicFile appIdleFile = new AtomicFile(getUserFile(userId));
try {
@@ -346,7 +345,7 @@ public class AppIdleHistory {
xml.startTag(null, TAG_PACKAGES);
- ArrayMap<String,PackageHistory> userHistory = getUserHistoryLocked(userId);
+ ArrayMap<String,PackageHistory> userHistory = getUserHistory(userId);
final int N = userHistory.size();
for (int i = 0; i < N; i++) {
String packageName = userHistory.keyAt(i);
@@ -374,8 +373,8 @@ public class AppIdleHistory {
idpw.increaseIndent();
ArrayMap<String, PackageHistory> userHistory = mIdleHistory.get(userId);
final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long totalElapsedTime = getElapsedTimeLocked(elapsedRealtime);
- final long screenOnTime = getScreenOnTimeLocked(elapsedRealtime);
+ final long totalElapsedTime = getElapsedTime(elapsedRealtime);
+ final long screenOnTime = getScreenOnTime(elapsedRealtime);
if (userHistory == null) return;
final int P = userHistory.size();
for (int p = 0; p < P; p++) {
@@ -386,15 +385,15 @@ public class AppIdleHistory {
TimeUtils.formatDuration(totalElapsedTime - packageHistory.lastUsedElapsedTime, idpw);
idpw.print(" lastUsedScreenOn=");
TimeUtils.formatDuration(screenOnTime - packageHistory.lastUsedScreenTime, idpw);
- idpw.print(" idle=" + (isIdleLocked(packageName, userId, elapsedRealtime) ? "y" : "n"));
+ idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
idpw.println();
}
idpw.println();
idpw.print("totalElapsedTime=");
- TimeUtils.formatDuration(getElapsedTimeLocked(elapsedRealtime), idpw);
+ TimeUtils.formatDuration(getElapsedTime(elapsedRealtime), idpw);
idpw.println();
idpw.print("totalScreenOnTime=");
- TimeUtils.formatDuration(getScreenOnTimeLocked(elapsedRealtime), idpw);
+ TimeUtils.formatDuration(getScreenOnTime(elapsedRealtime), idpw);
idpw.println();
idpw.decreaseIndent();
}
@@ -410,7 +409,7 @@ public class AppIdleHistory {
for (int i = 0; i < HISTORY_SIZE; i++) {
idpw.print(history[i] == 0 ? '.' : 'A');
}
- idpw.print(" idle=" + (isIdleLocked(packageName, userId, elapsedRealtime) ? "y" : "n"));
+ idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
idpw.print(" " + packageName);
idpw.println();
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 3c743b5cb355..469a8f144cb3 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -153,13 +153,17 @@ public class UsageStatsService extends SystemService implements
private volatile boolean mPendingOneTimeCheckIdleStates;
private boolean mSystemServicesReady = false;
- @GuardedBy("mLock")
+ private final Object mAppIdleLock = new Object();
+ @GuardedBy("mAppIdleLock")
private AppIdleHistory mAppIdleHistory;
+ @GuardedBy("mAppIdleLock")
private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
mPackageAccessListeners = new ArrayList<>();
+ @GuardedBy("mAppIdleLock")
private boolean mHaveCarrierPrivilegedApps;
+ @GuardedBy("mAppIdleLock")
private List<String> mCarrierPrivilegedApps;
public UsageStatsService(Context context) {
@@ -206,6 +210,8 @@ public class UsageStatsService extends SystemService implements
synchronized (mLock) {
cleanUpRemovedUsersLocked();
+ }
+ synchronized (mAppIdleLock) {
mAppIdleHistory = new AppIdleHistory(SystemClock.elapsedRealtime());
}
@@ -234,8 +240,8 @@ public class UsageStatsService extends SystemService implements
mPowerManager = getContext().getSystemService(PowerManager.class);
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
- synchronized (mLock) {
- mAppIdleHistory.updateDisplayLocked(isDisplayOn(), SystemClock.elapsedRealtime());
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.updateDisplay(isDisplayOn(), SystemClock.elapsedRealtime());
}
if (mPendingOneTimeCheckIdleStates) {
@@ -324,8 +330,8 @@ public class UsageStatsService extends SystemService implements
@Override public void onDisplayChanged(int displayId) {
if (displayId == Display.DEFAULT_DISPLAY) {
final boolean displayOn = isDisplayOn();
- synchronized (UsageStatsService.this.mLock) {
- mAppIdleHistory.updateDisplayLocked(displayOn, SystemClock.elapsedRealtime());
+ synchronized (UsageStatsService.this.mAppIdleLock) {
+ mAppIdleHistory.updateDisplay(displayOn, SystemClock.elapsedRealtime());
}
}
}
@@ -386,18 +392,20 @@ public class UsageStatsService extends SystemService implements
PackageManager.MATCH_DISABLED_COMPONENTS,
userId);
final int packageCount = packages.size();
- for (int i = 0; i < packageCount; i++) {
- final PackageInfo pi = packages.get(i);
- String packageName = pi.packageName;
- if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
- mAppIdleHistory.reportUsageLocked(packageName, userId, elapsedRealtime);
+ synchronized (mAppIdleLock) {
+ for (int i = 0; i < packageCount; i++) {
+ final PackageInfo pi = packages.get(i);
+ String packageName = pi.packageName;
+ if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
+ mAppIdleHistory.reportUsage(packageName, userId, elapsedRealtime);
+ }
}
}
}
void clearAppIdleForPackage(String packageName, int userId) {
- synchronized (mLock) {
- mAppIdleHistory.clearUsageLocked(packageName, userId);
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.clearUsage(packageName, userId);
}
}
@@ -429,7 +437,7 @@ public class UsageStatsService extends SystemService implements
}
void setChargingState(boolean charging) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
if (mCharging != charging) {
mCharging = charging;
postParoleStateChanged();
@@ -439,15 +447,16 @@ public class UsageStatsService extends SystemService implements
/** Paroled here means temporary pardon from being inactive */
void setAppIdleParoled(boolean paroled) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
+ final long now = System.currentTimeMillis();
if (mAppIdleTempParoled != paroled) {
mAppIdleTempParoled = paroled;
if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleTempParoled);
if (paroled) {
postParoleEndTimeout();
} else {
- mLastAppIdleParoledTime = checkAndGetTimeLocked();
- postNextParoleTimeout();
+ mLastAppIdleParoledTime = now;
+ postNextParoleTimeout(now);
}
postParoleStateChanged();
}
@@ -455,19 +464,18 @@ public class UsageStatsService extends SystemService implements
}
boolean isParoledOrCharging() {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
return mAppIdleTempParoled || mCharging;
}
}
- private void postNextParoleTimeout() {
+ private void postNextParoleTimeout(long now) {
if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
// Compute when the next parole needs to happen. We check more frequently than necessary
// since the message handler delays are based on elapsedRealTime and not wallclock time.
// The comparison is done in wallclock time.
- long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis)
- - checkAndGetTimeLocked();
+ long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis) - now;
if (timeLeft < 0) {
timeLeft = 0;
}
@@ -546,7 +554,7 @@ public class UsageStatsService extends SystemService implements
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
userId, isIdle ? 1 : 0, packageName));
if (isIdle) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
mAppIdleHistory.setIdle(packageName, userId, elapsedRealtime);
}
}
@@ -561,18 +569,23 @@ public class UsageStatsService extends SystemService implements
/** Check if it's been a while since last parole and let idle apps do some work */
void checkParoleTimeout() {
- synchronized (mLock) {
+ boolean setParoled = false;
+ synchronized (mAppIdleLock) {
+ final long now = System.currentTimeMillis();
if (!mAppIdleTempParoled) {
- final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
+ final long timeSinceLastParole = now - mLastAppIdleParoledTime;
if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
- setAppIdleParoled(true);
+ setParoled = true;
} else {
if (DEBUG) Slog.d(TAG, "Not long enough to go to parole");
- postNextParoleTimeout();
+ postNextParoleTimeout(now);
}
}
}
+ if (setParoled) {
+ setAppIdleParoled(true);
+ }
}
private void notifyBatteryStats(String packageName, int userId, boolean idle) {
@@ -593,17 +606,23 @@ public class UsageStatsService extends SystemService implements
void onDeviceIdleModeChanged() {
final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
- synchronized (mLock) {
- final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
+ boolean paroled = false;
+ synchronized (mAppIdleLock) {
+ final long timeSinceLastParole = System.currentTimeMillis() - mLastAppIdleParoledTime;
if (!deviceIdle
&& timeSinceLastParole >= mAppIdleParoleIntervalMillis) {
- if (DEBUG) Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
- setAppIdleParoled(true);
+ if (DEBUG) {
+ Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
+ }
+ paroled = true;
} else if (deviceIdle) {
if (DEBUG) Slog.i(TAG, "Device idle, back to prison");
- setAppIdleParoled(false);
+ paroled = false;
+ } else {
+ return;
}
}
+ setAppIdleParoled(paroled);
}
private static void deleteRecursively(File f) {
@@ -682,21 +701,24 @@ public class UsageStatsService extends SystemService implements
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
- // about apps that are on some kind of whitelist anyway.
- final boolean previouslyIdle = mAppIdleHistory.isIdleLocked(
- event.mPackage, userId, elapsedRealtime);
service.reportEvent(event);
- // Inform listeners if necessary
- if ((event.mEventType == Event.MOVE_TO_FOREGROUND
- || event.mEventType == Event.MOVE_TO_BACKGROUND
- || event.mEventType == Event.SYSTEM_INTERACTION
- || event.mEventType == Event.USER_INTERACTION)) {
- mAppIdleHistory.reportUsageLocked(event.mPackage, userId, elapsedRealtime);
- if (previouslyIdle) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
- /* idle = */ 0, event.mPackage));
- notifyBatteryStats(event.mPackage, userId, false);
+
+ synchronized (mAppIdleLock) {
+ // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
+ // about apps that are on some kind of whitelist anyway.
+ final boolean previouslyIdle = mAppIdleHistory.isIdle(
+ event.mPackage, userId, elapsedRealtime);
+ // Inform listeners if necessary
+ if ((event.mEventType == Event.MOVE_TO_FOREGROUND
+ || event.mEventType == Event.MOVE_TO_BACKGROUND
+ || event.mEventType == Event.SYSTEM_INTERACTION
+ || event.mEventType == Event.USER_INTERACTION)) {
+ mAppIdleHistory.reportUsage(event.mPackage, userId, elapsedRealtime);
+ if (previouslyIdle) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
+ /* idle = */ 0, event.mPackage));
+ notifyBatteryStats(event.mPackage, userId, false);
+ }
}
}
}
@@ -716,7 +738,7 @@ public class UsageStatsService extends SystemService implements
continue;
}
if (!packageName.equals(providerPkgName)) {
- forceIdleState(packageName, userId, false);
+ setAppIdleAsync(packageName, false, userId);
}
} catch (NameNotFoundException e) {
// Shouldn't happen
@@ -728,25 +750,28 @@ public class UsageStatsService extends SystemService implements
* Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle,
* then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind
* the threshold for idle.
+ *
+ * This method is always called from the handler thread, so not much synchronization is
+ * required.
*/
void forceIdleState(String packageName, int userId, boolean idle) {
final int appId = getAppId(packageName);
if (appId < 0) return;
- synchronized (mLock) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
- final boolean previouslyIdle = isAppIdleFiltered(packageName, appId,
- userId, elapsedRealtime);
- mAppIdleHistory.setIdleLocked(packageName, userId, idle, elapsedRealtime);
- final boolean stillIdle = isAppIdleFiltered(packageName, appId,
- userId, elapsedRealtime);
- // Inform listeners if necessary
- if (previouslyIdle != stillIdle) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
- /* idle = */ stillIdle ? 1 : 0, packageName));
- if (!stillIdle) {
- notifyBatteryStats(packageName, userId, idle);
- }
+ final boolean previouslyIdle = isAppIdleFiltered(packageName, appId,
+ userId, elapsedRealtime);
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.setIdle(packageName, userId, idle, elapsedRealtime);
+ }
+ final boolean stillIdle = isAppIdleFiltered(packageName, appId,
+ userId, elapsedRealtime);
+ // Inform listeners if necessary
+ if (previouslyIdle != stillIdle) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
+ /* idle = */ stillIdle ? 1 : 0, packageName));
+ if (!stillIdle) {
+ notifyBatteryStats(packageName, userId, idle);
}
}
}
@@ -767,7 +792,9 @@ public class UsageStatsService extends SystemService implements
synchronized (mLock) {
Slog.i(TAG, "Removing user " + userId + " and all data.");
mUserState.remove(userId);
- mAppIdleHistory.onUserRemoved(userId);
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.onUserRemoved(userId);
+ }
cleanUpRemovedUsersLocked();
}
}
@@ -822,13 +849,13 @@ public class UsageStatsService extends SystemService implements
}
private boolean isAppIdleUnfiltered(String packageName, int userId, long elapsedRealtime) {
- synchronized (mLock) {
- return mAppIdleHistory.isIdleLocked(packageName, userId, elapsedRealtime);
+ synchronized (mAppIdleLock) {
+ return mAppIdleHistory.isIdle(packageName, userId, elapsedRealtime);
}
}
void addListener(AppIdleStateChangeListener listener) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
if (!mPackageAccessListeners.contains(listener)) {
mPackageAccessListeners.add(listener);
}
@@ -836,7 +863,7 @@ public class UsageStatsService extends SystemService implements
}
void removeListener(AppIdleStateChangeListener listener) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
mPackageAccessListeners.remove(listener);
}
}
@@ -988,7 +1015,7 @@ public class UsageStatsService extends SystemService implements
return res;
}
- void setAppIdle(String packageName, boolean idle, int userId) {
+ void setAppIdleAsync(String packageName, boolean idle, int userId) {
if (packageName == null) return;
mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
@@ -1012,9 +1039,9 @@ public class UsageStatsService extends SystemService implements
}
private boolean isCarrierApp(String packageName) {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
if (!mHaveCarrierPrivilegedApps) {
- fetchCarrierPrivilegedAppsLocked();
+ fetchCarrierPrivilegedAppsLA();
}
if (mCarrierPrivilegedApps != null) {
return mCarrierPrivilegedApps.contains(packageName);
@@ -1027,13 +1054,14 @@ public class UsageStatsService extends SystemService implements
if (DEBUG) {
Slog.i(TAG, "Clearing carrier privileged apps list");
}
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
mHaveCarrierPrivilegedApps = false;
mCarrierPrivilegedApps = null; // Need to be refetched.
}
}
- private void fetchCarrierPrivilegedAppsLocked() {
+ @GuardedBy("mAppIdleLock")
+ private void fetchCarrierPrivilegedAppsLA() {
TelephonyManager telephonyManager =
getContext().getSystemService(TelephonyManager.class);
mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivileges();
@@ -1071,11 +1099,15 @@ public class UsageStatsService extends SystemService implements
for (int i = 0; i < userCount; i++) {
UserUsageStatsService service = mUserState.valueAt(i);
service.persistActiveStats();
- mAppIdleHistory.writeAppIdleTimesLocked(mUserState.keyAt(i));
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.writeAppIdleTimes(mUserState.keyAt(i));
+ }
}
// Persist elapsed and screen on time. If this fails for whatever reason, the apps will be
// considered not-idle, which is the safest outcome in such an event.
- mAppIdleHistory.writeAppIdleDurationsLocked();
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.writeAppIdleDurations();
+ }
mHandler.removeMessages(MSG_FLUSH_TO_DISK);
}
@@ -1100,20 +1132,26 @@ public class UsageStatsService extends SystemService implements
idpw.println();
if (args.length > 0) {
if ("history".equals(args[0])) {
- mAppIdleHistory.dumpHistory(idpw, mUserState.keyAt(i));
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.dumpHistory(idpw, mUserState.keyAt(i));
+ }
} else if ("flush".equals(args[0])) {
UsageStatsService.this.flushToDiskLocked();
pw.println("Flushed stats to disk");
}
}
}
- mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
+ synchronized (mAppIdleLock) {
+ mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
+ }
idpw.decreaseIndent();
}
pw.println();
- pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
- + "): " + mCarrierPrivilegedApps);
+ synchronized (mAppIdleLock) {
+ pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
+ + "): " + mCarrierPrivilegedApps);
+ }
pw.println();
pw.println("Settings:");
@@ -1252,7 +1290,7 @@ public class UsageStatsService extends SystemService implements
}
void updateSettings() {
- synchronized (mLock) {
+ synchronized (mAppIdleLock) {
// Look at global settings for this.
// TODO: Maybe apply different thresholds for different users.
try {
@@ -1384,7 +1422,7 @@ public class UsageStatsService extends SystemService implements
try {
userId = ActivityManager.getService().handleIncomingUser(
Binder.getCallingPid(), callingUid, userId, false, true,
- "setAppIdle", null);
+ "setAppInactive", null);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -1394,7 +1432,7 @@ public class UsageStatsService extends SystemService implements
try {
final int appId = getAppId(packageName);
if (appId < 0) return;
- UsageStatsService.this.setAppIdle(packageName, idle, userId);
+ UsageStatsService.this.setAppIdleAsync(packageName, idle, userId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1586,21 +1624,25 @@ public class UsageStatsService extends SystemService implements
@Override
public byte[] getBackupPayload(int user, String key) {
// Check to ensure that only user 0's data is b/r for now
- if (user == UserHandle.USER_SYSTEM) {
- final UserUsageStatsService userStats =
- getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
- return userStats.getBackupPayload(key);
- } else {
- return null;
+ synchronized (UsageStatsService.this.mLock) {
+ if (user == UserHandle.USER_SYSTEM) {
+ final UserUsageStatsService userStats =
+ getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
+ return userStats.getBackupPayload(key);
+ } else {
+ return null;
+ }
}
}
@Override
public void applyRestoredPayload(int user, String key, byte[] payload) {
- if (user == UserHandle.USER_SYSTEM) {
- final UserUsageStatsService userStats =
- getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
- userStats.applyRestoredPayload(key, payload);
+ synchronized (UsageStatsService.this.mLock) {
+ if (user == UserHandle.USER_SYSTEM) {
+ final UserUsageStatsService userStats =
+ getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
+ userStats.applyRestoredPayload(key, payload);
+ }
}
}
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index d9f352cbbf7b..8d335a51bb55 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -529,7 +529,6 @@ class UserUsageStatsService {
pw.decreaseIndent();
pw.println();
- pw.increaseIndent();
pw.println("ChooserCounts");
pw.increaseIndent();
for (UsageStats usageStats : pkgStats.values()) {
@@ -553,6 +552,7 @@ class UserUsageStatsService {
}
pw.println();
}
+ pw.decreaseIndent();
pw.println("configurations");
pw.increaseIndent();