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

Commit 45f4b4aa authored by Makoto Onuki's avatar Makoto Onuki
Browse files

ForegroundServiceDidNotStartInTimeException now has...

an inner exception that captures the stacktrace where
Context.startForegroundService() was called last time,
from the same process.

Bug: 124137635
Test: Manual test with a tesapp. 1: when startForegroundService() is called by
the same process:
```
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: FATAL EXCEPTION: main
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: Process: com.google.omakoto.testapp, PID: 9545
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{e7674af u0 com.google.omakoto.testapp/.MyFgs3}
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.generateForegroundServiceDidNotStartInTimeException(ActivityThread.java:1965)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:1934)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.access$2700(ActivityThread.java:255)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2190)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:201)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:288)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:7839)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: Caused by: android.app.StackTrace: Last startServiceCommon() call for this service was made here
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1868)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ContextImpl.startForegroundService(ContextImpl.java:1823)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at com.google.omakoto.testapp.MyReceiver.onReceive(MyReceiver.java:53)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.handleReceiver(ActivityThread.java:4345)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.access$1600(ActivityThread.java:255)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2102)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	... 7 more
```

Test: Manual test with a tesapp. 1: when startForegroundService() is called by
another process:
```
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: FATAL EXCEPTION: main
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: Process: com.google.omakoto.testapp:second, PID: 9432
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{dcaa127 u0 com.google.omakoto.testapp/.MyFgs3}
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread.generateForegroundServiceDidNotStartInTimeException(ActivityThread.java:1965)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:1934)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread.access$2700(ActivityThread.java:255)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2190)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:201)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:288)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:7839)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
```

Change-Id: I2dd8ec76213d53728eaa8fcc3760813d82a328a5
parent 4ad4975b
Loading
Loading
Loading
Loading
+23 −6
Original line number Diff line number Diff line
@@ -1293,8 +1293,11 @@ public final class ActivityThread extends ClientTransactionHandler
        }

        @Override
        public void scheduleCrash(String msg, int typeId) {
            sendMessage(H.SCHEDULE_CRASH, msg, typeId);
        public void scheduleCrash(String msg, int typeId, @Nullable Bundle extras) {
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = msg;
            args.arg2 = extras;
            sendMessage(H.SCHEDULE_CRASH, args, typeId);
        }

        public void dumpActivity(ParcelFileDescriptor pfd, IBinder activitytoken,
@@ -1924,11 +1927,11 @@ public final class ActivityThread extends ClientTransactionHandler
        }
    }

    private void throwRemoteServiceException(String message, int typeId) {
    private void throwRemoteServiceException(String message, int typeId, @Nullable Bundle extras) {
        // Use a switch to ensure all the type IDs are unique.
        switch (typeId) {
            case ForegroundServiceDidNotStartInTimeException.TYPE_ID:
                throw new ForegroundServiceDidNotStartInTimeException(message);
                throw generateForegroundServiceDidNotStartInTimeException(message, extras);

            case CannotDeliverBroadcastException.TYPE_ID:
                throw new CannotDeliverBroadcastException(message);
@@ -1951,6 +1954,15 @@ public final class ActivityThread extends ClientTransactionHandler
        }
    }

    private ForegroundServiceDidNotStartInTimeException
            generateForegroundServiceDidNotStartInTimeException(String message, Bundle extras) {
        final String serviceClassName =
                ForegroundServiceDidNotStartInTimeException.getServiceClassNameFromExtras(extras);
        final Exception inner = (serviceClassName == null) ? null
                : Service.getStartForegroundServiceStackTrace(serviceClassName);
        throw new ForegroundServiceDidNotStartInTimeException(message, inner);
    }

    class H extends Handler {
        public static final int BIND_APPLICATION        = 110;
        @UnsupportedAppUsage
@@ -2168,9 +2180,14 @@ public final class ActivityThread extends ClientTransactionHandler
                    handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                case SCHEDULE_CRASH:
                    throwRemoteServiceException((String) msg.obj, msg.arg1);
                case SCHEDULE_CRASH: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    String message = (String) args.arg1;
                    Bundle extras = (Bundle) args.arg2;
                    args.recycle();
                    throwRemoteServiceException(message, msg.arg1, extras);
                    break;
                }
                case DUMP_HEAP:
                    handleDumpHeap((DumpHeapData) msg.obj);
                    break;
+8 −0
Original line number Diff line number Diff line
@@ -1862,6 +1862,14 @@ class ContextImpl extends Context {
                            "Not allowed to start service " + service + ": " + cn.getClassName());
                }
            }
            // If we started a foreground service in the same package, remember the stack trace.
            if (cn != null && requireForeground) {
                if (cn.getPackageName().equals(getOpPackageName())) {
                    Service.setStartForegroundServiceStackTrace(cn.getClassName(),
                            new StackTrace("Last startServiceCommon() call for this service was "
                                    + "made here"));
                }
            }
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
+2 −0
Original line number Diff line number Diff line
@@ -321,6 +321,8 @@ interface IActivityManager {
    boolean isTopActivityImmersive();
    void crashApplicationWithType(int uid, int initialPid, in String packageName, int userId,
            in String message, boolean force, int exceptionTypeId);
    void crashApplicationWithTypeWithExtras(int uid, int initialPid, in String packageName,
            int userId, in String message, boolean force, int exceptionTypeId, in Bundle extras);
    /** @deprecated -- use getProviderMimeTypeAsync */
    @UnsupportedAppUsage(maxTargetSdk = 29, publicAlternatives =
            "Use {@link android.content.ContentResolver#getType} public API instead.")
+1 −1
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ oneway interface IApplicationThread {
    void scheduleOnNewActivityOptions(IBinder token, in Bundle options);
    void scheduleSuicide();
    void dispatchPackageBroadcast(int cmd, in String[] packages);
    void scheduleCrash(in String msg, int typeId);
    void scheduleCrash(in String msg, int typeId, in Bundle extras);
    void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path,
            in ParcelFileDescriptor fd, in RemoteCallback finishCallback);
    void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix,
+23 −2
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package android.app;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.os.Bundle;
import android.util.AndroidRuntimeException;

/**
@@ -33,6 +37,10 @@ public class RemoteServiceException extends AndroidRuntimeException {
        super(msg);
    }

    public RemoteServiceException(String msg, Throwable cause) {
        super(msg, cause);
    }

    /**
     * Exception used to crash an app process when it didn't call {@link Service#startForeground}
     * in time after the service was started with
@@ -44,8 +52,21 @@ public class RemoteServiceException extends AndroidRuntimeException {
        /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
        public static final int TYPE_ID = 1;

        public ForegroundServiceDidNotStartInTimeException(String msg) {
            super(msg);
        private static final String KEY_SERVICE_CLASS_NAME = "serviceclassname";

        public ForegroundServiceDidNotStartInTimeException(String msg, Throwable cause) {
            super(msg, cause);
        }

        public static Bundle createExtrasForService(@NonNull ComponentName service) {
            Bundle b = new Bundle();
            b.putString(KEY_SERVICE_CLASS_NAME, service.getClassName());
            return b;
        }

        @Nullable
        public static String getServiceClassNameFromExtras(@Nullable Bundle extras) {
            return (extras == null) ? null : extras.getString(KEY_SERVICE_CLASS_NAME);
        }
    }

Loading