• 前奏:

    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

  • 先看下大概流程图,时序图

  1. 首先是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 shortcutfinal 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 activitystartActivity(intent, opts.toBundle());} else {launcherApps.startMainActivity(intent.getComponent(), user,intent.getSourceBounds(),opts.toBundle());.....}
  2. 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);........}
  3. Instrumentation

    public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, String resultWho,Intent intent, int requestCode, Bundle options, UserHandle user) {//关键IApplicationThreadIApplicationThread 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);// 关键 ActivityManagerint 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。

  4. 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的类。

  5. 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);}
  1. 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;}
  2. 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);}
    ​
  3. 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 listapp.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 listapp.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);........}
  4. 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);}
  5. 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 libcoreEventLogger.setReporter(new EventLoggingReporter());
    ​// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal 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(newLogPrinter(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,有以下代码供其通信。

    @Overridepublic 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 ServiceManagerServiceManager.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 activityWindowManagerGlobal.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的工作。

AOSP Android 8.0 冷启动流程分析(二)相关推荐

  1. Android8.0(34)----Android 8.0 Settings流程分析与变动

    Android 8.0 Settings流程分析与变动 一,相比Android Settings 7.0 如下图,在7.0的基础上,去掉了7.0新加的侧滑菜单(可能是觉得有点鸡肋吧).多加了一级页面, ...

  2. Android 7.0 Keyguard流程分析

    在android 6.0 上Keyguard作为了SystemUI的一个库文件被引用,所以编译的时候不会出现Keyguard.apk这个文件,Keyguard也伴随着SystemUI的启动而启动,其中 ...

  3. Android 7.0系统启动流程分析

    随着Android版本的升级,aosp项目中的代码也有了些变化,本文基于Android 7.0分析Android系统启动流程.当我们按下电源键后,整个Android设备大体经过了一下过程:  今天我们 ...

  4. Android 8.0 recovery 流程分析

    这里主要分析non A/B模式下的recovery流程 A/B模式下的recovery在boot中 后续会不断补充,如果有疏漏或者错误的地方,请指出,共同学习,谢谢! 一.流程分析 首先列出recov ...

  5. Android 11 热点(softap)流程分析(二) WifiManager--AIDL

    Android 10以后引入了stable aidl方法,结合上一篇中WifiManager类中通过aidl调用到WifiServiceImpl类中方法,做个详细的记录. 一.frameworks/b ...

  6. Android 9.0 Vold 流程分析(-)

    Vold 介绍 Vold(volume Daemon),即Volume守护进程,用来管理Android中存储类的热拔插事件,处于Kernel和Framework之间,是两个层级连接的桥梁.vold 代 ...

  7. Android9.0 setMasterVolume流程分析(二十三)

    android audio 生产者与消费者 简介 全面接触生产者/消费者问题是在操作系统原理中,并发性原理讨论的问题 生产者/消费者问题.最近的工作偏向音频,接着上一篇文章,用生产者,消费者模型来理解 ...

  8. Android 手机灭屏流程分析详解

    参考地址:https://www.jianshu.com/p/9241f3a91095 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 1.前言 2.Pow ...

  9. android加载efi分区,高通Android UEFI XBL 代码流程分析

    高通Android UEFI XBL 代码流程分析 背景 之前学习的lk阶段点亮LCD的流程算是比较经典,但是高通已经推出了很多种基于UEFI方案的启动架构. 所以需要对这块比较新的技术进行学习.在学 ...

最新文章

  1. iOS开发业界毒瘤 Hook
  2. jvmti_从javaagent迁移到JVMTI:我们的经验
  3. Ant Design 4.0 进行时!
  4. 成功在两台电脑上安装了spark集群,mark下
  5. iOS:步进UIStepper、滑动块UISlider、开关UISwitch的基本使用
  6. 【php】用filter_var实现的简单参数验证
  7. 麦克风设计指导与选型参考
  8. 校园网未能找到pppoe服务器6,校园网PPPOE接入认证系统的研究与实现.doc
  9. 计算机网络学习笔记(18. 网络应用(层)内容概述)
  10. 2019年上海春运志愿服务启动 3000余名志愿者守护归乡路
  11. mysql集群 自增_为什么我们要从MySQL迁移到TiDB?
  12. 大麦盒子DM1004线刷降级填坑记录
  13. c语言的实验报告实验原理,c语言实验报告
  14. 赖美云的认证照_火箭少女最新路透照出炉:吴宣仪赖美云魅力十足,张紫宁傅菁凭颜值圈粉...
  15. 使用nginx配置子域名
  16. [书籍翻译]12周撰写期刊文章 学术出版成功指南——第 7 周:出示证据
  17. 基于Mysql的智慧医疗管理系统
  18. 一个很好用的小程序生成二维码海报的组件库
  19. 计算机实验adda转换心得体会,dsp实验ADDA
  20. 5分钟轻松学习多租户概念

热门文章

  1. Html标签——table表格
  2. 电机的matlab仿真实例,电机控制Matlab仿真模型
  3. Samba服务器搭建与配置
  4. 绘制森林资源图的工具介绍
  5. 英特尔固态硬盘测试软件,AS SSD测试:IOPS值高达11万_Intel 520_固态硬盘评测-中关村在线...
  6. FPGA(一)Vivado与ModelSim
  7. 2017年终总结,毕业和工作
  8. c++重写卷积网络的前向计算过程,复现theano的测试结果
  9. 戴尔7060安服务器系统,戴尔7060装win7系统教程和BIOS设置方法(USB驱动可用)
  10. 再见了 SELECT * !大厂的 MySQL 查询优化方案,确实牛逼!