android之AMS学习攻克

Activity相关学习-kill process

2019-01-22  本文已影响0人  weiinter105

前言

当startActivity过程中,Activity所依赖进程被杀会发生什么呢,如一个AMS相关的稳定性问题

相关流程

注册死亡回调

ActivityManagerService#attachApplicationLocked

7706    @GuardedBy("this")
7707    private final boolean attachApplicationLocked(IApplicationThread thread,
7708            int pid, int callingUid, long startSeq) {
7709
7710        // Find the application record that is being attached...  either via
7711        // the pid if we are running in multiple processes, or just pull the
7712        // next app record if we are emulating process with anonymous threads.
7713        ProcessRecord app;
7714        long startTime = SystemClock.uptimeMillis();
7715        if (pid != MY_PID && pid >= 0) {
7716            synchronized (mPidsSelfLocked) {
7717                app = mPidsSelfLocked.get(pid);
7718            }
7719        } else {
7720            app = null;
7721        }
7722
7723        // It's possible that process called attachApplication before we got a chance to
7724        // update the internal state.
7725        if (app == null && startSeq > 0) {
7726            final ProcessRecord pending = mPendingStarts.get(startSeq);
7727            if (pending != null && pending.startUid == callingUid
7728                    && handleProcessStartedLocked(pending, pid, pending.usingWrapper,
7729                            startSeq, true)) {
7730                app = pending;
7731            }
7732        }
7733
7734        if (app == null) {
7735            Slog.w(TAG, "No pending application record for pid " + pid
7736                    + " (IApplicationThread " + thread + "); dropping process");
7737            EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
7738            if (pid > 0 && pid != MY_PID) {
7739                killProcessQuiet(pid);
7740                //TODO: killProcessGroup(app.info.uid, pid);
7741            } else {
7742                try {
7743                    thread.scheduleExit();
7744                } catch (Exception e) {
7745                    // Ignore exceptions.
7746                }
7747            }
7748            return false;
7749        }
7750
7751        // If this application record is still attached to a previous
7752        // process, clean it up now.
7753        if (app.thread != null) {
7754            handleAppDiedLocked(app, true, true);
7755        }
7756
7757        // Tell the process all about itself.
7758
7759        if (DEBUG_ALL) Slog.v(
7760                TAG, "Binding process pid " + pid + " to record " + app);
7761
7762        final String processName = app.processName;
7763        try {
7764            AppDeathRecipient adr = new AppDeathRecipient(
7765                    app, pid, thread);
7766            thread.asBinder().linkToDeath(adr, 0); //注册死亡回调
7767            app.deathRecipient = adr;
7768        } catch (RemoteException e) {
7769            app.resetPackageList(mProcessStats);
7770            startProcessLocked(app, "link fail", processName);
7771            return false;
7772        }
7773
7774        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);

进程被杀时(如kill -9,lowmemorykiller)

ActivityManagerService#AppDeathRecipient


private final class AppDeathRecipient implements IBinder.DeathRecipient {
    final ProcessRecord mApp;
    final int mPid;
    final IApplicationThread mAppThread;

    AppDeathRecipient(ProcessRecord app, int pid,
            IApplicationThread thread) {
        if (DEBUG_ALL) Slog.v(
            TAG, "New death recipient " + this
            + " for thread " + thread.asBinder());
        mApp = app;
        mPid = pid;
        mAppThread = thread;
    }

    @Override
    public void binderDied() {
        if (DEBUG_ALL) Slog.v(
            TAG, "Death received in " + this
            + " for thread " + mAppThread.asBinder());
        synchronized(ActivityManagerService.this) {
            appDiedLocked(mApp, mPid, mAppThread, true);
        }
    }
}

ActivityManagerService#appDiedLocked

