注册

Activity启动流程(基于AOSP 11)

当点击Launcher的App icon的时候,点击事件传递给ItemClickHandler的onClickAppShortcut,并最终调用到launcher.startActivitySafely->BaseDraggingActivity.startActivitySafely:

    public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
@Nullable String sourceContainer) {
// ...
// 将Intent的Flag设置为FLAG_ACTIVITY_NEW_TASK
// 这样启动Activity就会在一个新的Activity任务栈中
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// ...
try {
// ... 省略一些快捷方式启动
else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
// 启动应用Activity
startActivity(intent, optsBundle);
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(),
Process.myUserHandle(), sourceContainer);
}
// ...
return true;
} catch (NullPointerException|ActivityNotFoundException|SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
}
return false;
}

startActivity的实现位于Activity中:

    public void startActivity(Intent intent, @Nullable Bundle options) {
// ... 都是调用startActivityForResult启动Activity
// 传入的requestCode是-1
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}

启动Activity最终通过Instrumentation的execStartActivity方法启动,而Instrumentation的作用其实是监控应用和系统交互的中间这,是安卓提供的一层Hook操作,让开发者有能力介入到Activity的各项声明周期中,比如可以用来测试,Activity的各项生命周期的回调也是通过这个类作为中间层实现的,execStartActivity核心是调用到:

int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getBasePackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token,
target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);

ActivityTaskManager是Android 10中新增加的一个类,接替了ActivityManager中Activity与ActivityTask交互的工作,而ActivitTaskManager.getService返回的就是IActivityTaskManager这个AIDL文件中声明的接口,而SystemServer进程中的系统服务ActivityTaskManagerService只需要继承IActivityTaskManager.Stub就可以实现用户进程与服务进程的通信。

new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};

首先获取到SystemServer进程中ActivityTaskManagerService这个系统服务的IBinder接口,然后将这个IBinder接口转换为IActivityTaskManager接口,这样引用进程就可以调用到IActivityTaskManager的方法,与ATMS进行通信了。

那么应用进程调用startActivity终于还是调用到ATMS的startActivity方法了,到这里,创建Activity的逻辑就从Launcher进程进入到了ATMS所在的SystemServer进程:

在ATMS的startActivity中,调用到ATMS.startActivityAsUser:

    private int startActivityAsUser(IApplicationThread caller, String callingPackage,
@Nullable String callingFeatureId, Intent intent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
// 前置权限校验
// 下面获取ActivityStart对象
// 这个对象是控制Activity启动的代理对象
// 7.0以后加入,收集Activity启动相关的各种参数逻辑
// 决定如何启动Activity一级Activity的Task和TaskStack关联
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
// ... 设置了很多参数
.execute();

}

在对ActivityStarter对象设置完一堆参数之后,调用其execute执行启动:

    int execute() {
try {
// ...
int res;
synchronized (mService.mGlobalLock) {
// ...
// 启动信息都在mRequest中了,执行这个请求
res = executeRequest(mRequest);
// 启动完成之后的一些通知等工作......
}
} finally {
onExecutionComplete();
}
}

executeRequest里边的逻辑很多,主要包含各种校验逻辑,比如检验启动参数,Flag等,总之,正常启动流程会去根据各种启动参数创建一个ActivityRecord对象,ActivityRecord对象就代表着一个在任务栈中的Activity实体,最后调用到ActivityStarter的startActivityUnchecked。

startActivityUnchecked->startActivityInner,在startActivityInner中,会先去对Activity启动Flag进行各种校验,比如如果启动的是一个根Activity,但是启动Flag并不是FLAG_ACTIVITY_NEW_TASK,那么会将LaunchFlag修改为FLAG_ACTIVITY_NEW_TASK。然后找到是否有可以重用的任务栈,如果没有,会去创建一个新的任务栈,在startActivityInner中关于启动的核心逻辑是调用:

mRootWindowContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);

