进程被杀&Task被移除

Source

现象

Kill查杀

image.png

Task被移除

当Task处于前台&Task中唯一的activity不处于onStop(可能处于onResume/onPause等)状态时,当前进程被kill查杀,当前activity会被finish导致task中因无activity而被移除。

12-08 15:20:54.991 18018 18018 I wm_on_resume_called: [0,170803945,com.zhihu.android.app.ui.activity.MainActivity,RESUME_ACTIVITY,23]
12-08 15:27:27.763  3076  4898 I am_proc_died: [0,18018,com.zhihu.android,0,2]
12-08 15:27:27.786  3076  4898 I wm_finish_activity: [0,170803945,51,com.zhihu.android/.app.ui.activity.MainActivity,proc died without state saved]
12-08 15:27:27.792  3076  4898 I wm_task_removed: [51,removeChild:removeChild last r=ActivityRecord{
    
      a2e42e9 u0 com.zhihu.android/.app.ui.activity.MainActivity} t-1 f}} in t=Task{
    
      c3e28 #51 type=standard A=10251:com.zhihu.android U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=0}]
12-08 15:27:27.792  3076  4898 I wm_task_removed: [51,removeChild]

Task不被移除

task处于后台-无特殊操作

activity处于onStop状态,进程被杀不做处理

12-08 15:36:55.176 29395 29395 I wm_on_stop_called: [0,17359319,com.zhihu.android.app.ui.activity.MainActivity,STOP_ACTIVITY_ITEM,328]
12-08 15:39:49.161  3076  3160 I am_proc_died: [0,29395,com.zhihu.android,700,15]
task处于前台-进程可能会被再次拉起

进程被杀时,onResume/onPause的activity被finish,onStop不做处理;且进程会因底下的页面会被重新拉起。

12-08 15:42:06.824 18020 18020 I wm_on_resume_called: [0,263348372,com.zhihu.android.mix.activity.ContentMixProfileActivity,RESUME_ACTIVITY,29]
12-08 15:42:07.182 18020 18020 I wm_on_stop_called: [0,17359319,com.zhihu.android.app.ui.activity.MainActivity,STOP_ACTIVITY_ITEM,4]
// 进程被杀
12-08 15:42:49.228  3076  6405 I am_proc_died: [0,18020,com.zhihu.android,0,2]
// top resume被finish
12-08 15:42:49.263  3076  6405 I wm_finish_activity: [0,263348372,53,com.zhihu.android/.mix.activity.ContentMixProfileActivity,proc died without state saved]
// top底下的activity变为top,且进程因top-activity被重新拉起
12-08 15:42:49.296  3076  3193 I am_proc_start: [0,26378,10251,com.zhihu.android,top-activity,{
    
      com.zhihu.android/com.zhihu.android.app.ui.activity.MainActivity}]
12-08 15:42:49.400  3076  6405 I wm_restart_activity: [0,17359319,53,com.zhihu.android/.app.ui.activity.MainActivity]
12-08 15:42:49.402  3076  6405 I wm_set_resumed_activity: [0,com.zhihu.android/.app.ui.activity.MainActivity,minimalResumeActivityLocked - onActivityStateChanged]
12-08 15:42:49.877 26378 26378 I wm_on_application_create_called: [0,com.zhihu.android,219]
12-08 15:42:50.487 26378 26378 I wm_on_create_called: [0,17359319,com.zhihu.android.app.ui.activity.MainActivity,performCreate,563]
12-08 15:42:50.538 26378 26378 I wm_on_start_called: [0,17359319,com.zhihu.android.app.ui.activity.MainActivity,handleStartActivity,50]

ForceStop查杀

在这里插入图片描述

无论Task前台与否,Task中所有activity都会被finish,最后task被移除

12-08 15:59:09.912 26388 26388 I wm_on_resume_called: [0,155633411,com.zhihu.android.mix.activity.ContentMixProfileActivity,RESUME_ACTIVITY,26]
12-08 15:59:10.326 26388 26388 I wm_on_stop_called: [0,129034736,com.zhihu.android.app.ui.activity.MainActivity,STOP_ACTIVITY_ITEM,11]
12-08 15:59:56.503  3076  7901 I wm_finish_activity: [0,155633411,54,com.zhihu.android/.mix.activity.ContentMixProfileActivity,proc died without state saved]
12-08 15:59:56.518  3076  7901 I wm_finish_activity: [0,129034736,54,com.zhihu.android/.app.ui.activity.MainActivity,proc died without state saved]
12-08 15:59:56.522  3076  7901 I wm_task_removed: [54,removeChild:removeChild last r=ActivityRecord{
    
      7b0e9f0 u0 com.zhihu.android/.app.ui.activity.MainActivity} t-1 f}} in t=Task{
    
      ade072f #54 type=standard A=10251:com.zhihu.android U=0 visible=false visibleRequested=false mode=fullscreen translucent=true sz=0}]
12-08 15:59:56.522  3076  7901 I wm_task_removed: [54,removeChild]

原理

Kill查杀

mHaveState 的赋值

代表是否保留上次保存的activity状态,初始值是true;;onResume后赋值为false;onStop后赋值为true

    private boolean mHaveState = true; 
    /** Update the saved state of an activity. */
    void setSavedState(@Nullable Bundle savedState) {
    
      
        mIcicle = savedState;
        mHaveState = mIcicle != null;
    }

在这里插入图片描述

activity被finish的情况

  • 执行了onResume & 没有声明stateNotNeeded=true & state不为RESTARTING_PROCESS
  • finishing 为true
  • crash次数超过2次&最近一次crash在1min内
handleAppDied

进程被kill后ams收到死亡回调后会进行一些清理操作,清理包括四大组件和进程相关信息,这里只讲activity相关。
Activity 被移除后如果Task中没有其他activity,则task也会被移除
在这里插入图片描述

    void handleAppDied() {
    
      
        final boolean remove;
        .......
        // onResume执行完mHaveState为false
        // 如果是forceStop查杀,此处finishing为true
        } else if ((!mHaveState && !stateNotNeeded
                && !isState(State.RESTARTING_PROCESS)) || finishing) {
    
      
            remove = true;
        } else if (!mVisibleRequested && launchCount > 2
                && lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
    
      
            remove = true;
        } else {
    
      
            // The process may be gone, but the activity lives on!
            remove = false;
        }
        if (remove) {
    
      
            if (!finishing || (app != null && app.isRemoved())) {
    
      
                Slog.w(TAG, "Force removing " + this + ": app died, no saved state");
                EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),
                        task != null ? task.mTaskId : -1, shortComponentName,
                        "proc died without state saved");
            }
        } else {
    
      
            nowVisible = mVisibleRequested;
        }
        mTransitionController.requestCloseTransitionIfNeeded(this);
        cleanUp(true /* cleanServices */, true /* setState */);
        if (remove) {
    
      
            .......
            removeFromHistory("appDied");
        }
    }