6164    @GuardedBy("this")
6165    final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
6166            boolean fromBinderDied) {
6167        // First check if this ProcessRecord is actually active for the pid.
6168        synchronized (mPidsSelfLocked) {
6169            ProcessRecord curProc = mPidsSelfLocked.get(pid);
6170            if (curProc != app) {
6171                Slog.w(TAG, "Spurious death for " + app + ", curProc for " + pid + ": " + curProc);
6172                return;
6173            }
6174        }
6175        BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6176        synchronized (stats) {
6177            stats.noteProcessDiedLocked(app.info.uid, pid);
6178        }
6179
6180        if (!app.killed) {
6181            if (!fromBinderDied) {
6182                killProcessQuiet(pid);
6183            }
6184            killProcessGroup(app.uid, pid);
6185            app.killed = true;
6186        }
6187
6188        // Clean up already done if the process has been re-started.
6189        if (app.pid == pid && app.thread != null &&
6190                app.thread.asBinder() == thread.asBinder()) {
6191            boolean doLowMem = app.instr == null;
6192            boolean doOomAdj = doLowMem;
6193            if (!app.killedByAm) { //app.killedByAm会在ProcessRecord.kill中置为true
6194                reportUidInfoMessageLocked(TAG,
6195                        "Process " + app.processName + " (pid " + pid + ") has died: "
6196                                + ProcessList.makeOomAdjString(app.setAdj)
6197                                + ProcessList.makeProcStateString(app.setProcState), app.info.uid);
6198                mAllowLowerMemLevel = true;
6199                if (mEnableNetOpts) {
6200                    networkOptsCheck(1, app.processName);
6201                }
6202            } else {
6203                // Note that we always want to do oom adj to update our state with the
6204                // new number of procs.
6205                mAllowLowerMemLevel = false;
6206                doLowMem = false;
6207            }
6208            if (mUxPerf != null) {
6209                mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_KILL, 0, app.processName, 0);
6210            }
6211            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName,
6212                    app.setAdj, app.setProcState);
6213            if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
6214                "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
6215            handleAppDiedLocked(app, false, true);
6216
6217            if (doOomAdj) {
6218                updateOomAdjLocked();
6219            }
6220            if (doLowMem) {
6221                doLowMemReportIfNeededLocked(app);
6222            }
6223        } else if (app.pid != pid) {
6224            // A new process has already been started.
6225            reportUidInfoMessageLocked(TAG,
6226                    "Process " + app.processName + " (pid " + pid
6227                            + ") has died and restarted (pid " + app.pid + ").", app.info.uid);
6228            EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
6229        } else if (DEBUG_PROCESSES) {
6230            Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
6231                    + thread.asBinder());
6232        }
6233
6234        // On the device which doesn't have Cgroup, log LmkStateChanged which is used as a signal
6235        // for pulling memory stats of other running processes when this process died.
6236        if (!hasMemcg()) {
6237            StatsLog.write(StatsLog.APP_DIED, SystemClock.elapsedRealtime());
6238        }
6239    }

ActivityManagerService#killProcessGroup
static void killProcessGroup(int uid, int pid) {
    if (sKillHandler != null) {
        sKillHandler.sendMessage(
                sKillHandler.obtainMessage(KillHandler.KILL_PROCESS_GROUP_MSG, uid, pid));
    } else {
        Slog.w(TAG, "Asked to kill process group before system bringup!");
        Process.killProcessGroup(uid, pid);
    }
}
...
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case KILL_PROCESS_GROUP_MSG:
            {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "killProcessGroup");
                Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */); //JNI调用
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            break;

            default:
                super.handleMessage(msg);
        }
    }
}

ActivityManagerService#handleAppDiedLocked

/**
 * Main function for removing an existing process from the activity manager
 * as a result of that process going away.  Clears out all connections
 * to the process.
 */
@GuardedBy("this")
private final void handleAppDiedLocked(ProcessRecord app,
        boolean restarting, boolean allowRestart) {
    int pid = app.pid;
    boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
            false /*replacingPid*/);
    if (!kept && !restarting) {
        removeLruProcessLocked(app);
        if (pid > 0) {
            ProcessList.remove(pid); //调用ProcessList的remove
        }
    }

    if (mProfileProc == app) {
        clearProfilerLocked();
    }

    // Remove this application's activities from active lists. 
    boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app); (针对被kill进程的activity进程处理)

    app.clearRecentTasks();

    app.activities.clear();

    if (app.instr != null) {
        Slog.w(TAG, "Crash of app " + app.processName
              + " running instrumentation " + app.instr.mClass);
        Bundle info = new Bundle();
        info.putString("shortMsg", "Process crashed.");
        finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
    }

    mWindowManager.deferSurfaceLayout();
    try {
        if (!restarting && hasVisibleActivities
                && !mStackSupervisor.resumeFocusedStackTopActivityLocked()) { 
            //最后还会调用到resumeFocusedStackTopActivityLocked
            // If there was nothing to resume, and we are not already restarting this process, but
            // there is a visible activity that is hosted by the process...  then make sure all
            // visible activities are running, taking care of restarting this process.
            mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
        }
    } finally {
        mWindowManager.continueSurfaceLayout();
    }
}
ActivityManagerService#cleanUpApplicationRecordLocked

注意注释
Main code for cleaning up a process when it has gone away. This is called both as a result of the process dying, or directly when stopping a process when running in single process mode.
返回进程是否restart了

/**
 * Main code for cleaning up a process when it has gone away.  This is
 * called both as a result of the process dying, or directly when stopping
 * a process when running in single process mode.
 *
 * @return Returns true if the given process has been restarted, so the
 * app that was passed in must remain on the process lists.
 */
