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

Commit 0d97cd1f authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix issue #10779747: Calendar Storage crash observed...

...while setting up a new user from settings.

The delayed service start stuff was too aggressive -- it would
allow a process to be killed between the an onReceive() that calls
startService() and that service being started.  This means that
apps that set up global state that they expect to remain set up
during that time could be lost.

This is the first part of a fix, which tightens up when we allow
services to be delayed.  Now we will immediately start the service
as long as it currently as a process running that is not in the
cached state.  (Previously we would delay if the process was in
the receiver state.)

This unfortunately means that our service start delay is much
less effective.  To address that, there will be a follow-on change
to tie broadcast delivery into this to see if we can delay the
finish of a broadcast as long as there are background services
starting in that process.

Change-Id: I2bba2295d10699ee3479375bbe87114b2cbb0826
parent 8a7a93e2
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -299,11 +299,17 @@ public final class ActiveServices {
        boolean addToStarting = false;
        if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) {
            ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid);
            if (proc == null || proc.curProcState >= ActivityManager.PROCESS_STATE_RECEIVER) {
            if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
                // If this is not coming from a foreground caller, then we may want
                // to delay the start if there are already other background services
                // that are starting.  This is to avoid process start spam when lots
                // of applications are all handling things like connectivity broadcasts.
                // We only do this for cached processes, because otherwise an application
                // can have assumptions about calling startService() for a service to run
                // in its own process, and for that process to not be killed before the
                // service is started.  This is especially the case for receivers, which
                // may start a service in onReceive() to do some additional work and have
                // initialized some global state as part of that.
                if (DEBUG_DELAYED_SERVICE) Slog.v(TAG, "Potential start delay of " + r + " in "
                        + proc);
                if (r.delayed) {
@@ -324,7 +330,7 @@ public final class ActiveServices {
            } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
                // We slightly loosen when we will enqueue this new service as a background
                // starting service we are waiting for, to also include processes that are
                // currently running other services.
                // currently running other services or receivers.
                addToStarting = true;
                if (DEBUG_DELAYED_STATS) Slog.v(TAG, "Not delaying, but counting as bg: " + r);
            } else if (DEBUG_DELAYED_STATS) {
+8 −1
Original line number Diff line number Diff line
@@ -445,7 +445,7 @@ public final class ProcessStatsService extends IProcessStats.Stub {
    static private void dumpHelp(PrintWriter pw) {
        pw.println("Process stats (procstats) dump options:");
        pw.println("    [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
        pw.println("    [--details] [--current] [--commit] [--write] [-h] [<package.name>]");
        pw.println("    [--details] [--current] [--commit] [--reset] [--write] [-h] [<package.name>]");
        pw.println("  --checkin: perform a checkin: print and delete old committed states.");
        pw.println("  --c: print only state in checkin format.");
        pw.println("  --csv: output data suitable for putting in a spreadsheet.");
@@ -456,6 +456,7 @@ public final class ProcessStatsService extends IProcessStats.Stub {
        pw.println("  --details: dump all execution details, not just summary.");
        pw.println("  --current: only dump current state.");
        pw.println("  --commit: commit current stats to disk and reset to start new stats.");
        pw.println("  --reset: reset current stats, without committing.");
        pw.println("  --write: write current in-memory stats to disk.");
        pw.println("  --read: replace current stats with last-written stats.");
        pw.println("  -a: print everything.");
@@ -557,6 +558,12 @@ public final class ProcessStatsService extends IProcessStats.Stub {
                        pw.println("Process stats committed.");
                    }
                    return;
                } else if ("--reset".equals(arg)) {
                    synchronized (mAm) {
                        mProcessStats.resetSafely();
                        pw.println("Process stats reset.");
                    }
                    return;
                } else if ("--write".equals(arg)) {
                    synchronized (mAm) {
                        writeStateSyncLocked();