RootWindowContainer是在WMS中创建的对象,可以理解为其管理者屏幕显示的内容。在RootWindowContainer中,会调用到ActivityStack的resumeTopActivityUncheckedLocked->resumeTopActivityInnerLocked。这个方法在11上长达400+行,逻辑很多,和我们要分析的主流程相关的重点如下:

// attachedToProcess的判断逻辑:要启动的Activity的进程是否存在以及
// 对应进程的ActivityThread是否存在,而我们这里启动的是一个新进程
// 的根Activity,此时新进程还未创建以及ActivityRecord还没有绑定到新进程中
if (next.attachedToProcess()) {
// ...
} else {
// ...
mStackSupervisor.startSpecificActivity(next, true, true);
}

ActivityStackSupervisor的startSpecificActivity如下:

    void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);

boolean knownToBeDead = false;
// 如果应用所在的进程已经存在,那么执行realStartActivityLocked
// 进行Activity启动
if (wpc != null && wpc.hasThread()) {
try {
// 这个函数后面再做分析
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}

// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}

r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

final boolean isTop = andResume && r.isTopRunningActivity();
// 如果应用进程不存在,ATMS(最终是AMS)将会异步启动应用进程
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}

对于应用进程不存在的情况,AMS会往SystemServer的消息队列中发送一个Lambda类型的Message(其实就是类似Runnable类型的消息),然后消息执行的时候,调用关系:

AMS.startProcessAsync->AMS.startProcess->AMS.startProcessLocked->ProcessList.startProcessLocked...->ProcessList.startProcess->Process.start,最终通过ZygoteProcess调用startViaZygote,通过Zygote进程fork出应用进程,完成应用进程的创建,在应用进程创建的同时,会往SystemServer的消息队列中发送一条超时消息(默认10s),超时到了应用进程仍然未启动的话,就会杀死这个启动失败的进程。

而在Zygote fork出子进程之后,就会执行到ActivityThrea的main方法,在ActivityThread的main方法中,做的最重要的两件事,开启主线程的Looper机制和创建ActivityThread并调用ActivityThread的attach函数,其中:

// mAppThread是ApplicationThread对象,在ActivityThread被创建的时候创建
// 是AMS与应用进程通信的桥梁
// 这里初始化RuntimeInit.mApplicationObject值
RuntimeInit.setApplicationObject(mAppThread.asBinder());
// 获取到AMS的Binder接口IActivityManager
final IActivityManager mgr = ActivityManager.getService();
try {
// 调用AMS的attachApplication
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}

AMS中attachApplication实现如下:

    public final void attachApplication(IApplicationThread thread, long startSeq) {
// 如果传入的ApplicationThread是空的,那么就会异常终止应用进程
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
// 获取binder调用方进程的pid和uid,这里的调用方就是应用进程
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
// 修改binder调用端的pid、uid为调用进程的pid、uid,并返回原uid和pid的组合
// 高32位表示上面的uid,低32位表示pid
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
// 恢复pid、uid
Binder.restoreCallingIdentity(origId);
}
}

attachApplicationLocked又是一个超长函数,内部主要是对App进程做一些检查设置等工作。

// 内部首先会去查找有没有旧的进程记录,如果有,做一些清理类的工作
// ...
// 然后比如debug模式也会做一些特殊的设置工作
// ...
// 再比如建立Binder死亡回调,当进AMS所在服务程异常退出的时候,
// Binder驱动可以通知到应用进程,并释放死亡进程锁占用的没有正常关闭的binder文件。
// 当SystemServer进程因为异常挂掉的时候,是有重启机制的
// ...
// 移除在AMS启动进程的过程中埋下的PROC_START_TIMEOUT_MSG消息
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
// ...
// IPC调用应用进程ApplicationThread的bindApplication:
thread.bindApplication(...);

AMS在完成对ApplicationThread一些设置工作后,会回到应用进程的bindApplication,bindApplication的时候,AMS会将一些通用的系统服务传递给应用进程,比如WMS,IMS等等。

