前言

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

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

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

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

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

Android架构

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

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

image

今天的主题不是此架构图的各个部分解释,而是离应用层更近的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:/ # lsacct     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 encryptiontrigger 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_secondaryon 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& 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.javaprivate 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.javaprivate Process.ProcessStartResult startViaZygote(final String processClass,... ){    ArrayList argsForZygote = new ArrayList();    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请求,给Zygoteprivate static Process.ProcessStartResult zygoteSendArgsAndGetResult(        ArrayList 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.javapublic 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 相关知识点个人总结
  • Android "画"美妆,修图(换证件照背景,污点修复等)

参考书籍

《Android 内核剖析》 柯元旦

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. android上一些方法的区别和用法的注意事项
  5. 浅析android通过jni控制service服务程序的简易流程
  6. android实现字体闪烁动画的方法
  7. Android(安卓)Wifi模块分析(三)
  8. Android中dispatchDraw分析
  9. Android四大基本组件介绍与生命周期

随机推荐

  1. Android(安卓)bluetooth介绍(四): a2dp conn
  2. Android(安卓)DrawerLayout 使用
  3. android属性动画最简单使用
  4. 【Android】九宫格的实现
  5. Android(安卓)viewpager 拿到当前显示的
  6. android dialog和activity 改变出现消失
  7. Mac Error Create Android(安卓)Project
  8. Android简单画板的实现
  9. Android(安卓)Weekly Notes Issue #234
  10. Managing Projects from Eclipse with AD