AOSP Android 8.0 冷启动流程分析(二)

  • 前奏:

    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 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());
                      .....
       }
  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) {
            //关键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。

  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 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);
                 ........
            }
  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 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的工作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值