android6.0源码目录简单分析

来源:互联网 发布:java amr转mp3 编辑:程序博客网 时间:2024/05/21 14:09
目录abi ==>应用程序二进制接口
    定义:应用程序和操作系统之间、一个应用和它的库之间、应用的组成部分之间的低接口
    
    ABI与API的区别:
        API定义了源代码和库之间的接口
        1、同样的代码可以在支持API的任何系统中编译
        2、ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行

    abi/cpp下目录:
        include:cxxabi.h、new、typeinfo
        src:
        Android.mk
        use_rtti.mk

    作用:
        abi规定了二进制文件的格式、内容,装载/卸载程序的要求,函数调用时的参数传递规则,寄存器、堆栈的使用

    实质:
        abi定义了运行时的兼容性问题
        api定义了静态状态下的兼容性问题



目录art==>Android Runtime
    Dalvik虚拟机通过以下方式提高性能
        1、Dex代码安装时或第一次动态加载时,odex化处理
        2、Android2.2版本提供了JIT机制提升性能
        3、提高硬件配置,如更多核CPU、更高频率CPU、更多的RAM

    1、Dalvik运行环境使用JIT来进行转译,应用每次运行的时候字节码都需要JIT转化为机器码——>拖慢应用的运行效率
    2、ART则使用AOT(Ahead Of Time)进行处理,会在应用程序安装完毕时,进行预先的基础性编译作业——>减去JIT运行时的机器码转化时间,应用的启动和执行都会变得更加快速

    ART
        优点:
            1、系统性能的显著提升
            2、应用启动更快、运行更快、体验更流畅、触感反馈更及时
            3、更长的电池续航能力
            4、支持更低的硬件
        缺点:
            1、更大的存储空间占用可能会增加10%~20%
            2、更长的应用安装时间
        总结:ART的功效就是“空间换时间”

    art目录下:
        compiler:主要负责Dalvik字节码到本地码的转换,编译为libart_compiler.so
        dex2oat:完成dex文件到oat文件的转换,编译为dex2oat
        runtime:Android ART运行时源代码,编译为libart.so
        oatdump:对oat文件进行分析并格式化显示出文件的组成结构
        jdwpspy:是java的调试支持部分,即JPWP服务端的实现

    ART——>基于Android4.4以后的版本,意味着最低的版本要求为Android4.4

    参考Blog:ART运行时无缝替换Dalvik虚拟机的过程分析
    
        关键点:
            1、ART虚拟机的启动过程
            2、Dex字节码翻译成本地机器码的过程

        分析关键1:ART虚拟机的启动过程
            Android系统在启动的时候创建Zygote进程充当应用程序孵化器,Zygote进程在启动的过程中又会创建一个Dalvik虚拟机
            Zygote进程是通过复制自己(也就是fork)来创建新的应用程序进程,这意味着Zygote进程会将自己的Dalvik虚拟机也复制给应用程序进程
            ==>Android系统通过将ART运行时抽象成一个Java虚拟机,以及通过系统属性persist.sys.dalvik.vm.lib和一个适配层JniInvocation就可以无缝地将Dalvik虚拟机替换为ART运行

        分析关键2:Dex字节码翻译成本地机器码的过程
            1、dex字节码优化——>dey文件——>存放odex文件
            2、dex2oat——>dex字节码翻译成本地机器码——>oat文件——>存放odex文件

            oat:自定义的elf文件,里面包含的都是本地机器指令
                字段oatdata:存储原来打包在APK里面的dex文件
                字段oatexec:翻译dex文件里面的类方法得到的本地机器指令
            
            最终,APK运行时,生成的oat文件会被加载到内存中,并且ART通过里面的oatdata和oatexec段找到任意一个类的方法对应的本地机器指令来执行

        1、调用JNI接口FindClass加载com.android.internal.os.ZygoteInit类
        2、调用JNI接口GetStaticMethodID找到com.android.internal.os.ZygotInit类的静态成员函数main
        3、调用JNI接口CalStaticVoidMethod开始执行com.android.internal.ZygoteInit类的静态成员函数main的本地机器指令
        完成上述的步骤,开始运行ART虚拟机
        当然相关的信息存放在dex2oat工具生成的oat文件中,故需要通过分析oat文件才可深入理解上述内容

        详见:参考罗升阳Blog ART相关



