diff options
author | Amith Yamasani <yamasani@google.com> | 2015-06-09 12:23:58 -0700 |
---|---|---|
committer | Amith Yamasani <yamasani@google.com> | 2015-06-12 09:05:22 -0700 |
commit | 6776849dc5ff851a225745393f082b702754e278 (patch) | |
tree | bb6d298a607751f57a662718cf3c6603f3057c1a /services/usage/java | |
parent | 4039f6570cff0013d3986b522d43e6eab7cc28a6 (diff) | |
download | frameworks_base-6776849dc5ff851a225745393f082b702754e278.zip frameworks_base-6776849dc5ff851a225745393f082b702754e278.tar.gz frameworks_base-6776849dc5ff851a225745393f082b702754e278.tar.bz2 |
Report app standby state to batterystats
Also reduce idle checks to the target user if possible.
Optimized calls to some internal methods
Bug: 21639147
Change-Id: If1faf26f862e5c4ca905f2603a4ba52a8d1af954
Diffstat (limited to 'services/usage/java')
-rw-r--r-- | services/usage/java/com/android/server/usage/AppIdleHistory.java | 49 | ||||
-rw-r--r-- | services/usage/java/com/android/server/usage/UsageStatsService.java | 103 |
2 files changed, 106 insertions, 46 deletions
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java index 9d3db16..e3c0868 100644 --- a/services/usage/java/com/android/server/usage/AppIdleHistory.java +++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java @@ -27,34 +27,27 @@ import com.android.internal.util.IndentingPrintWriter; */ public class AppIdleHistory { - private SparseArray<ArrayMap<String,byte[]>> idleHistory = new SparseArray<>(); + private SparseArray<ArrayMap<String,byte[]>> mIdleHistory = new SparseArray<>(); private long lastPeriod = 0; private static final long ONE_MINUTE = 60 * 1000; private static final int HISTORY_SIZE = 100; private static final int FLAG_LAST_STATE = 2; private static final int FLAG_PARTIAL_ACTIVE = 1; - private static final long PERIOD_DURATION = UsageStatsService.DEBUG ? ONE_MINUTE + private static final long PERIOD_DURATION = UsageStatsService.COMPRESS_TIME ? ONE_MINUTE : 60 * ONE_MINUTE; public void addEntry(String packageName, int userId, boolean idle, long timeNow) { - ArrayMap<String, byte[]> userHistory = idleHistory.get(userId); - if (userHistory == null) { - userHistory = new ArrayMap<>(); - idleHistory.put(userId, userHistory); - } - byte[] packageHistory = userHistory.get(packageName); - if (packageHistory == null) { - packageHistory = new byte[HISTORY_SIZE]; - userHistory.put(packageName, packageHistory); - } + ArrayMap<String, byte[]> userHistory = getUserHistory(userId); + byte[] packageHistory = getPackageHistory(userHistory, packageName); + long thisPeriod = timeNow / PERIOD_DURATION; // Has the period switched over? Slide all users' package histories if (lastPeriod != 0 && lastPeriod < thisPeriod && (thisPeriod - lastPeriod) < HISTORY_SIZE - 1) { int diff = (int) (thisPeriod - lastPeriod); - final int NUSERS = idleHistory.size(); + final int NUSERS = mIdleHistory.size(); for (int u = 0; u < NUSERS; u++) { - userHistory = idleHistory.valueAt(u); + userHistory = mIdleHistory.valueAt(u); for (byte[] history : userHistory.values()) { // Shift left System.arraycopy(history, diff, history, 0, HISTORY_SIZE - diff); @@ -74,12 +67,36 @@ public class AppIdleHistory { } } + private ArrayMap<String, byte[]> getUserHistory(int userId) { + ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId); + if (userHistory == null) { + userHistory = new ArrayMap<>(); + mIdleHistory.put(userId, userHistory); + } + return userHistory; + } + + private byte[] getPackageHistory(ArrayMap<String, byte[]> userHistory, String packageName) { + byte[] packageHistory = userHistory.get(packageName); + if (packageHistory == null) { + packageHistory = new byte[HISTORY_SIZE]; + userHistory.put(packageName, packageHistory); + } + return packageHistory; + } + public void removeUser(int userId) { - idleHistory.remove(userId); + mIdleHistory.remove(userId); + } + + public boolean isIdle(int userId, String packageName) { + ArrayMap<String, byte[]> userHistory = getUserHistory(userId); + byte[] packageHistory = getPackageHistory(userHistory, packageName); + return (packageHistory[HISTORY_SIZE - 1] & FLAG_LAST_STATE) == 0; } public void dump(IndentingPrintWriter idpw, int userId) { - ArrayMap<String, byte[]> userHistory = idleHistory.get(userId); + ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId); if (userHistory == null) return; final int P = userHistory.size(); for (int p = 0; p < P; p++) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 7a34757..8e1895e 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -43,6 +43,7 @@ import android.database.ContentObserver; import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.BatteryManager; +import android.os.BatteryStats; import android.os.Binder; import android.os.Environment; import android.os.Handler; @@ -65,6 +66,7 @@ import android.util.SparseArray; import android.view.Display; import com.android.internal.annotations.GuardedBy; +import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import com.android.server.DeviceIdleController; @@ -91,7 +93,7 @@ public class UsageStatsService extends SystemService implements static final String TAG = "UsageStatsService"; static final boolean DEBUG = false; - private static final boolean COMPRESS_TIME = false; + static final boolean COMPRESS_TIME = false; private static final long TEN_SECONDS = 10 * 1000; private static final long ONE_MINUTE = 60 * 1000; @@ -128,6 +130,7 @@ public class UsageStatsService extends SystemService implements IDeviceIdleController mDeviceIdleController; private DisplayManager mDisplayManager; private PowerManager mPowerManager; + private IBatteryStats mBatteryStats; private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); private File mUsageStatsDir; @@ -200,6 +203,8 @@ public class UsageStatsService extends SystemService implements mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class); mDeviceIdleController = IDeviceIdleController.Stub.asInterface( ServiceManager.getService(DeviceIdleController.SERVICE_NAME)); + mBatteryStats = IBatteryStats.Stub.asInterface( + ServiceManager.getService(BatteryStats.SERVICE_NAME)); mDisplayManager = (DisplayManager) getContext().getSystemService( Context.DISPLAY_SERVICE); mPowerManager = getContext().getSystemService(PowerManager.class); @@ -228,7 +233,7 @@ public class UsageStatsService extends SystemService implements } } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) { if (userId >=0) { - postCheckIdleStates(); + postCheckIdleStates(userId); } } } @@ -307,7 +312,7 @@ public class UsageStatsService extends SystemService implements mLastAppIdleParoledTime = checkAndGetTimeLocked(); postNextParoleTimeout(); } - postCheckIdleStates(); + postCheckIdleStates(UserHandle.USER_ALL); } } } @@ -332,22 +337,25 @@ public class UsageStatsService extends SystemService implements mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, DEFAULT_PAROLE_DURATION); } - void postCheckIdleStates() { - mHandler.removeMessages(MSG_CHECK_IDLE_STATES); - mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES); + void postCheckIdleStates(int userId) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0)); } - /** Check all running users' apps to see if they enter an idle state. */ - void checkIdleStates() { - final int[] runningUsers; + /** Check all running users' or specified user's apps to see if they enter an idle state. */ + void checkIdleStates(int checkUserId) { + final int[] userIds; try { - runningUsers = ActivityManagerNative.getDefault().getRunningUserIds(); + if (checkUserId == UserHandle.USER_ALL) { + userIds = ActivityManagerNative.getDefault().getRunningUserIds(); + } else { + userIds = new int[] { checkUserId }; + } } catch (RemoteException re) { return; } - for (int i = 0; i < runningUsers.length; i++) { - final int userId = runningUsers[i]; + for (int i = 0; i < userIds.length; i++) { + final int userId = userIds[i]; List<PackageInfo> packages = getContext().getPackageManager().getInstalledPackages( PackageManager.GET_DISABLED_COMPONENTS @@ -355,17 +363,22 @@ public class UsageStatsService extends SystemService implements userId); synchronized (mLock) { final long timeNow = checkAndGetTimeLocked(); + final long screenOnTime = getScreenOnTimeLocked(timeNow); + UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, + timeNow); final int packageCount = packages.size(); for (int p = 0; p < packageCount; p++) { final String packageName = packages.get(p).packageName; - final boolean isIdle = isAppIdleFiltered(packageName, userId, timeNow); + final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow, + screenOnTime); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, isIdle ? 1 : 0, packageName)); mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow); } } } - mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis); + 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 */ @@ -386,6 +399,20 @@ public class UsageStatsService extends SystemService implements } } + private void notifyBatteryStats(String packageName, int userId, boolean idle) { + try { + int uid = AppGlobals.getPackageManager().getPackageUid(packageName, userId); + if (idle) { + mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE, + packageName, uid); + } else { + mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE, + packageName, uid); + } + } catch (RemoteException re) { + } + } + void updateDisplayLocked() { boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState() == Display.STATE_ON; @@ -545,7 +572,7 @@ public class UsageStatsService extends SystemService implements final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage); final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow); - service.reportEvent(event, getScreenOnTimeLocked(timeNow)); + service.reportEvent(event, screenOnTime); // Inform listeners if necessary if ((event.mEventType == Event.MOVE_TO_FOREGROUND || event.mEventType == Event.MOVE_TO_BACKGROUND @@ -555,6 +582,7 @@ public class UsageStatsService extends SystemService implements // 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); mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow); } } @@ -586,6 +614,9 @@ public class UsageStatsService extends SystemService implements // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, /* idle = */ idle ? 1 : 0, packageName)); + if (!idle) { + notifyBatteryStats(packageName, userId, idle); + } mAppIdleHistory.addEntry(packageName, userId, idle, timeNow); } } @@ -660,19 +691,20 @@ public class UsageStatsService extends SystemService implements } } - private boolean isAppIdleUnfiltered(String packageName, int userId, long timeNow) { + private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService, + long timeNow, long screenOnTime) { synchronized (mLock) { - final long screenOnTime = getScreenOnTimeLocked(timeNow); - final UserUsageStatsService service = - getUserDataAndInitializeIfNeededLocked(userId, timeNow); - long beginIdleTime = service.getBeginIdleTime(packageName); - long lastUsedTime = service.getSystemLastUsedTime(packageName); - return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow); + long beginIdleTime = userService.getBeginIdleTime(packageName); + long lastUsedTime = userService.getSystemLastUsedTime(packageName); + return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, + timeNow); } } /** - * @param timestamp when the app was last used in device usage timebase + * @param beginIdleTime when the app was last used in device usage timebase + * @param lastUsedTime wallclock time of when the app was last used + * @param screenOnTime screen-on timebase time * @param currentTime current time in device usage timebase * @return whether it's been used far enough in the past to be considered inactive */ @@ -696,18 +728,29 @@ public class UsageStatsService extends SystemService implements } } + boolean isAppIdleFiltered(String packageName, int userId, long timeNow) { + final UserUsageStatsService userService; + final long screenOnTime; + synchronized (mLock) { + if (timeNow == -1) { + timeNow = checkAndGetTimeLocked(); + } + userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow); + screenOnTime = getScreenOnTimeLocked(timeNow); + } + return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime); + } + /** * 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, long timeNow) { + private boolean isAppIdleFiltered(String packageName, int userId, + UserUsageStatsService userService, long timeNow, long screenOnTime) { if (packageName == null) return false; synchronized (mLock) { - if (timeNow == -1) { - timeNow = checkAndGetTimeLocked(); - } // Temporary exemption, probably due to device charging or occasional allowance to // be allowed to sync, etc. if (mAppIdleParoled) { @@ -735,7 +778,7 @@ public class UsageStatsService extends SystemService implements return false; } - return isAppIdleUnfiltered(packageName, userId, timeNow); + return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime); } void setAppIdle(String packageName, boolean idle, int userId) { @@ -844,7 +887,7 @@ public class UsageStatsService extends SystemService implements break; case MSG_CHECK_IDLE_STATES: - checkIdleStates(); + checkIdleStates(msg.arg1); break; case MSG_CHECK_PAROLE_TIMEOUT: @@ -884,7 +927,7 @@ public class UsageStatsService extends SystemService implements UserHandle.USER_OWNER); mCheckIdleIntervalMillis = Math.min(DEFAULT_CHECK_IDLE_INTERVAL, mAppIdleDurationMillis / 4); - postCheckIdleStates(); + postCheckIdleStates(UserHandle.USER_ALL); } } |