Activity的启动流程(二):应用进程部分

Activity的启动流程(二):应用进程部分

Android小彩虹2021-08-22 8:28:551470A+A-

接上篇: Activity的启动流程(一):ActivityManagerService部分

上一篇我们分析了activity在AndroidManagerService部分的启动流程,这一篇我们再来看一下activity在应用进程部分的启动流程。学习activity在应用进程部分的启动流程对于我们深入理解android应用的工作原理,特别是学习一些插件化方面的知识是很有帮助的,因为上一篇中介绍的启动流程大部分位于AMS中,AMS是一个系统服务进程,我们无法对其进行修改,而本篇介绍的启动流程则位于应用进程中,我们可以利用反射等技术手段对其进行修改,某些插件化技术的核心原理就是通过对这部分的代码进行hook,以达到替换要启动的activity的目的。

1.分发启动新activity的事件

在上一篇的结尾处我们可以看到,AMS最后调用了ActivityThread的scheduleLaunchActivity方法,activity的启动流程从AMS进程进入到了应用进程:

            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);

我们来看一下ActivityThread中的scheduleLaunchActivity方法:

源码路径:\frameworks\base\core\java\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) {

        updateProcessState(procState, false);

        ActivityClientRecord r = new ActivityClientRecord();

        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.referrer = referrer;
        r.voiceInteractor = voiceInteractor;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
        r.persistentState = persistentState;

        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;

        r.startsNotResumed = notResumed;
        r.isForward = isForward;

        r.profilerInfo = profilerInfo;

        r.overrideConfig = overrideConfig;
        updatePendingConfiguration(curConfig);

        sendMessage(H.LAUNCH_ACTIVITY, r);
    }

在scheduleLaunchActivity方法中,将接收到的参数都封装到了一个ActivityClientRecord对象中。从名字就可以看出,ActivityClientRecord是activity在客户端的一个记录,主要封装了activity的一些相关信息。

在scheduleLaunchActivity方法的最后调用了sendMessage方法发送了一个消息,我们来看一下sendMessage方法:

    private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

可以看到sendMessage方法就是构建了一个Message对象,并通过mH这个对象进行了发送。很明显mH是一个Handler对象,这里是使用的Android的消息机制来进行消息分发。mH是一个类名为H的实例,而H则继承自Handler。mH主要用来处理主线程中的一些事件。使用消息机制来进行activity的启动可以保证Activity的启动是在主线程中进行的。该消息最终会被mH的handleMessage方法进行处理,源码如下:

    private class H extends Handler {

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                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;
                ...
            }
            ...
        }
    }

在handleMessage方法中,首先调用了getPackageInfoNoCheck,并将返回值赋值给了r的packageInfo变量。getPackageInfoNoCheck返回的是一个LoadedApk对象,该对象主要封装了一些APK相关的信息。之后系统又调用了handleLaunchActivity方法来进一步进行activity的启动。

先来看一下getPackageInfoNoCheck方法的代码:

    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage) {
        final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
        synchronized (mResourcesManager) {
            WeakReference<LoadedApk> ref;
            if (differentUser) {
                ref = null;
            } else if (includeCode) {
                // 注释1:查看是否有缓存
                ref = mPackages.get(aInfo.packageName);
            } else {
                ref = mResourcePackages.get(aInfo.packageName);
            }

            LoadedApk packageInfo = ref != null ? ref.get() : null;
            if (packageInfo == null || (packageInfo.mResources != null
                    && !packageInfo.mResources.getAssets().isUpToDate())) {
                ...
                //注释2:如果没有缓存,则创建新LoadedApk对象
                packageInfo =
                    new LoadedApk(this, aInfo, compatInfo, baseLoader,
                            securityViolation, includeCode &&
                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

                ...

                if (differentUser) {
                    // Caching not supported across users
                } else if (includeCode) {
                    // 注释3:将LoadedApk对象放入缓存
                    mPackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
                } else {
                    mResourcePackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
                }
            }
            return packageInfo;
        }
    }

首先,在注释1处,先尝试从mPackages对象中获取这个LoadedApk对象,如果获取不到的话,则会在注释2处创建一个新的LoadedApk对象,并在注释3处将这个LoadedApk加入到mPackages中。

我们再来看一下handleLaunchActivity方法的代码:

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {

        // 注释1:初始化WindowManager,通过Binder获取WindowServiceManager的本地代理
        WindowManagerGlobal.initialize();

        // 注释2:创建Activity
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            // 注释3
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

           ...
        }
        ...
    }

在注释1处,通过调用 WindowManagerGlobal.initialize()来对WindowManager进行了初始化,WindowManger是WindowManagerService在客户端的一个代理对象,而WindowManagerService与ActivityManagerService类似,也是一个系统服务,主要用来对窗口的显示进行控制。客户端通过WindowManger对象,利用Binder机制来与WindowManagerService进行通信。

在注释2处通过performLaunchActivity来创建了Activity的实例,至此我们要启动的Activity实例终于被创建出来了。

在注释3处则调用了handleResumeActivity方法使activity进入resume状态。

下面我们来看一下performLaunchActivity和handleResumeActivity具体对activity做了哪些初始化工作。

2.activity的初始化

performLaunchActivity方法的源码如下:

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

        ...

        ComponentName component = r.intent.getComponent();
        ...

        // 注释1:为activity创建context
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();

            // 注释2:创建activity实例
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            ...
        } ...

        try {
            ...
            if (activity != null) {
                ...
                appContext.setOuterContext(activity);
                // 注释3
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

                ...
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                // 设置主题
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                // 注释4:调用activity的OnCreate方法
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    //注释5:进入start状态
                    activity.performStart();
                    r.stopped = false;
                }
                ...
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } ...

        return activity;
    }

