Android M应用启动流程分析-阿里云开发者社区

开发者社区> lusing> 正文

Android M应用启动流程分析

简介: Android M的Activity启动的完整流程
+关注继续查看

更新:
2016-10-29:更新handleBindApplication部分。

我这个版本的原则是,有话则长,无话则短.

以下分析基于6.0.1_r10版本。
先看一张大图:
android_app_startup

1. 桌面的onClick事件(进程:桌面应用的进程)

我们暂时忽略Input处理的过程,以桌面的onClick事件被触发为起点。
这部分根据Launcher的不同而大同小异。

2. ActivityManagerService之startActivity(进程AmS)

路径:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
桌面调用framework,最后会调到AmS的startActivity方法.
现在是多用户时代了,startActivity现在唯一做的事儿,就是通过UserHandle.getCallingUserId()去获取当前的user id,然后调用startActivityAsUser方法。

3848    @Override
3849    public final int startActivity(IApplicationThread caller, String callingPackage,
3850            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
3851            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
3852        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
3853            resultWho, requestCode, startFlags, profilerInfo, options,
3854            UserHandle.getCallingUserId());
3855    }

3. ActivityManagerService之startActivityAsUser

这个方法如其名,还真是只处理跟user相关的工作,调用handleIncomingUser。
之后,调用ActivityStackSupervisor来去处理跟Activity状态相关真正逻辑。

3857    @Override
3858    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
3859            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
3860            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
3861        enforceNotIsolatedCaller("startActivity");
3862        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
3863                false, ALLOW_FULL_ONLY, "startActivity", null);
3864        // TODO: Switch to user app stacks here.
3865        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
3866                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
3867                profilerInfo, null, null, options, false, userId, null, null);
3868    }

4. ActivityStackSupervisor之startActivityMayWait(进程AmS)

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
先解释一下为什么叫MayWait,因为调用startActivity是可能要等待结果的startActivityForResult,那就要挂起调用者。
首先,startActivityMayWait要读取一些信息。从4.4开始,这部分逻辑写到resolveActivity方法中,它会调用PackageManagerService的resolveIntent方法。这个方法会先调用queryIntentActivities方法出查询相关的列表,然后再调用chooseBestActivity方法去选择。为了不影响主线,这些支线内容后面再讲。
主线往下走,进入startActivityLocked。Locked意思是调用者需要保证加锁保护,不能重复调用,在startActivityMayWait中,是采用mService对象,也就是构造ActivityStackSupervisor时传进来的ActivityManagerService的对象。
调用成功了之后,如果需要wait,就让mService.wait()去等待吧。新Activity还在征途上。

925    final int startActivityMayWait(IApplicationThread caller, int callingUid,
926            String callingPackage, Intent intent, String resolvedType,
927            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
928            IBinder resultTo, String resultWho, int requestCode, int startFlags,
929            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
930            Bundle options, boolean ignoreTargetSecurity, int userId,
931            IActivityContainer iContainer, TaskRecord inTask) {
...
941        // Collect information about the target of the Intent.
942        ActivityInfo aInfo =
943                resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
...
1045            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
1046                    voiceSession, voiceInteractor, resultTo, resultWho,
1047                    requestCode, callingPid, callingUid, callingPackage,
1048                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
1049                    componentSpecified, null, container, inTask);
...

5. ActivityStackSupervisor之startActivityLocked

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

前面先做一系列检查的工作,比如权限,比如Intent防火墙检查。
准备做好之后,就new一个ActivityRecord,用于存储Activity的各种状态和历史信息。
然后,通过getFocusedStack方法获取当前获取焦点的ActivityStack。ActivityStackSupervisor中的mFocusedStack中保存了当前的前台ActivityStack。
下面就准备切换新进程了,先判断一下是否可以切换,如果处于通话中界面等无法马上切换的情况。通过ActivityManagerService的checkAppSwitchAllowedLocked方法来做检查,如果当前不允许做进程切换,就先存到PendingActivityLaunch的列表中,等待以后有机会再调用。
如果允许做切换,那么先检查一下当前是否有以前的等待任务,如果有就先执行它们,调用doPendingActivityLaunchesLocked方法去执行这个循环。
如果以上都完成了,就调用startActivityUncheckedLocked。

