Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0468fbe8 authored by Varun Shah's avatar Varun Shah Committed by Android (Google) Code Review
Browse files

Merge "Introduce a new Service#onTimeout() callback with fgsType." into main

parents d5ef60a2 dcba7756
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+40 −0
Original line number Diff line number Diff line
@@ -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,
@@ -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) {
@@ -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);
@@ -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;
@@ -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.
+2 −0
Original line number Diff line number Diff line
@@ -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)")
+1 −0
Original line number Diff line number Diff line
@@ -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);
}
+34 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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