diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 9fe8e792681ce..9c8639d4b7b89 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -683,6 +683,11 @@ public abstract class ActivityManagerInternal { */ public abstract @TempAllowListType int getPushMessagingOverQuotaBehavior(); + /** + * Return the startForeground() grace period after calling startForegroundService(). + */ + public abstract int getServiceStartForegroundTimeout(); + /** * Returns the capability of the given uid */ diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index ab810c124b427..2643bed44e2e2 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -203,10 +203,6 @@ public final class ActiveServices { // How long we wait for a service to finish executing. static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; - // How long the startForegroundService() grace period is to get around to - // calling startForeground() before we ANR + stop it. - static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; - // Foreground service types that always get immediate notification display, // expressed in the same bitmask format that ServiceRecord.foregroundServiceType // uses. @@ -4240,7 +4236,7 @@ public final class ActiveServices { + " for fg-service launch"); } mAm.tempAllowlistUidLocked(r.appInfo.uid, - SERVICE_START_FOREGROUND_TIMEOUT, REASON_SERVICE_LAUNCH, + mAm.mConstants.mServiceStartForegroundTimeoutMs, REASON_SERVICE_LAUNCH, "fg-service-launch", TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, r.mRecentCallingUid); @@ -5713,12 +5709,23 @@ public final class ActiveServices { } if (app != null) { - mAm.mAnrHelper.appNotResponding(app, - "Context.startForegroundService() did not then call Service.startForeground(): " - + r); + final String annotation = "Context.startForegroundService() did not then call " + + "Service.startForeground(): " + r; + Message msg = mAm.mHandler.obtainMessage( + ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_ANR_MSG); + SomeArgs args = SomeArgs.obtain(); + args.arg1 = app; + args.arg2 = annotation; + msg.obj = args; + mAm.mHandler.sendMessageDelayed(msg, + mAm.mConstants.mServiceStartForegroundAnrDelayMs); } } + void serviceForegroundTimeoutANR(ProcessRecord app, String annotation) { + mAm.mAnrHelper.appNotResponding(app, annotation); + } + public void updateServiceApplicationInfoLocked(ApplicationInfo applicationInfo) { final int userId = UserHandle.getUserId(applicationInfo.uid); ServiceMap serviceMap = mServiceMap.get(userId); @@ -5739,7 +5746,7 @@ public final class ActiveServices { ComponentName service) { mAm.crashApplicationWithTypeWithExtras( app.uid, app.getPid(), app.info.packageName, app.userId, - "Context.startForegroundService() did not then call Service.startForeground(): " + "Context.startForegroundService() did not then call " + "Service.startForeground(): " + serviceRecord, false /*force*/, ForegroundServiceDidNotStartInTimeException.TYPE_ID, ForegroundServiceDidNotStartInTimeException.createExtrasForService(service)); @@ -5764,7 +5771,7 @@ public final class ActiveServices { ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG); msg.obj = r; r.fgWaiting = true; - mAm.mHandler.sendMessageDelayed(msg, SERVICE_START_FOREGROUND_TIMEOUT); + mAm.mHandler.sendMessageDelayed(msg, mAm.mConstants.mServiceStartForegroundTimeoutMs); } final class ServiceDumper { diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index cc8c6fb6c23ac..39a670ea7dbe7 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -216,8 +216,12 @@ final class ActivityManagerConstants extends ContentObserver { private static final String DEFAULT_COMPONENT_ALIAS_OVERRIDES = ""; private static final int DEFAULT_DEFER_BOOT_COMPLETED_BROADCAST = - DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY - | DEFER_BOOT_COMPLETED_BROADCAST_TARGET_T_ONLY; + DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY + | DEFER_BOOT_COMPLETED_BROADCAST_TARGET_T_ONLY; + + private static final int DEFAULT_SERVICE_START_FOREGROUND_TIMEOUT_MS = 30 * 1000; + + private static final int DEFAULT_SERVICE_START_FOREGROUND_ANR_DELAY_MS = 10 * 1000; // Flag stored in the DeviceConfig API. /** @@ -311,6 +315,12 @@ final class ActivityManagerConstants extends ContentObserver { private static final String KEY_DEFER_BOOT_COMPLETED_BROADCAST = "defer_boot_completed_broadcast"; + private static final String KEY_SERVICE_START_FOREGROUND_TIMEOUT_MS = + "service_start_foreground_timeout_ms"; + + private static final String KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS = + "service_start_foreground_anr_delay_ms"; + // Maximum number of cached processes we will allow. public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES; @@ -630,6 +640,19 @@ final class ActivityManagerConstants extends ContentObserver { volatile @BroadcastConstants.DeferBootCompletedBroadcastType int mDeferBootCompletedBroadcast = DEFAULT_DEFER_BOOT_COMPLETED_BROADCAST; + /** + * How long the Context.startForegroundService() grace period is to get around to + * calling Service.startForeground() before we generate ANR. + */ + volatile int mServiceStartForegroundTimeoutMs = DEFAULT_SERVICE_START_FOREGROUND_TIMEOUT_MS; + + /** + * How long from Service.startForeground() timed-out to when we generate ANR of the user app. + * This delay is after the timeout {@link #mServiceStartForegroundTimeoutMs}. + */ + volatile int mServiceStartForegroundAnrDelayMs = + DEFAULT_SERVICE_START_FOREGROUND_ANR_DELAY_MS; + /** * Defines component aliases. Format * ComponentName ":" ComponentName ( "," ComponentName ":" ComponentName )* @@ -913,6 +936,12 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_DEFER_BOOT_COMPLETED_BROADCAST: updateDeferBootCompletedBroadcast(); break; + case KEY_SERVICE_START_FOREGROUND_TIMEOUT_MS: + updateServiceStartForegroundTimeoutMs(); + break; + case KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS: + updateServiceStartForegroundAnrDealyMs(); + break; case KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED: updateNoKillCachedProcessesUntilBootCompleted(); break; @@ -1389,6 +1418,20 @@ final class ActivityManagerConstants extends ContentObserver { DEFAULT_MAX_EMPTY_TIME_MILLIS); } + private void updateServiceStartForegroundTimeoutMs() { + mServiceStartForegroundTimeoutMs = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_SERVICE_START_FOREGROUND_TIMEOUT_MS, + DEFAULT_SERVICE_START_FOREGROUND_TIMEOUT_MS); + } + + private void updateServiceStartForegroundAnrDealyMs() { + mServiceStartForegroundAnrDelayMs = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS, + DEFAULT_SERVICE_START_FOREGROUND_ANR_DELAY_MS); + } + private long[] parseLongArray(@NonNull String key, @NonNull long[] def) { final String val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, key, null); @@ -1669,6 +1712,10 @@ final class ActivityManagerConstants extends ContentObserver { pw.print("="); pw.println(mNoKillCachedProcessesPostBootCompletedDurationMillis); pw.print(" "); pw.print(KEY_MAX_EMPTY_TIME_MILLIS); pw.print("="); pw.println(mMaxEmptyTimeMillis); + pw.print(" "); pw.print(KEY_SERVICE_START_FOREGROUND_TIMEOUT_MS); + pw.print("="); pw.println(mServiceStartForegroundTimeoutMs); + pw.print(" "); pw.print(KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS); + pw.print("="); pw.println(mServiceStartForegroundAnrDelayMs); pw.println(); if (mOverrideMaxCachedProcesses >= 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c40f65f542100..eeff0de53a143 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1536,6 +1536,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int IDLE_UIDS_MSG = 58; static final int HANDLE_TRUST_STORAGE_UPDATE_MSG = 63; static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66; + static final int SERVICE_FOREGROUND_TIMEOUT_ANR_MSG = 67; static final int PUSH_TEMP_ALLOWLIST_UI_MSG = 68; static final int SERVICE_FOREGROUND_CRASH_MSG = 69; static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70; @@ -1724,6 +1725,12 @@ public class ActivityManagerService extends IActivityManager.Stub case SERVICE_FOREGROUND_TIMEOUT_MSG: { mServices.serviceForegroundTimeout((ServiceRecord) msg.obj); } break; + case SERVICE_FOREGROUND_TIMEOUT_ANR_MSG: { + SomeArgs args = (SomeArgs) msg.obj; + mServices.serviceForegroundTimeoutANR((ProcessRecord) args.arg1, + (String) args.arg2); + args.recycle(); + } break; case SERVICE_FOREGROUND_CRASH_MSG: { SomeArgs args = (SomeArgs) msg.obj; mServices.serviceForegroundCrash( @@ -17361,6 +17368,11 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @Override + public int getServiceStartForegroundTimeout() { + return mConstants.mServiceStartForegroundTimeoutMs; + } + @Override public int getUidCapability(int uid) { synchronized (ActivityManagerService.this) { diff --git a/services/core/java/com/android/server/am/BaseAppStateTracker.java b/services/core/java/com/android/server/am/BaseAppStateTracker.java index 2f76e24978340..cb21a4bf8f22c 100644 --- a/services/core/java/com/android/server/am/BaseAppStateTracker.java +++ b/services/core/java/com/android/server/am/BaseAppStateTracker.java @@ -16,7 +16,6 @@ package com.android.server.am; -import static com.android.server.am.ActiveServices.SERVICE_START_FOREGROUND_TIMEOUT; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -362,7 +361,7 @@ public abstract class BaseAppStateTracker { } long getServiceStartForegroundTimeout() { - return SERVICE_START_FOREGROUND_TIMEOUT; + return mActivityManagerInternal.getServiceStartForegroundTimeout(); } RoleManager getRoleManager() {