@GuardedBy("this")
private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
        boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
    if (index >= 0) {
        removeLruProcessLocked(app);
        ProcessList.remove(app.pid);
    }

    mProcessesToGc.remove(app);
    mPendingPssProcesses.remove(app);
    ProcessList.abortNextPssTime(app.procStateMemTracker);

    // Dismiss any open dialogs.
    if (app.crashDialog != null && !app.forceCrashReport) {
        app.crashDialog.dismiss();
        app.crashDialog = null;
    }
    if (app.anrDialog != null) {
        app.anrDialog.dismiss();
        app.anrDialog = null;
    }
    if (app.waitDialog != null) {
        app.waitDialog.dismiss();
        app.waitDialog = null;
    }

    app.crashing = false;
    app.notResponding = false;

    app.resetPackageList(mProcessStats);
    app.unlinkDeathRecipient();
    app.makeInactive(mProcessStats);
    app.waitingToKill = null;
    app.forcingToImportant = null;
    updateProcessForegroundLocked(app, false, false);
    app.foregroundActivities = false;
    app.hasShownUi = false;
    app.treatLikeActivity = false;
    app.hasAboveClient = false;
    app.hasClientActivities = false;

    mServices.killServicesLocked(app, allowRestart); //做Service的清理工作

    boolean restart = false;

    // Remove published content providers. 
//做ContentProvider的清理工作
  //清除publish ContentProvider
    for (int i = app.pubProviders.size() - 1; i >= 0; i--) {
        ContentProviderRecord cpr = app.pubProviders.valueAt(i);
        final boolean always = app.bad || !allowRestart;
        boolean inLaunching = removeDyingProviderLocked(app, cpr, always);
        if ((inLaunching || always) && cpr.hasConnectionOrHandle()) {
            // We left the provider in the launching list, need to
            // restart it.
            restart = true;
        }

        cpr.provider = null;
        cpr.proc = null;
    }
    app.pubProviders.clear();

    // Take care of any launching providers waiting for this process.
    if (cleanupAppInLaunchingProvidersLocked(app, false)) {
        restart = true;
    }

    // Unregister from connected content providers.
  //unregister工作
    if (!app.conProviders.isEmpty()) {
        for (int i = app.conProviders.size() - 1; i >= 0; i--) {
            ContentProviderConnection conn = app.conProviders.get(i);
            conn.provider.connections.remove(conn);
            stopAssociationLocked(app.uid, app.processName, conn.provider.uid,
                    conn.provider.name);
        }
        app.conProviders.clear();
    }

    // At this point there may be remaining entries in mLaunchingProviders
    // where we were the only one waiting, so they are no longer of use.
    // Look for these and clean up if found.
    // XXX Commented out for now.  Trying to figure out a way to reproduce
    // the actual situation to identify what is actually going on.
    if (false) {
        for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
            ContentProviderRecord cpr = mLaunchingProviders.get(i);
            if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles()) {
                synchronized (cpr) {
                    cpr.launchingApp = null;
                    cpr.notifyAll();
                }
            }
        }
    }

    skipCurrentReceiverLocked(app);

    // Unregister any receivers.
 //unregister 动态注册广播接收者
    for (int i = app.receivers.size() - 1; i >= 0; i--) {
        removeReceiverLocked(app.receivers.valueAt(i));
    }
    app.receivers.clear();

    // If the app is undergoing backup, tell the backup manager about it
    if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
        if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "
                + mBackupTarget.appInfo + " died during backup");
        mHandler.post(new Runnable() {
            @Override
            public void run(){
                try {
                    IBackupManager bm = IBackupManager.Stub.asInterface(
                            ServiceManager.getService(Context.BACKUP_SERVICE));
                    bm.agentDisconnected(app.info.packageName);
                } catch (RemoteException e) {
                    // can't happen; backup manager is local
                }
            }
        });
    }

    for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) {
        ProcessChangeItem item = mPendingProcessChanges.get(i);
        if (app.pid > 0 && item.pid == app.pid) {
            mPendingProcessChanges.remove(i);
            mAvailProcessChanges.add(item);
        }
    }
    mUiHandler.obtainMessage(DISPATCH_PROCESS_DIED_UI_MSG, app.pid, app.info.uid,
            null).sendToTarget();

    // If the caller is restarting this app, then leave it in its
    // current lists and let the caller take care of it.
    if (restarting) {
        return false;
    }

    if (!app.persistent || app.isolated) {
        if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
                "Removing non-persistent process during cleanup: " + app);
        if (!replacingPid) {
            removeProcessNameLocked(app.processName, app.uid, app); //将AMS中的mProcessNames保存的ProcessRecord记录移除
        }
        if (mHeavyWeightProcess == app) {
            mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
                    mHeavyWeightProcess.userId, 0));
            mHeavyWeightProcess = null;
        }
    } else if (!app.removed) {
        // This app is persistent, so we need to keep its record around.
        // If it is not already on the pending app list, add it there
        // and start a new process for it.
        if (mPersistentStartingProcesses.indexOf(app) < 0) {
            mPersistentStartingProcesses.add(app);
            restart = true;
        }
    }
    if ((DEBUG_PROCESSES || DEBUG_CLEANUP) && mProcessesOnHold.contains(app)) Slog.v(
            TAG_CLEANUP, "Clean-up removing on hold: " + app);
    mProcessesOnHold.remove(app);

    if (app == mHomeProcess) {
        mHomeProcess = null;
    }
    if (app == mPreviousProcess) {
        mPreviousProcess = null;
    }

    if (restart && !app.isolated) {
        // We have components that still need to be running in the
        // process, so re-launch it.
        if (index < 0) {
            ProcessList.remove(app.pid);
        }
        addProcessNameLocked(app);
        app.pendingStart = false;
        startProcessLocked(app, "restart", app.processName);
        return true;
    } else if (app.pid > 0 && app.pid != MY_PID) {
        // Goodbye!
        boolean removed;
        synchronized (mPidsSelfLocked) {
            mPidsSelfLocked.remove(app.pid);
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        }
        mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
        if (app.isolated) {
            mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
        }
        app.setPid(0);
    }
    return false;
}