1399    final int startActivityLocked(IApplicationThread caller,
1400            Intent intent, String resolvedType, ActivityInfo aInfo,
1401            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1402            IBinder resultTo, String resultWho, int requestCode,
1403            int callingPid, int callingUid, String callingPackage,
1404            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
1405            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
1406            ActivityContainer container, TaskRecord inTask) {
...
1675        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
1676                startFlags, true, options, inTask);
1677
1678        if (err < 0) {
1679            // If someone asked to have the keyguard dismissed on the next
1680            // activity start, but we are not actually doing an activity
1681            // switch...  just dismiss the keyguard now, because we
1682            // probably want to see whatever is behind it.
1683            notifyActivityDrawnForKeyguard();
1684        }
1685        return err;
1686    }

6. ActivityStackSupervisor之startActivityUncheckedLocked

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
通过一系列分析,找到了该执行的目标ActivityStack,然后调用该ActivityStack的startActivityLocked方法针对该任务做具体的操作。

1828    final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
1829            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
1830            boolean doResume, Bundle options, TaskRecord inTask) {
...
2457        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
2458        targetStack.mLastPausedActivity = null;
2459        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
2460        if (!launchTaskBehind) {
2461            // Don't set focus on an activity that's going to the back.
2462            mService.setFocusedActivityLocked(r, "startedActivity");
2463        }
2464        return ActivityManager.START_SUCCESS;
2465    }

7. ActivityStack之startActivityLocked

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
如果需要的话,这一步中会调用到WmS的setAppStartingWindow,开始准备新应用的启动窗口。
这其中,有重要一步是调用WindowManagerService的addAppToken方法去将信息共步给WmS,为下一步的显示做准备。
最后,调用ActivityStackSupervisor的resumeTopActivitiesLocked方法,将显示的Activities都resume一下。

2074    final void startActivityLocked(ActivityRecord r, boolean newTask,
2075            boolean doResume, boolean keepCurTransition, Bundle options) {
...
2232        if (doResume) {
2233            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
2234        }
2235    }

8. ActivityStackSupervisor之resumeTopActivitiesLocked

先获取当前焦点显示的ActivityStack,调其resumeTopActivityLocked。完成后,遍历所有能显示的Activity的stack。

2727    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
2728            Bundle targetOptions) {
2729        if (targetStack == null) {
2730            targetStack = mFocusedStack;
2731        }
2732        // Do targetStack first.
2733        boolean result = false;
2734        if (isFrontStack(targetStack)) {
2735            result = targetStack.resumeTopActivityLocked(target, targetOptions);
2736        }
2737
2738        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2739            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2740            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2741                final ActivityStack stack = stacks.get(stackNdx);
2742                if (stack == targetStack) {
2743                    // Already started above.
2744                    continue;
2745                }
2746                if (isFrontStack(stack)) {
2747                    stack.resumeTopActivityLocked(null);
2748                }
2749            }
2750        }
2751        return result;
2752    }

9. ActivityStack之resumeTopActivityLocked

调用resumeTopActivityInnerLocked

1540    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
1541        if (mStackSupervisor.inResumeTopActivity) {
1542            // Don't even start recursing.
1543            return false;
1544        }
1545
1546        boolean result = false;
1547        try {
1548            // Protect against recursion.
1549            mStackSupervisor.inResumeTopActivity = true;
1550            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
1551                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
1552                mService.updateSleepIfNeededLocked();
1553            }
1554            result = resumeTopActivityInnerLocked(prev, options);
1555        } finally {
1556            mStackSupervisor.inResumeTopActivity = false;
1557        }
1558        return result;
1559    }

10. ActivityStack之resumeTopActivityInnerLocked

这是第一次进入这个方法,这次我们是走pause桌面这一支,下一次我们就走到最后的startSpecificActivityLocked那一支。
调用startPausingLocked去pause。

