Activity启动流程分析(Android 9.0)

本文的重点是总结Activity启动过程中的几个关键点与相关逻辑所在的源码位置,具体的启动流程调用链真的很长,所以我还是按照我之前的方式来做,带着问题去找相关的代码逻辑。

Activity的启动流程

  1. 应用通过startActivity或是startActivityForResult方法向ActivityManagerService发出启动请求。

  2. ActivityManagerService接收到启动请求后会进行必要的初始化以及状态的刷新,然后解析Activity的启动模式,为启动Activity做一系列的准备工作。

  3. 做完上述准备工作后,会去判断栈顶是否为空,如果不为空即当前有Activity显示在前台,则会先进行栈顶Activity的onPause流程退出。

  4. 栈顶Activity执行完onPause流程退出后开始启动Activity。如果Activity被启动过则直接执行onRestart->onStart->onResume过程直接启动Activity(热启动过程)。否则执行Activity所在应用的冷启动过程。

  5. 冷启动过程首先会通过Zygote进程fork出一个新的进程,然后根据传递的”android.app.ActivityThread”字符串,反射出该对象并执行ActivityThread的main方法进行主线程的初始化。

  6. Activity所在应用的进程和主线程完成初始化之后开始启动Activity,首先对Activity的ComponentName、ContextImpl、Activity以及Application对象进行了初始化并相互关联,然后设置Activity主题,最后执行onCreate->onStart->onResume方法完成Activity的启动。

  7. 上述流程都执行完毕后,会去执行栈顶Activity的onStop过程。

带着问题看相关源码

Activity可以通过哪些方式进行启动?

startActivity的两种方式

  • Context方式

    # android/app/ContextImpl.java
         @Override
    public void startActivity(Intent intent, Bundle options) {
        ...
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }
    

    从源码我们可以看到Context方式最终调用的是Context的内保存的ActivityThreadInstumentationexecStartActivity()方法.

  • Activity方式

    # android/app/Activity.java
    
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
            ...
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            ...
    }
    

我们知道ActivitystartActivity方法最终调用的也是startActivityForResult()方法,所以我们直接看下startActivityForResult()方法,可以看到启动Activity也是使用内部的一个变量mInstrumentation这个Instumentation这个变量的的execStartActivity()方法,
所以可以看到这两种启动Activity的方式其实还是殊途同归的。

如何获取到的ActivityManagerService对象的

不管是哪种方式我们最后都需要发送请求给ActivityManagerService,AMS(ActivityManagerService)是一个系统进程的对象,我们自己的APP是没办法直接使用的,那么我们是如何去操作ActivityManagerService的呢?这里就牵扯到了IPC与AIDL,如果对这方面内容还不太熟悉,可以再去了解了解下。
也可以看下我的博客:

跨进程通信(IPC)

#android/app/ActivityManager.java

    /**
     * @hide
     */
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

从上面的源码我们可以看到通过ActivityManager获得AMS其实就是通过ServiceManager获取一个IBinder对象然后通过asInterface方法转成的一个IActivityManager对象。

在什么地方根据Intent查找到需要启动的Activity相关的信息且对应的是哪些类中

当我们调用ASM的startActivity()方法后,很多的启动Activity的流程都被提取到了一个ActivityStarter类中了,这个也是最新(Android 9.0)的源码修改的地方,
接下来就继续看下源码的流程

# com/android/server/am/ActivityStarter.java

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask, String reason) {
            
        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
        // Collect information about the target of the Intent.
       
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
            ......
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask, reason);
            ......
            return res;
        }
    }

从上面的源码可以看到通过调用ActivityStackSupervisorresolveIntentresolveActivity方法,最后执行了startActivityLocked方法.
这里出现了几种对象需要注意下:

  1. ResolveInfo:通过解析一个与IntentFilter相对应的Intent包含的信息,能够部分的代表AndroidManifeset中的标签
  2. ActivityInfo:对应从AndroidManifest中的或者标签收集的信息,能够从中获取部分Application相关的信息
  3. ActivityRecord:一个历史Stack中的实体,代表一个Activity.
  4. ApplicationInfo:对应的是从AndroidManifest中的标签收集的信息

