Loading core/java/android/os/Handler.java +20 −0 Original line number Diff line number Diff line Loading @@ -695,6 +695,14 @@ public class Handler { return mQueue.hasMessages(this, what, null); } /** * Return whether there are any messages or callbacks currently scheduled on this handler. * @hide */ public final boolean hasMessagesOrCallbacks() { return mQueue.hasMessages(this); } /** * Check if there are any pending posts of messages with code 'what' and * whose obj is 'object' in the message queue. Loading Loading @@ -728,6 +736,18 @@ public class Handler { } } /** * @hide */ public final void dumpMine(Printer pw, String prefix) { pw.println(prefix + this + " @ " + SystemClock.uptimeMillis()); if (mLooper == null) { pw.println(prefix + "looper uninitialized"); } else { mLooper.dump(pw, prefix + " ", this); } } @Override public String toString() { return "Handler (" + getClass().getName() + ") {" Loading core/java/android/os/Looper.java +14 −1 Original line number Diff line number Diff line Loading @@ -310,7 +310,20 @@ public final class Looper { */ public void dump(@NonNull Printer pw, @NonNull String prefix) { pw.println(prefix + toString()); mQueue.dump(pw, prefix + " "); mQueue.dump(pw, prefix + " ", null); } /** * Dumps the state of the looper for debugging purposes. * * @param pw A printer to receive the contents of the dump. * @param prefix A prefix to prepend to each line which is printed. * @param handler Only dump messages for this Handler. * @hide */ public void dump(@NonNull Printer pw, @NonNull String prefix, Handler handler) { pw.println(prefix + toString()); mQueue.dump(pw, prefix + " ", handler); } /** @hide */ Loading core/java/android/os/MessageQueue.java +21 −2 Original line number Diff line number Diff line Loading @@ -620,6 +620,23 @@ public final class MessageQueue { } } boolean hasMessages(Handler h) { if (h == null) { return false; } synchronized (this) { Message p = mMessages; while (p != null) { if (p.target == h) { return true; } p = p.next; } return false; } } void removeMessages(Handler h, int what, Object object) { if (h == null) { return; Loading Loading @@ -759,12 +776,14 @@ public final class MessageQueue { } } void dump(Printer pw, String prefix) { void dump(Printer pw, String prefix, Handler h) { synchronized (this) { long now = SystemClock.uptimeMillis(); int n = 0; for (Message msg = mMessages; msg != null; msg = msg.next) { if (h == null || h == msg.target) { pw.println(prefix + "Message " + n + ": " + msg.toString(now)); } n++; } pw.println(prefix + "(Total messages: " + n + ", polling=" + isPollingLocked() Loading core/java/android/provider/Settings.java +4 −1 Original line number Diff line number Diff line Loading @@ -9130,7 +9130,10 @@ public final class Settings { * <pre> * max_cached_processes (int) * background_settle_time (long) * foreground_service_ui_min_time (long) * fgservice_min_shown_time (long) * fgservice_min_report_time (long) * fgservice_screen_on_before_time (long) * fgservice_screen_on_after_time (long) * content_provider_retain_time (long) * gc_timeout (long) * gc_min_interval (long) Loading services/core/java/com/android/server/am/ActiveServices.java +108 −36 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.util.EventLog; import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; Loading Loading @@ -175,6 +176,9 @@ public final class ActiveServices { long mStartVisibleTime; long mEndTime; int mNumActive; // Temp output of foregroundAppShownEnoughLocked long mHideTime; } /** Loading Loading @@ -736,50 +740,90 @@ public final class ActiveServices { } } boolean foregroundAppShownEnoughLocked(ActiveForegroundApp aa, long nowElapsed) { if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Shown enough: pkg=" + aa.mPackageName + ", uid=" + aa.mUid); boolean canRemove = false; aa.mHideTime = Long.MAX_VALUE; if (aa.mShownWhileTop) { // If the app was ever at the top of the screen while the foreground // service was running, then we can always just immediately remove it. canRemove = true; if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "YES - shown while on top"); } else if (mScreenOn || aa.mShownWhileScreenOn) { final long minTime = aa.mStartVisibleTime + (aa.mStartTime != aa.mStartVisibleTime ? mAm.mConstants.FGSERVICE_SCREEN_ON_AFTER_TIME : mAm.mConstants.FGSERVICE_MIN_SHOWN_TIME); if (nowElapsed >= minTime) { // If shown while the screen is on, and it has been shown for // at least the minimum show time, then we can now remove it. if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "YES - shown long enough with screen on"); canRemove = true; } else { // This is when we will be okay to stop telling the user. long reportTime = nowElapsed + mAm.mConstants.FGSERVICE_MIN_REPORT_TIME; aa.mHideTime = reportTime > minTime ? reportTime : minTime; if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "NO -- wait " + (aa.mHideTime-nowElapsed) + " with screen on"); } } else { final long minTime = aa.mEndTime + mAm.mConstants.FGSERVICE_SCREEN_ON_BEFORE_TIME; if (nowElapsed >= minTime) { // If the foreground service has only run while the screen is // off, but it has been gone now for long enough that we won't // care to tell the user about it when the screen comes back on, // then we can remove it now. if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "YES - gone long enough with screen off"); canRemove = true; } else { // This is when we won't care about this old fg service. aa.mHideTime = minTime; if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "NO -- wait " + (aa.mHideTime-nowElapsed) + " with screen off"); } } return canRemove; } void updateForegroundApps(ServiceMap smap) { // This is called from the handler without the lock held. ArrayList<ActiveForegroundApp> active = null; synchronized (mAm) { final long now = SystemClock.elapsedRealtime(); final long nowPlusMin = now + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME; long nextUpdateTime = Long.MAX_VALUE; if (smap != null) { if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Updating foreground apps for user " + smap.mUserId); for (int i = smap.mActiveForegroundApps.size()-1; i >= 0; i--) { ActiveForegroundApp aa = smap.mActiveForegroundApps.valueAt(i); if (aa.mEndTime != 0 && (mScreenOn || aa.mShownWhileScreenOn)) { if (!aa.mShownWhileTop && aa.mEndTime < (aa.mStartVisibleTime + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) { // Check to see if this should still be displayed... we continue // until it has been shown for at least the timeout duration. if (nowPlusMin >= aa.mStartVisibleTime) { // All over! smap.mActiveForegroundApps.removeAt(i); smap.mActiveForegroundAppsChanged = true; continue; } else { long hideTime = aa.mStartVisibleTime + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME; if (hideTime < nextUpdateTime) { nextUpdateTime = hideTime; } } } else { if (aa.mEndTime != 0) { boolean canRemove = foregroundAppShownEnoughLocked(aa, now); if (canRemove) { // This was up for longer than the timeout, so just remove immediately. smap.mActiveForegroundApps.removeAt(i); smap.mActiveForegroundAppsChanged = true; continue; } if (aa.mHideTime < nextUpdateTime) { nextUpdateTime = aa.mHideTime; } } if (!aa.mAppOnTop) { if (active == null) { active = new ArrayList<>(); } if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Adding active: pkg=" + aa.mPackageName + ", uid=" + aa.mUid); active.add(aa); } } smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS); if (nextUpdateTime < Long.MAX_VALUE) { Message msg = smap.obtainMessage(); if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Next update time in: " + (nextUpdateTime-now)); Message msg = smap.obtainMessage(ServiceMap.MSG_UPDATE_FOREGROUND_APPS); smap.sendMessageAtTime(msg, nextUpdateTime + SystemClock.uptimeMillis() - SystemClock.elapsedRealtime()); } Loading Loading @@ -882,15 +926,14 @@ public final class ActiveServices { active.mNumActive--; if (active.mNumActive <= 0) { active.mEndTime = SystemClock.elapsedRealtime(); if (active.mShownWhileTop || active.mEndTime >= (active.mStartVisibleTime + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) { if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Ended running of service"); if (foregroundAppShownEnoughLocked(active, active.mEndTime)) { // Have been active for long enough that we will remove it immediately. smap.mActiveForegroundApps.remove(r.packageName); smap.mActiveForegroundAppsChanged = true; requestUpdateActiveForegroundAppsLocked(smap, 0); } else { requestUpdateActiveForegroundAppsLocked(smap, active.mStartVisibleTime + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME); } else if (active.mHideTime < Long.MAX_VALUE){ requestUpdateActiveForegroundAppsLocked(smap, active.mHideTime); } } } Loading @@ -904,26 +947,44 @@ public final class ActiveServices { // services that were started while the screen was off. if (screenOn) { final long nowElapsed = SystemClock.elapsedRealtime(); if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Screen turned on"); for (int i = mServiceMap.size()-1; i >= 0; i--) { ServiceMap smap = mServiceMap.valueAt(i); long nextUpdateTime = Long.MAX_VALUE; boolean changed = false; for (int j = smap.mActiveForegroundApps.size()-1; j >= 0; j--) { ActiveForegroundApp active = smap.mActiveForegroundApps.valueAt(j); if (active.mEndTime == 0) { if (!active.mShownWhileScreenOn) { changed = true; active.mShownWhileScreenOn = mScreenOn; active.mShownWhileScreenOn = true; active.mStartVisibleTime = nowElapsed; if (active.mEndTime != 0) { active.mEndTime = nowElapsed; } } else { if (!active.mShownWhileScreenOn && active.mStartVisibleTime == active.mStartTime) { // If this was never shown while the screen was on, then we will // count the time it started being visible as now, to tell the user // about it now that they have a screen to look at. active.mEndTime = active.mStartVisibleTime = nowElapsed; } if (foregroundAppShownEnoughLocked(active, nowElapsed)) { // Have been active for long enough that we will remove it // immediately. smap.mActiveForegroundApps.remove(active.mPackageName); smap.mActiveForegroundAppsChanged = true; changed = true; } else { if (active.mHideTime < nextUpdateTime) { nextUpdateTime = active.mHideTime; } } } } if (changed) { requestUpdateActiveForegroundAppsLocked(smap, nowElapsed + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME); } else if (smap.mActiveForegroundApps.size() > 0) { // Just being paranoid. // Need to immediately update. requestUpdateActiveForegroundAppsLocked(smap, 0); } else if (nextUpdateTime < Long.MAX_VALUE) { requestUpdateActiveForegroundAppsLocked(smap, nextUpdateTime); } } } Loading Loading @@ -2318,7 +2379,7 @@ public final class ActiveServices { return true; } // Is someone still bound to us keepign us running? // Is someone still bound to us keeping us running? if (!knowConn) { hasConn = r.hasAutoCreateConnections(); } Loading Loading @@ -3741,6 +3802,17 @@ public final class ActiveServices { pw.println(); } } if (smap.hasMessagesOrCallbacks()) { if (needSep) { pw.println(); } printedAnything = true; needSep = true; pw.print(" Handler - user "); pw.print(user); pw.println(":"); smap.dumpMine(new PrintWriterPrinter(pw), " "); } } } Loading Loading
core/java/android/os/Handler.java +20 −0 Original line number Diff line number Diff line Loading @@ -695,6 +695,14 @@ public class Handler { return mQueue.hasMessages(this, what, null); } /** * Return whether there are any messages or callbacks currently scheduled on this handler. * @hide */ public final boolean hasMessagesOrCallbacks() { return mQueue.hasMessages(this); } /** * Check if there are any pending posts of messages with code 'what' and * whose obj is 'object' in the message queue. Loading Loading @@ -728,6 +736,18 @@ public class Handler { } } /** * @hide */ public final void dumpMine(Printer pw, String prefix) { pw.println(prefix + this + " @ " + SystemClock.uptimeMillis()); if (mLooper == null) { pw.println(prefix + "looper uninitialized"); } else { mLooper.dump(pw, prefix + " ", this); } } @Override public String toString() { return "Handler (" + getClass().getName() + ") {" Loading
core/java/android/os/Looper.java +14 −1 Original line number Diff line number Diff line Loading @@ -310,7 +310,20 @@ public final class Looper { */ public void dump(@NonNull Printer pw, @NonNull String prefix) { pw.println(prefix + toString()); mQueue.dump(pw, prefix + " "); mQueue.dump(pw, prefix + " ", null); } /** * Dumps the state of the looper for debugging purposes. * * @param pw A printer to receive the contents of the dump. * @param prefix A prefix to prepend to each line which is printed. * @param handler Only dump messages for this Handler. * @hide */ public void dump(@NonNull Printer pw, @NonNull String prefix, Handler handler) { pw.println(prefix + toString()); mQueue.dump(pw, prefix + " ", handler); } /** @hide */ Loading
core/java/android/os/MessageQueue.java +21 −2 Original line number Diff line number Diff line Loading @@ -620,6 +620,23 @@ public final class MessageQueue { } } boolean hasMessages(Handler h) { if (h == null) { return false; } synchronized (this) { Message p = mMessages; while (p != null) { if (p.target == h) { return true; } p = p.next; } return false; } } void removeMessages(Handler h, int what, Object object) { if (h == null) { return; Loading Loading @@ -759,12 +776,14 @@ public final class MessageQueue { } } void dump(Printer pw, String prefix) { void dump(Printer pw, String prefix, Handler h) { synchronized (this) { long now = SystemClock.uptimeMillis(); int n = 0; for (Message msg = mMessages; msg != null; msg = msg.next) { if (h == null || h == msg.target) { pw.println(prefix + "Message " + n + ": " + msg.toString(now)); } n++; } pw.println(prefix + "(Total messages: " + n + ", polling=" + isPollingLocked() Loading
core/java/android/provider/Settings.java +4 −1 Original line number Diff line number Diff line Loading @@ -9130,7 +9130,10 @@ public final class Settings { * <pre> * max_cached_processes (int) * background_settle_time (long) * foreground_service_ui_min_time (long) * fgservice_min_shown_time (long) * fgservice_min_report_time (long) * fgservice_screen_on_before_time (long) * fgservice_screen_on_after_time (long) * content_provider_retain_time (long) * gc_timeout (long) * gc_min_interval (long) Loading
services/core/java/com/android/server/am/ActiveServices.java +108 −36 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.util.EventLog; import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; Loading Loading @@ -175,6 +176,9 @@ public final class ActiveServices { long mStartVisibleTime; long mEndTime; int mNumActive; // Temp output of foregroundAppShownEnoughLocked long mHideTime; } /** Loading Loading @@ -736,50 +740,90 @@ public final class ActiveServices { } } boolean foregroundAppShownEnoughLocked(ActiveForegroundApp aa, long nowElapsed) { if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Shown enough: pkg=" + aa.mPackageName + ", uid=" + aa.mUid); boolean canRemove = false; aa.mHideTime = Long.MAX_VALUE; if (aa.mShownWhileTop) { // If the app was ever at the top of the screen while the foreground // service was running, then we can always just immediately remove it. canRemove = true; if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "YES - shown while on top"); } else if (mScreenOn || aa.mShownWhileScreenOn) { final long minTime = aa.mStartVisibleTime + (aa.mStartTime != aa.mStartVisibleTime ? mAm.mConstants.FGSERVICE_SCREEN_ON_AFTER_TIME : mAm.mConstants.FGSERVICE_MIN_SHOWN_TIME); if (nowElapsed >= minTime) { // If shown while the screen is on, and it has been shown for // at least the minimum show time, then we can now remove it. if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "YES - shown long enough with screen on"); canRemove = true; } else { // This is when we will be okay to stop telling the user. long reportTime = nowElapsed + mAm.mConstants.FGSERVICE_MIN_REPORT_TIME; aa.mHideTime = reportTime > minTime ? reportTime : minTime; if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "NO -- wait " + (aa.mHideTime-nowElapsed) + " with screen on"); } } else { final long minTime = aa.mEndTime + mAm.mConstants.FGSERVICE_SCREEN_ON_BEFORE_TIME; if (nowElapsed >= minTime) { // If the foreground service has only run while the screen is // off, but it has been gone now for long enough that we won't // care to tell the user about it when the screen comes back on, // then we can remove it now. if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "YES - gone long enough with screen off"); canRemove = true; } else { // This is when we won't care about this old fg service. aa.mHideTime = minTime; if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "NO -- wait " + (aa.mHideTime-nowElapsed) + " with screen off"); } } return canRemove; } void updateForegroundApps(ServiceMap smap) { // This is called from the handler without the lock held. ArrayList<ActiveForegroundApp> active = null; synchronized (mAm) { final long now = SystemClock.elapsedRealtime(); final long nowPlusMin = now + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME; long nextUpdateTime = Long.MAX_VALUE; if (smap != null) { if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Updating foreground apps for user " + smap.mUserId); for (int i = smap.mActiveForegroundApps.size()-1; i >= 0; i--) { ActiveForegroundApp aa = smap.mActiveForegroundApps.valueAt(i); if (aa.mEndTime != 0 && (mScreenOn || aa.mShownWhileScreenOn)) { if (!aa.mShownWhileTop && aa.mEndTime < (aa.mStartVisibleTime + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) { // Check to see if this should still be displayed... we continue // until it has been shown for at least the timeout duration. if (nowPlusMin >= aa.mStartVisibleTime) { // All over! smap.mActiveForegroundApps.removeAt(i); smap.mActiveForegroundAppsChanged = true; continue; } else { long hideTime = aa.mStartVisibleTime + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME; if (hideTime < nextUpdateTime) { nextUpdateTime = hideTime; } } } else { if (aa.mEndTime != 0) { boolean canRemove = foregroundAppShownEnoughLocked(aa, now); if (canRemove) { // This was up for longer than the timeout, so just remove immediately. smap.mActiveForegroundApps.removeAt(i); smap.mActiveForegroundAppsChanged = true; continue; } if (aa.mHideTime < nextUpdateTime) { nextUpdateTime = aa.mHideTime; } } if (!aa.mAppOnTop) { if (active == null) { active = new ArrayList<>(); } if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Adding active: pkg=" + aa.mPackageName + ", uid=" + aa.mUid); active.add(aa); } } smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS); if (nextUpdateTime < Long.MAX_VALUE) { Message msg = smap.obtainMessage(); if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Next update time in: " + (nextUpdateTime-now)); Message msg = smap.obtainMessage(ServiceMap.MSG_UPDATE_FOREGROUND_APPS); smap.sendMessageAtTime(msg, nextUpdateTime + SystemClock.uptimeMillis() - SystemClock.elapsedRealtime()); } Loading Loading @@ -882,15 +926,14 @@ public final class ActiveServices { active.mNumActive--; if (active.mNumActive <= 0) { active.mEndTime = SystemClock.elapsedRealtime(); if (active.mShownWhileTop || active.mEndTime >= (active.mStartVisibleTime + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) { if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Ended running of service"); if (foregroundAppShownEnoughLocked(active, active.mEndTime)) { // Have been active for long enough that we will remove it immediately. smap.mActiveForegroundApps.remove(r.packageName); smap.mActiveForegroundAppsChanged = true; requestUpdateActiveForegroundAppsLocked(smap, 0); } else { requestUpdateActiveForegroundAppsLocked(smap, active.mStartVisibleTime + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME); } else if (active.mHideTime < Long.MAX_VALUE){ requestUpdateActiveForegroundAppsLocked(smap, active.mHideTime); } } } Loading @@ -904,26 +947,44 @@ public final class ActiveServices { // services that were started while the screen was off. if (screenOn) { final long nowElapsed = SystemClock.elapsedRealtime(); if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Screen turned on"); for (int i = mServiceMap.size()-1; i >= 0; i--) { ServiceMap smap = mServiceMap.valueAt(i); long nextUpdateTime = Long.MAX_VALUE; boolean changed = false; for (int j = smap.mActiveForegroundApps.size()-1; j >= 0; j--) { ActiveForegroundApp active = smap.mActiveForegroundApps.valueAt(j); if (active.mEndTime == 0) { if (!active.mShownWhileScreenOn) { changed = true; active.mShownWhileScreenOn = mScreenOn; active.mShownWhileScreenOn = true; active.mStartVisibleTime = nowElapsed; if (active.mEndTime != 0) { active.mEndTime = nowElapsed; } } else { if (!active.mShownWhileScreenOn && active.mStartVisibleTime == active.mStartTime) { // If this was never shown while the screen was on, then we will // count the time it started being visible as now, to tell the user // about it now that they have a screen to look at. active.mEndTime = active.mStartVisibleTime = nowElapsed; } if (foregroundAppShownEnoughLocked(active, nowElapsed)) { // Have been active for long enough that we will remove it // immediately. smap.mActiveForegroundApps.remove(active.mPackageName); smap.mActiveForegroundAppsChanged = true; changed = true; } else { if (active.mHideTime < nextUpdateTime) { nextUpdateTime = active.mHideTime; } } } } if (changed) { requestUpdateActiveForegroundAppsLocked(smap, nowElapsed + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME); } else if (smap.mActiveForegroundApps.size() > 0) { // Just being paranoid. // Need to immediately update. requestUpdateActiveForegroundAppsLocked(smap, 0); } else if (nextUpdateTime < Long.MAX_VALUE) { requestUpdateActiveForegroundAppsLocked(smap, nextUpdateTime); } } } Loading Loading @@ -2318,7 +2379,7 @@ public final class ActiveServices { return true; } // Is someone still bound to us keepign us running? // Is someone still bound to us keeping us running? if (!knowConn) { hasConn = r.hasAutoCreateConnections(); } Loading Loading @@ -3741,6 +3802,17 @@ public final class ActiveServices { pw.println(); } } if (smap.hasMessagesOrCallbacks()) { if (needSep) { pw.println(); } printedAnything = true; needSep = true; pw.print(" Handler - user "); pw.print(user); pw.println(":"); smap.dumpMine(new PrintWriterPrinter(pw), " "); } } } Loading