1561    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
...
1729        if (mResumedActivity != null) {
1730            if (DEBUG_STATES) Slog.d(TAG_STATES,
1731                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
1732            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
1733        }

11. ActivityStack之startPausingLocked

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
AmS开始发起pause桌面的操作
如果不是从桌面启动的话,就要去为上一个应用抓个用于显示在近期任务里的图。
prev.updateThumbnailLocked(screenshotActivities(prev), null);
处理完成之后,通知桌面应用去执行onPause。
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,userLeaving, prev.configChangeFlags, dontWait);
这个thread就是IPC的ApplicationThreadNative对象。

802    /**
803     * Start pausing the currently resumed activity.  It is an error to call this if there
804     * is already an activity being paused or there is no resumed activity.
805     *
806     * @param userLeaving True if this should result in an onUserLeaving to the current activity.
807     * @param uiSleeping True if this is happening with the user interface going to sleep (the
808     * screen turning off).
809     * @param resuming True if this is being called as part of resuming the top activity, so
810     * we shouldn't try to instigate a resume here.
811     * @param dontWait True if the caller does not want to wait for the pause to complete.  If
812     * set to true, we will immediately complete the pause here before returning.
813     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
814     * it to tell us when it is done.
815     */
816    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
817            boolean dontWait) {
...
860        if (prev.app != null && prev.app.thread != null) {
861            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
862            try {
863                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
864                        prev.userId, System.identityHashCode(prev),
865                        prev.shortComponentName);
866                mService.updateUsageStats(prev, false);
867                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
868                        userLeaving, prev.configChangeFlags, dontWait);

12. ApplicationThreadNative的schedulePauseActivity

路径:frameworks/base/core/java/android/app/ApplicationThreadNative.java
AmS要通过IPC来通知给桌面,于是通过Proxy来发送IPC操作.

718    public final void schedulePauseActivity(IBinder token, boolean finished,
719            boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
720        Parcel data = Parcel.obtain();
721        data.writeInterfaceToken(IApplicationThread.descriptor);
722        data.writeStrongBinder(token);
723        data.writeInt(finished ? 1 : 0);
724        data.writeInt(userLeaving ? 1 :0);
725        data.writeInt(configChanges);
726        data.writeInt(dontReport ? 1 : 0);
727        mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
728                IBinder.FLAG_ONEWAY);
729        data.recycle();
730    }

13. ActivityThread之schedulePauseActivity (桌面进程)

路径:frameworks/base/core/java/android/app/ActivityThread.java
通过IPC,运行桌面应用的ActivityThread的schedulePauseActivity。此处ActivityThread会将这个请求放入队列中,等待运行。

588        public final void schedulePauseActivity(IBinder token, boolean finished,
589                boolean userLeaving, int configChanges, boolean dontReport) {
590            sendMessage(
591                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
592                    token,
593                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
594                    configChanges);
595        }

在这段期间,WmS也没闲着,类似于之前我们在startActivityLocked时做的addWindow之类的操作一直在干活。

14. ActivityThread之handlePauseActivity (桌面进程)

终于从队列中轮到出场了,开始执行桌面的onPause吧。

不过先别急,执行onPause之前,先执行performUserLeavingActivity,最后会调到Activity的performUserLeaving。
这个方法做两步:

final void performUserLeaving() {
    onUserInteraction();
    onUserLeaveHint();
}

这些都做完了,调用performPauseActivity。

3305    private void handlePauseActivity(IBinder token, boolean finished,
3306            boolean userLeaving, int configChanges, boolean dontReport) {
...
3310            if (userLeaving) {
3311                performUserLeavingActivity(r);
3312            }
...
3315            performPauseActivity(token, finished, r.isPreHoneycomb());
...
3325                    ActivityManagerNative.getDefault().activityPaused(token);
...
}

15. ActivityThread之performPauseActivity

