Android进阶 --- ActivityManagerService模块分析

Android进阶 — ActivityManagerService模块分析

在这里插入图片描述

简介

作为一名合格的Android开发工程师,我们不仅要会使用四大组件,并且要知晓其背后运作的原理!当我们学会了其背后的运作原理,才能更好的帮助我们进行开发工作,知晓每个组件是如何与系统进行交互、数据传递以及调用逻辑,当遇bug难题,才能更好的对症下药及时解决。

本博文是由android8.1.0源码分析后的结果


AMS模块重点结构类解释

四大组件如Activity的打开、关闭等操作都是由App进程通过Binder跨进程调用到AMS(ActivityManagerService)进行处理完成的,AMS作为系统提供的模块,用于组织管理四大组件的业务逻辑调用,可以说它是四大组件的日常操作的中心枢纽,几乎所有的操作都会经过AMS,在分发到各个模块进行判断处理;所以,学会AMS将十分重要,为了更快理解AMS,我们先了解AMS的一些重点类,在以startActivity方法为样例,将重点类连接起来,融会贯通


Activity

窗口活动,四大组件之一,可以与用户进行交互的页面,运行在App客户端进程;Activity有自己的窗口大小,全屏或者部分窗口,可以配置启动模式LaunchMode以及启动时配置的Flag等,还可以配置栈taskAffinity属性等

ActivityRecord

运行在AMS服务端进程,记录一个Activity的相关信息,包括但不仅限于其包名、Activity名字、进程信息、启动Intent、运行状态等信息,还有它属于哪个栈TaskRecord、以及它的线程信息ProcessRecord;
它里面有一个重要的appToken成员,是一个唯一标识量,客户端和服务端都根据这个标识来确定对应的ActivityRecord或ActivityClientRecord,所以涉及到Activity信息相关的东西,在AMS和App进程之间不传用Activity来传递,一般都是由appToken来传递确定

ProcessRecord

记录一个进程信息,包含进程名、IApplicationThread客户端线程、uid、线程状态等相关信息,通常保存在AMS服务端,客户端访问服务端时,通过客户端的pid可以获取对应的ProcessRecord,进而可以知道向哪个客户端发起调用

TaskRecord

运行在AMS服务端进程,组织管理许多ActivityRecord,它就是我们俗称的Activity栈,它由自己的id、名字(affinity)以及它属于哪个ActivityStack管理等等信息

ActivityStack

运行在AMS服务端进程,它是一个更大的Activity栈,它管理了许多TaskRecord,在8.1.0源码中,一个系统只有固定大约7个ActivityStack栈,如HomeStack也就是Luncher的管理栈、全屏栈、窗口可调整大小的栈、占用屏幕专用区域栈(DOCKED_STACK)、始终存在顶部的栈等,这些栈的分类可以在ActivityManager的内部类StackId中查询到;
9.0系统发现这个ActivityStack可以超过7个,adb dumpsys可以查看到stackid会大于7,不知道是不是9.0代码修改了,知道的评论区留言下

ArrayList mTaskHistor 存储了许多TaskRecord,管理了Activity栈
ActivityRecord mPausingActivity 当前栈中暂停的Activity
ActivityRecord mLastPausedActivity
ActivityRecord mResumedActivity 正在运行的Activity
int mDisplayId 唯一标识,与本ActivityStack匹配

ActivityStackSupervisor

ActivityStack的管理者,管理了系统中所有的ActivityStack;
SparseArray<ActivityDisplay> mActivityDisplays; ActivityDisplay中存储了一个ActivityStack
ActivityStack mHomeStack; Launcher的栈
ActivityStack mFocusedStack; 当前获取焦点的栈
ActivityStack mLastFocusedStack; 上一个获取焦点的栈
除此之外,还有很多ActivityRecord的集合,如mStoppingActivities、mFinishingActivities和mGoingToSleepActivities等等

ActivityManagerService