ActiveServices#killServicesLocked

做进程关联的Service的相关清理工作

final void killServicesLocked(ProcessRecord app, boolean allowRestart) {
    // Report disconnected services.
    if (false) {
        // XXX we are letting the client link to the service for
        // death notifications.
        if (app.services.size() > 0) {
            Iterator<ServiceRecord> it = app.services.iterator();
            while (it.hasNext()) {
                ServiceRecord r = it.next();
                for (int conni=r.connections.size()-1; conni>=0; conni--) {
                    ArrayList<ConnectionRecord> cl = r.connections.valueAt(conni);
                    for (int i=0; i<cl.size(); i++) {
                        ConnectionRecord c = cl.get(i);
                        if (c.binding.client != app) {
                            try {
                                //c.conn.connected(r.className, null);
                            } catch (Exception e) {
                                // todo: this should be asynchronous!
                                Slog.w(TAG, "Exception thrown disconnected servce "
                                      + r.shortName
                                      + " from app " + app.processName, e);
                            }
                        }
                    }
                }
            }
        }
    }

    // Clean up any connections this application has to other services.
    for (int i = app.connections.size() - 1; i >= 0; i--) {
        ConnectionRecord r = app.connections.valueAt(i);
        removeConnectionLocked(r, app, null);
    }
    updateServiceConnectionActivitiesLocked(app);
    app.connections.clear();

    app.whitelistManager = false;

    // Clear app state from services.
    for (int i = app.services.size() - 1; i >= 0; i--) {
        ServiceRecord sr = app.services.valueAt(i);
        synchronized (sr.stats.getBatteryStats()) {
            sr.stats.stopLaunchedLocked();
        }
        if (sr.app != app && sr.app != null && !sr.app.persistent) {
            sr.app.services.remove(sr);
        }
        sr.app = null;
        sr.isolatedProc = null;
        sr.executeNesting = 0;
        sr.forceClearTracker();
        if (mDestroyingServices.remove(sr)) {
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr);
        }

        final int numClients = sr.bindings.size();
        for (int bindingi=numClients-1; bindingi>=0; bindingi--) {
            IntentBindRecord b = sr.bindings.valueAt(bindingi);
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Killing binding " + b
                    + ": shouldUnbind=" + b.hasBound);
            b.binder = null;
            b.requested = b.received = b.hasBound = false;
            // If this binding is coming from a cached process and is asking to keep
            // the service created, then we'll kill the cached process as well -- we
            // don't want to be thrashing around restarting processes that are only
            // there to be cached.
            for (int appi=b.apps.size()-1; appi>=0; appi--) {
                final ProcessRecord proc = b.apps.keyAt(appi);
                // If the process is already gone, skip it.
                if (proc.killedByAm || proc.thread == null) {
                    continue;
                }
                // Only do this for processes that have an auto-create binding;
                // otherwise the binding can be left, because it won't cause the
                // service to restart.
                final AppBindRecord abind = b.apps.valueAt(appi);
                boolean hasCreate = false;
                for (int conni=abind.connections.size()-1; conni>=0; conni--) {
                    ConnectionRecord conn = abind.connections.valueAt(conni);
                    if ((conn.flags&(Context.BIND_AUTO_CREATE|Context.BIND_ALLOW_OOM_MANAGEMENT
                            |Context.BIND_WAIVE_PRIORITY)) == Context.BIND_AUTO_CREATE) {
                        hasCreate = true;
                        break;
                    }
                }
                if (!hasCreate) {
                    continue;
                }
                // XXX turned off for now until we have more time to get a better policy.
                if (false && proc != null && !proc.persistent && proc.thread != null
                        && proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID
                        && proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                    proc.kill("bound to service " + sr.name.flattenToShortString()
                            + " in dying proc " + (app != null ? app.processName : "??"), true);
                }
            }
        }
    }

    ServiceMap smap = getServiceMapLocked(app.userId);

    // Now do remaining service cleanup.
    for (int i=app.services.size()-1; i>=0; i--) {
        ServiceRecord sr = app.services.valueAt(i);

        // Unless the process is persistent, this process record is going away,
        // so make sure the service is cleaned out of it.
        if (!app.persistent) {
            app.services.removeAt(i);
        }

        // Sanity check: if the service listed for the app is not one
        // we actually are maintaining, just let it drop.
        final ServiceRecord curRec = smap.mServicesByName.get(sr.name);
        if (curRec != sr) {
            if (curRec != null) {
                Slog.wtf(TAG, "Service " + sr + " in process " + app
                        + " not same as in map: " + curRec);
            }
            continue;
        }

        // Any services running in the application may need to be placed
        // back in the pending list.
        if (allowRestart && sr.crashCount >= mAm.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
                && (sr.serviceInfo.applicationInfo.flags
                    &ApplicationInfo.FLAG_PERSISTENT) == 0) {
            Slog.w(TAG, "Service crashed " + sr.crashCount
                    + " times, stopping: " + sr);
            EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
                    sr.userId, sr.crashCount, sr.shortName, app.pid);
            bringDownServiceLocked(sr);
        } else if (!allowRestart
                || !mAm.mUserController.isUserRunning(sr.userId, 0)) {
            bringDownServiceLocked(sr);
        } else {
            boolean canceled = scheduleServiceRestartLocked(sr, true);

            // Should the service remain running?  Note that in the
            // extreme case of so many attempts to deliver a command
            // that it failed we also will stop it here.
            if (sr.startRequested && (sr.stopIfKilled || canceled)) {
                if (sr.pendingStarts.size() == 0) {
                    sr.startRequested = false;
                    if (sr.tracker != null) {
                        sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
                                SystemClock.uptimeMillis());
                    }
                    if (!sr.hasAutoCreateConnections()) {
                        // Whoops, no reason to restart!
                        bringDownServiceLocked(sr);
                    }
                }
            }
        }
    }

    if (!allowRestart) {
        app.services.clear();

        // Make sure there are no more restarting services for this process.
        for (int i=mRestartingServices.size()-1; i>=0; i--) {
            ServiceRecord r = mRestartingServices.get(i);
            if (r.processName.equals(app.processName) &&
                    r.serviceInfo.applicationInfo.uid == app.info.uid) {
                mRestartingServices.remove(i);
                clearRestartingIfNeededLocked(r);
            }
        }
        for (int i=mPendingServices.size()-1; i>=0; i--) {
            ServiceRecord r = mPendingServices.get(i);
            if (r.processName.equals(app.processName) &&
                    r.serviceInfo.applicationInfo.uid == app.info.uid) {
                mPendingServices.remove(i);
            }
        }
    }

    // Make sure we have no more records on the stopping list.
    int i = mDestroyingServices.size();
    while (i > 0) {
        i--;
        ServiceRecord sr = mDestroyingServices.get(i);
        if (sr.app == app) {
            sr.forceClearTracker();
            mDestroyingServices.remove(i);
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr);
        }
    }

    app.executingServices.clear();
}