首先判断一下状态,如果已经pause了,那就需要先resume之。当然,如果pause了之后正在finishing中,就算了,不是的话,抛个RuntimeException,问问调用者不先resume是为哪般。
没有异常的话,先调用callCallActivityOnSaveInstanceState,这个会通过Instrumentation的callActivityOnSaveInstanceState去调用Activity的performSaveInstanceState, 然后会调到Activity的onSaveInstanceState。还会将对话框的信息做保存操作。
保存完状态之后,再调用Instrumentation的callActivityOnPause。然后调用Activity的performPause。
Activity在onPause之前,先通知各个Fragment去onPause,再调用Activity的onPause.
performPauseActivity结束后,回到launchPauseActivity,下面通知AMS,调IPC来做activityPaused。

16. ActivityManagerNative 之activityPaused

路径:frameworks/base/core/java/android/app/ActivityManagerNative.java
桌面的onPause执行完了,通过IPC通知AmS,可以启动新应用了。

17. ActivityManagerService之activityPaused

路径:services/core/java/com/android/server/am/ActivityManagerService.java
AmS收到activityPaused的消息,然后找到对应的ActivityStack的activityPausedLocked。

18. ActivityStack之activityPausedLocked

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
然后调用completePausedLocked。

19. ActivityStack之completePauseLocked

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
到此,桌面的onPause正式告一段落。
结束之后,再次调用前面我们已经遇到过的ActivityStackSupervisor的resumeTopActivitiesLocked,前一次我们走了一半就调pause过程去了,这次我们将走到最后。

20. ActivityStackSupervisor之resumeTopActivitiesLocked

还跟上次一样,调相应的ActivityStack的resumeTopActivityLocked。

21. ActivityStack之resumeTopActivityLocked

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
这个方法只是一个十几行的wrapper,除了设了个flag和处理锁屏之外,直接调用resumeTopActivityInnerLocked方法。

22. ActivityStack之resumeTopActivityInnerLocked

这个大方法走到最后,执行ActivityStackSupervisor的startSpecificActivityLocked。
(注:这个方法是5.0之后分出来的,4.4上还在resumeTopActivityLocked里面)

23. ActivityStackSupervisor之startSpecificActivityLocked (AmS进程)

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
从这里,又从ActivityStackSupervisor调回ActivityManagerService,调用startProcessLocked。

24. ActivityManagerService 之startProcessLocked

路径:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
通过调用android.os.Process的start去启动新进程。

25. Process.start

路径:frameworks/base/ core/java/android/os/Process.java
其实就是startViaZygote的一个简单封装。

481    public static final ProcessStartResult start(final String processClass,
482                                  final String niceName,
483                                  int uid, int gid, int[] gids,
484                                  int debugFlags, int mountExternal,
485                                  int targetSdkVersion,
486                                  String seInfo,
487                                  String abi,
488                                  String instructionSet,
489                                  String appDataDir,
490                                  String[] zygoteArgs) {
491        try {
492            return startViaZygote(processClass, niceName, uid, gid, gids,
493                    debugFlags, mountExternal, targetSdkVersion, seInfo,
494                    abi, instructionSet, appDataDir, zygoteArgs);
495        } catch (ZygoteStartFailedEx ex) {
496            Log.e(LOG_TAG,
497                    "Starting VM process through Zygote failed");
498            throw new RuntimeException(
499                    "Starting VM process through Zygote failed", ex);
500        }
501    }

26. Process.startViaZygote

路径:frameworks/base/core/java/android/os/Process.java
主要是处理参数,然后调用zygoteSendArgsAndGetResult去通过socket通信去通知zygote。

27. Process.zygoteSendArgsAndGetResult

路径:frameworks/base/core/java/android/os/Process.java
通过socket通知Zygote进程去fork新进程。接收方是ZygoteConnection。

28. ZygoteConnection.runOnce

路径:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
从socket中读取命令并执行。
这个可以往下再分为4步:

  • readArgumentList
  • apply security policies
  • apply security policies
  • preForkAndSpecialize

29. Zygote之forkAndSpecialize

路径:/frameworks/base/core/java/com/android/internal/os/Zygote.java
这步分为三个子步骤:

  • preFork
  • nativeForkAndSpecialize
  • postForkCommon

