美文网首页App启动流程Android系统方面那些事
App启动流程:App进程内部操作-1

App启动流程:App进程内部操作-1

作者: sjandroid | 来源:发表于2019-05-12 22:37 被阅读26次

    目录

    • 概述
    • 总结
    • 详细过程
    • 重要类说明

    概述

    在冷启动过程中,“当为App创建完进程”之后,就需要“激活处于焦点栈栈顶的待启动Activity”。关于冷启动过程的前两步操作,《为目标App启动做准备》《启动App进程》 的流程请点击查看。

    由于“App进程内部操作”部分内容比较多一些,所以这部分的内容被分成了2个小章节来分析。
    第一节:也就是本节是从“App进程启动完毕之后,从ActivityThread.main()开始” 至 “App进程接收到AMS通过scheduleLaunchActivity()发起的 LAUNCH_ACTIVITY 消息”为止。
    第二节:《App启动流程:App进程内部操作-2》,则从“App接收到LAUNCH_ACTIVITY开始” 至 “通过Activity.handleResumeActivity()真正完成待启动Activity的实例化并执行其View树的绘制”为止。

    当前源码的分析是基于 Android8.0。


    总结

    1:当Zygote进程创建并初始化完App进程后,就会通过反射执行ActivityThread.main()对main线程进行初始化。
    2:通过ActivityManager.getService()获取AMS服务在本进程的BInder 代理,而后通过这个代理对象通知AMS执行attachApplication()操作。

    这是一次IPC操作,从App进程切换至system_server进程

    3:AMS接收到App进程发起的“attachApplication()操作”操作后会执行如下操作:
    3.1:根据 调用者进程的pid,获取记录此进程信息的ProcessRecord。
    3.2:注册“Binder服务死亡通知”,App进程挂掉之后其Binder服务也会随之停止掉,此时AMS需要接收到这个通知,然后去回收一些此进程使用的资源。
    3.3:把当前App进程的ApplicationThread赋值给ProcessRecord中的thread。并重置此ProcessRecord中一些参数。
    3.4:通过App进程的ApplicationThread服务在system_server进程的Binder代理对象,执行bindApplication()来通知App进程继续后续“绑定”操作。

    这是一次IPC操作,从system_server进程切换至App进程

    4:App进程接收到AMS发起的bindApplication()操作后会执行如下操作:
    4.1:通过 ServiceManager.initServiceCache()更新系统服务在App进程的Binder缓存。
    4.2:通过Handler消息机制,向App进程的主线程发一个“BIND_APPLICATION”消息,使操作切换至主线程继续后续执行。
    5:App进程会通过handleBindApplication()处理bindApplication()操作。 具体所做的事情如下:
    5.1:设置App进程名、为低内存设备关闭硬件加速功能、如果系统的版本号低于3.1,则更换AsyncTask的内部的线程池实现方法、系统版本号大于等于 3.0 的话,则开启严格模式来检查“是否在主线程开启了网络请求、初始化http代理、创建全局唯一Instrumentation实例 等。
    5.2:通过LoadedApk.makeApplication()创建App进程的唯一Application实例,回调Application的attachBaseContext()、onCreate()。

    App进程执行完bindApplication()操作后,又会回到system_server进程继续后续操作。

    这些操作包括如下部分:
    6.1:从“焦点栈”中获取“处于栈顶的待启动Activity对应的ActivityRecord”。
    6.2:通知App进程执行“scheduleLaunchActivity()”操作,在App进程进行待启动Activity的实例化、各种生命周期方法的执行、相应PhoneWindow维护的View树的绘制等操作。

    这是一次IPC操作,从system_server进程切换至App进程

    7:App 进程接收到LLAUNCH_ACTIVITY消息之后,会在App进程内部的handleLaunchActivity()对待启动Activity进行激活等初始化操作。 具体操作如下:
    7.1:从空闲消息处理器列表中 移除 “在主线程空闲时,执行强制GC操作的空闲消息处理器” 。
    7.2:在创建待启动Activity之前,先获取WMS服务在本进程的Binder代理并保存至WindowManagerGlobal。
    7.3:通过performLaunchActivity()初始化ContextImpl实例、对目标Activity进行初始化、执行Activity的绑定操作、执行Activity的相应生命周期方法、等Activity执行完Resume之后,才开始对Activity的View树进行App进程内部的测量、摆放、绘制等操作。并通过ViewRootImpl内部的“编舞者来接收IO硬件产生的“Vsync”刷新信号,进而对PhoneView维护的视图树进行周期性的刷新操作。
    7.4:根据AMS传递给App 进程的startsNotResumed,来决定是否需要“禁止Resume待启动Activity,如果禁止就会执行该Activity的pasue操作”。
    7.5:如果初始化Activity实例失败,告诉AMS需要 “移除” 此Activity对应保存在AMS 服务中的Activity栈中的ActivityRecord。


    详细过程

    当Zygote进程创建并初始化完App进程后,就会通过反射执行ActivityThread.main()对main线程进行初始化。

    1.1.ActivityThread.main()

    main()方法是子进程执行其主线程初始化的唯一入口。

    源码

    public static void main(String[] args) {
            //开始记录ActivityThread的初始化事件
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
            ......
            //为主线程创建Looper
            Looper.prepareMainLooper();
            
            //初始化App进程内的ActivityThread唯一实例
            ActivityThread thread = new ActivityThread();
            //见小节[1.2]
            thread.attach(false);
    
            //sMainThreadHandler就是ActivityThead.H类的实例
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
    
            //ActivityThread初始化完毕之后,结束记录该事件的耗时
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            //启动主线程Looper,开始处理消息
            Looper.loop();
    
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
    

    1.2.ActivityThread.attach()

    总结
    1:通过ViewRootImpl.addFirstDrawHandler()注册“View树的首次绘制完毕回调事件”。
    2:通过ViewRootImpl.addConfigCallback()注册“手机配置信息发生更改之后的回调事件。”
    3:通过ActivityManager.getService()获取AMS服务在本进程的BInder 代理,而后通过这个代理对象通知AMS执行attachApplication()操作。

    源码

    private void attach(boolean system) {
            //把当前ActivityThread实例对象赋值给sCurrentActivityThread 属性。使用的时候方便通过currentActivityThread()获取。
            sCurrentActivityThread = this;
            //用于区分“当前进程是否是系统进程”。
            mSystemThread = system;
            if (!system) {
                //见小节[1.2.1]
                ViewRootImpl.addFirstDrawHandler(new Runnable() {
                    @Override
                    public void run() {
                        ensureJitEnabled();
                    }
                });
                ......
                //见小节[1.3]
                final IActivityManager mgr = ActivityManager.getService();
                try {
                 //见小节[2.1]
                    mgr.attachApplication(mAppThread);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
                ......
            } else {
               //是系统进程的话,设置该进程的name为“system_process”。
               //可以启动一个模拟器或者刷root之后,打开可debug的进程之后,显示的那个“system_process”。如果要调试FrameWorker层的代码的话,那么此进程就是要debug的那个进程。
                android.ddm.DdmHandleAppName.setAppName("system_process",
                        UserHandle.myUserId());
                ......
            }
    
            ......
            //见小节[1.2.2]
            ViewRootImpl.ConfigChangedCallback configChangedCallback
                    = (Configuration globalConfig) -> {
                synchronized (mResourcesManager) {
                    // We need to apply this change to the resources immediately, because upon returning
                    // the view hierarchy will be informed about it.
                    if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                            null /* compat */)) {
                        updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                                mResourcesManager.getConfiguration().getLocales());
    
                        // This actually changed the resources! Tell everyone about it.
                        if (mPendingConfiguration == null
                                || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                            mPendingConfiguration = globalConfig;
                            sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                        }
                    }
                }
            };
            ViewRootImpl.addConfigCallback(configChangedCallback);
        }
    

    1.2.1.ViewRootImpl.addFirstDrawHandler():

    总结:
    1:注册“View树绘制第一帧时的回调事件”。
    2:在View树绘制第一帧时,用于通知注册了此事件的被观察者,View开始绘制第一帧了。

    源码

    public static void addFirstDrawHandler(Runnable callback) {
            synchronized (sFirstDrawHandlers) {
                if (!sFirstDrawComplete) {
                    sFirstDrawHandlers.add(callback);
                }
            }
        }
    
    private void draw(boolean fullRedrawNeeded) {
            ......
            //通知那些注册了“绘制第一帧”事件的被观察者,开始绘制第一帧了
            if (!sFirstDrawComplete) {
                synchronized (sFirstDrawHandlers) {
                    sFirstDrawComplete = true;
                    final int count = sFirstDrawHandlers.size();
                    for (int i = 0; i< count; i++) {
                        mHandler.post(sFirstDrawHandlers.get(i));
                    }
                }
            }
        ......
        }
    

    1.2.2.ViewRootImpl.addConfigCallback():添加当手机自身的配置信息发生改变之后(横竖屏切换、字体大小发生了更改等等)的回调事件。

    Configuration:该类表示的是“设备的配置信息”。该类定义了许多与手机本身相关的配置信息。
    1.orientation:表示当前手机的屏幕状态(横竖屏就是用这个来判断)。
    2.densityDpi:屏幕密度(eg:440dpi)。
    3.appBounds:屏幕大小。
    4.screenLayout:该参数是一个“复合值”。具体的存储的信息如下:
    4.1.屏幕整体大小:可通过该值与相应的mask进行位运算获得当前屏幕是“SMALL”、“NORMAL”、“LARGE”、“XLARGE”。
    4.2.屏幕布局:表示当前屏幕中的元素是“从左往右布局”还是“从右往左布局”。取值范围为:“SCREENLAYOUT_LAYOUTDIR_LTR”、“SCREENLAYOUT_LAYOUTDIR_RTL”。
    4.3.屏幕是否是圆形
    5.fontScale:字体的缩放比率。

    源码

    public static void addConfigCallback(ConfigChangedCallback callback) {
            synchronized (sConfigCallbacks) {
                sConfigCallbacks.add(callback);
            }
        }
    

    1.3.ActivityManager.getService():获取AMS服务在本进程的Binder代理。

    源码

    public static IActivityManager getService() {
            //调用IActivityManagerSingleton.get()会触发IActivityManagerSingleton中声明的create()。
            //见小节[1.3.1]
            return IActivityManagerSingleton.get();
        }
    

    1.3.1.Singleton.create()

    源码

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
                new Singleton<IActivityManager>() {
                    @Override
                    protected IActivityManager create() {
                        //见小节[1.3.2]
                        final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                        //见小节[1.3.7]
                        final IActivityManager am = IActivityManager.Stub.asInterface(b);
                        return am;
                    }
                };
    

    1.3.2.ServiceManager.getService():获得相应系统服务在本进程的 IBinder 引用。

    总结:
    1:如果ServiceManager内部的HashMap缓存了此Binder服务的话,则返回。
    2:如果没有,则通过 getIServiceManager().getService() 重新与system_server进程建立连接,获取相应服务在本进程的Binder代理。
    3:这个Binder代理对象与系统服务对象不是一个。因为AMS运行在system_server进程,此对象运行在 App进程。采用“进程隔离”的方式,每个进程都有自己的 虚拟内存地址空间,且每个进程被分配的虚拟内存地址都不一样,这就导致每个进程可访问的内存区域是不一样的,进程之间没有交集,这就避免了 “修改进程A内存区域会影响到进程B内存中的数据”。

    源码

    public static IBinder getService(String name) {
            try {
                IBinder service = sCache.get(name);
                //此时,从本地服务缓存中获取的AMS服务的本地代理肯定为 null。
                //因为这些系统服务的本地代理还没有通过 initSerivceCache()缓存起来。
                if (service != null) {
                    return service;
                } else {
                    //见小节[1.3.3]、[1.3.6]
                    return Binder.allowBlocking(getIServiceManager().getService(name));
                }
            } catch (RemoteException e) {
                Log.e(TAG, "error in getService", e);
            }
            return null;
        }
    

    1.3.3.ServiceManager.getIServiceManager():获取ServiceManager内部保存的IServiceManager实例。

    总结:
    1:如果IServiceManager实例已经初始化过了,则直接返回此实例。
    2:如果还没初始化过,则需要先初始化然后返回此类实例。

    源码

    private static IServiceManager getIServiceManager() {
            //非首次调用,则返回此类实例
            if (sServiceManager != null) {
                return sServiceManager;
            }
    
            // 初始化IServiceManager类实例
            //见小节[1.3.4]、[1.3.5]
            sServiceManager = ServiceManagerNative
                    .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
            return sServiceManager;
        }
    

    1.3.4.BinderInternal.getContextObject():获取一个IServiceManager,通过它可以获取到一些其它系统服务。

    总结:
    1:该方法是一个native方法,用于获取“IServiceManager类型的实例”。
    2:该IServiceManager接口的实例可以用来“查询其它服务”。

    源码

    /**
         * Return the global "context object" of the system.  This is usually
         * an implementation of IServiceManager, which you can use to find
         * other services.
         */
        public static final native IBinder getContextObject();
    

    1.3.5.ServiceManagerNative.asInterface():获取一个IServiceManager类型的IBinder服务。

    Binder使用上的简单介绍
    1:Binder这种IPC方式采用的是CS架构。
    2:IBinder表示“此类是可以用来进行IPC通信的,它提供了IPC通信的能力”。
    2.1:Binder类实现了IBidner接口,实现了 “onTransact()”。
    2.2:通常我们所提供的服务类要继承Binder,重写 OnTransact() 方法用于根据自己的业务处理来自Client端的请求。

    总结
    1:首先,判断通过“BinderInternal.getContextObject()”获得的IBinder服务是否是当前进程所创建,如果是直接返回此IBInder 服务。
    2:如果不是,则返回一个 ServiceManagerProxy,把服务端在本进程的IBinder服务实例保存到这个代理对象中。这样做是为了 方便以后通过此IBinder实例与服务的所属进程进行通信。

    源码

    static public IServiceManager asInterface(IBinder obj)
        {
            if (obj == null) {
                return null;
            }
            //根据“descriptor”从本进程中查找该Binder服务。
            //1:如果此IBinder服务所属者是当前进程的话,则返回该服务。
            //2:如果不是,则返回ServiceManagerProxy。其中“obj”是服务端进程的IBinder服务在本进程的一个实例。
            IServiceManager in =
                (IServiceManager)obj.queryLocalInterface(descriptor);
            if (in != null) {
                return in;
            }
            
            return new ServiceManagerProxy(obj);
        }
    
        //把IBinder服务在本进程的一个实例保存至ServiceManagerProxy中。
        //方便以后通过此IBinder实例与服务的所属进程进行通信。
        public ServiceManagerProxy(IBinder remote) {
            mRemote = remote;
        }
    

    1.3.6.IServiceManager.getService():通过Binder IPC方式,根据name从system_server进程获取系统服务在本地进程的Binder代理对象。

    源码

    /**
         * Retrieve an existing service called @a name from the
         * service manager.  Blocks for a few seconds waiting for it to be
         * published if it does not already exist.
         */
        public IBinder getService(String name) throws RemoteException;
    

    1.3.7.IActivityManager.Stub.asInterface():

    总结:
    1:把获取的IBinder对象封装到AMS服务在子进程的Binder代理对象中。
    2:此代理对象的实际类型为 IActivity.Stub.Proxy。
    3:此代理对象与AMS对象一样都实现了IActivityManager接口,此接口定了AMS向外提供了哪些操作。这样做的好处是“在使用的时候,就可以直接知道可以使用AMS提供的哪些方法了”。

    说明:
    1:从8.0开始,AMS这种用于IPC通信的系统服务的实现方式改为AIDL 来实现。
    2:8.0之前AMS内提供的 用于处理进程间操作的业务 全部是在ActivityManagerNative内部来实现,而从8.0开始采用AIDL之后,AMS直接继承自IActivityService.Stub原来处理进程间操作的业务全部挪到AMS来中完成。

    因为看不到IActivityService.Stub的内部实现,所以以下代码就摘抄了一个AS编译的AIDL文件生成的的asInterface()实现(通过AIDL方式编译的此方法的实现格式是一样)。

    public static sj.IMyAidlInterface asInterface(android.os.IBinder obj) {
        //判断IBinder服务是否为空
        if ((obj==null)) {
            return null;
        }
        
        //查询此服务是否是本进程创建的
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    
        if (((iin!=null)&&(iin instanceof sj.IMyAidlInterface))) {
            return ((sj.IMyAidlInterface)iin);
        }
        
        //此服务不是本进程创建的话,则返回与之对应的Proxy对象。
        return new sj.IMyAidlInterface.Stub.Proxy(obj);
    }
    
    ......
    
    Proxy(android.os.IBinder remote) {
          mRemote = remote;
    }
    

    2.1.ActivityManagerService.attachApplication()

    总结:
    1:通过ActivityManager.getService()获取AMS服务在本进程的Binder代理对象后,调用该代理对象的 attachApplication() 就会进行一次进程切换。
    2:App进程会被阻塞住,一直等到system_server进程内部的AMS.attachApplication()执行完毕为止。

    参数说明:
    IApplicationThread threa:App进程的ApplicationThread唯一实例。关于ApplicationThread的介绍请查看 本章-重要类说明

    源码

    @Override
        public final void attachApplication(IApplicationThread thread) {
            synchronized (this) {
                //获取调用者进程的pid(已经启动的App进程的id)。
                int callingPid = Binder.getCallingPid();
                final long origId = Binder.clearCallingIdentity();
                //见小节[2.2]
                attachApplicationLocked(thread, callingPid);
                Binder.restoreCallingIdentity(origId);
            }
        }
    

    2.2.ActivityManagerService.attachApplicationLocked()

    总结:
    1:根据 调用者进程的pid,获取记录此进程信息的ProcessRecord。如果获取的ProcessRecord为null的话,则表示“之前创建App进程那步出现了问题(ProcessRecord用于记录App运行在的进程信息)”,这种情况直接返回不再继续后续操作。
    2:注册“Binder服务死亡通知”。这里的“服务端”指的是App进程的ApplicationThread实例(ApplicationThread继承IApplicationThread.Stub,它是在此Binder IPC通信中扮演的是服务端角色)。App进程挂掉之后其Binder服务也会随之停止掉,此时AMS需要接收到这个通知,然后去回收一些此进程使用的资源(eg:重置此进程对应的ProcessRecord中的数据,进程被kill掉之后其ProcessRecord并不会从mPidsSelfLocked缓存中移除)。
    3:把当前App进程的ApplicationThread赋值给ProcessRecord中的thread。并重置此ProcessRecord中一些参数。
    4:通过App进程的ApplicationThread服务在system_server进程的Binder代理对象,执行bindApplication()来通知App进程继续后续“绑定”操作。
    4.1:如果执行“bindApplication()”之后的绑定操作失败了则:取消掉已经注册的 Binder服务死亡通知。调用startProcessLocked()再通知Zygote进程重新走一遍fork子进程流程。

    源码

    private final boolean attachApplicationLocked(IApplicationThread thread,
                int pid) {
    
            // 根据调用者进程的pid,获取记录此进程信息的ProcessRecord.
            ProcessRecord app;
            long startTime = SystemClock.uptimeMillis();
            if (pid != MY_PID && pid >= 0) {
                synchronized (mPidsSelfLocked) {
                    app = mPidsSelfLocked.get(pid);
                }
            } else {
                app = null;
            }
    
            if (app == null) {  
                ......
                //如果获取的ProcessRecord为null的话,则表示“之前创建App进程那步出现了问题(ProcessRecord用于记录App运行在的进程信息)”,这种情况直接返回不再继续后续操作。
                return false;
            }
    
           ......
            try {
                //注册“Binder服务死亡通知”。
                //这里的“服务端”指的是App进程的ApplicationThread实例(ApplicationThread继承IApplicationThread.Stub,它是在此Binder IPC通信中扮演的是服务端角色。App进程挂掉之后其Binder服务也会随之停止掉,此时AMS需要接收到这个通知,然后去回收一些此进程使用的资源(eg:重置此进程对应的ProcessRecord中的数据,进程被kill掉之后其ProcessRecord并不会从mPidsSelfLocked缓存中移除)。)
                AppDeathRecipient adr = new AppDeathRecipient(
                        app, pid, thread);
                thread.asBinder().linkToDeath(adr, 0);
                app.deathRecipient = adr;
            } catch (RemoteException e) {
                ......
                return false;
            }
    
            ......
            //把当前App进程的ApplicationThread赋值给ProcessRecord中的thread。
            app.makeActive(thread, mProcessStats);
            //ProcessRecord一些参数的重置操作。
            app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
            app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            app.forcingToImportant = null;
            updateProcessForegroundLocked(app, false, false);
            app.hasShownUi = false;
            app.debugging = false;
            app.cached = false;
            app.killedByAm = false;
            app.killed = false;
    
            ......
    
            try {
               ......
                //不清楚ProcessRecord中ActiveInstrumentation类型的 instr是做什么的。
                //但是无论此属性是否为null,AMS服务都会通过App进程的ApplicationThread服务在system_server进程的Binder代理对象执行bindApplication()来通知App进程继续后续操作。
                if (app.instr != null) {
                    //见小节[2.4]
                    thread.bindApplication(processName, appInfo, providers,
                            app.instr.mClass,
                            profilerInfo, app.instr.mArguments,
                            app.instr.mWatcher,
                            app.instr.mUiAutomationConnection, testMode,
                            mBinderTransactionTrackingEnabled, enableTrackAllocation,
                            isRestrictedBackupMode || !normalMode, app.persistent,
                            new Configuration(getGlobalConfiguration()), app.compat,
                            getCommonServicesLocked(app.isolated), //见小节[2.3]
                            mCoreSettingsObserver.getCoreSettingsLocked(),
                            buildSerial);
                } else {
                    thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                            null, null, null, testMode,
                            mBinderTransactionTrackingEnabled, enableTrackAllocation,
                            isRestrictedBackupMode || !normalMode, app.persistent,
                            new Configuration(getGlobalConfiguration()), app.compat,
                            getCommonServicesLocked(app.isolated), //见小节[2.3]
                            mCoreSettingsObserver.getCoreSettingsLocked(),
                            buildSerial);
                }
            ......
            } catch (Exception e) {
                 //如果此操作出现了问题导致抛出了异常情况。
                app.resetPackageList(mProcessStats);
                //取消掉已经注册的 Binder服务死亡通知。
                app.unlinkDeathRecipient();
                //调用startProcessLocked()再通知Zygote进程重新fork一个新的子进程。
                startProcessLocked(app, "bind fail", processName);
                return false;
            }
    
            boolean badApp = false;
            boolean didSomething = false;
            
            //See if the top visible activity is waiting to run in this process...
            //激活处于“焦点栈栈顶的待启动Activity”
            //见小节[3.1]
            if (normalMode) {
                try {
                    if (mStackSupervisor.attachApplicationLocked(app)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
                    ......
                }
            }
            ......
    
            return true;
        }
    

    2.3.getCommonServicesLocked.getCommonServicesLocked():获得一些公共的系统服务。

    总结:
    1:获得一些公共的系统Binder服务。
    1.1:如果isolated为true的话,则只把PMS服务的IBinder对象回传给App进程。
    1.2:如果isolated为fasle的话,则把PMS、WMS、AlarmManagerService(闹钟服务)的IBinder对象回传给App进程。
    2:获得的这些服务,会通过Binder这种IPC方式回传给App进程,App进程接收到AMS发起的binderApplication()请求后,会首先通过 ServiceManager.initServiceCache()更新系统服务在App进程的Binder缓存。

    源码

    private HashMap<String, IBinder> getCommonServicesLocked(boolean isolated) {
            //如果 isolated为true的话,则只把系统服务中的“PMS”对应的Binder对象存储到Map中。
            if (isolated) {
                if (mIsolatedAppBindArgs == null) {
                    mIsolatedAppBindArgs = new HashMap<>();
                    mIsolatedAppBindArgs.put("package", ServiceManager.getService("package"));
                }
                return mIsolatedAppBindArgs;
            }
    
            if (mAppBindArgs == null) {
                mAppBindArgs = new HashMap<>();
    
               //如果 isolated为false的话,则把系统服务中的“PMS、WMS、AlarmManagerService”对应的Binder对象存储到Map中。
                mAppBindArgs.put("package", ServiceManager.getService("package"));
                mAppBindArgs.put("window", ServiceManager.getService("window"));
                mAppBindArgs.put(Context.ALARM_SERVICE,
                        ServiceManager.getService(Context.ALARM_SERVICE));
            }
            return mAppBindArgs;
        }
    

    2.4.ApplicationThread.bindApplication()

    总结:
    1:通过 ServiceManager.initServiceCache()更新系统服务在App进程的Binder缓存。
    2:通过Handler消息机制,向App进程的主线程发一个“BIND_APPLICATION”消息,使操作切换至主线程继续后续执行。
    3:该操作是一次IPC过程,涉及到进程切换,从AMS所在的system_server进程切换至App进程。AMS要想主动发起与App进程的通信,就得借助于Binder这种IPC方式,因为ApplicationThread承担的是服务端的角色,客户端发起的请求,服务端接收后都会把这些操作扔到Bidner线程池中执行,这样做的好处是提高了服务端的“并发”性能。

    源码

    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) {
                    //通过 ServiceManager.initServiceCache()更新系统服务在App进程的Binder缓存。
                     //见小节[2.5]
                   ServiceManager.initServiceCache(services);
                }
    
                AppBindData data = new AppBindData();
                ......
                //见小节[2.6]
                sendMessage(H.BIND_APPLICATION, data);
            }
    

    2.5.ServiceManager.initServiceCache():更新系统服务在App进程的Binder缓存。

    源码

    public static void initServiceCache(Map<String, IBinder> cache) {
            if (sCache.size() != 0) {
                throw new IllegalStateException("setServiceCache may only be called once");
            }
            sCache.putAll(cache);
        }
    

    2.6.ActivityThread.handleBindApplication()

    总结:
    1:做一些准备操作。 记录进程的开始时间、设置App进程名、为低内存设备关闭硬件加速功能、如果系统的版本号低于3.1,则更换AsyncTask的内部的线程池实现方法系统版本号大于等于 3.0 的话,则开启严格模式来检查“是否在主线程开启了网络请求、初始化http代理、创建全局唯一Instrumentation实例 等。
    2:通过LoadedApk.makeApplication()创建App进程的唯一Application实例。

    源码

    private void handleBindApplication(AppBindData data) {
            ......
            //记录进程的开始时间。
            Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
            ......
            //设置App进程名
            Process.setArgV0(data.processName);
            //设置App进程在ddms模块显示的进程名
            android.ddm.DdmHandleAppName.setAppName(data.processName,
                                                    UserHandle.myUserId());
    
            if (data.persistent) {
                //为 低内存设备关闭硬件加速功能,这是为了节省资源开销。
                if (!ActivityManager.isHighEndGfx()) {
                    ThreadedRenderer.disable(false);
                }
            }
    
            ......
    
            // 如果系统的版本号低于3.1,则设置AsyncTask的内部的线程池实现方法。
            if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
                AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            }
    
            ......
    
            //系统版本号大于等于 3.0 的话,则开启严格模式来检查“是否在主线程开启了网络请求,如果开始了会抛出NetworkOnMainThreadException”。
            if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
                StrictMode.enableDeathOnNetwork();
            }
    
            //??
            if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
                StrictMode.enableDeathOnFileUriExposure();
            }
    
            ......
            //如果App可debug调试的话,则进行debug调试的相关设置
            if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
                ......
            }
    
            // 根据App是否可debug调试,来设置是否可以trace进程信息。
            boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
            Trace.setAppTracingAllowed(isAppDebuggable);
            if (isAppDebuggable && data.enableBinderTracking) {
                Binder.enableTracing();
            }
    
            //初始化http代理
            final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
            if (b != null) {
                // In pre-boot mode (doing initial launch to collect password), not
                // all system is up.  This includes the connectivity service, so don't
                // crash if we can't get it.
                final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
                try {
                    final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
                    Proxy.setHttpProxySystemProperty(proxyInfo);
                } catch (RemoteException e) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw e.rethrowFromSystemServer();
                }
            }
    
            ......
            
            // 创建全局唯一Instrumentation实例,该mInstrumentation会在Activity创建完毕执行其attach()时保存至Activity内部。
            if (ii != null) {
                try {
                    //创建Instrumentation实例
                    mInstrumentation = (Instrumentation)
                        cl.loadClass(data.instrumentationName.getClassName()).newInstance();
                } catch (Exception e) {}
                ......
                mInstrumentation.init(this, instrContext, appContext, component,
                        data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
               ......
            } else {
                mInstrumentation = new Instrumentation();
            }
    
            ......
            try {
                //创建App进程的唯一Application实例
                //见小节[2.7]
                Application app = data.info.makeApplication(data.restrictedBackupMode, null);
                //回调Instrumentation.onCreate()
                try {
                    mInstrumentation.onCreate(data.instrumentationArgs);
                }
               ......
                //回调Application的onCreate()生命周期方法
                try {
                    //见小节[2.8]
                    mInstrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                    ......
                }
            } finally {
                StrictMode.setThreadPolicy(savedPolicy);
            }
            ......
        }
    

    2.7.LoadedApk.makeApplication()

    总结:
    1:该方法做事是:创建Applicaton实例并执行该实例的attachBaseContext()与onCreate()生命周期方法。
    2:判断App进程的Application是否实例化了,如果已经创建了则返回该Application。
    3:系统采用反射的方式实例化Applation实例,第一步就是先指定“实例化Application的类的全限定名”。
    4:通过Instrumentation.newApplication()初始化Application实例并回调其attachBaseContext()。
    5:保存创建完毕的Application实例。
    6:通过Instrumentation.callApplicationOnCreate()回调Application的onCreate()。

    源码

    public Application makeApplication(boolean forceDefaultAppClass,
                Instrumentation instrumentation) {
            //判断App进程的唯一Application是否创建了,如果创建则直接返回。
            //一个进程只有一个Application实例。
            if (mApplication != null) {
                return mApplication;
            }
        
           //记录 创建Application花费的时间
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
    
            Application app = null;
            
           //指定“实例化Application的类的全限定名”。
           //ApplicationInfo记录的是Manifest文件中<application>中的属性信息。
           //如果“<application>未指定自定义Applcation”或者 “强制使用默认的Application”来初始化Application实例的话,则使用默认Application来
    
    初始化
            String appClass = mApplicationInfo.className;
            if (forceDefaultAppClass || (appClass == null)) {
                appClass = "android.app.Application";
            }
    
            try {
                java.lang.ClassLoader cl = getClassLoader();
                if (!mPackageName.equals("android")) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            "initializeJavaContextClassLoader");
                    initializeJavaContextClassLoader();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                }
                //创建ContextImpl实例。
                ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
                //见小节[2.7.1]
                app = mActivityThread.mInstrumentation.newApplication(
                        cl, appClass, appContext);
                appContext.setOuterContext(app);
            } catch (Exception e) {
                ......
            }
    
            mActivityThread.mAllApplications.add(app);
            //保存创建完毕的Application实例
            mApplication = app;
            
            //传入的instrumentation为null,不走这里
            if (instrumentation != null) {
                try {
                    instrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                    ......
                }
            }
    
            ......
    
            return app;
        }
    

    2.7.1.Instrumentation.newApplication()

    总结:实例化Application实例并回调Application的attachBaseContext()生命周期方法。

    源码

    public Application newApplication(ClassLoader cl, String className, Context context)
                throws InstantiationException, IllegalAccessException, 
                ClassNotFoundException {
            return newApplication(cl.loadClass(className), context);
        }
    
    
    static public Application newApplication(Class<?> clazz, Context context)
                throws InstantiationException, IllegalAccessException, 
                ClassNotFoundException {
            Application app = (Application)clazz.newInstance();
            app.attach(context);
            return app;
        }
    
    
    /* package */ final void attach(Context context) {
            attachBaseContext(context);
            mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
        }
    

    2.8.Instrumentation.callApplicationOnCreate()

    总结:实例化Application实例并回调Application的attachBaseContext()生命周期方法。

    源码

    public void callApplicationOnCreate(Application app) {
            app.onCreate();
        }
    

    3.1.ActivityStackSupervisor.attachApplicationLocked()

    总结:从“焦点栈”中获取“处于栈顶的待启动Activity对应的ActivityRecord”并激活此ActivityRecord描述的App进程的Activity。
    1:一个ActivityDisplay实例表示一块屏幕,一个ActivityDisplay实例中存储了多个ActivityStack实例。
    2:遍历每个ActivityDisplay中的ActivityStack集合,找到ActivityDisplay中的那个“焦点栈(ActivityStackSupervisor.mFocusedStack)”。
    3:找到“焦点栈”之后,调用其topRunningActivityLocked()从其内部保存TaskRecord列表中找到“处于栈顶的待启动Activity对应的ActivityRecord”。
    4:调用ActivityStackSupervisor.realStartActivityLocked()激活处于焦点栈的待启动Activity。

    源码

    boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
            //获取App进程名
            final String processName = app.processName;
            boolean didSomething = false;
            //遍历ActivityDisplay集合。
            //一个ActivityDisplay实例表示一块屏幕,一个ActivityDisplay实例中存储了多个ActivityStack实例。
            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
                //遍历每个ActivityDisplay中的ActivityStack集合。
                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                    final ActivityStack stack = stacks.get(stackNdx);
                    //找到ActivityDisplay中的那个“焦点栈”。
                    if (!isFocusedStack(stack)) {
                        continue;
                    }
                    //从“焦点栈”中获取“处于栈顶的待启动Activity”。
                    ActivityRecord hr = stack.topRunningActivityLocked();
                    if (hr != null) {
                        //待启动Activity对应的ActivityRecord信息只是添加到了AMS中的“Activity栈”中(具体是保存到ActivityTask中的TaskRecord列表中)。
                        //该Activity实例还没有在App进程进行实例化,此时“ActivityRecord中保存的用于描述其所属进程的ProcessRecord还未被赋值”。所以ActivityRecord.app为null。
                        //检查“待启动Activity是否未被添加到所属进程”、“App进程的uid与待启动Activity在Manifest中声明的uid一致”、“App进程名与从Manifest文件中解析出的进程名一致”这3个条件是否都满足。
                        if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                                && processName.equals(hr.processName)) {
                            try {
                                //见小节[3.2]
                                if (realStartActivityLocked(hr, app, true, true)) {
                                    didSomething = true;
                                }
                            } catch (RemoteException e) {
                                Slog.w(TAG, "Exception in new application when starting activity "
                                      + hr.intent.getComponent().flattenToShortString(), e);
                                throw e;
                            }
                        }
                    }
                }
            }
            if (!didSomething) {
                ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            }
            return didSomething;
        }
    

    3.2.ActivityStackSupervisor.realStartActivityLocked()

    总结:
    1:检查是否“所有的ActivityStack中的mPausingActivity表示的正在处于暂停状态的Activity执行完毕暂停操作了”。如果还有ActivityStack种的Activity正在执行暂停操作的话,则先不会执行待启动 Activity 的激活操作。
    2:把描述App进程信息的ProcessRecord对象保存至ActivityRecord中。
    3:通知App进程执行“ scheduleLaunchActivity()”操作,在App进程进行待启动Activity的实例化、各种生命周期方法的执行、相应PhoneWindow维护的View树的绘制等操作。**

    源码

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                boolean andResume, boolean checkConfig) throws RemoteException {
            //检查是否“所有的ActivityStack中的mPausingActivity表示的正在处于暂停状态的Activity执行完毕暂停操作了”
            if (!allPausedActivitiesComplete()) {
                ......
                return false;
            }
    
            ......
        
        //把描述App进程信息的ProcessRecord对象保存至ActivityRecord中。
        r.app = app;
        ......
            try {
                ......
                //见小节[3.3]
                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);
    
               ......
            } catch (RemoteException e) {
                ......
            }
    
            ......
            //andResume为true,走这里
            //见小节[4.1]
            if (andResume) {
                stack.minimalResumeActivityLocked(r);
            } else {
                ......
                r.state = PAUSED;
            }
    
            ......
    
            return true;
        }
    

    3.3.ApplicationThread.scheduleLaunchActivity()

    总结:通过Binder IPC方式,通知App进程执行待启动Activity的启动操作。
    1:缓存AMS传递给App进程的参数信息(eg:startsNotResumed被赋值为了false,该值表示“是否需要禁止Resume待启动Activity”。如果禁止就会执行该Activity的pasue操作。true:禁止,false:不禁止)。
    1:ApplicationThread作为Binder通信的服务端,其内部操作是通过Handler消息机制,向App进程的主线程发一个“LAUNCH_ACTIVITY”消息,使操作切换至主线程继续后续执行。
    2:该操作是一次IPC过程,涉及到进程切换,从AMS所在的system_server进程切换至App进程。AMS要想主动发起与App进程的通信,就得借助于Binder这种IPC方式,因为ApplicationThread承担的是服务端的角色,客户端发起的请求,服务端接收后都会把这些操作扔到Bidner线程池中执行,这样做的好处是提高了服务端的“并发”性能。

    源码

    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) {
    
               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;
                
                //该值为false,在AMS所在的system_server通过Binder请求App进程的时候,notResumed为赋值为了“!andResume”,而andResume为true。
                //该值表示“是否禁止Resume待启动Activity”,如果禁止就会执行该Activity的pasue操作。true:禁止,false:不禁止。
                r.startsNotResumed = notResumed;
                r.isForward = isForward;
    
                r.profilerInfo = profilerInfo;
    
                r.overrideConfig = overrideConfig;
                updatePendingConfiguration(curConfig);
    
                sendMessage(H.LAUNCH_ACTIVITY, r);
            }
    

    由于文章字数过长,请查看App启动流程:App进程内部操作-2


    重要类说明

    ApplicationThread
    • 从Android8.0开始,很多用于Binder IPC的类改用AIDL的方式实现,其中ApplicationThread的实现也发生了改变。
    • 该类由原来继承自ApplicationThreadNative 改为在8.0版本继承自 IApplicationThread.Stub。但是不管怎么变,我们可以知道 ApplicationThread还是用来做IPC通信的,且它在Binder这种CS架构中担任的是 服务端角色。

    ServiceManager
    • IServiceManager sServiceManager:该IServiceManager接口的实例可以用来“查询其它服务”(eg:从system_server进程获取AMS服务的本进程代理)。
    • HashMap<String, IBinder> sCache:用于缓存系统服务在本进程的Binder代理对象。
    • initServiceCache():缓存系统服务在App进程的Binder服务。当App冷启动完毕后,会执行“AMS.attachApplication()”,在该方法内部经过层层调用,会通过传入的App进程内唯一的ApplicationThread实例通过Binder这种IPC方式,回调执行子进程的 bindApplication() 用于“初始化App进程的唯一Application实例”。在初始化之前,会首先执行 SystemService.initServiceCache()缓存系统服务在App进程的Binder服务”。
    • getService():获取系统服务在本进程的Binder代理对象。
      1:如果ServiceManager内部的HashMap缓存了此Binder服务的话,则返回。
      2:如果没有,则通过 getIServiceManager().getService() 通过Binder驱动获取Native层ServiceManager的Binder服务后,再通过ServiceManager获取已向其注册的相应Binder服务在本进程的Binder代理对象。
      3:这个Binder代理对象与系统服务对象不是一个。因为AMS运行在system_server进程,此对象运行在 App进程。采用“进程隔离”的方式,每个进程都有自己的 虚拟内存地址空间,且每个进程被分配的虚拟内存地址都不一样,这就导致每个进程可访问的内存区域是不一样的,进程之间没有交集,这就避免了 “修改进程A内存区域会影响到进程B内存中的数据”。

    Instrumentation

    作用:
    1:用于检测,Application、Activity各个生命周期方法的执行。
    之所以能检测,是因为在Instrumentation内部的相应方法内部,会执行Application、Activity相应生命周期方法的执行。
    也可以说“Application、Activity各个生命周期方法的执行是通过Instrumentation中的相应方法来触发的”。
    2:用于检测,Activity启动结果是否成功。
    Activity 通过Intent进行跳转的操作,被封装到该类的execStartActivity()中去进一步执行。
    2.1:在启动目标Activity时会通过执行该类的execStartActivity()。
    2.2:首先,通过AMS.startActivity()启动目标Activity。不论启动是否成功,都会返回一个int类型的result。
    2.3:其次,会通过checkStartActivityResult()来检查Activity启动结果。
    返回的启动结果在[-100,-1]范围的话,则会根据实际的res值抛出相应的异常,用于提示此次启动Activity具体是因为什么问题而导致启动失败了。
    (像是常见的,Activity没有在manifest文件注册导致的抛出ActivityNotFoundException的原因等)。
    3:其他使用场景:
    3.1:自定义检测器(这个好像是用于Android 测试的),可以监听Application、Activity的各个生命周期方法调用。

    就像该类的说明一下,此类是“实现应用程序检测代码的基类”。
    要想自定义“检测器的话”,可以在Manifest文件中通过<instrumentation>指定具体的自定义检测器。
    3.2:可以Hook Instrumentation来达到监听Application、Activity 的目的。因为它在App进程中是唯一的,Application、Activity各个生命周期方法的执行是通过Instrumentation中的相应方法来触发的。所以说Instrumentation作为Hook点来说是比较“稳定”的,因为它在App进程中只有一个实例。


    ActivityClientRecord :
    • 在App进程每个Acticity组件都有一个该类的对象来对已启动Activity组件进行描述。
    • 该类与ActivityRecord相对应。
    • 该类存储在App进程,而ActivityRecord则存储在SystemServer进程中的AMS中的Activity栈结构中。

    Activity

    重要属性:
    1:mStartedActivity
    作用:该属性表示“是否启动了其他Activity”。该属性只有在Activity的几个startXX()(
    startActivityForResult()、startActivityIfNeeded()、startActivityForResultAsUser()等等)方法被重置为true,默认值为false。
    1:如果mStartedActivity为true,则表示启动了其他Activity,进一步则会使当前Activity不可见。
    2:如果为false,则表示可见。


    ThreadedRenderer
    StrictMode

    相关文章

      网友评论

        本文标题:App启动流程:App进程内部操作-1

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