summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java56
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java45
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;