美文网首页Android技术知识
Android Framework 启动流程简单解析!

Android Framework 启动流程简单解析!

作者: 搬砖小老弟 | 来源:发表于2022-06-12 20:47 被阅读0次

    对于Android开发,干上几年后,都要进阶,或者直接转行了。如果你还在干Android,想要进阶 对Framework的了解是必不可少的过程,下面就开始进入今天的主题吧。

    我们知道,对于任何程序语言而言,入口一般都是main函数。

    那Android的程序入口在哪呢? 他的main函数是怎么启动起来的呢?

    可能熟悉Android的朋友,知道一个应用程序的入口在ActivityThread中,那有个问题,ActivityThread中的main函数是何时被谁被调用的呢?

    将从本文中找到以上答案,如果已经熟悉了此过程的朋友,可以在温习一下。

    Android架构

    Android 平台的基础是 Linux 内核。Android Runtime (ART/Dalvik) 依靠 Linux 内核来执行底层功能,例如线程和低层内存管理等。

    而在Android Runtime之上就是我们经常接触的Java API Framework层, 如下图是Android的系统架构图

    今天的主题不是此架构图的各个部分解释,而是离应用层更近的Framework层启动过程分析。

    Android Framework概述

    如果我们这里抛开Android架构图,那狭义的Framewrok主要包含那些内容呢?

    按我的理解,可以分为三个部分 服务端,客户端,和依赖Linux底层能力的驱动部分。

    服务端

    主要是ActivityManagerService(AMS), WindowManagerService(WMS),PackageM anerService(PMS)

    • AMS 主要用于管理所有应用程序的Activity
    • WMS 管理各个窗口,隐藏,显示等
    • PMS 用来管理跟踪所有应用APK,安装,解析,控制权限等.

    还有用来处理触摸消息的两个类KeyInputQueue和InputDispatchThread,一个用来读消息,一个用来分发消息.

    客户端

    主要包括ActivityThread,Activity,DecodeView及父类View,PhoneWindow,ViewRootImpl及内部类W等

    • ActivityThread主要用来和AMS通讯的客户端,Activity是我们编写应用比较熟悉的类
    • 后面几个类的介绍,可以参考我的另一篇博客 Android 绘制原理浅析【干货】

    依赖Linux底层能力的驱动

    主要是SurfaceFlingger(SF)和Binder驱动

    • 每一个窗口都对应一个Surface,SF驱动的作用就是把每一个Surface显示到同一个屏幕上
    • Binder 内核驱动的作用,就是为上面的服务端和客户端(或者服务端和服务端之间),提供IPC通讯用的。

    Zygote

    系统中运行的第一个Dalvik虚拟机程序叫做zygote,该名称的意义是“一个卵”,,因为接下来的所有 Dalvik虚拟机进程都是通过这个“卵” 孵化出来的。

    zygote进程中包含两个主要模块,分别如下:

    • Socket服务端。该 Socket服务端用于接收启动新的Dalvik进程的命令。
    • Framework共享类及共享资源。当zygote进程启动后,会装载一些共享的类及资源,其中共享类是在preload-classes文件中被定义,共享资源是在preload-resources中被定义。因为zygote进程用于孵化出其他Dalvik进程,因此,这些类和资源装载后,新的Dalvik进程就不需要再装载这些类和资源了,这也就是所谓的共享。

    zygote进程对应的具体程序是app_rocess,该程序存在于system/bin目录下,启动该程序的指令是 在 init.rc中进行配置的。

    Zygote 有️两个优秀的特点

    • 每fork出的一个进程都是一个Dalvik虚拟机,独立的进程可以防止一个程序的崩溃导致所有程序都崩溃,这种虚拟机类似Java虚拟机,对于程序员来说,可以直接使用Java开发应用
    • zygote进程预先会装载共享类和共享资源,这些类及资源实际上就是SDK中定义的大部分类和资源。因此,当通过zygote孵化出新的进程后,新的APK进程只需要去装载A PK 自身包含的类和资源即可,这就有效地解决了多个APK共享Framework资源的问题。

    SystemServer

    zygote孵化出的第一个Dalvik进程叫做SystemServer,SystemServer仅仅是该进程的别名,而该进程具体对应的程序依然是app_process,因为SystemServer是从app_process中孵化出来的。

    SystemServer中创建了一个Socket客户端,并有AmS负责管理该客户端,之后所有的Dalvik进程都将通过该Socket客户端间接被启动。当需要启动新的APK进程时,AmS中会通过该Socket客户端向 zygote进程的Socket服务端发送一个启动命令,然 后 zygote会孵化出新的进程。 上面提到的服务端,AMS,PMS,WMS等都是在SystemServer中启动的.

    Android Framework 源头

    操作系统的一般启动流程,分为三个步骤

    1. 开机通电后,加载bootloader程序
    2. 操作系统内核初始化
    3. 执行第一个应用程序

    Android 系统是基于Linux 内核Kernel,前面Linux bootloader这里不做介绍,直接介绍操作系统内核初始化,在这个时候,它会加载init.rc文件.

    init.rc文件

    在Android根目录下面,可以直接找到init.rc

    generic_x86:/ # ls
    acct     bin        cache   config data         dev init            init.rc              init.usb.rc      lost+found mnt oem  product sdcard  sys    ueventd.rc 
    adb_keys bugreports charger d      default.prop etc init.environ.rc init.usb.configfs.rc init.zygote32.rc metadata   odm proc sbin    storage system vendor        
    

    打开init.rc

    generic_x86:/ # cat init.rc
    # ..... 省略其他
     # Now we can start zygote for devices with file based encryption
    trigger zygote-start
    
    # It is recommended to put unnecessary data/ initialization from post-fs-data
    # to start-zygote in device's init.rc to unblock zygote start.
    on zygote-start 
        # A/B update verifier that marks a successful boot.
        exec_start update_verifier_nonencrypted
        start netd
        start zygote
        start zygote_secondary
    
    on property:vold.decrypt=trigger_restart_framework
        stop surfaceflinger
    # 启动SF
        start surfaceflinger  
        
    # ..... 省略其他 media(媒体)  network(网络)等启动
    

    也就是在 init.rc时,启动Android 内核。

    app_process

    Android 内核也是main方法开始,他的main方法在 frameworks/base/cmds/app_process/app_main.cpp下

    int main(int argc, char* const argv[])
    {
        ...
        //初始化AndroidRuntime
        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
        
        bool zygote = false;
        bool startSystemServer = false;
        bool application = false;
        String8 niceName;
        String8 className;
    
        // 根据参数具体判断启动那个服务
        ++i;  // Skip unused "parent dir" argument.
        while (i < argc) {
            const char* arg = argv[i++];
            if (strcmp(arg, "--zygote") == 0) {
                zygote = true;
                niceName = ZYGOTE_NICE_NAME;
            } else if (strcmp(arg, "--start-system-server") == 0) {
                startSystemServer = true;
            } else if (strcmp(arg, "--application") == 0) {
                application = true;
            } else if (strncmp(arg, "--nice-name=", 12) == 0) {
                niceName.setTo(arg + 12);
            } else if (strncmp(arg, "--", 2) != 0) {
                className.setTo(arg);
                break;
            } else {
                --i;
                break;
            }
        }
        if (!className.isEmpty()) {
            args.add(application ? String8("application") : String8("tool"));
            runtime.setClassNameAndArgs(className, argc - i, argv + i);
        }else{
            ....
            //启动SystemServer
            if (startSystemServer) {
                args.add(String8("start-system-server"));
            }
        }
        ....
         if (zygote) {
           //启动Zygote
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        } else if (className) {
            runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
        } else {
            fprintf(stderr, "Error: no class name or --zygote supplied.\n");
            app_usage();
            LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        }
    }
    

    在这个Main方法中,先初始化了AppRuntime,他的父类是AndroidRuntime。然后我们看到了启动了Java类ZygoteInit。

    那c++代码里怎么启动Java类呢,我们继续看 start方法

    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
       ...
       //启动Java虚拟机
         if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
            return;
        }
        ...
        //找到Java 里面的Main方法
         jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
                "([Ljava/lang/String;)V");
            if (startMeth == NULL) {
                ALOGE("JavaVM unable to find main() in '%s'\n", className);
                /* keep going */
            } else {
            //执行Main方法
                env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
        ....    
    }
    

    可以看到最后先创建了Java虚拟机,调用了Java的main方法,是不是感觉有些熟悉感了。

    ZygoteInit

    上面介绍到,会启动Java的ZygoteInit类,那他里面干了些什么呢? 我们来看一下关键代码,还是从Main方法开始

    //ZygoteInit.java
      public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
        ZygoteHooks.startZygoteNoThreadCreation();
    
        //创建socket
        zygoteServer.createZygoteSocket(socketName);
        Zygote.createBlastulaSocket(blastulaSocketName);
    
        if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
                //预加载系统资源
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
        } else {
            Zygote.resetNicePriority();
        }
    
        //fork SystemServer进程
        if (startSystemServer) {
            Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
            // child (system_server) process.
            if (r != null) {
                r.run();
                return;
            }
        }
    
        //等待Socket的接入
        if (caller == null) {
            Log.i(TAG, "Accepting command socket connections");
            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);
        }
    

    注释写了大概Zygote 启动里面的初始化内容

    • 创建Socket
    • 加载系统资源
    • 启动SystemServer
    • runSelectLoop 等待socket接入,开始执行fork新的进程.

    SystemServer

    下面继续看SystemServer 启动的过程,从Main方法开始

    //SystemServer.java
       /**
         * The main entry point from zygote.
         */
        public static void main(String[] args) {
            new SystemServer().run();
        }
    

    很简单,创建一个自己的对象,并执行run方法,看一下run方法

    private void run() {
        ...
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }
    
        VMRuntime.getRuntime().clearGrowthLimit();
        // The system server has to run all of the time, so it needs to be
        // as efficient as possible with its memory usage.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
    
        android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();
    
       // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        mSystemServiceManager.setStartInfo(mRuntimeRestart,
                mRuntimeStartElapsedTime, mRuntimeStartUptime);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    
       try {
            traceBeginAndSlog("StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
               Slog.e("System", "******************************************");
                Slog.e("System", "************ Failure starting system services", ex);
                throw ex;
        } finally {
            traceEnd();
        }
    
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    

    run方法里面主要进行了设置手机时间,设置虚拟机内存大小,创建消息循环Looper,创建SystemServiceManager等,最主要的是启动了各类服务,我们接着看一下startBootstrapServices ,startCoreServices,startOtherServices方法

    private void startBootstrapServices() {
        Installer installer = mSystemServiceManager.startService(Installer.class);
        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
    
        mActivityManagerService = mSystemServiceManager.startService(
                    ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        ....
    }
    
    private void startCoreServices() {
        ...
         mSystemServiceManager.startService(BatteryService.class);
         ...
    }
    
     private void startOtherServices() {
            final Context context = mSystemContext;
            VibratorService vibrator = null;
            DynamicAndroidService dynamicAndroid = null;
            IStorageManager storageManager = null;
            NetworkManagementService networkManagement = null;
            IpSecService ipSecService = null;
            NetworkStatsService networkStats = null;
            NetworkPolicyManagerService networkPolicy = null;
            ConnectivityService connectivity = null;
            NsdService serviceDiscovery= null;
            WindowManagerService wm = null;
            SerialService serial = null;
            NetworkTimeUpdateService networkTimeUpdater = null;
            InputManagerService inputManager = null;
            TelephonyRegistry telephonyRegistry = null;
            ConsumerIrService consumerIr = null;
            MmsServiceBroker mmsService = null;
            HardwarePropertiesManagerService hardwarePropertiesService = null;
            ....
    }
    

    在这些方法中启动了,我们的核心服务,和常用服务。 代码中也可以看到AMS,PMS,WMS等相关服务.

    Launcher启动介绍

    一般服务启动完成后,就会想继调用systemReady()方法。 在SysytemServer startOtherServices中看到一个监听回调

    mActivityManagerService.systemReady(() -> {
      try {
            startSystemUi(context, windowManagerF);
        } catch (Throwable e) {
            reportWtf("starting System UI", e);
        }
      }
    }
    
    static final void startSystemUi(Context context, WindowManagerService windowManager) {
            Intent intent = new Intent();
            intent.setComponent(new ComponentName("com.android.systemui",
                        "com.android.systemui.SystemUIService"));
            intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
            //Slog.d(TAG, "Starting service: " + intent);
            context.startServiceAsUser(intent, UserHandle.SYSTEM);
            windowManager.onSystemUiStarted();
    }
    

    而Ams启动完成后,显示Launcher

    //AMS.java
     public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
     ...
         startHomeActivityLocked(currentUserId, "systemReady");
         //
         mStackSupervisor.resumeFocusedStackTopActivityLocked();
     ...
     }
    

    其实到这里大致流程就介绍完了,但是文章开始的ActivityThread的main方法是何时被调用的,还没回答,这里不详细展开,简略回答一些.

    ActivityThread的main方法如何被调用的?

    AMS是管理Activity的启动结束等,查看AMS代码,当当前启动的APP没有创建进程时,会最终调用到ZygoteProcess,然后向 Zygote发送一个socket请求。

    resumeTopActivityLocked -> startProcessLocked -> Process.start() -> ZygoteProcess.start() -> ZygoteProcess.startViaZygote() —> ZygoteProcess.zygoteSendArgsAndGetResult()

    接下来,看一下大致代码

    //AMS.java
    private final boolean startProcessLocked(ProcessRecord app, String hostingType,
                String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
                //这里entryPoint为ActivityThread
         final String entryPoint = "android.app.ActivityThread";
    
        return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
                        runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                        startTime);    
    }
    

    //ZygoteProcess.java
    private Process.ProcessStartResult startViaZygote(final String processClass,... ){
        ArrayList<String> argsForZygote = new ArrayList<String>();
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        argsForZygote.add("--runtime-flags=" + runtimeFlags);
        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
        if (startChildZygote) {
            argsForZygote.add("--start-child-zygote");
        }
        argsForZygote.add(processClass);
        synchronized(mLock) {
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                                  useBlastulaPool,
                                                  argsForZygote);
        }
    }
    
    //发起Socket请求,给Zygote
    private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ArrayList<String> args,..){
        blastulaSessionSocket = zygoteState.getBlastulaSessionSocket();
    
        final BufferedWriter blastulaWriter = new BufferedWriter(
                new OutputStreamWriter(blastulaSessionSocket.getOutputStream()),
                                    Zygote.SOCKET_BUFFER_SIZE);
        final DataInputStream blastulaReader =
        new DataInputStream(blastulaSessionSocket.getInputStream());
        blastulaWriter.write(msgStr);
        blastulaWriter.flush();
        ...
    }
    

    最终 Zygote收到请求调用ZygoteInit中zygoteinit方法

    //ZygoteInit.java
     public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
                ClassLoader classLoader) {
            if (RuntimeInit.DEBUG) {
                Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
            }
    
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
            RuntimeInit.redirectLogStreams();
    
            RuntimeInit.commonInit();
            ZygoteInit.nativeZygoteInit();
            return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
        }
    

    在 RuntimeInit中findStaticMain,最后在ZygoteInit中执行最终返回的这个Runnable,达到调用main方法的目的.

    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
                ClassLoader classLoader) {
            nativeSetExitWithoutCleanup(true);
            VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
            VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
            final Arguments args = new Arguments(argv);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            return findStaticMain(args.startClass, args.startArgs, classLoader);
        }
    
    protected static Runnable findStaticMain(String className, String[] argv,
                ClassLoader classLoader) {
            ..
            m = cl.getMethod("main", new Class[] { String[].class });
            return new MethodAndArgsCaller(m, argv);
        }
    

    总结

    如果你都看到这了,希望帮忙点个赞,谢谢啦。 因为本人水平有限,各路大佬如看到文中有错误,欢迎指出,在此表示感谢。

    最后为了帮助到大家有效率的学好 Android Framework知识点,特意整理了一份Framework的开发进阶滋尿,帮助大家在技术的道路上更进一步,大家有需要的可以点击这里查看获取方式 传送门直达!!!

    相关文章

      网友评论

        本文标题:Android Framework 启动流程简单解析!

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