目录bionic==>系统底层库
    针对Android系统定制的仿生C库、链接器等所在目录。Android并没有使用linux的glibc库,bionic C库针对嵌入式系统优化,添加了一些Android特定的函数API,同时大大减少库的体积,也避免了LGPL版权的问题

    bionic目录下:
        libc库 --> C库,如stdio、stdlib、string
        libdl --> 动态链接库访问接口
        libm --> 数学函数库,提供常见的数序运算和浮点运算
        libstd --> 标准C++库
        libthreaddb --> 线程调试库,可利用此库对多线程程序进行调试
        linker --> 链接器



目录bootable==>启动引导相关
    bootable目录下:
        bootloader --> 引导
        diskinstaller --> Android镜像打包器
        recovery --> 系统恢复相关
    
    recovery目录下:
        1、恢复出厂设置
        2、OTA升级
    
    recovery.cpp -->main流程
        1、将标准输出、标准错误重定位到 /tmp/recovery.log
        2、load_volume_table()——>根据/etc/recovery.fstab,建立分区表
        3、get_args()——>从cache/recovery/command文件中读入参数,写入arg*中
        4、解析参数arg*——>get_bootloader_message()——>misc分区——>mtd分区工具
        5、——>minui建立图像部分、进度条、及事件处理。
        6、据解析的内容,确定下步的任务——>调用具体功能函数,如安装升级包,擦除cache分布、userdata分区等
        7、finish_recovery()——>清除recoverycommand,准备启动系统,tmp/recovery.log复制到cache:recovery/log,将intent写入cache/recovery/intent
        8、重启机器

    内容1:factory reset
        erase_volume() reformats/data
        erase_volume() reformats/cache
    关键点:
        解析arg参数及根据参数执行相关内容,卸载挂载点、清除分区数据、misc分区数据
    
        misc分区存放recovery引导信息

    内容2:OTA安装
        install_package() attempts to install the update
        确保升级包已mount