public final void bindApplication(...) {
if (services != null) {
// 将AMS传过来的通用系统服务缓存到ServiceManager的
// 静态cache中
ServiceManager.initServiceCache(services);
}
// 通过ActivityThread的H(继承自Handler)
// 发送一条SET_CORE_SETTINGS的消息给主线程,
// 将coreSettings设置给ActivityThread对象
// 并触发当前进程所有Activity的重启(因为ActivityThread的核心设置被修改了)
setCoreSettings(coreSettings);
// AppBindData是bindApplication的一堆数据的封装
AppBindData data = new AppBindData();
// 通过mH发送BIND_APPLICATION消息给主线程
sendMessage(H.BIND_APPLICATION, data);
}

下面bindApplication的逻辑进入H中,H是ActivityThread中的自定义Handler,比如Service的创建,绑定,Activity的生命周期处理都在这里边:

而对于BIND_APPLICATION,handleMessage将调用到handleBindApplication。

在handleBindApplication中,会填充data.info字段,其实是LoadApk对象,通过getPackageInfo获取,其包含了比如mPackagerName应用包名,mDataDir应用数据目录,mResources,mApplication等信息。

然后是完成Context的创建:

final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
// createAppContext
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
String opPackageName) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
// 创建ContextImpl对象,初始化了ApplicationContext的mMainThread、packageInfo等字段
// 在ContextImpl的构造方法中,还创建了ApplicationContentResolver这个对象
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
0, null, opPackageName);
context.setResources(packageInfo.getResources());
// 是否是系统状态栏的Context
context.mIsSystemOrSystemUiContext = isSystemOrSystemUI(context);
return context;
}

完成Context的创建之后,后面会继续Application对象的创建,还是在handleBindApplication中:

Application app;
// ...
app = data.info.makeApplication(data.restrictedBackupMode, null);

// LoadedApk.makeApplication:
// ...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// 调用newApplication创建Application对象
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
// ...
// 将Application赋值给LoadedApk的mApplication,并添加到ActivityThread的Application列表
mApplication = app;

在newApplication中:

public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
// 内部就是反射Application Class的newInstance
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
// 将Context对象绑定给Application
app.attach(context);
return app;
}