ActivityStackSupervior#handleAppDiedLocked

boolean handleAppDiedLocked(ProcessRecord app) {
    boolean hasVisibleActivities = false;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
        for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = display.getChildAt(stackNdx);
            hasVisibleActivities |= stack.handleAppDiedLocked(app);
        }
    }
    return hasVisibleActivities;
}
ActivityStack#handleAppDiedLocked

针对ActivityStack的处理

/**
 * Reset local parameters because an app's activity died.
 * @param app The app of the activity that died.
 * @return result from removeHistoryRecordsForAppLocked.
 */
boolean handleAppDiedLocked(ProcessRecord app) {
    if (mPausingActivity != null && mPausingActivity.app == app) {
        if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
                "App died while pausing: " + mPausingActivity);
        mPausingActivity = null;
    }
    if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
        mLastPausedActivity = null;
        mLastNoHistoryActivity = null;
    }

    return removeHistoryRecordsForAppLocked(app);
}
ActivityStack#removeHistoryRecordsForAppLocked
4501    private boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
4502        removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities"); //移除mLRUActivities中保存的Activity
4503        removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
4504                "mStoppingActivities");
4505        removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
4506                "mGoingToSleepActivities");
4507        removeHistoryRecordsForAppLocked(mStackSupervisor.mActivitiesWaitingForVisibleActivity, app,
4508                "mActivitiesWaitingForVisibleActivity");
4509        removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
4510                "mFinishingActivities");
4511
4512        boolean hasVisibleActivities = false;
4513
4514        // Clean out the history list.
4515        int i = numActivities();
4516        if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4517                "Removing app " + app + " from history with " + i + " entries");
4518        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4519            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4520            mTmpActivities.clear();
4521            mTmpActivities.addAll(activities);
4522
4523            while (!mTmpActivities.isEmpty()) {
4524                final int targetIndex = mTmpActivities.size() - 1;
4525                final ActivityRecord r = mTmpActivities.remove(targetIndex);
4526                if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4527                        "Record #" + targetIndex + " " + r + ": app=" + r.app);
4528
4529                if (r.app == app) {
4530                    if (r.visible) {
4531                        hasVisibleActivities = true;
4532                    }
4533                    final boolean remove;
4534                    if ((!r.haveState && !r.stateNotNeeded) || r.finishing) { //此时r.finishing = false,说明不在
                                //haveState会在activityResumedLocked中被赋值为false;haveState在activityStoppedLocked中被置为true
                               //那么看起来进程被kill,r.finishing = false时,正常情况下只有最上面的resumed的Activity需要remove
4535                        // Don't currently have state for the activity, or
4536                        // it is finishing -- always remove it.
4537                        remove = true; //是否需要remove
4538                    } else if (!r.visible && r.launchCount > 2 &&
4539                            r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
4540                        // We have launched this activity too many times since it was
4541                        // able to run, so give up and remove it.
4542                        // (Note if the activity is visible, we don't remove the record.
4543                        // We leave the dead window on the screen but the process will
4544                        // not be restarted unless user explicitly tap on it.)
4545                        remove = true;
4546                    } else {
4547                        // The process may be gone, but the activity lives on!
4548                        remove = false;
4549                    }
4550                    if (remove) {
4551                        if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE,
4552                                "Removing activity " + r + " from stack at " + i
4553                                + ": haveState=" + r.haveState
4554                                + " stateNotNeeded=" + r.stateNotNeeded
4555                                + " finishing=" + r.finishing
4556                                + " state=" + r.getState() + " callers=" + Debug.getCallers(5));
4557                        if (!r.finishing) {
4558                            Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
4559                            EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
4560                                    r.userId, System.identityHashCode(r),
4561                                    r.getTask().taskId, r.shortComponentName,
4562                                    "proc died without state saved");
4563                            if (r.getState() == RESUMED) {
4564                                mService.updateUsageStats(r, false);
4565                            }
4566                        }
4567                    } else {
4568                        // We have the current state for this activity, so
4569                        // it can be restarted later when needed.
4570                        if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null");
4571                        if (DEBUG_APP) Slog.v(TAG_APP,
4572                                "Clearing app during removeHistory for activity " + r);
4573                        r.app = null; //将r.app置为null
4574                        // Set nowVisible to previous visible state. If the app was visible while
4575                        // it died, we leave the dead window on screen so it's basically visible.
4576                        // This is needed when user later tap on the dead window, we need to stop
4577                        // other apps when user transfers focus to the restarted activity.
4578                        r.nowVisible = r.visible;
4579                        if (!r.haveState) {
4580                            if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
4581                                    "App died, clearing saved state of " + r);
4582                            r.icicle = null;
4583                        }
4584                    }
4585                    cleanUpActivityLocked(r, true, true); 
                        //此时调用cleanUpActivityLocked,cleanServices = true,setState = true
