diff options
| -rw-r--r-- | services/core/java/com/android/server/am/ActiveServices.java | 56 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ServiceRecord.java | 45 |
2 files changed, 60 insertions, 41 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index eec22c92b5dc..3486cd5f4d46 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -3724,6 +3724,33 @@ public final class ActiveServices { return fgsType; } + /** + * @return the constant time limit defined for the given foreground service type. + */ + private long getTimeLimitForFgsType(int foregroundServiceType) { + return switch (foregroundServiceType) { + case ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING -> + mAm.mConstants.mMediaProcessingFgsTimeoutDuration; + case ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC -> + mAm.mConstants.mDataSyncFgsTimeoutDuration; + // Add logic for time limits introduced in the future for other fgs types above. + default -> Long.MAX_VALUE; + }; + } + + /** + * @return the next stop time for the given type, based on how long it has already ran for. + * The total runtime is automatically reset 24hrs after the first fgs start of this type + * or if the app has recently been in the TOP state when the app calls startForeground(). + */ + private long getNextFgsStopTime(int fgsType, TimeLimitedFgsInfo fgsInfo) { + final long timeLimit = getTimeLimitForFgsType(fgsType); + if (timeLimit == Long.MAX_VALUE) { + return Long.MAX_VALUE; + } + return fgsInfo.getLastFgsStartTime() + Math.max(0, timeLimit - fgsInfo.getTotalRuntime()); + } + private void maybeUpdateFgsTrackingLocked(ServiceRecord sr, int previousFgsType) { final int previouslyTimeLimitedType = getTimeLimitedFgsType(previousFgsType); if (previouslyTimeLimitedType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE @@ -3755,7 +3782,7 @@ public final class ActiveServices { } traceInstant("FGS start: ", sr); - final long nowRealtime = SystemClock.elapsedRealtime(); + final long nowUptime = SystemClock.uptimeMillis(); // Fetch/create/update the fgs info for the time-limited type. SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid); @@ -3766,10 +3793,10 @@ public final class ActiveServices { final int timeLimitedFgsType = getTimeLimitedFgsType(sr.foregroundServiceType); TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(timeLimitedFgsType); if (fgsTypeInfo == null) { - fgsTypeInfo = sr.createTimeLimitedFgsInfo(nowRealtime); + fgsTypeInfo = sr.createTimeLimitedFgsInfo(nowUptime); fgsInfo.put(timeLimitedFgsType, fgsTypeInfo); } - fgsTypeInfo.setLastFgsStartTime(nowRealtime); + fgsTypeInfo.setLastFgsStartTime(nowUptime); // We'll cancel the previous ANR timer and start a fresh one below. mFGSAnrTimer.cancel(sr); @@ -3777,7 +3804,7 @@ public final class ActiveServices { final Message msg = mAm.mHandler.obtainMessage( ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr); - final long timeoutCallbackTime = sr.getNextFgsStopTime(timeLimitedFgsType, fgsTypeInfo); + final long timeoutCallbackTime = getNextFgsStopTime(timeLimitedFgsType, fgsTypeInfo); if (timeoutCallbackTime == Long.MAX_VALUE) { // This should never happen since we only get to this point if the service record's // foregroundServiceType attribute contains a type that can be timed-out. @@ -3833,6 +3860,20 @@ public final class ActiveServices { mFGSAnrTimer.discard(sr); return; } + + final long lastTopTime = sr.app.mState.getLastTopTime(); + final long constantTimeLimit = getTimeLimitForFgsType(fgsType); + final long nowUptime = SystemClock.uptimeMillis(); + if (constantTimeLimit > (nowUptime - lastTopTime)) { + // The app was in the TOP state after the FGS was started so its time allowance + // should be counted from that time since this is considered a user interaction + mFGSAnrTimer.discard(sr); + final Message msg = mAm.mHandler.obtainMessage( + ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr); + mAm.mHandler.sendMessageAtTime(msg, lastTopTime + constantTimeLimit); + return; + } + Slog.e(TAG_SERVICE, "FGS (" + ServiceInfo.foregroundServiceTypeToLabel(fgsType) + ") timed out: " + sr); mFGSAnrTimer.accept(sr); @@ -3843,14 +3884,13 @@ public final class ActiveServices { final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(fgsType); if (fgsTypeInfo != null) { // Update total runtime for the time-limited fgs type and mark it as timed out. - final long nowRealtime = SystemClock.elapsedRealtime(); fgsTypeInfo.updateTotalRuntime(); - fgsTypeInfo.setTimeLimitExceededAt(nowRealtime); + fgsTypeInfo.setTimeLimitExceededAt(nowUptime); logFGSStateChangeLocked(sr, FOREGROUND_SERVICE_STATE_CHANGED__STATE__TIMED_OUT, - nowRealtime > fgsTypeInfo.getLastFgsStartTime() - ? (int) (nowRealtime - fgsTypeInfo.getLastFgsStartTime()) : 0, + nowUptime > fgsTypeInfo.getLastFgsStartTime() + ? (int) (nowUptime - fgsTypeInfo.getLastFgsStartTime()) : 0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN, FOREGROUND_SERVICE_STATE_CHANGED__FGS_START_API__FGSSTARTAPI_NA, diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 065f3bd6b1e6..68f7cc1cee3c 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -30,9 +30,9 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; -import android.annotation.ElapsedRealtimeLong; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UptimeMillisLong; import android.app.BackgroundStartPrivileges; import android.app.IApplicationThread; import android.app.Notification; @@ -677,29 +677,29 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN * Data container class to help track certain fgs info for time-restricted types. */ static class TimeLimitedFgsInfo { - @ElapsedRealtimeLong + @UptimeMillisLong private long mFirstFgsStartTime; - @ElapsedRealtimeLong + @UptimeMillisLong private long mLastFgsStartTime; - @ElapsedRealtimeLong + @UptimeMillisLong private long mTimeLimitExceededAt = Long.MIN_VALUE; private long mTotalRuntime = 0; - TimeLimitedFgsInfo(@ElapsedRealtimeLong long startTime) { + TimeLimitedFgsInfo(@UptimeMillisLong long startTime) { mFirstFgsStartTime = startTime; mLastFgsStartTime = startTime; } - @ElapsedRealtimeLong + @UptimeMillisLong public long getFirstFgsStartTime() { return mFirstFgsStartTime; } - public void setLastFgsStartTime(@ElapsedRealtimeLong long startTime) { + public void setLastFgsStartTime(@UptimeMillisLong long startTime) { mLastFgsStartTime = startTime; } - @ElapsedRealtimeLong + @UptimeMillisLong public long getLastFgsStartTime() { return mLastFgsStartTime; } @@ -712,11 +712,11 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN return mTotalRuntime; } - public void setTimeLimitExceededAt(@ElapsedRealtimeLong long timeLimitExceededAt) { + public void setTimeLimitExceededAt(@UptimeMillisLong long timeLimitExceededAt) { mTimeLimitExceededAt = timeLimitExceededAt; } - @ElapsedRealtimeLong + @UptimeMillisLong public long getTimeLimitExceededAt() { return mTimeLimitExceededAt; } @@ -1858,8 +1858,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN /** * Called when a time-limited FGS starts. */ - public TimeLimitedFgsInfo createTimeLimitedFgsInfo(@ElapsedRealtimeLong long nowRealtime) { - return new TimeLimitedFgsInfo(nowRealtime); + public TimeLimitedFgsInfo createTimeLimitedFgsInfo(@UptimeMillisLong long nowUptime) { + return new TimeLimitedFgsInfo(nowUptime); } /** @@ -1872,27 +1872,6 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN != ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE; } - /** - * @return the next stop time for the given type, based on how long it has already ran for. - * The total runtime is automatically reset 24hrs after the first fgs start of this type - * or if the app has recently been in the TOP state when the app calls startForeground(). - */ - long getNextFgsStopTime(int fgsType, TimeLimitedFgsInfo fgsInfo) { - final long timeLimit; - switch (ams.mServices.getTimeLimitedFgsType(fgsType)) { - case ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING: - timeLimit = ams.mConstants.mMediaProcessingFgsTimeoutDuration; - break; - case ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC: - timeLimit = ams.mConstants.mDataSyncFgsTimeoutDuration; - break; - // Add logic for time limits introduced in the future for other fgs types above. - default: - return Long.MAX_VALUE; - } - return fgsInfo.mLastFgsStartTime + Math.max(0, timeLimit - fgsInfo.mTotalRuntime); - } - private boolean isAppAlive() { if (app == null) { return false; |