Binder跨进程的服务端,面向外部提供一系列的接口,主要是负责接收外部调用,预处理部分数据,真正的执行逻辑是交给ActivityStarter去处理

ActivityStarter

真正的业务处理类,它会组织以上所有的类进行业务调用、处理等

ActivityThread

客户端进程的入口类,入口方法为main方法;startActivity时,AMS判断启动目标Activity还没有进程,会以LocalSocket方法向zygote孵化器发起创建进程请求,zygote根据自身创建好进程后,会议ActivityThread的main作为入口开始执行,这样一个App进程就开始执行了
在ActivityThread内部有一个内部类ApplicationThread,它是一个IApplicationThread.Stub类型,也就是一个Binder类,在上诉main方法中,会调用AMS的attachApplication将这个ActivityThread绑定到ProcessRecord上去,这样客户端和服务端App都对应匹配上了

Instrumentation

Activity生命周期类负责的类,四大组件的生命周期几乎都是由它来控制的

LoadedApk

我们的类class从哪里来,肯定是由classLoader来加载,那classLoader又从系统中哪个位置去加载出来呢?这一些列的操作都是由它来控制

连接以上类的框架图

在这里插入图片描述

如上如所示,列举了部分包含依赖关系组织架构,其中ActivityRecord与Activity对应,主要是根据appToken对应的,appToken是一个IApplicationToken.Stub类型;一般来说,客户端通过Intent意图启动Activity,AMS拿到Intent意图后会创建ActivityRecord记录此次Activity,其构造方法自动实例化appToken,服务端完成相应逻辑后会将ActivityInfo(记录Activity的载体类)和appToken传递给客户端,客户端获取到ActivityInfo会将其重要信息提取到ActivityClientRecord中去,同时classLoader加载到class类并保存到其中,最后将appToken和ActivityClientRecord保存到ActivityThread的成员ArrayMap<IBinder, ActivityClientRecord>中;至此以后,后续在涉及到此类的都可以用这个appToken来传递了;
ProcessRecord是保存一个线程状态的类,这个线程一般来说是App客户端线程,他们之间是如何建立起对应关系的?大概是这样一个流程:
startActivity时,AMS发现这个Activity还没有自己的App进程,会通知zygote孵化器孵化一个App进程,并创建一个ProcessRecord,其保存了zygote返回给AMS的pid,这个pid就是客户端App的pid,App客户端进程启动后,会以ActivityThread的main作为入口点执行,执行过程中,会跨进程Binder调用AMS的attachApplication(IApplicationThread.Stub)方法,AMS此时就会从自己保存的ProcessRecord列表中找到pid与App进程的pid相同的,找到后并设置App进程的回调接口,也就是attachApplication传递过来的参数IApplicationThread.Stub,这样就建立好对应回调关系了


业务逻辑分析

以上只是列举了AMS各个模块之间的包含关系,还需要一个完整的业务线将他们组织起来,这里就以在桌面Launcher上点击图标启动app为例开始阐述业务逻辑,先来一个流程图:
在这里插入图片描述

startActivity执行逻辑大体如上图,标红的方法是逻辑当中比较关键性的地方,执行逻辑有分叉,走向不同的逻辑,整个业务逻辑可以大致分为几个业务线:

  • startActivity正常执行逻辑
  • 暂停其他Activity逻辑
  • 创建App进程逻辑

startActivity正常执行逻辑

假设我们在桌面Launcher上点击一个App图标,并且这个app从未运行过,它会按照上图Launcher执行,需要注意的是Launcher不在是调用自己Instrumentation来startActivity,而是会调用一个系统服务LauncherAppsService来发起启动,再由他与AMS发起调用,这样就走到AMS的业务逻辑

