1- 总体概述
启动流程:
1- 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
2-system_server进程接收到请求后,向zygote进程发送创建进程的请求;
3-Zygote进程fork出新的子进程,即App进程
4-App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
5-system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
6-App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
7-主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。
source file:
frameworks/base/services/core/java/com/android/server/am/
-ActivityManagerService.java
- ActivityStackSupervisor.java
- ActivityStack.java
- ActivityRecord.java
- ProcessRecord.java
frameworks/base/core/java/android/app/IApplicationThread.aidl
frameworks/base/core/java/android/app/Instrumentation.java
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
2-详细分解
从Activity.java 启动,到realStartActivityLocked 部分
Activity.java:
--->startActivity:[Activity.java]
-->startActivityForResult
-->mInstrumentation.execStartActivity [Instrumentation.java]
--->ActivityManager.getService().startActivity [ActivityManagerService.java]
--->startActivityAsUser
---->mActivityStarter.startActivityMayWait [ActivityStarter.java]
---->startActivityLocked
---->doPendingActivityLaunchesLocked
----->startActivity:[ActivityStarter.java]
----->startActivityUnchecked
--->mTargetStack.startActivityLocked [ActivityStack.java] //锁定要show 的Activity
--->mSupervisor.resumeFocusedStackTopActivityLocked [ActivityStackSupervisor.java] //重点
---->resumeTopActivityUncheckedLocked [ActivityStack.java]
---->resumeTopActivityInnerLocked//这里任务比较多,考虑启动阶段,休眠, 不显示activity. 失败返回home
----->mStackSupervisor.startSpecificActivityLocked[ActivityStackSupervisor.java]
----->realStartActivityLocked //真正启动Activity, 由app 存在,不用创建process,走到下面的流程
-else->mService.startProcessLocked [ActivityManagerService.java]启动process, 不存在则创建
从上面的流程接着分析startProcessLocked-->realStartActivityLocked-->onCreate,onStart..
AMS.startProcessLocked
--->AMP.attachApplication, 创建之后,就会attach app
---->AMS.attachApplicationLocked
---->mStackSupervisor.attachApplicationLocked [ActivityStackSupervisor.java]
--->realStartActivityLocked // 找到第一个 非finish activity ,进行真正启动,更新配置
--->app.forceProcessStateUpTo //将该进程设置为前台进程
--->app.thread.scheduleLaunchActivity //这里才是启动开始走到onCreate
---->( if (r.launchFailed) 如果第二次启动失败,则进行giveup )
---->scheduleLaunchActivity [IApplicationThread.aidl] //aidl 最后转换binder 通信
----》scheduleLaunchActivity [ActivityThread.java]
--->sendMessage(H.LAUNCH_ACTIVITY, r); //使用了handler 机制,进行了通信
---->handleMessage:handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); //handleMessage 处理
--->handleConfigurationChanged //处理config变化
--->WindowManagerGlobal.initialize() //初始化wms
--->performLaunchActivity ----mInstrumentation.callActivityOnCreate //回调onCreate
--->handleResumeActivity //回调onStart ,onResume
ActivityStackSupervisor.java:realStartActivityLocked下面的函数认为比较重要
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
if (!allPausedActivitiesComplete()) {
// While there are activities pausing we skipping starting any new activities until
// pauses are complete. NOTE: that we also do this for activities that are starting in
// the paused state because they will first be resumed then paused on the client side.
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"realStartActivityLocked: Skipping start of r=" + r
+ " some activities pausing...");
return false;
}
final TaskRecord task = r.getTask();
final ActivityStack stack = task.getStack();
beginDeferResume();
try {
r.startFreezingScreenLocked(app, 0);
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
r.app = app;
if (mKeyguardController.isKeyguardLocked()) {
r.notifyUnknownVisibilityLaunched();
}
// Have the window manager re-evaluate the orientation of the screen based on the new
// activity order. Note that as a result of this, it can call back into the activity
// manager with a new orientation. We don't care about that, because the activity is
// not currently running so we are just restarting it anyway.
if (checkConfig) {
final int displayId = r.getDisplayId();
final Configuration config = mWindowManager.updateOrientationFromAppTokens(
getDisplayOverrideConfiguration(displayId),
r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId);
// Deferring resume here because we're going to launch new activity shortly.
// We don't want to perform a redundant launch of the same record while ensuring
// configurations and trying to resume top activity of focused stack.
mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */,
displayId);
}
//这里应该显示了shouldBeVisible
if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,
true /* isTop */)) {
// We only set the visibility to true if the activity is allowed to be visible
// based on
// keyguard state. This avoids setting this into motion in window manager that is
// later cancelled due to later calls to ensure visible activities that set
// visibility back to false.
r.setVisibility(true);
}
final int applicationInfoUid =
(r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {
Slog.wtf(TAG,
"User ID for activity changing for " + r
+ " appInfo.uid=" + r.appInfo.uid
+ " info.ai.uid=" + applicationInfoUid
+ " old=" + r.app + " new=" + app);
}
app.waitingToKill = null;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);
int idx = app.activities.indexOf(r);
if (idx < 0) {
app.activities.add(r);
}
mService.updateLruProcessLocked(app, true, null);
mService.updateOomAdjLocked();
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE",
false);
}
try {
if (app.thread == null) {
throw new RemoteException();
}
List results = null;
List newIntents = null;
if (andResume) {
// We don't need to deliver new intents and/or set results if activity is going
// to pause immediately after launch.
results = r.results;
newIntents = r.newIntents;
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Launching: " + r + " icicle=" + r.icicle + " with results=" + results
+ " newIntents=" + newIntents + " andResume=" + andResume);
EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId,
System.identityHashCode(r), task.taskId, r.shortComponentName);
if (r.isHomeActivity()) {
// Home process is the root process of the task.
mService.mHomeProcess = task.mActivities.get(0).app;
}
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
r.sleeping = false;
r.forceNewConfig = false;
mService.showUnsupportedZoomDialogIfNeededLocked(r);
mService.showAskCompatModeDialogLocked(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
ProfilerInfo profilerInfo = null;
if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
if (mService.mProfileProc == null || mService.mProfileProc == app) {
mService.mProfileProc = app;
ProfilerInfo profilerInfoSvc = mService.mProfilerInfo;
if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
if (profilerInfoSvc.profileFd != null) {
try {
profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
} catch (IOException e) {
profilerInfoSvc.closeFd();
}
}
profilerInfo = new ProfilerInfo(profilerInfoSvc);
}
}
}
app.hasShownUi = true;
app.pendingUiClean = true;
app.forceProcessStateUpTo(mService.mTopProcessState);
// Because we could be starting an Activity in the system process this may not go
// across a Binder interface which would create a new Configuration. Consequently
// we have to always create a new Configuration here.
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
r.setLastReportedConfiguration(mergedConfiguration);
logIfTransactionTooLarge(r.intent, r.icicle);
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);
if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
// This may be a heavy-weight process! Note that the package
// manager will ensure that only activity can run in the main
// process of the .apk, which is the only thing that will be
// considered heavy-weight.
if (app.processName.equals(app.info.packageName)) {
if (mService.mHeavyWeightProcess != null
&& mService.mHeavyWeightProcess != app) {
Slog.w(TAG, "Starting new heavy weight process " + app
+ " when already running "
+ mService.mHeavyWeightProcess);
}
mService.mHeavyWeightProcess = app;
Message msg = mService.mHandler.obtainMessage(
ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
msg.obj = r;
mService.mHandler.sendMessage(msg);
}
}
} catch (RemoteException e) {
//这里是系统工程可以处理的,如果不想二次启动activity ,就修改framework 流程
if (r.launchFailed) {
// This is the second time we failed -- finish activity
// and give up.
Slog.e(TAG, "Second failure launching "
+ r.intent.getComponent().flattenToShortString()
+ ", giving up", e);
mService.appDiedLocked(app);
stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
"2nd-crash", false);
return false;
}
// This is the first time we failed -- restart process and
// retry.
r.launchFailed = true;
app.activities.remove(r);
throw e;
}
} finally {
endDeferResume();
}
r.launchFailed = false;
if (stack.updateLRUListLocked(r)) {
Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list");
}
if (andResume && readyToResume()) {
// As part of the process of launching, ActivityThread also performs
// a resume.
stack.minimalResumeActivityLocked(r);
} else {
// This activity is not starting in the resumed state... which should look like we asked
// it to pause+stop (but remain visible), and it has done so and reported back the
// current icicle and other state.
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to PAUSED: " + r + " (starting in paused state)");
r.state = PAUSED;
}
// Launch the new version setup screen if needed. We do this -after-
// launching the initial activity (that is, home), so that it can have
// a chance to initialize itself while in the background, making the
// switch back to it faster and look better.
if (isFocusedStack(stack)) {
mService.startSetupActivityLocked();
}
// Update any services we are bound to that might care about whether
// their client may have activities.
if (r.app != null) {
mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
}
return true;
}
备注: 以上分析是基于android O
Ref:
http://gityuan.com/2016/03/12/start-activity/
http://androidxref.com/8.0.0_r4/
https://developer.android.com/guide/components/activities/intro-activities