目录build==>编译Android系统、Android SDK、及相关文档
    make、shell、Python
    
    解决问题:
        1、如何将Android模块统一管理
        2、如何能够在不同的操作系统上进行编译
        3、如何在编译时能够支持面向不同的硬件设备

    build目录下:
        core-->Build系统核心文件
            定义了整个Build系统的框架

        注:
            针对某个产品的make文件,通常位于device,该目录下又以公司名、及产品名分为两级目录
            针对某个产品的make文件
    
        envsetup.sh脚本——>初始化编译环境并引入辅助的shell函数
        例如 lunch:提供一个菜单让开发人员选择需要编译的目标产品(target product)和变体(variant),并做一些检查、设置环境变量、并打印出主要的环境变量
  
        m:在源码树根目录执行make
        mm:Build当前目录下的模块
        mmm:Build指定目录下的模块
        。。。

        整个Build系统的入口文件main.mk,在main.mk中又包含其他的文件,其他的文件又包含更加的文件——>引入整个Build系统

    main.mk:最主要的make文件。该文件首先对编译环境进行检查,同时引入其他的make文件,另外还还定义了droid、sdk
    help.mk:列出主要的make目标及其说明
    pathmap.mk:将许多头文件的路径通过名值对的方式定义为映射表,并提供include_path_for函数来获取,例如通过$call include_path_for(frameworks_native)便可以获取到framework本地代码的需要的头文件路径
    envsetup.mk:配置Build系统需要环境变量,当前编译的主机平台信息就是在这个文件中确定的,另外文件还指定了各种编译结果的输出路径
    combo/select.mk:根据当前编译器的平台选择平台相关的make
    dumpvar.mk:在Build之前,显示此次的Build配置信息
    config.mk:整个Build系统的配置文件,主要内容1、定义了许多的常量来负责不同类型模块的编译2、定义编译器参数,以及常见文件后缀3、根据Broadconfig.mk文件配置产品相关的参数4、设置一些常用工具的路径如flex、e2fsck、dx
    definitions.mk:定义了大量的函数,都是Build系统的其他文件将用到的,如my_dir,find_subdir_files等
    distdir.mk:针对disk目标的定义,dist目标用来拷贝文件到指定路径
    dex_preopt.mk:针对启动jar包的预先优化
    pdk_config.mk:针对pdf的配置文件
    post_clean.mk:在前一次Build的基础上检查当前Build的配置,并执行必要清理工作
    legacy_prebuilds.mk:该文件之定义了GRANDFATHERED_ALL_PREBUILD变量
    Makefile:被main.mk包含该文件中的内容,辅助main.mk的一些额外内容

    模块的类型:c/c++库、APK应用、Java库、可执行文件等

    java、c/c++库还分静态、动态库,可执行文件可针对设备、也可以针对主机,这些在config.mk中定义了许多的常量,每一常量描述了一种类型模块的编译方式。当然,详细的编译方式都是在对应的make文件中定义。由于不同类型的模块的编译过程会有一些相同的步骤——>复用共同的代码。复用的方式:将共同的代码放到专门的文件中,然后在其他文件中包含这些文件

    make droid——>编译整个系统的镜像
    make framework——>编译所有java framework内容

    在Build系统添加新内容:
        1、添加新产品
    开发新的Android产品的时候,首先在Build系统中添加对于该产品的定义,而通常对产品定义的文件位于device目录(也可能是vendor目录),device目录下根据公司名以及产品名分为二级目录
    
        产品定义至少需要四个文件:1、AndroidProducts.mk2、产品版本定义文件3、BroadConfig.mk4、vendorsetup.sh

        AndroidProducts.mk:定义一个变量——>PRODUCT_MAKEFILES,该变量的值为产品版本定义文件名的列表
        产品版本定义文件:对特定产品版本的定义(可多个文件,多个版本)。一般情况下,我们不需要定义所有变量(版本相关),,Build系统已经预先定义了一些组合,位于build/target/product,该目录下每个文件都定义了一个组合,我们只需要继承这些预置的定义,然后再覆盖自己想要的变量定义即可
        BroadConfig.mk:该文件用来配置硬件主板,它定义的都是设备底层的硬件特性,如设备的主板相关信息,wifi,bootloader,内核等
        vendorsetup.sh:该文件的作用是通过add_lunch_combo函数在lunch函数中添加一个菜单选项

            注释:
        build/envsetup.sh会扫描所有的device和vendor二级目录下的名称为vendorsetup.sh的文件,并根据其中的内容确定lunch函数菜单选项

        2、添加新模块
    一个模块的所有文件通常位于同一个文件夹,为了将当前模块添加到整个Build系统中,每个模块都需要专门的make文件(Android.mk),Build系统会扫描名称为Android.mk的文件,并根据该文件的内容编译出相应的产物

    编译是以模块为单位的,每一个模块都有一个唯一的名称,一个模块的依赖对象只能是另一个模块,而不能是其他类型的对象(先定义成模块)
    