4586                    if (remove) {
4587                        removeActivityFromHistoryLocked(r, "appDied");
4588                    }
4589                }
4590            }
4591        }
4592
4593        return hasVisibleActivities;
4594    }
ActivityStack#cleanUpActivityLocked
/**
 * Perform the common clean-up of an activity record.  This is called both
 * as part of destroyActivityLocked() (when destroying the client-side
 * representation) and cleaning things up as a result of its hosting
 * processing going away, in which case there is no remaining client-side
 * state to destroy so only the cleanup here is needed.
 *
 * Note: Call before #removeActivityFromHistoryLocked.
 */
private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
    onActivityRemovedFromStack(r);

    r.deferRelaunchUntilPaused = false;
    r.frozenBeforeDestroy = false;

    if (setState) {
        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)"); //将Activity从
        r.setState(DESTROYED, "cleanupActivityLocked"); //将Activity的状态置为destoryed
        if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r);
        r.app = null; //将ActivityRecord.app置为null
    }

    // Inform supervisor the activity has been removed.
    mStackSupervisor.cleanupActivity(r);


    // Remove any pending results.
    if (r.finishing && r.pendingResults != null) {
        for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
            PendingIntentRecord rec = apr.get();
            if (rec != null) {
                mService.cancelIntentSenderLocked(rec, false);
            }
        }
        r.pendingResults = null;
    }

    if (cleanServices) {
        cleanUpActivityServicesLocked(r);
    }

    // Get rid of any pending idle timeouts.
    removeTimeoutsForActivityLocked(r);
    // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
    // manager so it can update its bookkeeping.
    mWindowManager.notifyAppRelaunchesCleared(r.appToken);
}
ActivityStack#removeActivityFromHistoryLocked
private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
    finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
    r.makeFinishingLocked(); //首先将finishing属性置为true
    if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
            "Removing activity " + r + " from stack callers=" + Debug.getCallers(5));

    r.takeFromHistory();
    removeTimeoutsForActivityLocked(r);
    if (DEBUG_STATES) Slog.v(TAG_STATES,
            "Moving to DESTROYED: " + r + " (removed from history)");
    r.setState(DESTROYED, "removeActivityFromHistoryLocked");
    if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
    r.app = null;
    r.removeWindowContainer();
    final TaskRecord task = r.getTask();
    final boolean lastActivity = task != null ? task.removeActivity(r) : false;
    // If we are removing the last activity in the task, not including task overlay activities,
    // then fall through into the block below to remove the entire task itself
    final boolean onlyHasTaskOverlays = task != null
            ? task.onlyHasTaskOverlayActivities(false /* excludingFinishing */) : false;

    if (lastActivity || onlyHasTaskOverlays) {
        if (DEBUG_STACK) {
            Slog.i(TAG_STACK,
                    "removeActivityFromHistoryLocked: last activity removed from " + this
                            + " onlyHasTaskOverlays=" + onlyHasTaskOverlays);
        }

        // The following block can be executed multiple times if there is more than one overlay.
        // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
        // of the task by id and exiting early if not found.
        if (onlyHasTaskOverlays) {
            // When destroying a task, tell the supervisor to remove it so that any activity it
            // has can be cleaned up correctly. This is currently the only place where we remove
            // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
            // state into removeTask(), we just clear the task here before the other residual
            // work.
            // TODO: If the callers to removeTask() changes such that we have multiple places
            //       where we are destroying the task, move this back into removeTask()
            mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
                    !REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY, reason);
        }

        // We must keep the task around until all activities are destroyed. The following
        // statement will only execute once since overlays are also considered activities.
        if (lastActivity) {
            removeTask(task, reason, REMOVE_TASK_MODE_DESTROYING);
        }
    }
    cleanUpActivityServicesLocked(r);
    r.removeUriPermissionsLocked();
}