进程被重新拉起

在这里插入图片描述

ForceStop查杀

forceStop时传入killPackageProcessesLSP的参数setRemoved为true,会提前将相关进程对应的Activity mark finish(i避免进程又因为next top被重新拉起),等待进程死亡时去执行finish操作。

    boolean handleAppDied() {
    
      
        mAtm.mTaskSupervisor.removeHistoryRecords(this);
        .......
        // forceStop 查杀,会将所有的activity都标记为finihsing
        if (isRemoved()) {
    
      
            for (int i = activities.size() - 1; i >= 0; i--) {
    
      
                activities.get(i).makeFinishingLocked();
            }
        }
        for (int i = activities.size() - 1; i >= 0; i--) {
    
      
            final ActivityRecord r = activities.get(i);
            if (r.mVisibleRequested || r.isVisible()) {
    
      
                // While an activity launches a new activity, it's possible that the old activity
                // is already requested to be hidden (mVisibleRequested=false), but this visibility
                // is not yet committed, so isVisible()=true.
                hasVisibleActivities = true;
            }

            final TaskFragment taskFragment = r.getTaskFragment();
            if (taskFragment != null) {
    
      
                // There may be a pausing activity that hasn't shown any window and was requested
                // to be hidden. But pausing is also a visible state, it should be regarded as
                // visible, so the caller can know the next activity should be resumed.
                hasVisibleActivities |= taskFragment.handleAppDied(this);
            }
            r.handleAppDied();
        }
        clearRecentTasks();
        clearActivities();

        return hasVisibleActivities;
    }

结论&建议

如果想进程被杀时task也同步被移除:

  1. ActivityManager#forceStopPackage()
    @SystemApi
        // 注意声明权限
    @RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)
    public void forceStopPackage(String packageName) {
    
      
        forceStopPackageAsUser(packageName, mContext.getUserId());
    }
  1. ActivityTaskManager#removeTask

注意此种方式会同步移除最近任务中的卡片

    /** Removes task by a given taskId */
    // 声明权限
    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
    public boolean removeTask(int taskId) {
    
      
        try {
    
      
            return getService().removeTask(taskId);
        } catch (RemoteException e) {
    
      
            throw e.rethrowFromSystemServer();
        }
    }