-
前奏:
Android系统虽然基于Linux系统的,但是由于Android属于嵌入式设备,并没有像PC那样的BISO程序,取而代之的是Bootloader----系统启动加载器。
-
/boot : 存放引导程序,内核和内存操作程序
-
/system : 电脑C盘,存放系统及系统应用
-
/recovery : 恢复分区,进行系统恢复
-
/data : 用户数据区,包含用户数据有联系人、短信、设置、用户安装的程序
-
/cache : 系统缓存区,保存系统最常访问的数据和应用数据
-
/misc : 包含一些杂项内容,如系统设置和系统功能启用禁用设置
-
/sdcard : 用户自己的存储区,存放照片、音乐、视频等文
-
Android从点击桌面icon到APP显示流程
所谓冷启动就是启动该应用时,后台没有该应用的进程,此时系统会创建一个进程分配给它(AMS通过Socket和Zygote通信,Zygote通过forkAndSpecialize()方法向Linux内核申请新进程),之后会创建和初始化Application,然后通过反射执行ActivityThread中的main方法.而热启动则是,当启动应用的时候,后台已经存在该应用的进程,比如按home键返回主界面再打开该应用,此时会从已有的进程中来启动应用,这种方式下,不会重新走Application这一步.
-
Launcher3是分两层显示的,第一层就是开机启动和用户按Home键后显示的页面(桌面),第二层是用来展示系统中所有需要显示到Launcher上的应用(我们常说的抽屉)。当然,并非所有的Launcher都有两层结构,比如小米Launcher就只有一层结构,可根据实际需求进行设计。
-
开始分析,以下源码基于API 26,也就是Android 8.0
-
先看下大概流程图,时序图
-
首先是Lanucher,其本质也是一个APP,当我们点击桌面APP图标时,首先会相应它的onClick方法,然后调用startActivitySafely(v,intent,tag)方法,通过intent的addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)让Android创建一个新的Task存放即将打开的Activity,也就是应用的MainActivity,useLaunchAnimation是用于后续判断是否显示启动APP的动画,最终会调用Activity类的startActivity()方法或者launcherApps.startMainActivity(),后者是只在用户句柄不为空且其他用户的句柄调用时才触发,涉及Android多用户安全机制,这里以startActivity()讲解。
public void onClick(View v) { // Make sure that rogue clicks don't get through while allapps is launching, or after the // view has detached (it's possible for this to happen if the view is removed mid touch). ...... Object tag = v.getTag(); if (tag instanceof ShortcutInfo) { // Open shortcut final Intent intent = ((ShortcutInfo) tag).intent; int[] pos = new int[2]; v.getLocationOnScreen(pos); intent.setSourceBounds(new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight())); boolean success = startActivitySafely(v, intent, tag); ...... } boolean startActivitySafely(View v, Intent intent, Object tag) { boolean success = false; try { success = startActivity(v, intent, tag); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e); } return success; } boolean startActivity(View v, Intent intent, Object tag) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { // Only launch using the new animation if the shortcut has not opted out (this is a // private contract between launcher and may be ignored in the future). boolean useLaunchAnimation = (v != null) && !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION); UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE); LauncherApps launcherApps = (LauncherApps) this.getSystemService(Context.LAUNCHER_APPS_SERVICE); if (useLaunchAnimation) { ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); if (user == null || user.equals(android.os.Process.myUserHandle())) { // Could be launching some bookkeeping activity startActivity(intent, opts.toBundle()); } else { launcherApps.startMainActivity(intent.getComponent(), user, intent.getSourceBounds(), opts.toBundle()); ..... }
-
Activity
触发了Activity类的startActivity(),最后都会调用startActivityResult(Intent,requestCode,Bundle)方法,如果Lanucher有mParentActivity的话,将会调用mParent.startActivityFromChild(),这个方法最终还是会调用mInstrumentation.execStartActivity(),这个方法将创建过程委托给Instrumentation的execStartActivity()
@Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } } public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) { startActivityForResult(intent, requestCode, null); } public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); ........ }else{ if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } } public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, child, intent, requestCode, options); ........ }
-
Instrumentation
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, String resultWho, Intent intent, int requestCode, Bundle options, UserHandle user) { //关键IApplicationThread IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); ActivityResult result = null; if (am.ignoreMatchingSpecificIntents()) { result = am.onStartActivity(intent); } if (result != null) { am.mHits++; return result; } else if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; } break; } } } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(who); // 关键 ActivityManager int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }
参数IBinder contextThread取得的是传过来的IApplicationThread类型对象,由mMainThread.getApplicationThread()取得的,自然是代表Launcher的ApplicationThread。
其中target.onProvideReferrer()方法返回的是null,除非该方法被重写。
然后判断是否有ActivityMonitor,如果由,则即将要打开的Activity是否和ActivityMonitor中保存的IntentFilter匹配,如果匹配则增加ActivityMonitor的计数。
最后调用ActivityManager.getService.startActivity()启动Activity并且检查启动是否成功,因此,最终负责启动Activity的是ActivityManager。
上述内容涉及到ActivityManager、ApplicationThread、ActivityThread。
首先通过ActivityManager.getService()实际是在调用IActivityManager.Stub.asInterface(IBinder),通过源码发现ActivityManagerService 继承IActivityManager.Stub,这里和 7.0 不一样,没有使用代理和ActivityManagerService进行通信,所以getService()拿到的就是ActivityManagerService。
-
ActivityManagerService
其实startActivity()最终还是调用startActivityAsUser()方法,然后再调用ActivityStater的startActivityMayWait()、startActivityLocked()、startActivityUnchecked()方法,中间会有各种解析保存Activity的方法。
@Override public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) { enforceNotIsolatedCaller("startActivity"); userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); // TODO: Switch to user app stacks here. return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, bOptions, false, userId, null, null, "startActivityAsUser"); }
首先enforceNotIsolatedCaller()方法,进行安全检查,判断当前用户是否允许启动Activity
其次,mUserController.handleIncomingUser()方法则是对传入的userId进行安全性检查和转换
最后才是startActivityMayWait()方法,这是重点。调用对象ActivityStarter可以看作是管理ActivityTask的类。
-
ActivityStarter
在执行完startActivityMayWait()后可以看时序图,主要是做一些检查和新建TASK的事情,然后再startActivityUnchecked()方法里可以看到resumeTargetStackIfNeeded(),这里的意思就是将所有ActivityStack栈顶的Activity切换到resume状态
if (!mAddingToTask && mReuseTask == null) { // We didn't do anything... but it was needed (a.k.a., client don't use that // intent!) And for paranoia, make sure we have correctly resumed the top activity. resumeTargetStackIfNeeded(); if (outActivity != null && outActivity.length > 0) { outActivity[0] = reusedActivity; } return START_TASK_TO_FRONT; } private void resumeTargetStackIfNeeded() { if (mDoResume) { mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions); } else { ActivityOptions.abort(mOptions); } mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); }
-
ActivityStack
再mSupervisor.resumeFocusedStackTopActivityLocked()方法后面会发现,它又调用了ActivityStack的 7 resumeTopActivityUncheckedLocked()方法,然后内部调用了resumeTopActivityInnerLocked方法,这个方法主要是做一些前期的检查,避免做多余的工作浪费时间,并且确保目标Activity处于正确的状态,使得我们后面能把它切换到resume状态并显示,至于代码,大家可以看源码,源码内都有注释,都是一些Activity启动的条件处理。
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { if (mStackSupervisor.inResumeTopActivity) { // Don't even start recursing. return false; } boolean result = false; try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } // When resuming the top activity, it may be necessary to pause the top activity (for // example, returning to the lock screen. We suppress the normal pause logic in // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the end. // We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here to ensure // any necessary pause logic occurs. mStackSupervisor.checkReadyForSleepLocked(); return result; }
我们直接看resumeTopActivityInnerLocked()中将Launcher切换到pause状态部分,用WindowManager将Launcher的窗口隐藏。startPausingLocked()方法就是说把当前ActivityStack中正在显示的Activity切换到pause状态,中间遇到错误或者需要finish activity将会调用startPausingLocked()方法,这里Launcher置为了pause状态。方法resumeTopActivityInnerLocked()内最后执行的方法是ActivityStackSupervisor的startSpecificActivityLocked()方法,此时目标Activity已经切换到resume状态了,在可见之前会先调用startPausingLocked将其他Activity变成不可见。
// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity // to be paused, while at the same time resuming the new resume activity only if the // previous activity can't go into Pip since we want to give Pip activities a chance to // enter Pip before resuming the next activity. final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0 && !lastResumedCanPip; boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false); if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); pausing |= startPausingLocked(userLeaving, false, next, false); } if (pausing && !resumeWhilePausing) { if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES, "resumeTopActivityLocked: Skip resume: need to start pausing"); // At this point we want to put the upcoming activity's process // at the top of the LRU list, since we know we will be needing it // very soon and it would be a waste to let it get killed if it // happens to be sitting towards the end. if (next.app != null && next.app.thread != null) { mService.updateLruProcessLocked(next.app, true, null); } if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } else if (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) { // It is possible for the activity to be resumed when we paused back stacks above if the // next activity doesn't have to wait for pause to complete. // So, nothing else to-do except: // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. executeAppTransition(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; }
-
ActivityStackSupervisor
首先会通过报名和uid取得ProcessRecord,判断它是否创建,创建了则直接启动Activity,否则利用ActivityManagerService的startProcessLocked()方法创建进程。
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.getStack().setLaunchTime(r); if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, 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. } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }
-
ActivityManagerService
最后又回到ActivityManagerService中来了,由它来创建进程,首先判断的是是否是隔离进程(isolated),由于不是隔离进程,所以app=null,然后再调用newProcessRecordLocked()重新new ProcessRecord,最后调用重载的startProcessLocked()方法创建进程,最后调用Process.start方法,这里注意方法的第一个参数entryPoint ,这个参数传入的就是null,所以请留意这行代码 if (entryPoint == null) entryPoint = "android.app.ActivityThread";
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) { long startTime = SystemClock.elapsedRealtime(); ProcessRecord app; if (!isolated) { app = getProcessRecordLocked(processName, info.uid, keepIfLarge); checkTime(startTime, "startProcess: after getProcessRecord"); if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) { // If we are in the background, then check to see if this process // is bad. If so, we will just silently fail. if (mAppErrors.isBadProcessLocked(info)) { if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid + "/" + info.processName); return null; } } else { // When the user is explicitly starting a process, then clear its // crash count so that we won't make it bad until they see at // least one crash dialog again, and make the process good again // if it had been bad. if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid + "/" + info.processName); mAppErrors.resetProcessCrashTimeLocked(info); if (mAppErrors.isBadProcessLocked(info)) { EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, UserHandle.getUserId(info.uid), info.uid, info.processName); mAppErrors.clearBadProcessLocked(info); if (app != null) { app.bad = false; } } } } else { // If this is an isolated process, it can't re-use an existing process. app = null; } // We don't have to do anything more if: // (1) There is an existing application record; and // (2) The caller doesn't think it is dead, OR there is no thread // object attached to it so we know it couldn't have crashed; and // (3) There is a pid assigned to it, so it is either starting or // already running. if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName + " app=" + app + " knownToBeDead=" + knownToBeDead + " thread=" + (app != null ? app.thread : null) + " pid=" + (app != null ? app.pid : -1)); if (app != null && app.pid > 0) { if ((!knownToBeDead && !app.killed) || app.thread == null) { // We already have the app running, or are waiting for it to // come up (we have a pid but not yet its thread), so keep it. if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app); // If this is a new package in the process, add the package to the list app.addPackage(info.packageName, info.versionCode, mProcessStats); checkTime(startTime, "startProcess: done, added package to proc"); return app; } // An application record is attached to a previous process, // clean it up now. if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app); checkTime(startTime, "startProcess: bad proc running, killing"); killProcessGroup(app.uid, app.pid); handleAppDiedLocked(app, true, true); checkTime(startTime, "startProcess: done killing old proc"); } String hostingNameStr = hostingName != null ? hostingName.flattenToShortString() : null; if (app == null) { checkTime(startTime, "startProcess: creating new process record"); app = newProcessRecordLocked(info, processName, isolated, isolatedUid); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); return null; } app.crashHandler = crashHandler; checkTime(startTime, "startProcess: done creating new process record"); } else { // If this is a new package in the process, add the package to the list app.addPackage(info.packageName, info.versionCode, mProcessStats); checkTime(startTime, "startProcess: added package to existing proc"); } // If the system is not ready yet, then hold off on starting this // process until it is. if (!mProcessesReady && !isAllowedWhileBooting(info) && !allowWhileBooting) { if (!mProcessesOnHold.contains(app)) { mProcessesOnHold.add(app); } if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "System not ready, putting on hold: " + app); checkTime(startTime, "startProcess: returning with proc on hold"); return app; } checkTime(startTime, "startProcess: stepping in to startProcess"); startProcessLocked( app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs); checkTime(startTime, "startProcess: done starting proc!"); return (app.pid != 0) ? app : null; } private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { ........ startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, entryPointArgs); ........ }
-
Process
process创建进程是通过Zygote进程完成的,然后fork()创建进程,在zygote内对这个参数的介绍是 Class name whose static main() to run,所以可以知道这里是执行ActivityThread的main()方法。
public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] zygoteArgs) { return zygoteProcess.start(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, zygoteArgs); }
-
ActivityThread
main()方法首先是进行一些初始化(包括参数设置、性能安全监控之类的),然后初始化Looper(Looper、Hanndler消息机制),创建ActivityThread,存储线程的Handler,最后启动Looper监听消息。
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false); Environment.initForCurrentUser(); // Set the reporter for event logging in libcore EventLogger.setReporter(new EventLoggingReporter()); // Make sure TrustedCertificateStore looks in the right place for CA certificates final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); 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")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
ActivityThread是通过Binder将ApplicationThread对象传递给ActivityManagerService,并完成启动Activity的后续工作。
到这一步,已经将Launcher切换到了pause状态,但是目标应用进程和线程还没有创建,所以暂时还没有把目标应用的MainActivity切换到resume状态。所以应用进程需要和ActivityManagerService所在的system_server进程通信。
在thread.attach(false)里面可以查看到以下两行代码
final IActivityManager mgr = ActivityManager.getService(); mgr.attachApplication(mAppThread);
是不是很熟悉,因为在之前已经见到过了,返回的依旧是如下
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am;
所以,可以看出来吧,这里实现了ActivityThread与ActivityManagerService通信。
ActivityManagerService,有以下代码供其通信。
@Override public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); }
回到ActivityThread,在attachApplicationLocked()后会调用bindApplication(),然后通过Message把消息发送出去。
public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableBinderTracking, boolean trackAllocation, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map services, Bundle coreSettings, String buildSerial) { if (services != null) { // Setup the service cache in the ServiceManager ServiceManager.initServiceCache(services); } setCoreSettings(coreSettings); AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableBinderTracking = enableBinderTracking; data.trackAllocation = trackAllocation; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; data.buildSerial = buildSerial; sendMessage(H.BIND_APPLICATION, data); }
主要是看最后sendMessage(H.BIND_APPLICATION, data)是如何处理H.BIND_APPLICATION消息的。
case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;
在handleBindApplication方法里,首先进行一些初始化操作,设置进程名,创建进程的Instrumentation、Application、装载Provider等,最后调用mInstrumentation.callApplicationOnCreate(app),也就是APP的onCreate()方法。
然后进入到ActivityStatckSupervisor类的attachApplicationLocked()方法,该方法遍历mActivityDislays列表得到当前所有ActivityStack,然后取得前台得ActivityStack栈顶ActivityRecord,不为空则调用realStartActivityLockd()方法。
在realStartActivityLocked()方法里会执行thread.scheduleLaunchActivity(),让ActivityThread调度执行Ac'ti'vi't'y生命周期方法,完成Activity的启动。
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);
上述代码,在ActivityThread里会发送一条H.LAUNCH_ACTIVITY的消息,和之前操作类似。之后会调用handleLaunchActivity()方法
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(); } // Make sure we are running with the most recent config. handleConfigurationChanged(null, null); if (localLOGV) Slog.v( TAG, "Handling launch of " + r); // Initialize before creating the activity WindowManagerGlobal.initialize(); Activity a = performLaunchActivity(r, customIntent); if (a != null) { r.createdConfig = new Configuration(mConfiguration); reportSizeConfigurations(r); Bundle oldState = r.state; handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason); if (!r.activity.mFinished && r.startsNotResumed) { // The activity manager actually wants this one to start out paused, because it // needs to be visible but isn't in the foreground. We accomplish this by going // through the normal startup (because activities expect to go through onResume() // the first time they run, before their window is displayed), and then pausing it. // However, in this case we do -not- need to do the full pause cycle (of freezing // and such) because the activity manager assumes it can just retain the current // state it has. performPauseActivityIfNeeded(r, reason); // We need to keep around the original state, in case we need to be created again. // But we only do this for pre-Honeycomb apps, which always save their state when // pausing, so we can not have them save their state when restarting from a paused // state. For HC and later, we want to (and can) let the state be saved as the // normal part of stopping the activity. if (r.isPreHoneycomb()) { r.state = oldState; } } } else { // If there was an error, for any reason, tell the activity manager to stop us. try { ActivityManager.getService() .finishActivity(r.token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } }
在上述代码中有一个performLaunchActivity()方法,通过反射得到MainActivity方法,然后调用mInstrumentation.callActivityOnCreate()、activity.performStart()、handleResumeActivity()、performPauseActivityIfNeeded()、finishActivity()。
总结
-
Launcher通过Binder建立Launcher所在进程与system_server进程,即ActivityManagerService的进程通信,通知Activity启动
-
ActivityManagerService通过Binder让Launcher进入pause状态
-
Launcher进入pause后,通过Binder告知ActivityManagerService,然后ActivityManagerService创建一个进程(应用进程)启动ActivityThread,也可以说是UI线程。
-
ActivityThread 通过Binder将ApplicationThread类型的Binder对象传给ActivityManangerService,方便之后的调度任务
-
ActivityManagerService通知ActivityThread启动Activity
-
ActivityThread调度执行Activity的生命周期方法,完成启动Activity的工作。