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

Commit ad5499dd authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Hopefully get rid of some ANRs.

Don't hold the activity manager lock the entire time we are processing an ANR,
which often causes us to cause a second ANR as someone else calls into the
activity manager and gets blocked.

Change-Id: Ife4db82b12d6f4378ac2705bd6f60beb1244a1e6
parent 9d32d24d
Loading
Loading
Loading
Loading
+77 −48
Original line number Diff line number Diff line
@@ -4757,19 +4757,32 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        return tracesFile;
    }
    final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity,
    final void appNotResponding(ProcessRecord app, HistoryRecord activity,
            HistoryRecord parent, final String annotation) {
        ArrayList<Integer> pids = new ArrayList<Integer>(20);
        
        synchronized (this) {
            // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
        if (mShuttingDown || app.notResponding || app.crashing) {
            if (mShuttingDown) {
                Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
                return;
            } else if (app.notResponding) {
                Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
                return;
            } else if (app.crashing) {
                Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
                return;
            }
            
            // In case we come through here for the same app before completing
            // this one, mark as anring now so we will bail out.
            app.notResponding = true;
            // Log the ANR to the event log.
            EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
                    annotation);
            // Dump thread traces as quickly as we can, starting with "interesting" processes.
        ArrayList<Integer> pids = new ArrayList<Integer>(20);
            pids.add(app.pid);
    
            int parentPid = app.pid;
@@ -4785,6 +4798,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                    if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
                }
            }
        }
        File tracesFile = dumpStackTraces(pids);
@@ -4806,7 +4820,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        String cpuInfo = null;
        if (MONITOR_CPU_USAGE) {
            updateCpuStatsNow();
            synchronized (mProcessStatsThread) { cpuInfo = mProcessStats.printCurrentState(); }
            synchronized (mProcessStatsThread) {
                cpuInfo = mProcessStats.printCurrentState();
            }
            info.append(cpuInfo);
        }
@@ -4834,6 +4850,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
        // Unless configured otherwise, swallow ANRs in background processes & kill the process.
        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
        
        synchronized (this) {
            if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
                Process.killProcess(app.pid);
                return;
@@ -4856,7 +4874,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            }
    
            mHandler.sendMessage(msg);
        return;
        }
    }
    private final void decPersistentCountLocked(ProcessRecord app)
@@ -11855,6 +11873,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
    }
    void serviceTimeout(ProcessRecord proc) {
        String anrMessage = null;
        
        synchronized(this) {
            if (proc.executingServices.size() == 0 || proc.thread == null) {
                return;
@@ -11875,13 +11895,17 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            }
            if (timeout != null && mLruProcesses.contains(proc)) {
                Slog.w(TAG, "Timeout executing service: " + timeout);
                appNotRespondingLocked(proc, null, null, "Executing service " + timeout.shortName);
                anrMessage = "Executing service " + timeout.shortName;
            } else {
                Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
                msg.obj = proc;
                mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
            }
        }
        
        if (anrMessage != null) {
            appNotResponding(proc, null, null, anrMessage);
        }
    }
    
    // =========================================================
@@ -12680,6 +12704,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
    }
    private final void broadcastTimeout() {
        ProcessRecord app = null;
        String anrMessage = null;
        synchronized (this) {
            if (mOrderedBroadcasts.size() == 0) {
                return;
@@ -12705,8 +12732,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                return;
            }
            ProcessRecord app = null;
            Object curReceiver = r.receivers.get(r.nextReceiver-1);
            Slog.w(TAG, "Receiver during timeout: " + curReceiver);
            logBroadcastReceiverDiscard(r);
@@ -12724,7 +12749,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
            }
            
            if (app != null) {
                appNotRespondingLocked(app, null, null, "Broadcast of " + r.intent.toString());
                anrMessage = "Broadcast of " + r.intent.toString();
            }
            if (mPendingBroadcast == r) {
@@ -12736,6 +12761,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                    r.resultExtras, r.resultAbort, true);
            scheduleBroadcastsLocked();
        }
        
        if (anrMessage != null) {
            appNotResponding(app, null, null, anrMessage);
        }
    }
    private final void processCurBroadcastLocked(BroadcastRecord r,
+11 −4
Original line number Diff line number Diff line
@@ -458,8 +458,10 @@ class HistoryRecord extends IApplicationToken.Stub {
    }

    public boolean keyDispatchingTimedOut() {
        HistoryRecord r;
        ProcessRecord anrApp = null;
        synchronized(service) {
            HistoryRecord r = getWaitingHistoryRecordLocked();
            r = getWaitingHistoryRecordLocked();
            if (r != null && r.app != null) {
                if (r.app.debugging) {
                    return false;
@@ -472,8 +474,7 @@ class HistoryRecord extends IApplicationToken.Stub {
                }
                
                if (r.app.instrumentationClass == null) { 
                    service.appNotRespondingLocked(r.app, r, this,
                            "keyDispatchingTimedOut");
                    anrApp = r.app;
                } else {
                    Bundle info = new Bundle();
                    info.putString("shortMsg", "keyDispatchingTimedOut");
@@ -482,8 +483,14 @@ class HistoryRecord extends IApplicationToken.Stub {
                            r.app, Activity.RESULT_CANCELED, info);
                }
            }
            return true;
        }
        
        if (anrApp != null) {
            service.appNotResponding(anrApp, r, this,
                    "keyDispatchingTimedOut");
        }
        
        return true;
    }
    
    /** Returns the key dispatching timeout for this application token. */