#######ActivityStack#removeTask

/**
 * Removes the input task from this stack.
 * @param task to remove.
 * @param reason for removal.
 * @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING},
 *             {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
 */
void removeTask(TaskRecord task, String reason, int mode) {
    for (ActivityRecord record : task.mActivities) {
        onActivityRemovedFromStack(record);
    }

    final boolean removed = mTaskHistory.remove(task);

    if (removed) {
        EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.taskId, getStackId());
    }

    removeActivitiesFromLRUListLocked(task);
    updateTaskMovement(task, true);

    if (mode == REMOVE_TASK_MODE_DESTROYING && task.mActivities.isEmpty()) {
        // TODO: VI what about activity?
        final boolean isVoiceSession = task.voiceSession != null;
        if (isVoiceSession) {
            try {
                task.voiceSession.taskFinished(task.intent, task.taskId);
            } catch (RemoteException e) {
            }
        }
        if (task.autoRemoveFromRecents() || isVoiceSession) {
            // Task creator asked to remove this when done, or this task was a voice
            // interaction, so it should not remain on the recent tasks list.
            mStackSupervisor.mRecentTasks.remove(task);
        }

        task.removeWindowContainer();
    }

    if (mTaskHistory.isEmpty()) {
        if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
        // We only need to adjust focused stack if this stack is in focus and we are not in the
        // process of moving the task to the top of the stack that will be focused.
        if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
                && mStackSupervisor.isFocusedStack(this)) {
            String myReason = reason + " leftTaskHistoryEmpty";
            if (!inMultiWindowMode() || !adjustFocusToNextFocusableStack(myReason)) {
                mStackSupervisor.moveHomeStackToFront(myReason); //将桌面stack移到前台
            }
        }
        if (isAttached()) {
            getDisplay().positionChildAtBottom(this); //stack中的task为空时,移到最后
        }
        if (!isActivityTypeHome()) {
            remove();
        }
    }

    task.setStack(null);

    // Notify if a task from the pinned stack is being removed (or moved depending on the mode)
    if (inPinnedWindowingMode()) {
        mService.mTaskChangeNotificationController.notifyActivityUnpinned();
    }
}

#######ActivityStack#remove
完全移除stack

733    /** Removes the stack completely. Also calls WindowManager to do the same on its side. */
734    void remove() {
735        removeFromDisplay();
736        mWindowContainerController.removeContainer();
737        mWindowContainerController = null;
738        onParentChanged();
739    }