在注释1处,系统首先为activity创建了context对象,并通过这个context对象获取了一个ClassLoader,用于加载要启动的activity。

在注释2处,通过调用mInstrumentation的newActivity方法创建了activity的实例。

在注释3处调用了activity的attach方法来对activity进行一些初始化工作。

在注释4处调用了mInstrumentation的callActivityOnCreate方法,从这个方法的名字就可以看出,该方法内部调用了activity的onCreate方法。

在注释5处调用了activity的performStart()方法,使activity进入start状态。

我们首先来看mInstrumentation的newActivity方法:

源码路径:\frameworks\base\core\java\android\app\Instrumentation.java public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }

newActivity方法只有一行代码,就是通过反射加载了要启动的activity类并创建了一个实例对象。

我们再来看一下activity的attach方法做了哪些初始化工作:

源码路径:\frameworks\base\core\java\android\app\Activity.java final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        // 注释1:为activity创建window对象
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        //设置软键盘状态模式
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }

        // 注释2:初始化一些成员变量
        mUiThread = Thread.currentThread();
        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        // 注释3:为window设置windowManager
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);
    }

在注释1处为该activity创建了一个window对象,可以看到这个window对象其实是一个PhoneWindow对象。在Android系统中,每个Activity都对应一个window对象,window主要和activity的窗口显示有关。

在注释2处为该activity初始化了一些成员变量,如主线程、ui线程、application对象等。

在注释3处为window设置了WindowManager对象。

看完了activity的attach方法,我们再来看Instrumentation的callActivityOnCreate方法:

源码路径:\frameworks\base\core\java\android\app\Instrumentation.java public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }

可以看到在callActivityOnCreate方法中又调用了activity.performCreate来进一步初始化activity。performCreate方法的源码如下:

源码路径:\frameworks\base\core\java\android\app\Activity.java final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        restoreHasCurrentPermissionRequest(icicle);
        // 注释1:调用onCreate
        onCreate(icicle, persistentState);
        mActivityTransitionState.readState(icicle);
        // 注释2
        performCreateCommon();
    }

在注释1处直接调用了onCreate方法,我们通常会重写activity的onCreate方法来进行一些自定义的初始化工作。在注释2处又调用了performCreateCommon方法,我们来看一下该方法的源码:

    final void performCreateCommon() {
        mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                com.android.internal.R.styleable.Window_windowNoDisplay, false);
        mFragments.dispatchActivityCreated();
        mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    }

可以看到在performCreateCommon方法中调用了mFragments的dispatchActivityCreated方法,该方法内部会通知activity内的相关fragment,并触发这些fragment的onActivityCreated方法。


回到ActivityThread的handleLaunchActivity方法中。在分析完performLaunchActivity方法后,我们再来看一下handleResumeActivity方法做了哪些工作。handleResumeActivity方法代码如下:

源码路径:\frameworks\base\core\java\android\app\ActivityThread.java final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        
        ...

        // 注释1
        r = performResumeActivity(token, clearHide, reason);

        if (r != null) {
            final Activity a = r.activity;

            ...

            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                ...
            } else if (!willBeVisible) ...

            cleanUpPendingRemoveWindows(r, false /* force */);

            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                ...
                WindowManager.LayoutParams l = r.window.getAttributes();
                ...
            }

            ...

            // 通activity manager该activity已经处于resumed状态
            if (reallyResume) {
                try {
                    ActivityManager.getService().activityResumed(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }

        } else {
            ...
        }
    }

handleResumeActivity方法的代码很长,但是我们不用纠结于代码细节。在注释1处调用了performResumeActivity,后面的代码都是一些与window、decorView、windowManager相关的操作,不难猜出是与activity的显示有关,我们在这里就不深入分析了。我们主要来看一下performResumeActivity方法:

    public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
                + " finished=" + r.activity.mFinished);
        if (r != null && !r.activity.mFinished) {
            ...
            try {
               ...
                r.activity.performResume();

                ...
            } ...
        }
        return r;
    }

performResumeActivity方法主要是调用了activity的performResume方法:

    final void performResume() {
        ...

        //调用activity的onResume方法
        mInstrumentation.callActivityOnResume(this);
        ...

        //通知fragment进入Resume状态
        mFragments.dispatchResume();
        mFragments.execPendingActions();

        ...
    }

首先,系统调用了mInstrumentation的callActivityOnResume,在callActivityOnResume方法内部会直接调用activity的onResume方法,这点与之前调用onCreate方法比较相似,这里就不再进一步分析了。这样,activity就进入生命周期的Resume阶段了。

总结

我们对这部分的activity启动流程进行一下总结:

  1. AMS调用ActivityThread的scheduleLaunchActivity方法,启动流程从AMS进入应用进程
  2. ActivityThread通过消息机制分发启动activity的事件,确保activity的启动处于主线程中。
  3. 通过反射创建activiy实例,并对该实例进行一些初始化工作
  4. 该activity开始了它的生命周期,分别调用了onCreate、onStart、onResume方法,最终显示在屏幕上。

至此activity的创建流程就分析完了,本人水平有限,如果有哪里写的不好还望各位大佬多多指点。关于启动流程中应用进程的创建部分并没有在这里进行介绍,因为这部分内容比较多,之后会单独写一篇文章介绍应用进程的创建流程。

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1
本网站由 提供CDN/云存储服务

联系我们