diff options
| -rw-r--r-- | services/core/java/com/android/server/am/ActiveServices.java | 88 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ServiceRecord.java | 33 |
2 files changed, 69 insertions, 52 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 94bf813d3696..9be0e1ff464e 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -3783,6 +3783,14 @@ public final class ActiveServices { return fgsInfo.getLastFgsStartTime() + Math.max(0, timeLimit - fgsInfo.getTotalRuntime()); } + private TimeLimitedFgsInfo getFgsTimeLimitedInfo(int uid, int fgsType) { + final SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(uid); + if (fgsInfo != null) { + return fgsInfo.get(fgsType); + } + return null; + } + private void maybeUpdateFgsTrackingLocked(ServiceRecord sr, int previousFgsType) { final int previouslyTimeLimitedType = getTimeLimitedFgsType(previousFgsType); if (previouslyTimeLimitedType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE @@ -3793,16 +3801,12 @@ public final class ActiveServices { if (previouslyTimeLimitedType != ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) { // FGS is switching types and the previous type was time-limited so update the runtime. - final SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid); - if (fgsInfo != null) { - final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(previouslyTimeLimitedType); - if (fgsTypeInfo != null) { - // Update the total runtime for the previous time-limited fgs type. - fgsTypeInfo.updateTotalRuntime(); - // TODO(b/330399444): handle the case where an app is running 2 services of the - // same time-limited type in parallel and stops one of them which leads to the - // second running one gaining additional runtime. - } + final TimeLimitedFgsInfo fgsTypeInfo = getFgsTimeLimitedInfo( + sr.appInfo.uid, previouslyTimeLimitedType); + if (fgsTypeInfo != null) { + // Update the total runtime for the previous time-limited fgs type. + fgsTypeInfo.updateTotalRuntime(SystemClock.uptimeMillis()); + fgsTypeInfo.decNumParallelServices(); } if (!sr.isFgsTimeLimited()) { @@ -3825,10 +3829,10 @@ public final class ActiveServices { final int timeLimitedFgsType = getTimeLimitedFgsType(sr.foregroundServiceType); TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(timeLimitedFgsType); if (fgsTypeInfo == null) { - fgsTypeInfo = sr.createTimeLimitedFgsInfo(nowUptime); + fgsTypeInfo = sr.createTimeLimitedFgsInfo(); fgsInfo.put(timeLimitedFgsType, fgsTypeInfo); } - fgsTypeInfo.setLastFgsStartTime(nowUptime); + fgsTypeInfo.noteFgsFgsStart(nowUptime); // We'll cancel the previous ANR timer and start a fresh one below. mFGSAnrTimer.cancel(sr); @@ -3852,13 +3856,12 @@ public final class ActiveServices { return; // if the current fgs type is not time-limited, return. } - final SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid); - if (fgsInfo != null) { - final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(timeLimitedType); - if (fgsTypeInfo != null) { - // Update the total runtime for the previous time-limited fgs type. - fgsTypeInfo.updateTotalRuntime(); - } + final TimeLimitedFgsInfo fgsTypeInfo = getFgsTimeLimitedInfo( + sr.appInfo.uid, timeLimitedType); + if (fgsTypeInfo != null) { + // Update the total runtime for the previous time-limited fgs type. + fgsTypeInfo.updateTotalRuntime(SystemClock.uptimeMillis()); + fgsTypeInfo.decNumParallelServices(); } Slog.d(TAG_SERVICE, "Stop FGS timeout: " + sr); mFGSAnrTimer.cancel(sr); @@ -3913,24 +3916,21 @@ public final class ActiveServices { mFGSAnrTimer.accept(sr); traceInstant("FGS timed out: ", sr); - final SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid); - if (fgsInfo != null) { - final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(fgsType); - if (fgsTypeInfo != null) { - // Update total runtime for the time-limited fgs type and mark it as timed out. - fgsTypeInfo.updateTotalRuntime(); - fgsTypeInfo.setTimeLimitExceededAt(nowUptime); - - logFGSStateChangeLocked(sr, - FOREGROUND_SERVICE_STATE_CHANGED__STATE__TIMED_OUT, - 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, - false /* fgsRestrictionRecalculated */ - ); - } + final TimeLimitedFgsInfo fgsTypeInfo = getFgsTimeLimitedInfo(sr.appInfo.uid, fgsType); + if (fgsTypeInfo != null) { + // Update total runtime for the time-limited fgs type and mark it as timed out. + fgsTypeInfo.updateTotalRuntime(nowUptime); + fgsTypeInfo.setTimeLimitExceededAt(nowUptime); + + logFGSStateChangeLocked(sr, + FOREGROUND_SERVICE_STATE_CHANGED__STATE__TIMED_OUT, + nowUptime > fgsTypeInfo.getFirstFgsStartUptime() + ? (int) (nowUptime - fgsTypeInfo.getFirstFgsStartUptime()) : 0, + FGS_STOP_REASON_UNKNOWN, + FGS_TYPE_POLICY_CHECK_UNKNOWN, + FOREGROUND_SERVICE_STATE_CHANGED__FGS_START_API__FGSSTARTAPI_NA, + false /* fgsRestrictionRecalculated */ + ); } try { @@ -3949,6 +3949,16 @@ public final class ActiveServices { if (fgsType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) { return; // no timed out FGS type was found (either it was stopped or it switched types) } + + synchronized (mAm) { + final TimeLimitedFgsInfo fgsTypeInfo = getFgsTimeLimitedInfo(sr.appInfo.uid, fgsType); + if (fgsTypeInfo != null) { + // Runtime is already updated when the service times out - if the app didn't + // stop the service, decrement the number of parallel running services here. + fgsTypeInfo.decNumParallelServices(); + } + } + final String reason = "A foreground service of type " + ServiceInfo.foregroundServiceTypeToLabel(fgsType) + " did not stop within its timeout: " + sr.getComponentName(); @@ -3958,7 +3968,6 @@ public final class ActiveServices { Slog.wtf(TAG, reason); return; } - if (android.app.Flags.enableFgsTimeoutCrashBehavior()) { // Crash the app synchronized (mAm) { @@ -4005,7 +4014,6 @@ public final class ActiveServices { private void stopServiceAndUpdateAllowlistManagerLocked(ServiceRecord service) { maybeStopShortFgsTimeoutLocked(service); - maybeStopFgsTimeoutLocked(service); final ProcessServiceRecord psr = service.app.mServices; psr.stopService(service); psr.updateBoundClientUids(); @@ -6291,7 +6299,6 @@ public final class ActiveServices { Slog.w(TAG_SERVICE, "Short FGS brought down without stopping: " + r); maybeStopShortFgsTimeoutLocked(r); } - maybeStopFgsTimeoutLocked(r); // Report to all of the connections that the service is no longer // available. @@ -6416,7 +6423,6 @@ public final class ActiveServices { final boolean exitingFg = r.isForeground; if (exitingFg) { maybeStopShortFgsTimeoutLocked(r); - maybeStopFgsTimeoutLocked(r); decActiveForegroundAppLocked(smap, r); synchronized (mAm.mProcessStats.mLock) { ServiceState stracker = r.getTracker(); diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 8eca4fc0d2ff..218434049869 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -690,10 +690,14 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN private long mTimeLimitExceededAt = Long.MIN_VALUE; @UptimeMillisLong private long mTotalRuntime = 0; + private int mNumParallelServices = 0; - TimeLimitedFgsInfo(@UptimeMillisLong long startTime) { - mFirstFgsStartUptime = startTime; - mFirstFgsStartRealtime = SystemClock.elapsedRealtime(); + public void noteFgsFgsStart(@UptimeMillisLong long startTime) { + mNumParallelServices++; + if (mNumParallelServices == 1) { + mFirstFgsStartUptime = startTime; + mFirstFgsStartRealtime = SystemClock.elapsedRealtime(); + } mLastFgsStartTime = startTime; } @@ -707,17 +711,23 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN return mFirstFgsStartRealtime; } - public void setLastFgsStartTime(@UptimeMillisLong long startTime) { - mLastFgsStartTime = startTime; - } - @UptimeMillisLong public long getLastFgsStartTime() { return mLastFgsStartTime; } - public void updateTotalRuntime() { - mTotalRuntime += SystemClock.uptimeMillis() - mLastFgsStartTime; + public void decNumParallelServices() { + if (mNumParallelServices > 0) { + mNumParallelServices--; + } + if (mNumParallelServices == 0) { + mLastFgsStartTime = 0; + } + } + + public void updateTotalRuntime(@UptimeMillisLong long nowUptime) { + mTotalRuntime += nowUptime - mLastFgsStartTime; + mLastFgsStartTime = nowUptime; } @UptimeMillisLong @@ -735,6 +745,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } public void reset() { + mNumParallelServices = 0; mFirstFgsStartUptime = 0; mFirstFgsStartRealtime = 0; mLastFgsStartTime = 0; @@ -1872,8 +1883,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN /** * Called when a time-limited FGS starts. */ - public TimeLimitedFgsInfo createTimeLimitedFgsInfo(@UptimeMillisLong long nowUptime) { - return new TimeLimitedFgsInfo(nowUptime); + public TimeLimitedFgsInfo createTimeLimitedFgsInfo() { + return new TimeLimitedFgsInfo(); } /** |