// attach如下:
final void attach(Context context) {
// attachBaseContext就是将context赋值给Application(继承自ContextWrapper的)的mBase字段
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

继续回到应用进程的handleBindApplication中,在创建完Application对象之后:

// 回调到Application对象的onCreate方法
mInstrumentation.callApplicationOnCreate(app);

应用进程终于创建完成了,现在我们回到AMS的attachApplicationLocked中,在bindApplication完成Application对象的创建之后:

// 如果Application有待启动的Activity,那么执行Activity的启动
// 对于我们从Launcher中点击icon启动一个App来说,创建完新的进程和Application之后
// 就需要启动MainActivity
if (normalMode) {
try {
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
// ActivityTaskManagerService的内部类LocalService实现的attachApplication方法:
// 内部调用
mRootWindowContainer.attachApplication(wpc);

RootWindowContainer.attachApplication如下:

    boolean attachApplication(WindowProcessController app) throws RemoteException {
boolean didSomething = false;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
mTmpRemoteException = null;
mTmpBoolean = false; // Set to true if an activity was started.

final DisplayContent display = getChildAt(displayNdx);
for (int areaNdx = display.getTaskDisplayAreaCount() - 1; areaNdx >= 0; --areaNdx) {
final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(areaNdx);
for (int taskNdx = taskDisplayArea.getStackCount() - 1; taskNdx >= 0; --taskNdx) {
final ActivityStack rootTask = taskDisplayArea.getStackAt(taskNdx);
if (rootTask.getVisibility(null /*starting*/) == STACK_VISIBILITY_INVISIBLE) {
break;
}
// 找到待启动的ActivityRecord,然后
// 调用startActivityForAttachedApplicationIfNeeded
final PooledFunction c = PooledLambda.obtainFunction(
RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
PooledLambda.__(ActivityRecord.class), app,
rootTask.topRunningActivity());
rootTask.forAllActivities(c);
c.recycle();
if (mTmpRemoteException != null) {
throw mTmpRemoteException;
}
}
}
didSomething |= mTmpBoolean;
}
if (!didSomething) {
ensureActivitiesVisible(null, 0, false /* preserve_windows */);
}
return didSomething;
}

而startActivityForAttachedApplicationIfNeeded的实现,就是把我们找到的待启动的ActivityRecord,调用到mStackSupervisor.realStartActivityLocked。

回到ActivityStackSupervisor的startSpecificActivity:

    void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);

boolean knownToBeDead = false;
// 如果应用所在的进程已经存在,那么执行realStartActivityLocked
// 进行Activity启动
if (wpc != null && wpc.hasThread()) {
try {
// 这个函数后面再做分析
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}

// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}

r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

final boolean isTop = andResume && r.isTopRunningActivity();
// 如果应用进程不存在,ATMS(最终是AMS)将会异步启动应用进程
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}

AMS在调用到mService.startProcessAsync启动一个新的应用进程之后,最终还是通过ActivityStackSupervisor的realStartActivityLocked,启动应用进程的首个Activity,那么再往下看,就是一般Activity的启动流程了,realStartActivityLocked仍然比较长,取我们关心的逻辑:

// 创建一个Activity启动的事务,ClientTransaction是一个实现了Parcelable接口的类
// 即该事务对象可以跨进程传递
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final DisplayContent dc = r.getDisplay().mDisplayContent;
// 往事务中添加一个LaunchActivityItem,代表事务的Callback,后面会执行Callback中的逻辑
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),...));
// ...
// 调度事务,
mService.getLifecycleManager().scheduleTransaction(clientTransaction);

先来看下事务是怎样获取的:

public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {
// 先从对象池中找,找不到就创建
ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);
if (instance == null) {
instance = new ClientTransaction();
}
// 将IApplicationThread赋值给事务的mClient字段,
// 表示这个事务的接收端是哪个进程的ApplicationThread
instance.mClient = client;
instance.mActivityToken = activityToken;
return instance;
}

ClinetLifeCycleManager的调度事务实现如下:

void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
// ...
}
//transaction.schedule();实现如下,IPC调用到应用进程ApplicationThread的scheduleTransaction
mClient.scheduleTransaction(this);

而ApplicationThread中的scheduleTransaction实现,就是调用ActivityThread的scheduleTransaction方法(AT继承自ClientTransactionHandler,实现在父类中):

void scheduleTransaction(ClientTransaction transaction) {
// 当事务在客户端进程执行的时候,在执行之前做一个hook callback操作
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

发送出去的消息最终还是交给H来处理:

final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);

mTransactionExecutor并不是什么多线程的Executor,不过是对事务有序处理的逻辑封装,其execute如下:

public void execute(ClientTransaction transaction) {
// ...
// executeCallbacks中的重点就是执行传入事务的callback的execute方法
// item.execute(mTransactionHandler, token, mPendingActions);
//
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
// ...
}

而AMS在调用realStartActivityLocked传入事务的callback就是LaunchActivityItem,他的execute如下:

public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
// 创建一个ActivityClientRecord对象
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
// 这里client实际上就是TransactionExecutor中的mTransactionHandler
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
}

在ActivityThread中,ActivityThread对象创建的时候就会创建mTransactionExecutor对象,并把this引用传入到TransactionExecutor的构造方法中,所以这里mTransactionHandler正是实现了ClientTransactionHandler接口的ActivityThread对象,在ActivityThread的handleLaunchActivity中:

final Activity a = performLaunchActivity(r, customIntent);

而performLaunchActivity就会去创建对应的Activity对象,关于performLaunchActivity的分析,可以看前两篇Android UI系统工作流程。

0 个评论

要回复文章请先登录注册