ActivityStarter相当于startActivity前期预处理逻辑,因为传递过来的Activity实质是一个Intent意图,所以其主要的工作内容:

  1. 从PMS(PackageManagerService)中查询到意图Intent相关的Activity信息,包括包名、class名字、启动模式等等
  2. 检查启动者相关的权限,是否有相关的权限等等
  3. 把传递过来的参数转化为后续需要的参数,也就是AMS模块需要的参数类型等等
    包括上述工作内容,但不仅限于以上逻辑,这里我们重点关注下startActivityUnchecked,由于篇幅较长,省略部分,只显示关键代码:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
    
    
	launcher启动 inTask-null sourceRecord-null voiceSession-null mStartActivity - r
	以下函数主要是设置本类ActivityStarter的成员变量为参数值
	setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
	        voiceInteractor);
	
	检查lunchMode启动模式以及配置到mLaunchFlags
	computeLaunchingTaskFlags();
	计算源的ActivityStack
	computeSourceStack();
	将配置的flag配置到Intent上去
	mIntent.setFlags(mLaunchFlags);
	找到现存的任务TaskRecord,把当前Activity添加进去,返回null则表示没有找到可以添加的任务
	ActivityRecord reusedActivity = getReusableIntentActivity();
	....省略后面逻辑....
}


为mStartActivity查找一个现存任务站TaskRecord,然后将mStartActivity插入进栈
private ActivityRecord getReusableIntentActivity() {
    
    
     当Lunchmode为singTask和singInstance或者flags为New_TASK标志时,才可以去根据Activity去查找Stack,进行复用stack
    就是对集中标志的理解
    boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
            (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
            || mLaunchSingleInstance || mLaunchSingleTask;
    putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
    ActivityRecord intentActivity = null;
    if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
    
    
        final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
        intentActivity = task != null ? task.getTopActivity() : null;
    } else if (putIntoExistingTask) {
    
    
        if (mLaunchSingleInstance) {
    
    
           info就是ActivityInfo
           intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
        } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
    
    
            intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
                    !mLaunchSingleTask);
        } else {
    
    
            根据intent去每个TaskRecord的启动意图Intent比较,否则就根据taskAffinity相比较,先比较前者,前者说明Activity已存在,后者说明在同一个任务栈里面
            intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
        }
    }
    intentActivity有可能为null,那就需要创建一个新的任务栈TaskRecord
    return intentActivity;
}

getReusableIntentActivity方法和我们配置taskAffinity相关,就是任务栈的亲和属性,我们都知道,不配置这个属性,Activity会默认加入到包名相同的任务栈TaskRecord中去,当我们配置taskAffinity=“xxx”时,会将Activity加入到名字为xxx的栈里面去,但是记住,从源码中可以看到,必须该Activity的为mLaunchSingleInstance || mLaunchSingleTask才会进入else if条件,mSupervisor.findTaskLocked和findActivityLocked才会去查找相应的栈,最后这个函数返回是null,说明没有为这个Activity找到合适任务栈,就需要重新创建TaskRecord;