以后我们可能还会遇到TaskReocrd、PackageInfo之类的对象,想详细了解的可以利用搜索引擎了解下。

在启动新的Activity前是如何让上一个Activity执行onPuase()的生命周期的

ActivityStarter调用多个startActivity后,执行到了startActivityUnchecked()方法中

# com/android/server/am/ActivityStarter.java
    // Note: This method should only be called from {@link startActivity}.
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        ...        
        mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                                mOptions);
        ...
        return START_SUCCESS;
    }

最终这个方法会调用到ActivityStackSupervisorresumeFocusedStackTopActivityLocked,这个方法的代码很多,很可能找不到我们需要看的那段代码,z这个时候我们就需要回忆下APP的启动流程,接下来会进入哪个流程,根据将要执行的流程在去找对应逻辑的代码。

继续跟着代码看,又经过一系列的代码,代码路程走到了ActivityStackresumeTopActivityInnerLocked方法

# com/android/server/am/ActivityStack.java
 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        ...
        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);
        }
        ...
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
        return true;
    }

又是一个非常长的流程,代码量也很大,真的需要好好看看才能找到需要的代码段,最后我们找到我们需要了解的代码,上面的代码逻辑主要有两个作用:

1. 判断是否有已经处于onResume状态的Activity,如果有的话调用startPausingLocked方法执行onPause生命周期

# com/android/server/am/ActivityStack.java
    /**
     * Start pausing the currently resumed activity.  It is an error to call this if there
     * is already an activity being paused or there is no resumed activity.
     *
     * @param userLeaving True if this should result in an onUserLeaving to the current activity.
     * @param uiSleeping True if this is happening with the user interface going to sleep (the
     * screen turning off).
     * @param resuming The activity we are currently trying to resume or null if this is not being
     *                 called as part of resuming the top activity, so we shouldn't try to instigate
     *                 a resume here if not null.
     * @param pauseImmediately True if the caller does not want to wait for the activity callback to
     *                         complete pausing.
     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
     * it to tell us when it is done.
     */
    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean pauseImmediately) {
            ...
            prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                            userLeaving, prev.configChangeFlags, pauseImmediately);
            ...
    }

从代码我们可以看到这里调用了一个IApplicationThreadschedulePauseActivity方法,这里的IApplicationThread对象就是一个Binder对象,对应的就是APP的ApplicationThread,于是我们直接去看ApplicationThread对象的对应方法。

# android.app.ActivityThread.ApplicationThread

        public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            int seq = getLifecycleSeq();
            if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
                    + " operation received seq: " + seq);
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                    configChanges,
                    seq);
        }
        
        private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
        if (DEBUG_MESSAGES) Slog.v(
                TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
                        "seq= " + seq);
        Message msg = Message.obtain();
        msg.what = what;
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = obj;
        args.argi1 = arg1;
        args.argi2 = arg2;
        args.argi3 = seq;
        msg.obj = args;
        mH.sendMessage(msg);
        }

通过代码我们可以知道,这里最终向H这个Handler对象发送了一个H.PAUSE_ACTIVITY的消息,继续往下分析。

# android.app.ActivityThread.H

         public void handleMessage(Message msg) {
             case PAUSE_ACTIVITY: {
                                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                                SomeArgs args = (SomeArgs) msg.obj;
                                handlePauseActivity((IBinder) args.arg1, false,
                                        (args.argi1 & USER_LEAVING) != 0, args.argi2,
                                        (args.argi1 & DONT_REPORT) != 0, args.argi3);
                                ...
                            } break;
            }

这里可以看到当Msg.WhatH.PAUSE_ACTIVITY时实际上调用的是handlePauseActivity方法,接着看代码

