美文网首页android之AMS学习攻克Activity启动流程面试
Android进阶(三):Application启动过程(最详细

Android进阶(三):Application启动过程(最详细

作者: Linhaojian | 来源:发表于2018-12-06 13:59 被阅读362次

    1.前言

    • 最近一直在看 《Android进阶解密》 的一本书,这本书编写逻辑、流程都非常好,而且很容易看懂,非常推荐大家去看看(没有收广告费,单纯觉得作者写的很好)。
    • 上一篇简单的介绍了Android进阶(二): 应用进程启动过程,最终知道了ActivityThread就是代表应用进程
    • 今天就介绍ActivityThread启动之后,是如何启动 Application (基于Android 8.0 系统)。
    • 文章中实例 linhaojian的Github

    2.Application启动过程的时序图

    Application启动流程.png

    3.源码分析

    3.1 ActivityThread初始化

    public static void main(String[] args) {
            //...
            //创建ActivityThread对象 & 调用attach()
            ActivityThread thread = new ActivityThread();
            thread.attach(false, startSeq);
            //创建主线程的Handler
            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
            Looper.loop(); 
    }
    
    • 主要做了2件事,实例化ActivityThread & 创建主线程Handler与Looper接收信息

    3.2 ActivityThread的attach函数

        private void attach(boolean system, long startSeq) {
            //...
                RuntimeInit.setApplicationObject(mAppThread.asBinder());
                // 获取ActivityManagerService的代理对象
                final IActivityManager mgr = ActivityManager.getService();// 1
                try {
                    //通知AMS进行application的初始化
                    mgr.attachApplication(mAppThread, startSeq);// 2
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
        }
    
    • 注释1:获取ActivityManagerService的代理对象
    • 注释2:通过代理对象调用attachApplication(),获取启动application所需信息(应用进程相关数据)

    3.3 ActivityManagerService的attachApplication函数

        public final void attachApplication(IApplicationThread thread, long startSeq) {
            synchronized (this) {
                int callingPid = Binder.getCallingPid();
                final int callingUid = Binder.getCallingUid();
                final long origId = Binder.clearCallingIdentity();
                attachApplicationLocked(thread, callingPid, callingUid, startSeq);// 1
                Binder.restoreCallingIdentity(origId);
            }
        }
    
    • 注释1:调用attachApplicationLocked()

    3.4 ActivityManagerService的attachApplicationLocked函数

        private final boolean attachApplicationLocked(IApplicationThread thread,
                int pid, int callingUid, long startSeq) {
            // 根据pid获取存储在AMS中,对应进程的相关信息
            ProcessRecord app;
            long startTime = SystemClock.uptimeMillis();
            if (pid != MY_PID && pid >= 0) {
                synchronized (mPidsSelfLocked) {
                    app = mPidsSelfLocked.get(pid);// 1
                }
            } else {
                app = null;
            }
            // ...
            thread.bindApplication(processName, appInfo, providers, null, profilerInfo, // 2
                null, null, null, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(getGlobalConfiguration()), app.compat,
                getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, isAutofillCompatEnabled);
             // ...
        }
    
    • 注释1:根据pid获取存储在AMS中,对应应用进程的相关信息
    • 注释2:通知ActivityThread启动application(IApplicationThread是ActivityThread的内部类,负责与ActivityManagerService通讯)

    3.5 ActivityThread的handleBindApplication函数

    • AMS中调用了ActivityThread的bindApplication函数,其内部其实是完成了Handler切换到主线程,并且最后活调用handleBindApplication(),下面我们看看其内部源码;
        private void handleBindApplication(AppBindData data) {
            // 将UI线程注册为运行时的虚拟机.
            VMRuntime.registerSensitiveThread();
            if (data.trackAllocation) {
                DdmVmInternal.enableRecentAllocations(true);
            }
            // ...
            // 创建上下文对象
            final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
            updateLocaleListFromAppContext(appContext,
                    mResourcesManager.getConfiguration().getLocales());
            if (!Process.isIsolated()) {
                final int oldMask = StrictMode.allowThreadDiskWritesMask();
                try {
                    setupGraphicsSupport(appContext);
                } finally {
                    StrictMode.setThreadPolicyMask(oldMask);
                }
            } else {
                ThreadedRenderer.setIsolatedProcess(true);
            }
            // Continue loading instrumentation.
            if (ii != null) {
                // ...
            } else {
                mInstrumentation = new Instrumentation();// 1
                mInstrumentation.basicInit(this);
            }
            Application app;
            final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
            final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
            try {
                // If the app is being launched for full backup or restore, bring it up in
                // a restricted environment with the base application class.
                // 初始化Applcation类
                app = data.info.makeApplication(data.restrictedBackupMode, null); // 2
                // Propagate autofill compat state
                app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
                mInitialApplication = app;
                // don't bring up providers in restricted mode; they may depend on the
                // app's custom Application class
                if (!data.restrictedBackupMode) {
                    if (!ArrayUtils.isEmpty(data.providers)) {
                        installContentProviders(app, data.providers);
                        // For process that contains content providers, we want to
                        // ensure that the JIT is enabled "at some point".
                        mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                    }
                }
                // Do this after providers, since instrumentation tests generally start their
                // test thread at this point, and we don't want that racing.
                try {
                    mInstrumentation.onCreate(data.instrumentationArgs); // 3
                }
                catch (Exception e) {
                    throw new RuntimeException(
                        "Exception thrown in onCreate() of "
                        + data.instrumentationName + ": " + e.toString(), e);
                }
                try {
                    //调用Applcation的OnCreate函数
                    mInstrumentation.callApplicationOnCreate(app); // 4
                } catch (Exception e) {
                    if (!mInstrumentation.onException(app, e)) {
                        throw new RuntimeException(
                          "Unable to create application " + app.getClass().getName()
                          + ": " + e.toString(), e);
                    }
                }
            } finally {
                // If the app targets < O-MR1, or doesn't change the thread policy
                // during startup, clobber the policy to maintain behavior of b/36951662
                if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
                        || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
                    StrictMode.setThreadPolicy(savedPolicy);
                }
            }
            // Preload fonts resources
            FontsContract.setApplicationContextForResources(appContext);
            if (!Process.isIsolated()) {
                try {
                    final ApplicationInfo info =
                            getPackageManager().getApplicationInfo(
                                    data.appInfo.packageName,
                                    PackageManager.GET_META_DATA /*flags*/,
                                    UserHandle.myUserId());
                    if (info.metaData != null) {
                        final int preloadedFontsResource = info.metaData.getInt(
                                ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
                        if (preloadedFontsResource != 0) {
                            data.info.getResources().preloadFonts(preloadedFontsResource);
                        }
                    }
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
        }
    
    • 注释1:创建Instrumentation,负责跟踪Application还在Activity的生命周期
    • 注释2:创建Application对象 & 调用其attach()
    • 注释3:调用Instrumentation的onCreate(),内部是空实现
    • 注释4:调用Instrumentation的callApplicationOnCreate(),内部是调用application的onCreate,如下代码;
    public class Instrumentation {
        public void callApplicationOnCreate(Application app) {
            app.onCreate();
        }
    }
    

    4.类关系

    Application启动类结构.png
    • ActivityThread :通过IActivityManager类,通知AMS准备application启动所需进程数据 ;
    • ActivityManagerService :获取application启动所需进程数据 ;
    • Instrumentation :创建&启动Application;跟踪Application的生命周期;

    5.总结

    • 到此,Application启动过程介绍完毕。
    • 如果喜欢我的分享,可以点击 关注 或者 ,你们支持是我分享的最大动力 。
    • linhaojian的Github

    欢迎关注linhaojian_CSDN博客或者linhaojian_简书

    不定期分享关于安卓开发的干货。


    写技术文章初心

    • 技术知识积累
    • 技术知识巩固
    • 技术知识分享
    • 技术知识交流

    相关文章

      网友评论

        本文标题:Android进阶(三):Application启动过程(最详细

        本文链接:https://www.haomeiwen.com/subject/lwvzqqtx.html