29-1. ZygoteHooks.PreFork

路径:/libcore/dalvik/src/main/java/dalvik/system/ ZygoteHooks.java
这步离开了frameworks/base,进入了libcore。这里面要注意,不能调用Android的API,打个log什么的都要注意。

  • Daemons.stop()
    停掉GC,停掉finalizer等,fork进程时不需要这些
  • waitUntilAllThreadsStopped()
    确保fork之前只有一个线程在运行
  • nativePreFork()
    给虚拟机一个机会去在fork之前做点处理

29-2. com_android_internal_os_Zygote_nativeForkAndSpecialize

路径:/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
这是我们第一次进入C++层。真正做事的函数是ForkAndSpecializeCommon。

真正开始fork新进程

  • SetSigChldHandler
  • Fork and detach(新进程从这一步开始诞生)
  • child process setup

这一步是值得大书特书的一步,因为从这一步开始,更具体地说是从Fork and detach开始,新应用的进程终于fork出来了。从此zygote老进程的事情我们不再关心,我们来看新进程号就好了。

Child process setup之后,有一个重要的函数会被执行到,这就是ZygoteHooks_nativePostForkChild。
在这个函数中,我们熟悉的AOC版本号的log会输出出来。
这个函数的AOC版本路径在:/aliyunos/aoc/vm/native/dalvik_system_ZygoteHooks.cc中。

#if defined(AOC_VERSION)
LOG(INFO) << "==========================";
LOG(INFO) << "+ AOC version " << Runtime::GetVersionString() << " +";
LOG(INFO) << "==========================";
#endif

对应的ART版本在:/art/runtime/native/dalvik_system_ZygoteHooks.cc中。

29-3. postForkCommon

路径:/libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
只干一件事,把preFork里面stop的monitor们重新打开。这一步要注意,原来的Zygote里面的不要去管了,只看新进程的就好。

30. RuntimeInit.zygoteInit

路径:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

31. RuntimeInit.invokeStaticMain

路径:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
初始化完成,通过反射来调用ActivityThread的main方法

32. ActivityThread main

路径:frameworks/base/ core/java/android/app/ActivityThread.java
执行ActivityThread的main方法,新的应用正式上路

33. Proxy:attachApplication

路径:frameworks/base/
新的Activity建好了,要通知AmS,走IPC。

34. ActivityManagerService之attachApplication

路径: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
AmS收到attach的通知,一切准备就绪。

35. AMS:attachApplicationLocked

路径:frameworks/base/ services/core/java/com/android/server/am/ActivityManagerService.java
其它部分都是线性的,这部分我们不得不分成两个部分各表一支了。这两部分分别走IPC,最后在ActivityThread的队列中汇合。
首先是bindApplication。

36. ApplicationThreadProxy之bindApplication

IPC调用
路径:frameworks/base/core/java/android/app/ApplicationThreadNative.java

37. ActivityThread之bindApplication

路径:frameworks/base/core/java/android/app/ActivityThread.java
主要包括两部分的操作,虽然这个方法不叫做scheduleXXX,但是实际上两步的操作都是放到队列中。
到这一步的时候,其实我们只是启动了一个空进程而己,跟实际的apk还一点关系也没有。
首先,如果services不为空的话,先初始化一下services cache。
ServiceManager.initServiceCache(services);
然后,schedule第一个任务,setCoreSettings(coreSettings);
这个最终会走到handleSetCoreSettings。
下面,PM才出场去读真正的package的信息。读好之后,再去将BIND_APPLICATION消息放到队列里去,这时候可能正在执行setCoreSettings。

38. ActivityThread之handleBindApplication

真正启动Activity之前,还得做一些准备工作。比如install provider就是在这时候做的。

38-1 LoadedApk之makeApplication

我们都知道,在Activity之外,对于每个应用,还对应一个Application类。这个Application就是在LoadApk的makeApplication方法时构造的。