# android.app.ActivityThread    

    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
            ...
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
            ...
    }
    
    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
            ...
            mInstrumentation.callActivityOnPause(r.activity);
            ...
    }

最后发现又回到了Instrumentation类中,并调用了callActivityOnPause方法。

# android/app/Instrumentation.java
    public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }
# android/app/Activity.java
    final void performPause() {
        ...
        onPause();
        ...
    }

最后终于执行到了ActivityonPause生命周期.

2. 调用ActivityStackSupervisorstartSpecificActivityLocked方法继续启动新的Activity

# com/android/server/am/ActivityStackSupervisor.java
    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);
    }

这里可以看到,先判断了Activity所在的进程是否已经在运行中,如果已经在运行中就直接启动Activity,不然就先创建Process,这里就又回到了
ActivityManagerServicestartProcessLocked方法.

    # frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
 private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            ...
            ProcessStartResult startResult;
            if (hostingType.equals("webview_service")) {
                startResult = startWebView(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, entryPointArgs);
            } else {
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, entryPointArgs);
            }
            ...
    }

这里我就不详细分析了(暂时感觉自己也分析不好),主要是进程的zygote进行进程的fork创建出一个新的进程出来,之后会通过反射的方式执行这个应用的main()方法。

新的Activity是在如何执行到的onCreate()生命周期的

先来看下main方法的代码:

# android/app/ActivityThread.java

    public static void main(String[] args) {
            ...
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
            ...
    }

可以看到这里进行了ActivityThread的初始化,之后的逻辑便是创建Instrumentation的创建,绑定创建的Applicaton对象.

# android/app/ActivityThread.java
    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        } else {
            ...    
           mInstrumentation = new Instrumentation();
           ...
        }

这里我们发现创建了ApplicationThread之后还需要绑定到ActivityManagerService中,继续看

# com/android/server/am/ActivityManagerService.java

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

这里我们可以看到AMS把进程的Pid与ApplicationThread进行了绑定,方便之后通过进程的Pid能够直接找到对应的ApplicationThread.

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        ...    
        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
        ...
        return true;
    }

流程这时候又走到了ActivityStackSupervisor这个类了.

# com/android/server/am/ActivityStackSupervisor.java
    boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        final String processName = app.processName;
        ...        
        if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
        ...                    
        return didSomething;
    }

继续看

# com/android/server/am/ActivityStackSupervisor.java
    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
            ...
            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);
            ...
        return true;
    }

从上面的代码我们可以看到最终又回到到了ApplicatoinThread中的scheduleLaunchActivity,后面的逻辑基本就和onPause的流程是一致的了,我就不再详细分析了,有兴趣的可以自己看看吧,最终会走到我们熟悉的onCreate生命周期中。

# android/app/ActivityThread.java

    @Override
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
            ...
            sendMessage(H.LAUNCH_ACTIVITY, r);
    }
# android.app.ActivityThread.H
    case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    } break;
# android/app/ActivityThread.java
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
            ...
            Activity a = performLaunchActivity(r, customIntent);
            ...
    } 
    
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
        ...
        return activity;
    }
# android/app/Instrumentation.java

    /**
     * Perform calling of an activity's {@link Activity#onCreate}
     * method.  The default implementation simply calls through to that method.
     *
     * @param activity The activity being created.
     * @param icicle The previously frozen state (or null) to pass through to onCreate().
     */
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
# android/app/Activity.java

    final void performCreate(Bundle icicle) {
        restoreHasCurrentPermissionRequest(icicle);
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

总结

尽管已经省略了很多操作的逻辑,但是APP启动的流程还是特别的长,逻辑还一直都是跳来跳去的,经常还会被突然出现的一些类给拦住…这个也让我明白了在分析代码的时候一定要搞清楚涉及的几个类的作用,同时记住关键的流程,这样才能保持清晰的思路去分析代码。最后能够理解多少就要靠大家自己的一些体会了。

参考文档

(Android 9.0)Activity启动流程源码分析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值