目录cts==>兼容性测试用例
    手机制造商、运营商在Android打造、定制自己特有的手机操作系统==>添加/更改Android系统源码==>规范更改==>方便上层应用的移植

    CTS:对手机的硬件、软件、接口、性能进行测试

    通过CTS测试的Android手机系统,Google才会颁发许可,以保证不同厂商之间的Android系统的兼容

    一系列Junit Test Suit==>配置xml文件+命令==>自动化测试

    测试内容:
        1、数据——>必须实现一种无线连接、速率达到200Kbit/s
        2、Camera——>至少2M pixels
        3、重力加速——>必须有,三维>50Hz
        4、指南针——>必须有,三维>10Hz
        5、GPS——>必须有
        6、内存,Nand、MMS/SMS、AlarmClock
        7、第二次启动一个应用的时间不能超过第一次启动时间
        8、CTS测试——>必须通过最新的CTS
        9、升级——>必须有一种方法升级系统(OTA、USB、SD卡)

    CtsTestCaseList.mk——>cts模块组件的编译选项配置,对于自己添加的测试用例,需要添加进这里面的cts_test_package变量中
    
    cts/tools/tradefed_host/README——>介绍如何配置cts环境以及使用的常用命令



目录dalvik==>一个应用对应一个单独的Dalvik虚拟机实例
    不同点:
        Dalvik虚拟机使用dex格式类文件,一个dex文件包含若干个类==>可以将各个类中重复的字符串,和其他常数只保存一次——>节省空间,适合在内存和处理器速度有限的手机系统中使用。
        Java虚拟机使用class格式类文件,一个class文件包含一个类

        ==>包含相同类的未压缩的dex文件稍少于一个已压缩的jar文件

        Dalvik虚拟机使用的指令是基于寄存器的==>更多指令空间
        Java虚拟机使用的指令是基于堆栈的==>更多指令

        ==>本地机器语言基于寄存器执行的,而基于寄存器的指令更容易进行OTA编译及优化

    特性:
        内存管理、垃圾收集、JIT、JNI、以及进程和线程管理

    1、内存管理
        Dalvik内存==>1、Java Object Heap
                                 2、Bitmap Memory
                                 3、Native Heap

        Java Object Heap:是用来分配Java对象的
            Dalvik启动的时候,可以通过-Xms和-Xmx选项来指定Java Object Heap的最大值(默认16M)和最小值(默认2M),通常设置最大值、最小值相等

       Bitmap Memory==>External Memory:用来处理图像

       Native Heap:native code中使用malloc等分配出来的内存,可以自由使用,但仍受系统的限制

    2、垃圾收集(GC)
        Dalvik自动回收那些不再使用的Java Object

        垃圾收集机制:
            大多数情况下,垃圾收集线程与其他线程是并发执行的
            一次可能只收集一部分垃圾
            一次垃圾收集造成的程序中止时间通常小于5ms

    3、即时编译(JIT)
        相对于AOT而言,JIT是在程序运行的过程中进行编译。

        优点:运用程序的运行时信息来对编译出来的代码进行优化

        缺点:占用程序的运行时间

    4、Java本地调用(JNI)
        虚拟机运行在目标机器之上,它需要将自己的指令翻译成目标机器指令来执行,并且有些功能需要调用目标机器运行的操作系统接口来完成==>函数调用可以从Java层穿越到C/C++层,当然C/C++层也可调用Java层

        Java运行时库大部分是通过调用目标机器操作系统接口来实现的,如android.os.process==>fork

        官方提供NDK,但远不如SDK

    5、进程和线程管理
        虚拟机的进程和线程都是与目标机器本地操作系统的进程和线程一一对应==>本地操作系统调用进程和线程

        Android应用程序进程:
            1、每一个Android应用程序都有一个Dalvik虚拟机实例
            2、每一个Android应用程序进程都是由一个成为Zygote的进程fork出来的

        参考:罗升阳Blog
            Dalvik虚拟机的启动过程
            Dalvik虚拟机的运行过程
            JNI函数的注册过程
            Java进程和线程的创建过程分析

        Dalvik目录下:
            dexdump——>生成dex文件反编译查看工具
            dexlist——>查看dex文件里所有类的方法的工具
            dexopt——>生成dex优化工具
            dx——>生成从Java字节码转换成dalvik机器码的工具
            libdex——>生成主机和设备处理dex文件的库
            tools——>保存编译/运行相关的工具
            (*)vm——>保存虚拟机绝大部分代码,包括读取指令、执行指令等
            hit——>生成显示堆栈/对象信息的工具