554    public Application makeApplication(boolean forceDefaultAppClass,
555            Instrumentation instrumentation) {
556        if (mApplication != null) {
557            return mApplication;
558        }
559
560        Application app = null;
561
562        String appClass = mApplicationInfo.className;
563        if (forceDefaultAppClass || (appClass == null)) {
564            appClass = "android.app.Application";
565        }

下面调用ClassLoader,并且生成ApplicationContext.

567        try {
568            java.lang.ClassLoader cl = getClassLoader();
569            if (!mPackageName.equals("android")) {
570                initializeJavaContextClassLoader();
571            }
572            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);

下面将通过Intrumentation的newApplication方法去真正创建Application

573            app = mActivityThread.mInstrumentation.newApplication(
574                    cl, appClass, appContext);
575            appContext.setOuterContext(app);
576        } catch (Exception e) {
577            if (!mActivityThread.mInstrumentation.onException(app, e)) {
578                throw new RuntimeException(
579                    "Unable to instantiate application " + appClass
580                    + ": " + e.toString(), e);
581            }
582        }
583        mActivityThread.mAllApplications.add(app);
584        mApplication = app;

38-2 Application之newApplication

通过反射构造对象,然后调用Application的attach方法。

993    static public Application newApplication(Class<?> clazz, Context context)
994            throws InstantiationException, IllegalAccessException,
995            ClassNotFoundException {
996        Application app = (Application)clazz.newInstance();
997        app.attach(context);
998        return app;
999    }

38-3 Application之attach

attach再调用attachBaseContext。

