startActivity流程(上)

介绍

这篇文章是讲,从手机桌面(Launcher)点击一个未启动app的图标到这个app启动完成的流程(冷启动)。

总体流程

startActivity流程
Launcher、AMS、Zygote、app都处于不同的进程,他们之间需要跨进程才能通信。

用户点击Launcher的app图标后,Launcher通知AMS,如果目标app未启动(冷启动),AMS会通过Socket来通知Zygote去创建进程,Zygote就fork出我们要启动的app进程。
紧接着app要打开HomeActivity,需要与AMS交互

  1. app -> AMS : 因为AMS启动时,就注册到ServiceManager了,所以app调用getService就能从ServiceManager获取到AMS的代理类IActivityManager(客户端)。app从而通过IActivityManager调用AMS(服务端)的方法。
  2. AMS -> app : AMS准备一个IBinder,叫IApplicationThread(服务端)。当app进程启动完成后,会调用IApplicationThread的attachApplication方法,把app的代理类ApplicationThread(客户端)作为参数传给AMS。AMS可以调用ApplicationThread的方法从而控制app。

IApplicationThread的实现类是ActivityThread的内部类ApplicationThread

看完流程图,我们再来看时序图
在这里插入图片描述
图中的4就是attachApplication的过程,把app的代理类ApplicationThread交给AMS。
图中的5就是AMS做完一些处理后,通过app的代理类ApplicationThread来启动app的HomeActivity。

涉及的数据结构

在看源码之前,需要先了解几个重要的数据结构

ProcessRecord(进程)

第一类数据:描述身份的数据

  • ApplicationInfo info:AndroidManifest.xml中定义的Application信息
  • boolean isolated:是不是isolated进程
  • int uid:进程uid
  • int userId:这个是android做的多用户系统id,就像windows可以登录很多用户一样,android也希望可以实现类似的多用户
  • String processName:进程名字,默认情况下是包名
  • UidRecord uidRecord:记录已经使用的uid
  • IApplicationThread thread:这个很重要,它是ApplicationThread的客户端,AMS就是通过这个对象给apk进程发送异步消息的(管理四大组件的消息),所以只有这个对象不为空的情况下,才代表apk进程可以使用了
  • int pid:进程的pid
  • String procStatFile:proc目录下每一个进程都有一个以pid命名的目录文件,这个目录下记载着进程的详细信息,这个目录及目录下的文件是内核创建的, proc是内核文件系统,proc就是process的缩写,涉及的目的就是导出进程内核信息
  • int[] gids:gid组
  • CompatibilityInfo compat : 兼容性信息
  • String requiredAbi : abi信息
  • String instructionSet : 指令集信息

第二类数据:描述进程中组件的数据

  • pkgList:进程中运行的包
  • ArraySet pkgDeps:进程运行依赖的包
  • ArrayList activities:进程启动的所有的activity组件记录表
  • ArraySet services:进程启动的所有的service组件记录表
  • ArraySet executingServices:正在运行(executing)是怎么定义的?首先需要明确的是系统是怎么控制组件的?发送消息给apk进程,apk进程处理消息,上报消息完成,这被定义为一个完整的执行过程,因此正在执行(executing)被定义为发送消息到上报完成这段时间
  • ArraySet connections:绑定service的客户端记录表
  • ArraySet receivers:广播接收器的记录表
  • ContentProviderRecord pubProviders:pub是publish(发布)的意思,ContentProvider需要安装然后把自己发布到系统(AMS)中后,才能使用,安装指的是apk进程加载ContentProvider子类、初始化创建数据库等过程,发布是将ContentProvider的binder客户端注册到AMS中
  • ArrayList conProviders:使用ContentProvider的客户端记录表
  • BroadcastRecord curReceiver:当前进程正在执行的广播 在本节中以上组件信息只是做一个简单的描述,以后单独分析组件管理的时候在详细介绍

此外还有描述进程状态的数据、和pss相关的数据、和时间相关的数据、crash和anr相关的数据、和instrumentation相关的数据、电源信息和调试信息等,

ActivityRecord

Activity在AMS内部是以ActivityRecord的形式存在的,Activity和ActivityRecord是一一对应的。

  • ProcessRecord app:跑在哪个进程
  • TaskRecord task :跑在哪个task
  • ActivityInfo info :Activity信息
  • int mActivityType:Activity类型
  • ActivityState state:Activity状态
  • ApplicationInfo appInfo :跑在哪个app
  • ComponentName realActivity :组件名
  • String packageName :包名
  • String processName :进程名
  • int launchMode:启动模式
  • int userId :该Activity运行在哪个用户id

mActivityType

  • APPLICATION_ACTIVITY_TYPE:普通应用类型
  • HOME_ACTIVITY_TYPE:桌面类型
  • RECENTS_ACTIVITY_TYPE:最近任务类型

ActivityState

  • INITIALIZING
  • RESUMED:已恢复
  • PAUSING
  • PAUSED:已暂停
  • STOPPING
  • STOPPED:已停止
  • FINISHING
  • DESTROYING
  • DESTROYED:已销毁

ActivityRecord是在ActivityStarter的startActivity方法里创建的

TaskRecord

任务栈TaskRecord,内部维护一个 ArrayList 用来保存ActivityRecord。

  • ActivityStack stack:当前所属的stack
  • ArrayList mActivities:当前task的所有Activity列表
  • int taskId
  • String affinity:是指root activity的affinity,即该Task中第一个Activity
  • int mCallingUid
  • String mCallingPackage:调用者的包名

TaskRecord是在ActivityStarter的setTaskFromReuseOrCreateNewTask里创建的。

ActivityStack

ActivityStack,内部维护了一个 ArrayList ,用来管理TaskRecord。
手机有三个虚拟按键,按最右边的正方形按键,会显示最近任务,这个最近任务就是一个ActivityStack,桌面应用也是一个ActivityStack。

ArrayList mTaskHistory //保存所有的Task列表
ArrayList mStacks; //所有stack列表
final int mStackId;
int mDisplayId;
ActivityRecord mPausingActivity //正在pause
ActivityRecord mLastPausedActivity
ActivityRecord mResumedActivity //已经resumed
ActivityRecord mLastStartedActivity
所有前台stack的mResumedActivity的state == RESUMED, 则表示allResumedActivitiesComplete, 此时mLastFocusedStack = mFocusedStack;

ActivityStackSupervisor

ActivityStackSupervisor,顾名思义,就是用来管理ActivityStack的

  • ActivityStack mHomeStack:桌面的stack
  • ActivityStack mFocusedStack:当前聚焦stack
  • ActivityStack mLastFocusedStack:正在切换
  • SparseArray mActivityDisplays:displayId为key
  • SparseArray mActivityContainers: mStackId为key
  • home的栈ID等于0,即HOME_STACK_ID = 0;

ActivityStackSupervisor内部有两个不同的ActivityStack对象:mHomeStack、mFocusedStack,用来管理不同的任务。
ActivityStackSupervisor内部包含了创建ActivityStack对象的方法。

AMS初始化时会创建一个ActivityStackSupervisor对象

在这里插入图片描述

详细的流程

在这里插入图片描述

  • Instrumentation:管理Activity的生命周期以及启动
  • ActivityManagerProxy:AMS的代理对象
  • ApplicationThreadProxy:启动APP的代理对象
  • ApplicationThread是一个Binder服务,不是主线程

第9步是通过Handler来跨线程通信,从子线程ApplicationThread走到主线程ActivityThread。

猜你喜欢

转载自blog.csdn.net/weixin_41504476/article/details/109723466