接上面startActivityUnchecked剩余的函数部分:

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
    
    
	....
	找到现存的任务TaskRecord,把当前Activity添加进去,返回null则表示没有找到可以添加的任务
    ActivityRecord reusedActivity = getReusableIntentActivity();
	if (reusedActivity != null) {
    
    
       如果找到的reusedActivity不为空,说明为此次启动的mStartActivity找到了合适的任务栈
       if (mStartActivity.getTask() == null) {
    
    
           mStartActivity.setTask(reusedActivity.getTask());
       }
       if (reusedActivity.getTask().intent == null) {
    
    
           // This task was started because of movement of the activity based on affinity...
           // Now that we are actually launching it, we can assign the base intent.
           reusedActivity.getTask().setIntent(mStartActivity);
       }
	   如果启动flag是FLAG_ACTIVITY_CLEAR_TOP,那就要注意了
       if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
               || isDocumentLaunchesIntoExisting(mLaunchFlags)
               || mLaunchSingleInstance || mLaunchSingleTask) {
    
    
           final TaskRecord task = reusedActivity.getTask();

           移除mStartActivity之上的Activity,根据mLaunchFlags确定是否要移除mStartActivity,具体细节
           可自行跟入performClearTaskForReuseLocked进去看
           final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                   mLaunchFlags);

        	....
           }
       }
 
        int result = START_SUCCESS;
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
    
    
            newTask = true;
            创建一个新的Task来启动我们的目标ActivityStack和TaskRecord,并且将创建的Stack赋值给成员mTargetStack
            result = setTaskFromReuseOrCreateNewTask(
                    taskToAffiliate, preferredLaunchStackId, topStack);
        } else if (mSourceRecord != null) {
    
    
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
    
    
            result = setTaskFromInTask();
        } else {
    
    
            // This not being started from an existing activity, and not part of a new task...
            // just put it in the top task, though these days this case should never happen.
            setTaskToCurrentTopOrCreateNewTask();
        }
        if (result != START_SUCCESS) {
    
    
            return result;
        }
		启动Activity 协调组织windowmanager布置转场布局动画等
        mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
                mOptions);
        mDoResume传进来的参数赋值的,为true
        if (mDoResume) {
    
    
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            在上面创建Stack的时候,会将mTargetStart设置为获取焦点Focus
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
    
    
               
                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                mWindowManager.executeAppTransition();
             进入else   
            } else {
    
    
                isFocusable是否可获取焦点  当然可以返回true  mTargetStack是否已经是FocusedStack获取焦点状态的栈,显然还不是 才刚刚创建
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
    
    
                   将mTargetStack设置为获取焦点状态   
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                执行到这里,为此次启动的Activity检查好了权限、Activity启动配置信息、ActivityStack以及TaskRecord任务栈等信息,需要为我们真正启动Activity做准备了
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
    
    
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
                preferredLaunchDisplayId, mTargetStack.mStackId);
        return START_SUCCESS;
}

部分细节可查看上面的代码注释,这里在重点分析setTaskFromReuseOrCreateNewTask创建任务栈逻辑,如下:

private int setTaskFromReuseOrCreateNewTask(
            TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
    
    
	创建一个新的ActivityStack
	mTargetStack = computeStackFocus(
        mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);

	if (mReuseTask == null) {
    
    	
    创建新的TaskRecord栈
    	final TaskRecord task = mTargetStack.createTaskRecord(
            mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
            mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
            mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
            mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
    	将mStartActivity添加到task中去
    	addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
    	if (mLaunchBounds != null) {
    
    
      	  final int stackId = mTargetStack.mStackId;
      	  if (StackId.resizeStackWithLaunchBounds(stackId)) {
    
    
      	      mService.resizeStack(
                    stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
      	  } else {
    
    
            mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
       	 }
    }
    .........
	
	if (!mMovedOtherTask) {
    
    
	    updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
	            preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
	}
	mDoResume为true,进入if
	if (mDoResume) {
    
    
		此步骤会让mTargetStack成为获取焦点状态
	  	mTargetStack.moveToFront("reuseOrNewTask");
	}   
	return START_SUCCESS;		
}

private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
            int launchFlags, ActivityOptions aOptions) {
    
    
	........
	if (stack == null) {
    
    
            首先会尝试获取一个DynamicStack,动态Stack,是根据ID来确定的,ID>=0即可
            final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
            for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
    
    
                stack = homeDisplayStacks.get(stackNdx);
                if (isDynamicStack(stack.mStackId)) {
    
    
                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                            "computeStackFocus: Setting focused stack=" + stack);
                    return stack;
                }
            }
            找不到合适的,就需要创建一个新的了,重点关注这里的StackId只有以下几种确定的可能
            final int stackId = task != null ? task.getLaunchStackId() :
                    bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
                            FULLSCREEN_WORKSPACE_STACK_ID;
            这里就去根据stackId去创建,由于stackId上局代码确定了几种可能,那说明这个创建后的stack的数量
            就是固定的,也就是整个Android系统的ActivityStack数量是固定的
            stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
        }
        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
                + r + " stackId=" + stack.mStackId);
        return stack;
}

