今天要分析下fwk中activity的启动流程,之前看别人画的流程图,总是很快就忘记了,而且总是摸不着重点,遇到具体问题时还是不知道从何入手,又得从头看起。后来我想通了一件事,我们在分析这种源码时不应该过渡纠结于流程图与某个具体函数,而应该从宏观角度想想:要实现这个功能,他应该要包含哪些步骤?
学习activity启动流程时,请带着这样几个问题去阅读源码:
- 新的activity是何时被创建的?进程内启动activity与启动一个新进程过程有什么区别?
- 启动activity时,当前的activity应该是要进到后台的,那这个时间顺序是怎样的?这几个activity的顺序由谁来管理?
- 启动过程中的切换动画是什么时候调用的?activity启动后activity、window、application是什么时候绑定在一起的?
这几个问题的答案见我下面的标红部分,希望能有助于大家在遇到实际问题时,能直接定位到相关节点去分析,节省时间。
目录
具体流程
整个流程可以分为两大步骤:启动前准备与真正启动。
- 启动前准备:在ActivityStarter和ActivityStackSupervisor 类中完成当前activity的暂停,并通知新的Activity的启动;(涉及Intent解析,activity在栈中的进出。旧Activity.onPause--新Activity.onCreate-onStart-Resume--旧Activity.onStop。)
- 在ActivityThread中完成activity、application的创建和绑定,并调用界面显示等;
具体流程如下:
- Activity的startActivity
- Instrumentation#execStartActivity
- ActivityManagerNative.getDefault().startActivity;(getDefault()返回的是ActivityManagerService的远程接口ActivityManagerProxy,通过binder通信调用ActivityManagerService.startActivity。AMS通知ActivityThread是通过ApplicationThread(在frameworks/base/core/java/android/app/ActivityThread.java中)和ApplicationThreadProxy。)
- ActivityStarter.startActivityMayWait 中调用startActivityLocked;
- 解析Intent得到更多信息; 根据ResolveIntentHelper().resolveIntentInternal, chooseBestActivity 去获取最匹配的Activity信息等
- 调用startActivityLocked;
- startActivity方法;
- startActivityUnchecked;
- ActivityStarter.startActivityUnchecked(实质会根据信息中launchMode,flag等来计算调度ActivityStack中的task,ActivityRecord等,);
- ActivityStack.startActivityLocked(源码为mTargetStack.startActivityLocked。将activity添加到栈顶,初始化WindowManager,回到StackSupervisor,调用StackSupervisor.resumeTopActivitiesLocked,再调回ActivityStack.resumeTopActivityInnerLocked);
- WindowManagerService.prepareAppTransition 去准备activity跳转动画;
- next.setVisibility 去使得动画可见
- 调用ActivityStack.startPausingLocked暂停交互当前Activity,里面通过prev.app.thread.schedulePauseActivity调用ActivityThread.handlePauseActivity,接着调用performPauseActivityIfNeeded,然后是Instrumentation 的callActivityOnPause,调用activity.performPause();然后的onPause,然后调用ActivityManagerNative.getDefault()(获取代理对象ActivityManagerProxy).activityPaused告诉ActivityManagerService 旧的Activity已经onPause,可以启动新的Activity了。
- ActivityStack.startActivityLocked(源码为mTargetStack.startActivityLocked。将activity添加到栈顶,初始化WindowManager,回到StackSupervisor,调用StackSupervisor.resumeTopActivitiesLocked,再调回ActivityStack.resumeTopActivityInnerLocked);
- ActivityStackSupervisor.startSpecificActivityLocked:(如果是新进程就调用startProcessLocked;如果不是就调用realStartActivityLocked)
- 在新进程中启动时会执行到startProcessLocked(最终调用ActivityManagerService.startProcessLocked去创建新进程,主要是调用Process.start接口来创建一个新的进程,新的进程会导入android.app.ActivityThread类,并且执行它的main函数)
- ActivityThread.main调用attach方法,最终调到ActivityManagerService.attachApplicationLocked里面,此时Process(并不是application)已经创建,就调用ActivityStackSupervisor.realStartActivityLocked(里面也有更新Configuration)去真正启动activity,最终调用到ActivityThread.handleLaunchActivity:
- ActivityThread.handleLaunchActivity;
- handleLaunchActivity:
- 解析前面传过来的ActivityClientRecord,来收集activity的相关信息(是前面生成的);
- performLaunchActivity去实例化activity对象和application对象;
- 用mInstrumentation.newActivity去实例activity;
- 调用LoadedApk.makeApplication:去创建application对象(若使用了多进程,application对象会存在多个。);
- 创建Configuration;
- 调用activity.attach把activity、application和window关联起来(需要用到Configuration);
- 设置应用theme主题;
- 通过调用mInstrumentation.callActivityOnCreate去调用Activity.performCreate,里面可以调用onCreate;
- 调用mInstrumentation.callActivityOnRestoreInstanceState
- handleResumeActivity:
- performResumeActivity;
- Activity.performResume:
- performRestart:
- onResume:
- Activity.performResume:
- decor.setVisibility(View.INVISIBLE);此时视图才可见。
- performResumeActivity;
- handleLaunchActivity:
切换Activity窗口时Window变化的过程可参考:
Android窗口管理服务WindowManagerService切换Activity窗口(App Transition)的过程分析_罗升阳的博客-CSDN博客
进程启动流程
ActivityManagerService.startProcessLocked--ProcessList.startProcessLock---Process.start---ZygoteProcess.start-----startViaZygote---zygoteSendArgsAndGetResult(参数openZygoteSocketIfNeeded中打开socket和zygote通信)---attemptZygoteSendArgsAndGetResult
相关类简介
(参考:android 从点击图标到启动Activity的流程_ambitionsd的博客-CSDN博客):
ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期
ActivityThread,App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作
ApplicationThread,用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。
ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的。
Instrumentation,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。
ActivityStack:这个并不是我们平时所说的任务栈,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。ActivityStack管理了一系列的TaskRecord,通过mStackId来唯一标识,持有ActivityStackSupervisor的引用。
ActivityStackSupervisor,这是高版本才有的类,它用来管理多个ActivityStack,早期的版本只有一个ActivityStack对应着手机屏幕,后来高版本支持多屏以后,就
有了多个ActivityStack,于是就引入了ActivityStackSupervisor用来管理多个ActivityStack。
ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。
TaskRecord:这个才是我们平时所说的任务栈,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。
ActivityStarter:启动activity相关逻辑;
App与AMS通过Binder进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信。
另外强烈推荐看下:https://www.jianshu.com/p/94816e52cd77
这篇文章详细介绍了ActivityRecord、 TaskRecord,ActivityStack。
启动权限问题
在ActivityStarter.startActivity中有如下几处权限判断地方:
展锐平台:
if(!am.judgeStartAllowLocked(intent, targetPkg, targetUid, callingUid, callingPackage, "start-activity")){
return ActivityManager.START_INTENT_NOT_RESOLVED;
}
ActivityManagerService.judgeStartAllowLocked---PowerControllerInternal.judgeAppLaunchAllowed----BackgroundCleanHelper.judgeAppLaunchAllowed
白名单在 Util.mWhiteAppList 和 BackgroundCleanHelper.mInternalWhiteAppList
Android原生:
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
inTask != null, callerApp, resultRecord, resultStack);
if (abort) Slog.i(TAG,"->startActivity for " + intent
+ " checkStartAnyActivityPermission result:false");
boolean firewallCheck = !mService.getPermissionPolicyInternal().checkStartActivity(intent,
callingUid, callingPackage);
if (firewallCheck) Slog.i(TAG,"->startActivity for " + intent
+ " mIntentFirewall.checkStartActivity result:false");
abort |= firewallCheck;
ActivityManager.checkComponentPermission---PackageManagerService.checkUidPermission----PermissionManagerService.checkUidPermission (通用权限校验)
PermissionPolicyService.Internal.checkStartActivity----isActionRemovedForCallingPackage(判断action在该SDK上是否被移除了)
判断权限是否需要review.
// If permissions need a review before any of the app components can run, we
// launch the review activity and pass a pending intent to start the activity
// we are to launching now after the review is completed.
if (aInfo != null) {
if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
aInfo.packageName, userId)) {
IIntentSender target = mService.getIntentSenderLocked(
ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
callingUid, userId, null, null, 0, new Intent[]{intent},
new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_ONE_SHOT, null);
Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);