183    /**
184     * @hide
185     */
186    /* package */ final void attach(Context context) {
187        attachBaseContext(context);
188        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
189    }
```

### 38-4 ContextThemeWrapper之attachBaseContext

50 @Override
51 protected void attachBaseContext(Context newBase) {
52 super.attachBaseContext(newBase);
53 }


### 38-5 ContextWrapper的attachBaseContext

65 protected void attachBaseContext(Context base) {
66 if (mBase != null) {
67 throw new IllegalStateException("Base context already set");
68 }
69 mBase = base;
70 }


Application构造好之后,将调用Application的onCreate方法。

586 if (instrumentation != null) {
587 try {
588 instrumentation.callApplicationOnCreate(app);
589 } catch (Exception e) {
590 if (!instrumentation.onException(app, e)) {
591 throw new RuntimeException(
592 "Unable to create application " + app.getClass().getName()
593 + ": " + e.toString(), e);
594 }
595 }
596 }


最后更新所有R常量的值

598 // Rewrite the R 'constants' for all library apks.
599 SparseArray packageIdentifiers = getAssets(mActivityThread)
600 .getAssignedPackageIdentifiers();
601 final int N = packageIdentifiers.size();
602 for (int i = 0; i < N; i++) {
603 final int id = packageIdentifiers.keyAt(i);
604 if (id == 0x01 || id == 0x7f) {
605 continue;
606 }
607
608 rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
609 }
610
611 return app;
612 }


下面花开两朵说另一枝,回到attachApplicationLocked方法,它将会调用到realStartActivityLocked。

### 39.    ActivityStackSupervisor之realStartActivityLocked(AmS进程)

路径:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
这时算是真正启动,通过Activity,可以执行onCreate了。

### 40.    ApplicationThreadNative之scheduleLaunchActivity

路径:frameworks/base/core/java/android/app/ApplicationThreadNative.java
IPC通道,通知本地进程

### 41.    ActivityThread之scheduleLaunchActivity

路径:frameworks/base/ core/java/android/app/ActivityThread.java
ActivityThread收到,将命令放入队列。

### 42.    ActivityThread之handleLaunchActivity

路径:frameworks/base/ core/java/android/app/ActivityThread.java
正式开始Activity的启动流程。

### 43.    ActivityThread之performLaunchActivity

路径:frameworks/base/ core/java/android/app/ActivityThread.java
负责new出Activity的实例,makeApplication,然后调用Activity.attach向系统注册。
最后,通过callActivityOnCreate来调用应用的onCreate方法。

### 44.    ActivityThread之handleResumeActivity

路径:frameworks/base/ core/java/android/app/ActivityThread.java
首先,通过performResumeActivity方法调用应用的onResume方法。
如大家所熟知的,执行完onResume之后,真正的绘制工作就才真正开始。
ActivityThread通过ViewManager对象调用其addView方法,开始正式通知WmS要添加窗口了。实际上,获取的这个ViewManager,是其子接口WindowManager的实现类WindowManagerImpl的方法。这个WindowManagerImpl的对象是通过
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)调用从系统服务获取到的。

### 45.    WindowManagerImpl之addView

路径:frameworks/base/core/java/android/view/WindowManagerImpl.java
ViewManager只是一个接口,用于定义功能,本身并不与WmS打交道。它通过单例对象WindowManagerGlobal去访问ViewRootImpl,再由ViewRootImpl去跟WmS通信。

### 46.    WindowManagerGlobal之addView

路径:frameworks/base/core/java/android/view/WindowManagerGlobal.java
WindowManagerGlobal也只是个二传手,最终调用ViewRootImpl类的setView来真正与WmS交互。

### 47.    ViewRootImpl之setView

路径:frameworks/base/core/java/android/view/ViewRootImpl.java
ViewRootImpl被构造出来后,会通过WindowManagerGlobal的getWindowSession方法去创建一个与WmS之间的连接。构造中会调到这一句:

mWindowSession = WindowManagerGlobal.getWindowSession();


在正式添加到WmS之前,首先要保证这个View树可以正常接收事件,于是先发起一次requestLayout。

### 48.    ViewRootImpl之requestLayout

这个方法本身是WmS最简单的方法之一,先检查一下是不是UI线程,如果是,就scheduleTraversals,申请做一次遍历。
准备好了之后,setView就会通过mWindowSession去IPC通知WmS去添加一个窗口。

### 49.    Session之addToDisplay

路径:frameworks/base/services/core/java/com/android/server/wm/Session.java
IPC调用WmS的addWindow方法。

### 50.    WindowManagerService之addWindow

路径:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
第一步先检查权限,比如部分系统窗口就不是应用可以添加的。
第二步去检查是不是重复添加了。

if (mWindowMap.containsKey(client.asBinder())) {

Slog.w(TAG, "Window " + client + " is already added");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;

}


第三步,如果是子窗口,就寻找父窗口。
第四步,检查窗口的有效性。
第五步,用WindowState对象来管理窗口的状态。

win = new WindowState(this, session, client, token,attachedWindow, appOp0, seq, attrs, viewVisibility, displayContent);


第六步,调整Window属性
第七步,将token加入到mTokenMap中。
第八步,将client.asBinder()加到mWindowMap中。
第九步,将Window们按顺序排列,调用addWindowToListInOrderLocked方法。
这些做完,addView就算完成了,剩下的事情就看遍历的了。

### 51.    ViewRootImpl之scheduleTraversals

准备好了之后,放入队列等待被遍历。

### 52.    ViewRootImpl之doTraversal

遍历操作,实际逻辑都在performTraversals中。

### 53.    ViewRootImpl之performTraversals

遍历的核心逻辑,主要有三个步骤:measure, layout和draw。
如果是第一次调用,所有的子对象还没有attach到窗口上,需要首先dispatchAttachedToWindow。Attach到哪里呢,PhoneWindow的DecorView。
这个方法没有被DecorView重载,直接调用的是ViewGroup的dispatchAttachedToWindow。

### 54.    ViewGroup之dispatchAttachedToWindow

根元素被attach到Window上之后,开始递归它的子节点,使每个子节点都attach到父节点上。
执行结束后,通过回调onAttachedToWindow来通知节点已经被attach到Window上了。
在被attach到Window之前,View实际上是没有大小的,因为还不知道被用到哪里呢,无法去做测量。
然后,回到performTraversals中,在执行三大操作之前,先去看看队列里还有什么未执行的任务没有,有的话就先执行之。

getRunQueue().executeActions(mAttachInfo.mHandler);


由于是第一次画,所以mLayoutRequested为true,我们还不知道窗口大小是多大,于是来一次测量,调用measureHierarchy.

windowSizeMayChange |= measureHierarchy(host, lp, res,desiredWindowWidth, desiredWindowHeight);


测量完成之后,就可以开始布局了,调用relayoutWindow.

### 55.    ViewRootImpl之relayoutWindow

relayoutWindow当然不是本地能搞得定的,于是通过IPC调,mWindowSession的relayout去通知WmS去干这事儿。

### 56.    Session之relayout

IPC调用,调用WmS的relayoutWindow。

### 57.    WindowManagerService之relayoutWindow

WmS准备第一次画之前,先来个进场动画吧。

winAnimator.applyEnterAnimationLocked();

然后创建个新的Surface吧。

SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();

最后调用performLayoutAndPlaceSurfacesLocked方法

### 58.    WindowManagerService之performLayoutAndPlaceSurfacesLocked

这里边还要走一个最多6次的循环,每次都调用performLayoutAndPlaceSurfacesLockedLoop。

### 59.    WindowManagerService之performLayoutAndPlaceSurfacesLockedLoop

调用performLayoutAndPlaceSurfacesLockedInner

### 60.    WindowManagerService之performLayoutAndPlaceSurfacesLockedInner

真正执行layout的逻辑。
Measure和layout完成了,最后终于可以画了。回到performTraversals中,调用performDraw。

### 61.    ViewRootImpl之performDraw

先调用draw去通知绘制线程开始画。
然后把所有的动画全停掉。

### 62.    ViewRootImpl之draw

如果支持硬件加速,就调用HardwareRenderer抽象类的draw方法去画。

### 63.    ThreadedRenderer之draw

路径:frameworks/base/core/java/android/view/ThreadedRenderer.java

### 64.    ThreadedRenderer之nSyncAndDrawFrame

这是个native方法,真正实现调用GPU去绘制。调用的是android_view_ThreadedRender_syncAndDrawFrame函数。

### 65.    android_view_ThreadedRenderer_syncAndDrawFrame函数

路径:frameworks/base/core/jni/android_view_ThreadedRenderer.cpp
再调用RenderProxy的syncAndDrawFrame。

### 66.    RenderProxy::syncAndDrawFrame

路径:frameworks/base/libs/hwui/renderthread/RenderProxy.cpp
调用DrawFrameTask的drawFrame函数。

### 67.    DrawFrameTask::drawFrame

路径:frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp
调用postAndWait。

### 68.    DrawFrameTask::postAndWait

放到队列里,等着VSYNC信号来了就调用吧。

void DrawFrameTask::postAndWait() {
AutoMutex _lock(mLock);
mRenderThread->queue(this);
mSignal.wait(mLock);
}

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Android M应用启动流程分析
Android M的Activity启动的完整流程
3206 0
iOS平台应用开发的敏捷设计流程
  本文翻译自《Computer Arts》中对专注于iPhone和iPad应用开发的设计师Sarah Parmenter的访谈录,希望对iPhone应用开发的朋友能有所帮助。   以下为全部译文:   对设计师来说,iPhone和iPad是全新的平台。
634 0
Android之路 - 冷启动解决方案:实现秒开
前言 关于 splash 页面相信每个Android开发者都是非常熟悉的,而且很多人也遇到过需要在splash加个广告图片,然后延迟3秒在进入主页面,splash 应该只是一个启动页面,不应该放广告,但是那又能怎么样呢?又敌不过产品经理。
2023 0
[Android]Android焦点流程代码分析
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/7286503.html 通过View的View::focusSearch进行焦点搜索对应方向上的下一个可以获取焦点的View: public View focus...
1005 0
Android系统启动过程学习
版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/53780960 使用 an...
770 0
+关注
lusing
刘子瑛,阿里系统框架专家。工作十余年,一直对新编程语言、新开发方法、数学与算法相关和并发等相关领域保持浓厚的兴趣。乐于通过技术分享促进新技术。
181
文章
60
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载