Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -7425,6 +7425,7 @@ package android.app { method public int onStartCommand(android.content.Intent, int, int); method public void onTaskRemoved(android.content.Intent); method public void onTimeout(int); method @FlaggedApi("android.app.introduce_new_service_ontimeout_callback") public void onTimeout(int, int); method public void onTrimMemory(int); method public boolean onUnbind(android.content.Intent); method public final void startForeground(int, android.app.Notification); core/java/android/app/ActivityThread.java +40 −0 Original line number Diff line number Diff line Loading @@ -1231,6 +1231,15 @@ public final class ActivityThread extends ClientTransactionHandler sendMessage(H.PING, pong); } @Override public final void scheduleTimeoutServiceForType(IBinder token, int startId, int fgsType) { if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, "scheduleTimeoutServiceForType. token=" + token); } sendMessage(H.TIMEOUT_SERVICE_FOR_TYPE, token, startId, fgsType); } @Override public final void bindApplication( String processName, Loading Loading @@ -2288,6 +2297,8 @@ public final class ActivityThread extends ClientTransactionHandler public static final int INSTRUMENT_WITHOUT_RESTART = 170; public static final int FINISH_INSTRUMENTATION_WITHOUT_RESTART = 171; public static final int TIMEOUT_SERVICE_FOR_TYPE = 172; String codeToString(int code) { if (DEBUG_MESSAGES) { switch (code) { Loading Loading @@ -2341,6 +2352,7 @@ public final class ActivityThread extends ClientTransactionHandler case DUMP_RESOURCES: return "DUMP_RESOURCES"; case TIMEOUT_SERVICE: return "TIMEOUT_SERVICE"; case PING: return "PING"; case TIMEOUT_SERVICE_FOR_TYPE: return "TIMEOUT_SERVICE_FOR_TYPE"; } } return Integer.toString(code); Loading Loading @@ -2427,6 +2439,14 @@ public final class ActivityThread extends ClientTransactionHandler case PING: ((RemoteCallback) msg.obj).sendResult(null); break; case TIMEOUT_SERVICE_FOR_TYPE: if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceTimeoutForType: " + msg.obj); } handleTimeoutServiceForType((IBinder) msg.obj, msg.arg1, msg.arg2); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case CONFIGURATION_CHANGED: mConfigurationController.handleConfigurationChanged((Configuration) msg.obj); break; Loading Loading @@ -5136,6 +5156,26 @@ public final class ActivityThread extends ClientTransactionHandler Slog.wtf(TAG, "handleTimeoutService: token=" + token + " not found."); } } private void handleTimeoutServiceForType(IBinder token, int startId, int fgsType) { Service s = mServices.get(token); if (s != null) { try { if (localLOGV) Slog.v(TAG, "Timeout service " + s); s.callOnTimeLimitExceeded(startId, fgsType); } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to call onTimeLimitExceeded on service " + s + ": " + e, e); } Slog.i(TAG, "handleTimeoutServiceForType: exception for " + token, e); } } else { Slog.wtf(TAG, "handleTimeoutServiceForType: token=" + token + " not found."); } } /** * Resume the activity. * @param r Target activity record. Loading core/java/android/app/IActivityManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -942,6 +942,8 @@ interface IActivityManager { /** Returns if the service is a short-service is still "alive" and past the timeout. */ boolean shouldServiceTimeOut(in ComponentName className, in IBinder token); /** Returns if the service has a time-limit restricted type and is past the time limit. */ boolean hasServiceTimeLimitExceeded(in ComponentName className, in IBinder token); void registerUidFrozenStateChangedCallback(in IUidFrozenStateChangedCallback callback); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)") Loading core/java/android/app/IApplicationThread.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -178,5 +178,6 @@ oneway interface IApplicationThread { in TranslationSpec targetSpec, in List<AutofillId> viewIds, in UiTranslationSpec uiTranslationSpec); void scheduleTimeoutService(IBinder token, int startId); void scheduleTimeoutServiceForType(IBinder token, int startId, int fgsType); void schedulePing(in RemoteCallback pong); } core/java/android/app/Service.java +34 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.text.TextUtils.formatSimple; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -1161,4 +1162,37 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac */ public void onTimeout(int startId) { } /** @hide */ public final void callOnTimeLimitExceeded(int startId, int fgsType) { // Note, because all the service callbacks (and other similar callbacks, e.g. activity // callbacks) are delivered using the main handler, it's possible the service is already // stopped when before this method is called, so we do a double check here. if (mToken == null) { Log.w(TAG, "Service already destroyed, skipping onTimeLimitExceeded()"); return; } try { if (!mActivityManager.hasServiceTimeLimitExceeded( new ComponentName(this, mClassName), mToken)) { Log.w(TAG, "Service no longer relevant, skipping onTimeLimitExceeded()"); return; } } catch (RemoteException ex) { } if (Flags.introduceNewServiceOntimeoutCallback()) { onTimeout(startId, fgsType); } } /** * Callback called when a particular foreground service type has timed out. * * @param startId the startId passed to {@link #onStartCommand(Intent, int, int)} when * the service started. * @param fgsType the foreground service type which caused the timeout. */ @FlaggedApi(Flags.FLAG_INTRODUCE_NEW_SERVICE_ONTIMEOUT_CALLBACK) public void onTimeout(int startId, int fgsType) { } } Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -7425,6 +7425,7 @@ package android.app { method public int onStartCommand(android.content.Intent, int, int); method public void onTaskRemoved(android.content.Intent); method public void onTimeout(int); method @FlaggedApi("android.app.introduce_new_service_ontimeout_callback") public void onTimeout(int, int); method public void onTrimMemory(int); method public boolean onUnbind(android.content.Intent); method public final void startForeground(int, android.app.Notification);
core/java/android/app/ActivityThread.java +40 −0 Original line number Diff line number Diff line Loading @@ -1231,6 +1231,15 @@ public final class ActivityThread extends ClientTransactionHandler sendMessage(H.PING, pong); } @Override public final void scheduleTimeoutServiceForType(IBinder token, int startId, int fgsType) { if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, "scheduleTimeoutServiceForType. token=" + token); } sendMessage(H.TIMEOUT_SERVICE_FOR_TYPE, token, startId, fgsType); } @Override public final void bindApplication( String processName, Loading Loading @@ -2288,6 +2297,8 @@ public final class ActivityThread extends ClientTransactionHandler public static final int INSTRUMENT_WITHOUT_RESTART = 170; public static final int FINISH_INSTRUMENTATION_WITHOUT_RESTART = 171; public static final int TIMEOUT_SERVICE_FOR_TYPE = 172; String codeToString(int code) { if (DEBUG_MESSAGES) { switch (code) { Loading Loading @@ -2341,6 +2352,7 @@ public final class ActivityThread extends ClientTransactionHandler case DUMP_RESOURCES: return "DUMP_RESOURCES"; case TIMEOUT_SERVICE: return "TIMEOUT_SERVICE"; case PING: return "PING"; case TIMEOUT_SERVICE_FOR_TYPE: return "TIMEOUT_SERVICE_FOR_TYPE"; } } return Integer.toString(code); Loading Loading @@ -2427,6 +2439,14 @@ public final class ActivityThread extends ClientTransactionHandler case PING: ((RemoteCallback) msg.obj).sendResult(null); break; case TIMEOUT_SERVICE_FOR_TYPE: if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceTimeoutForType: " + msg.obj); } handleTimeoutServiceForType((IBinder) msg.obj, msg.arg1, msg.arg2); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case CONFIGURATION_CHANGED: mConfigurationController.handleConfigurationChanged((Configuration) msg.obj); break; Loading Loading @@ -5136,6 +5156,26 @@ public final class ActivityThread extends ClientTransactionHandler Slog.wtf(TAG, "handleTimeoutService: token=" + token + " not found."); } } private void handleTimeoutServiceForType(IBinder token, int startId, int fgsType) { Service s = mServices.get(token); if (s != null) { try { if (localLOGV) Slog.v(TAG, "Timeout service " + s); s.callOnTimeLimitExceeded(startId, fgsType); } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to call onTimeLimitExceeded on service " + s + ": " + e, e); } Slog.i(TAG, "handleTimeoutServiceForType: exception for " + token, e); } } else { Slog.wtf(TAG, "handleTimeoutServiceForType: token=" + token + " not found."); } } /** * Resume the activity. * @param r Target activity record. Loading
core/java/android/app/IActivityManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -942,6 +942,8 @@ interface IActivityManager { /** Returns if the service is a short-service is still "alive" and past the timeout. */ boolean shouldServiceTimeOut(in ComponentName className, in IBinder token); /** Returns if the service has a time-limit restricted type and is past the time limit. */ boolean hasServiceTimeLimitExceeded(in ComponentName className, in IBinder token); void registerUidFrozenStateChangedCallback(in IUidFrozenStateChangedCallback callback); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)") Loading
core/java/android/app/IApplicationThread.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -178,5 +178,6 @@ oneway interface IApplicationThread { in TranslationSpec targetSpec, in List<AutofillId> viewIds, in UiTranslationSpec uiTranslationSpec); void scheduleTimeoutService(IBinder token, int startId); void scheduleTimeoutServiceForType(IBinder token, int startId, int fgsType); void schedulePing(in RemoteCallback pong); }
core/java/android/app/Service.java +34 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.text.TextUtils.formatSimple; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -1161,4 +1162,37 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac */ public void onTimeout(int startId) { } /** @hide */ public final void callOnTimeLimitExceeded(int startId, int fgsType) { // Note, because all the service callbacks (and other similar callbacks, e.g. activity // callbacks) are delivered using the main handler, it's possible the service is already // stopped when before this method is called, so we do a double check here. if (mToken == null) { Log.w(TAG, "Service already destroyed, skipping onTimeLimitExceeded()"); return; } try { if (!mActivityManager.hasServiceTimeLimitExceeded( new ComponentName(this, mClassName), mToken)) { Log.w(TAG, "Service no longer relevant, skipping onTimeLimitExceeded()"); return; } } catch (RemoteException ex) { } if (Flags.introduceNewServiceOntimeoutCallback()) { onTimeout(startId, fgsType); } } /** * Callback called when a particular foreground service type has timed out. * * @param startId the startId passed to {@link #onStartCommand(Intent, int, int)} when * the service started. * @param fgsType the foreground service type which caused the timeout. */ @FlaggedApi(Flags.FLAG_INTRODUCE_NEW_SERVICE_ONTIMEOUT_CALLBACK) public void onTimeout(int startId, int fgsType) { } }