目录developers==>开发者目录
    具体作用未知

目录development==>提供开发所需的工具、例程
    工具:cmds/monkey、ide、sdk——>build/sdk.atree、ndk、pdk
    
    例程:apps——>核心应用
            samples——>API演示程序、NotePad等 
    


目录device==>Android源码中对产品的描述文件夹,各个平台的差异还是比较大的,作为要编译的产品的配置文件夹。
    例子:./htc/flounder

    ./htc/flounder/Android.mk——>/build/envsetup.sh——>lunch函数

    ./htc/flounder/AndroidProducts.mk——>存放规则/device/厂商目录/产品目录,定义当前产品的主配置

    ./htc/flounder/BoardConfig.mk——>硬件配置相关,包含/vendor/htc/flounder/BoardConfigVendor.mk

    ./htc/flounder/Device.mk——>配置产品编译需要的组件,主要是PRODUCT_COPY_FILES、PRODUCT_PACKAGES
    
    vendorsetup.sh==>lunch加载,供编译者选择,详见Build



目录docs

目录external

目录frameworks
    上面的external、frameworks目录在后续文档中将重点分析



目录hardware==>硬件抽象层
    描述对linux kernel中的相关驱动模块的具体操作,而在kernel中的驱动模块只拥有通用错左接口,比如设置寄存器值、IO拉高拉低、但是具体设置什么值,拉高拉低的时序都是在hardware层相应的module中,这是Google对硬件驱动的商业保护

    ./libhardware/hardware.c——>hardware机制核心所在,定义了相关规则,比如load打开modules编译生成的.so,抽象成一个module,向上层提供hw_get_module接口以及module配置宏

    ./libhardware/modules——>与kernel相对应module存放的地方,头文件存放在同级目录的include中,在其中定义了module结构、接口方法、以及唯一的moduleID

    rit机制



目录libnativehelper

目录libcore
       运行库:
            1、核心库——>提供基本的Java类库的功能==>基础数据结构、数学、IO、工具、数据库、网络等库
                ==>Java部分打包成core.jar(分为标准API:java包、扩展API:javax包)
                ==>C/C++部分==>libjavacore.a静态库

            2、dalvik虚拟机

        android系统API是基于android核心库实现的android系统应用框架层的API

        android包、API位置:frameworks/base/core/java
                                            frameworks/base/location/java
                                            frameworks/base/graphics/java
                                            frameworks/base/media/java
                                            frameworks/baseopengl/java
                                            frameworks/base/wifi/java

        android资源包
            资源文件:图片、多国语言字符串、布局文件、
    
            位于frameworks/base/core/res



目录sdk

目录ndk

目录pdk
    上述的三个目录后续将重点分析



目录packages==>应用程序包
    packages目录下:
        app——>蓝牙、浏览器、计算器、日历、相机、联系人通讯录、桌面闹钟、拨号器、Email、相册、登录启动项(显示图片框架等图形界面、负责应用的调度)、音乐播放器、安装/卸载应用、设置、录音机等系统默认应用(出厂时安装应用) 
    
        inputmethods——>输入法

        providers——>提供应用界面所需的数据、如日历、联系人等

        services——>彩信、来电

        wallpapers——>墙纸==>基础壁纸、动态壁纸等



目录platform_testing

目录prebuild==>预编译

目录system==>Android系统底层的文件系统、应用组件、包含一些系统库、以及启动的配置文件
    Init.cpp、propery_service.cpp==>系统启动

    Android启动过程

    system目录下:
        Vold——>磁盘挂载机器
            linux下采用udev机制

        目录tools
6 0