由于本源码是Android 8.1.0上查看的,说明在系统上ActivityStack是固定的,可以使用

adb shell dumpsys activity activities

来查看栈信息,确实是固定的,但是Android9.0就不同了,整个系统对于ActivityStack数量没有限制,可以有很多,不知为何要做这种修改,是为了分屏同时进行吗?知道的可在评论区留言

继续startActivityUnchecked,后面会依次走到ActivityStack的resumeTopActivityInnerLocked方法


ActivityStack — resumeTopActivityInnerLocked

在resumeTopActivityInnerLocked中,业务可能会发生变化,走向两条不同的逻辑,但是最终又会走回到此方法;

逻辑1:其他Activity还在pause中,没有pause完成,就需要先去暂停其他Activity,当其他Activity都pause完成,最后又经过一些列逻辑走回到resumeTopActivityInnerLocked

逻辑2:当所有Activity都pause完成了,就可以继续往下执行,启动我们的目标Activity了

所以,这里经常有面试官会问你,A启动B,A的onPause和B的onCreate谁先执行啊?

看代码把!

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    
    
   AMS还没启动完成
   if (!mService.mBooting && !mService.mBooted) {
    
    
       // Not ready yet!
       return false;
   }
  获取下一个正在执行的Activity,因为在创建TaskRecord将即将要启动的ActivityRecord已经添加进去了
  final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
  因为马上要启动Activity了,暂停所有的Activity初始化工作
  mStackSupervisor.cancelInitializingActivities();

  // Remember how we'll process this pause/resume situation, and ensure
  // that the state is reset however we wind up proceeding.
  final boolean userLeaving = mStackSupervisor.mUserLeaving;
  mStackSupervisor.mUserLeaving = false;

  if (!hasRunningActivity) {
    
    
      // There are no activities left in the stack, let's look somewhere else.
      return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
  }
  如果当前Stack的ResumeActivity就是next就啥也不做了,传递参数即可
  if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
               mStackSupervisor.allResumedActivitiesComplete()) {
    
    
       executeAppTransition(options);
       if (DEBUG_STATES) Slog.d(TAG_STATES,
               "resumeTopActivityLocked: Top activity resumed " + next);
       if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
       return false;
   }
   必须要等待ActivityStack的mPausingActivity处于Pause状态才能继续执行
   如果没有pause成功就返回,不在继续往下执行,不用担心,当其他暂停成功后会有另外一条业务逻辑发起此函数的调用,进而执行我们的Activity
  if (!mStackSupervisor.allPausedActivitiesComplete()) {
    
    
         if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                 "resumeTopActivityLocked: Skip resume: some activity pausing.");
         if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
         return false;
   }
  暂停其他堆栈的Activity
  boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
  if (mResumedActivity != null) {
    
    
       if (DEBUG_STATES) Slog.d(TAG_STATES,
               "resumeTopActivityLocked: Pausing " + mResumedActivity);
       暂停上一个resume状态的Activity
       pausing |= startPausingLocked(userLeaving, false, next, false);
   }
   暂停中情况说明还没暂停完成,不在往下执行
   if (pausing && !resumeWhilePausing) {
    
    
        ......
   		return true;
   } else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
         ....
         return true;
   }
   .......							

暂停其他Activity逻辑

在以上代码中,逻辑1会从pauseBackStacks这里出发,会暂停其他ActivityStack中的mResumedActivity,如下:

boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
    
                                                                                                                                                                                                
    boolean someActivityPaused = false;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
    
    
    	每个ActivityStack都是以DisplayId匹配,并存储在mActivityDisplays成员
        ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
        遍历所有的ActivityStack列表
        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
    
    
            final ActivityStack stack = stacks.get(stackNdx);
            如果此Stack没有获取焦点,并且有正在运行Activity  -- mResumedActivity
            if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
    
    
            	那就去暂停他把!dontWait是否立即返回还是等待
                someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
                        dontWait);
            }
        }
    }
    return someActivityPaused;
}

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean pauseImmediately) {
    
    
	ActivityRecord prev = mResumedActivity;
	mResumedActivity = null;
    mPausingActivity = prev;
    mLastPausedActivity = prev;
	if (prev.app != null && prev.app.thread != null) {
    
    
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
          try {
    
    
              .......
              跨进程调用使上一个Activity暂停Pause,pause完成后会调用回到AMS,逻辑流程查看上面的流程图
              prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                      userLeaving, prev.configChangeFlags, pauseImmediately);
          } catch (Exception e) {
    
    
              // Ignore exception, if process died other code will cleanup.
              Slog.w(TAG, "Exception thrown during pause", e);
              mPausingActivity = null;
              mLastPausedActivity = null;
              mLastNoHistoryActivity = null;
          }
      } else {
    
    
          mPausingActivity = null;
          mLastPausedActivity = null;
          mLastNoHistoryActivity = null;
      }
      if (mPausingActivity != null) {
    
    
            .......
            pauseImmediately传递进来为false
            if (pauseImmediately) {
    
    
                completePauseLocked(false, resuming);
                return false;
            走此逻辑,并返回为true,会回到resumeTopActivityInnerLocked中去,而
            resumeTopActivityInnerLocked的if条件发现是true又会走上面流程图1的逻辑
            } else {
    
    
                发送pause time out消息,防止pause客户端Activity时间过程,当客户端pause完成后,会
                跨进程返回到AMS,取消掉这个timeout消息
                schedulePauseTimeout(prev);
                return true;
            }

        } else {
    
    
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
            if (resuming == null) {
    
    
                mStackSupervisor.resumeFocusedStackTopActivityLocked();
            }
            return false;
        }
}

至此,Activity正常启动流程将中止了,暂停逻辑也会走到App客户端进程去,当App客户端pause完成后,会调用跨进程调用AMS的activityPaused方法,进而在此走回到resumeTopActivityInnerLocked方法

我们继续沿着resumeTopActivityInnerLocked的后续启动流程查看:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    
    
	........
   业务逻辑走到这里,必须所有其他Activity都pause完成
   如果即将启动的App进程存在,就直接执行
	if (next.app != null && next.app.thread != null) {
    
    
	 	next.sleeping = false;
        mService.showUnsupportedZoomDialogIfNeededLocked(next);
        mService.showAskCompatModeDialogLocked(next);
        next.app.pendingUiClean = true;
        next.app.forceProcessStateUpTo(mService.mTopProcessState);
        next.clearOptionsLocked();
        真正resumeActivity的步骤,记住这里只是resume,并没有oncreate onstart
        next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                mService.isNextTransitionForward(), resumeAnimOptions);
	}else {
    
    
	真正执行启动Activity会走此逻辑
        if (!next.hasBeenLaunched) {
    
    
            next.hasBeenLaunched = true;
        } else {
    
    
            if (SHOW_APP_STARTING_PREVIEW) {
    
    
                next.showStartingWindow(null /* prev */, false /* newTask */,
                        false /* taskSwich */);
            }
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
        }
        if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
        以下函数会是真正执行Activity启动
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }	
}

next为即将启动的ActivityRecord,由于此时next的进程还没有,所以会走到else执行startSpecificActivityLocked方法!


创建App进程逻辑

