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

Commit bf7a1552 authored by Jing Ji's avatar Jing Ji
Browse files

Wait for the dying app fully killed on getting content provider

If we are acquiring a content provider, but the hosting process
is dying, wait for its death notification come in, before
restart this process.

Bug: 141857656
Test: manual
Change-Id: Ib2a8014bb3f22485172d0574cfce14bc6895034b
parent 847e6761
Loading
Loading
Loading
Loading
+49 −12
Original line number Diff line number Diff line
@@ -568,6 +568,11 @@ public class ActivityManagerService extends IActivityManager.Stub
    private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds;
    private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes.
    /**
     * How long between a process kill and we actually receive its death recipient
     */
    private static final long PROC_KILL_TIMEOUT = 5000; // 5 seconds;
    OomAdjuster mOomAdjuster;
    final LowMemDetector mLowMemDetector;
@@ -3738,6 +3743,9 @@ public class ActivityManagerService extends IActivityManager.Stub
                "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
            handleAppDiedLocked(app, false, true);
            // Execute the callback if there is any.
            doAppDiedCallbackLocked(app);
            if (doOomAdj) {
                updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END);
            }
@@ -3749,6 +3757,10 @@ public class ActivityManagerService extends IActivityManager.Stub
            reportUidInfoMessageLocked(TAG,
                    "Process " + app.processName + " (pid " + pid
                            + ") has died and restarted (pid " + app.pid + ").", app.info.uid);
            // Execute the callback if there is any.
            doAppDiedCallbackLocked(app);
            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
        } else if (DEBUG_PROCESSES) {
            Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
@@ -3762,6 +3774,39 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    @GuardedBy("this")
    private void doAppDiedCallbackLocked(final ProcessRecord app) {
        if (app.mAppDiedCallback != null) {
            app.mAppDiedCallback.run();
            app.mAppDiedCallback = null;
        }
    }
    @GuardedBy("this")
    private void waitForProcKillLocked(final ProcessRecord app, final String formatString,
            final long startTime) {
        app.mAppDiedCallback = () -> {
            synchronized (ActivityManagerService.this) {
                // called when this app receives appDiedLocked()
                ActivityManagerService.this.notifyAll();
            }
        };
        checkTime(startTime, String.format(formatString, "before appDied"));
        long now = SystemClock.uptimeMillis();
        long timeout = PROC_KILL_TIMEOUT + now;
        while (app.mAppDiedCallback != null && timeout > now) {
            try {
                wait(timeout - now);
            } catch (InterruptedException e) {
            }
            now = SystemClock.uptimeMillis();
        }
        checkTime(startTime, String.format(formatString, "after appDied"));
        if (app.mAppDiedCallback != null) {
            Slog.w(TAG, String.format(formatString, "waiting for app killing timed out"));
        }
    }
    /**
     * If a stack trace dump file is configured, dump process stack traces.
     * @param firstPids of dalvik VM processes to dump stack traces for first
@@ -6779,18 +6824,12 @@ public class ActivityManagerService extends IActivityManager.Stub
                // Note if killedByAm is also set, this means the provider process has just been
                // killed by AM (in ProcessRecord.kill()), but appDiedLocked() hasn't been called
                // yet. So we need to call appDiedLocked() here and let it clean up.
                // yet. So we need to wait for appDiedLocked() here and let it clean up.
                // (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see
                // how to test this case.)
                if (cpr.proc.killed && cpr.proc.killedByAm) {
                    checkTime(startTime, "getContentProviderImpl: before appDied (killedByAm)");
                    final long iden = Binder.clearCallingIdentity();
                    try {
                        appDiedLocked(cpr.proc);
                    } finally {
                        Binder.restoreCallingIdentity(iden);
                    }
                    checkTime(startTime, "getContentProviderImpl: after appDied (killedByAm)");
                    waitForProcKillLocked(cpr.proc, "getContentProviderImpl: %s (killedByAm)",
                            startTime);
                }
            }
@@ -6894,9 +6933,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
                            + " is crashing; detaching " + r);
                    boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
                    checkTime(startTime, "getContentProviderImpl: before appDied");
                    appDiedLocked(cpr.proc);
                    checkTime(startTime, "getContentProviderImpl: after appDied");
                    waitForProcKillLocked(cpr.proc, "getContentProviderImpl: %s", startTime);
                    if (!lastRef) {
                        // This wasn't the last ref our process had on
                        // the provider...  we have now been killed, bail.
+3 −0
Original line number Diff line number Diff line
@@ -329,6 +329,9 @@ class ProcessRecord implements WindowProcessListener {

    boolean mReachable; // Whether or not this process is reachable from given process

    // A callback that should be executed on app died; after that it'll be set to null
    Runnable mAppDiedCallback;

    void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
            long startTime) {
        this.startUid = startUid;