在removeHistoryRecordsForAppLocked中说过
!r.haveState && !r.stateNotNeeded) || r.finishing时,remove = true;
haveState会在activityResumedLocked中被赋值为false;haveState在activityStoppedLocked中被置为true
那么可能只有最上面的resumed的Activity需要执行removeActivityFromHistoryLocked

如自己写一个demo,MainActivity->ActivityA->kill -9->dumpsys activity a

发现

  Stack #18: type=standard mode=fullscreen
  isSleeping=false
  mBounds=Rect(0, 0 - 0, 0)

    Task id #65
    mBounds=Rect(0, 0 - 0, 0)
    mMinWidth=-1
    mMinHeight=-1
    mLastNonFullscreenBounds=null
    * TaskRecord{d186cc1 #65 A=com.test.weijuncheng.testactivity U=0 StackId=18 sz=1}
      userId=0 effectiveUid=u0a159 mCallingUid=u0a27 mUserSetupComplete=true mCallingPackage=com.miui.home
      affinity=com.test.weijuncheng.testactivity
      intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.test.weijuncheng.testactivity/.MainActivity}
      realActivity=com.test.weijuncheng.testactivity/.MainActivity
      autoRemoveRecents=false isPersistable=true numFullscreen=1 activityType=1
      rootWasReset=true mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
      Activities=[ActivityRecord{35f118b u0 com.test.weijuncheng.testactivity/.MainActivity t65}]
      askedCompatMode=false inRecents=true isAvailable=true
      stackId=18
      hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true supportsSplitScreenWindowingMode=true lastActiveTime=14601609 (inactive for 586s)
      * Hist #0: ActivityRecord{35f118b u0 com.test.weijuncheng.testactivity/.MainActivity t65}
          packageName=com.test.weijuncheng.testactivity processName=com.test.weijuncheng.testactivity
          launchedFromUid=10027 launchedFromPackage=com.miui.home userId=0
          app=null
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.test.weijuncheng.testactivity/.MainActivity bnds=[584,778][752,946] (has extras) }
          frontOfTask=true task=TaskRecord{d186cc1 #65 A=com.test.weijuncheng.testactivity U=0 StackId=18 sz=1}
          taskAffinity=com.test.weijuncheng.testactivity
          realActivity=com.test.weijuncheng.testactivity/.MainActivity
          baseDir=/data/app/com.test.weijuncheng.testactivity-al6qKDybRW_UdbV4YRC9PQ==/base.apk
          dataDir=/data/user/0/com.test.weijuncheng.testactivity
          stateNotNeeded=false componentSpecified=true mActivityType=standard
          compat={440dpi} labelRes=0x7f0b001d icon=0x7f0a0000 theme=0x7f0c0005
          mLastReportedConfigurations:
           mGlobalConfig={1.0 ?mcc?mnc [en_US] ldltr sw392dp w392dp h768dp 440dpi nrml long port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=Rect(0, 80 - 1080, 2210) mWindowingMode=fullscreen mActivityType=undefined} s.8 themeChanged=0 themeChangedFlags=0}
           mOverrideConfig={1.0 ?mcc?mnc [en_US] ldltr sw392dp w392dp h768dp 440dpi nrml long port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1080, 2130) mAppBounds=Rect(0, 80 - 1080, 2210) mWindowingMode=fullscreen mActivityType=standard} s.8 themeChanged=0 themeChangedFlags=0}
          CurrentConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw392dp w392dp h768dp 440dpi nrml long port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1080, 2130) mAppBounds=Rect(0, 80 - 1080, 2210) mWindowingMode=fullscreen mActivityType=standard} s.8 themeChanged=0 themeChangedFlags=0}
          taskDescription: label="null" icon=null iconResource=0 iconFilename=null primaryColor=ff008577
           backgroundColor=fffafafa
           statusBarColor=ff00574b
           navigationBarColor=ffffffff
          launchFailed=false launchCount=0 lastLaunchTime=-9m49s25ms
          haveState=true icicle=Bundle[mParcelledData.dataSize=1132]
          state=DESTROYED stopped=true delayedResume=false finishing=false
          keysPaused=false inHistory=true visible=false sleeping=false idle=true mStartingWindowState=STARTING_WINDOW_SHOWN
          fullscreen=true noDisplay=false immersive=false launchMode=0
          frozenBeforeDestroy=false forceNewConfig=false
          mActivityType=standard
          waitingVisible=false nowVisible=false lastVisibleTime=-9m47s613ms
          resizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
          mLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=false
          realComponentName=com.test.weijuncheng.testactivity/.MainActivity

此时下方的ActivityRecord还能被dump出来(不同于正常回退的情况)


kill process Activity.png kill -9 测试进程.png
上一篇 下一篇

猜你喜欢

热点阅读