在startSpecificActivityLocked方法中,会判断是否存在App客户端进程,如果有就直接启动,没有我们就去创建:

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
    
    
        根据进程名去AMS和uid里面查找进程记录
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.getStack().setLaunchTime(r);
        App进程存在直接执行
        if (app != null && app.thread != null) {
    
    
            try {
    
    
                .....
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
    
    
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
        }
		开始启动进程信息,这个函数里面会创建进程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

startProcessLocked是一个重载函数,会进行多次调用,大致会先创建ProcessRecord类,在创建App进程,创建进程成功后会返回进程的pid,此时ProcessRecord保存,并且AMS将这个pid和ProcessRecord匹配保存到map数据模型中去;看看关键核心代码把:

private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    
    
	......
	如果入口点为null,则就默认启动类为ActivityThread
	if (entryPoint == null) entryPoint = "android.app.ActivityThread";
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
             app.processName);
     checkTime(startTime, "startProcess: asking zygote to start proc");
     ProcessStartResult startResult;
     启动类型为web_service
     if (hostingType.equals("webview_service")) {
    
    
         startResult = startWebView(entryPoint,
                 app.processName, uid, uid, gids, debugFlags, mountExternal,
                 app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                 app.info.dataDir, null, entryPointArgs);
     } else {
    
    
         启动类型为Activity,Process内部会以localsocket方式连接上zygote,并返回启动结果
         startResult = Process.start(entryPoint,
                 app.processName, uid, uid, gids, debugFlags, mountExternal,
                 app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                 app.info.dataDir, invokeWith, entryPointArgs);
     }
	......
	synchronized (mPidsSelfLocked) {
    
    
     	 pid是通过zygote进程孵化出来的客户端进程pid,pid和客户端的App保存在SparessArray中    
         this.mPidsSelfLocked.put(startResult.pid, app);
         这里是为true,实质是要求新创建的进程及时attach到AMS上,再删除这个消息;防止启动的进程异常
         if (isActivityProcess) {
    
    
             Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
             msg.obj = app;
             mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                     ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
         }
     }
	........	
}

到这里,startActivity算是正在执行完了,但是我们的Activity都还没启动,咋回事!
这里就是由App进程启动完后,跨检查调用AMS的attachApplication了,在启动Activity,因为Activity已经配置到ActivityStack和TaskRecord即将启动的了,其他的Activity也都暂停完成了

需要注意的是,Process与孵化进程zygote是以LocalSocket方式交互的,第二个是进程入口类ActivityThread

ActivityThread的启动main方法

main方法中主要就是:

  • 创建ActivityThread
  • 创建Looper及消息队列
  • 开启消息队列循环遍历消息
    还有一个关键的地方,就是attach:
public static void main(String[] args) {
    
    
  Looper.prepareMainLooper();
  ActivityThread thread = new ActivityThread();
  thread.attach(false);
   if (sMainThreadHandler == null) {
    
    
       sMainThreadHandler = thread.getHandler();
   }    
   if (false) {
    
    
       Looper.myLooper().setMessageLogging(new
               LogPrinter(Log.DEBUG, "ActivityThread"));
   }    
   Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
   Looper.loop();
}

final ApplicationThread mAppThread = new ApplicationThread();   
private void attach(boolean system) {
    
    
        sCurrentActivityThread = this;
        mSystemThread = system;
        ........
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        ActivityManagerService的客户端
        final IActivityManager mgr = ActivityManager.getService();
        try {
    
    
            把mAppThread设置到ActivityManagerService端去了    
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
    
    
            throw ex.rethrowFromSystemServer();
        }
        .....
}

上面代码很清楚了,mgr.attachApplication(mAppThread)就将回调设置到AMS,走到AMS的逻辑了,后续流程看看上面流程图就知道了,我们重点关注一下attachApplicationLocked方法

 private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
    
    
	ProcessRecord app;
  long startTime = SystemClock.uptimeMillis();
     if (pid != MY_PID && pid >= 0) {
    
    
         synchronized (mPidsSelfLocked) {
    
    
             mPidSelfLocked保存了客户端进程号对应的ProcessRecord进程记录信息
             在上面创建进程的时候保存过,这里取出来
             app = mPidsSelfLocked.get(pid);
         }
     } else {
    
    
         app = null;
     }
	 makeActive实质就是将app.thread = thread
     app.makeActive(thread, mProcessStats);
     app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
     app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
     app.forcingToImportant = null;
     updateProcessForegroundLocked(app, false, false);
     app.hasShownUi = false;
     app.debugging = false;
     app.cached = false;
     app.killedByAm = false;
     app.killed = false;
	 发起App客户端进程的Application onCreate事件调用,因为这个App进程才启动,要先启动Application
     if (app.instr != null) {
    
    
          thread.bindApplication(processName, appInfo, providers,
                  app.instr.mClass,
                  profilerInfo, app.instr.mArguments,
                  app.instr.mWatcher,
                  app.instr.mUiAutomationConnection, testMode,
                  mBinderTransactionTrackingEnabled, enableTrackAllocation,
                  isRestrictedBackupMode || !normalMode, app.persistent,
                  new Configuration(getGlobalConfiguration()), app.compat,
                  getCommonServicesLocked(app.isolated),
                  mCoreSettingsObserver.getCoreSettingsLocked(),
                  buildSerial);
      } else {
    
    
          thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                  null, null, null, testMode,
                  mBinderTransactionTrackingEnabled, enableTrackAllocation,
                  isRestrictedBackupMode || !normalMode, app.persistent,
                  new Configuration(getGlobalConfiguration()), app.compat,
                  getCommonServicesLocked(app.isolated),
                  mCoreSettingsObserver.getCoreSettingsLocked(),
                  buildSerial);
      }
	if (normalMode) {
    
    
    	try {
    
    
    		又会走到ActivityStackSupervisor中,启动我们即将启动Activity
            if (mStackSupervisor.attachApplicationLocked(app)) {
    
    
                didSomething = true;
            }
        } catch (Exception e) {
    
    
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);                                                                                                                                                                                                     
            badApp = true;
        }
    }
}

这里,我们直接去看realStartActivityLocked方法逻辑把!

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
    
    
            ......
	app.hasShownUi = true;
	app.pendingUiClean = true;
	app.forceProcessStateUpTo(mService.mTopProcessState);
	final MergedConfiguration mergedConfiguration = new MergedConfiguration(
	        mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
	r.setLastReportedConfiguration(mergedConfiguration);
	启动APP进程的Launch事件,就是onCreate,Activity还没执行onStart/onResume,为什么???
	app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
	        System.identityHashCode(r), r.info,
	        // TODO: Have this take the merged configuration instead of separate global and
	        // override configs.
	        mergedConfiguration.getGlobalConfiguration(),
	        mergedConfiguration.getOverrideConfiguration(), r.compat,
	        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
	        r.persistentState, results, newIntents, !andResume,
	        mService.isNextTransitionForward(), profilerInfo);
	.......
}

因为只执行onCreate事件,还没有执行onStart和onResume事件,搞不明白?我们去app进程看看:

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
    
    

    updateProcessState(procState, false);
	new一个ActivityClientRecord
    ActivityClientRecord r = new ActivityClientRecord();
	.....
	赋值
    r.token = token;
    r.startsNotResumed = notResumed;
    .....
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

scheduleLaunchActivity执行时,还不是App的主线程,通过发送Handler消息会回到主线程中去,最终会走到handleLaunchActivity进行启动Activity

 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    
    
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;
        if (r.profilerInfo != null) {
    
    
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }
        handleConfigurationChanged(null, null);
        WindowManagerGlobal.initialize();
        执行classLoader加载类并且执行onCreate,这里就不继续跟进去了
        执行完成后,会将ActivityClientRecord保存到mActivities成员map中去
        Activity a = performLaunchActivity(r, customIntent);
		if (a != null) {
    
    
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            这里执行onStart/onResume事件
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
		}else{
    
    
			.....
		}

到这里就算真正启动完成了

总结

AMS模块是四大组件的核心模块,要了解模块由哪些组成,并了解其贯通运行逻辑!这里重点掌握启动模式以及FLAG,任务栈和Activity栈这些属性,启动时,Activity依据什么样的条件去归属到对应的栈中!

还有多参考这种耦合式设计,将重要的参数检查、权限等核心工作放在一个进程,启动目标放到另一个进程,这样即使目标进程奔溃,也不影响核心工作进程!

猜你喜欢

转载自blog.csdn.net/jackzhouyu/article/details/109021412