查看原文
其他

Android VNDK/VSDK Snapshot编译框架

Roland OPPO内核工匠
2024-09-26

1.背景


背景一:


为解决Android版本碎片化问题,引入Treble架构,它提供了稳定的新SoC供应商接口,引入HAL 接口定义语言(HIDL/Stable AIDL,技术栈依然是Binder),它指定了 vendor HAL 和system framework的接口, 解耦system Framework 与Vendor HAL, system/vendor组件功能互相独立,从而使得Vendor Freeze成为可能。


背景二:


经过调查AOSP源码的vendor组件有30%~40%的仓库与system组件耦合,耦合仓库的类型,主要包括:AOSP framework框架仓、prebuilts、external、平台仓、odm自研仓、build仓。


背景三:


紧接着Google对Treble架构进一步演进,增强了system/vendor组件之间的interface化能力,从AndroidR开始设计了VNDK和VSDK的snapshot方案。


system组件通过预编译形成vendor Snapshot,可提供给不同Android版本的vendor组件使用,这部分也是Treble方案落地的一个重要环节和基础支撑。


2.VNDK基本概念


在Android的Treble架构中为了规范和约束system/vendor组件之间的耦合关系,对Native库进行几大类的划分,通过定义不同类型的相互耦合程度和使用约束来达到管控system/vendor组件之间模块的耦合度。


2.1 core library:


只在系统镜像,只被系统模块使用,不允许被vendor、vendor_available、vndk和vndk-sp的library依赖

其bp中的格式为

cc_library {

    name: "libThatIsCore",

    ...

}

不包含vendor、vendor_available、vndk和vndk-sp属性


2.2 vendor-only(proprietary) library:


只给vendor使用,而且二进制位置在vendor镜像

其bp中的格式为

cc_library {

    name: "libThatIsVendorOnly",

    proprietary: true,

    # or: vendor: true, # (for things in AOSP)

    ...

}

不包含vndk属性


2.3 vendor_available library:


被vendor镜像使用到的libary,同时存在vendor和core变体,打包在vendor和system镜像中,其bp中的格式为

cc_library {

    name: "libThatIsVendorAvailable",

    vendor_available: true,

    ...

}

不包含vndk属性


2.4 vndk libary:


被vendor模块使用,但是二进制在system镜像

其bp中的格式为


cc_library {

    name: "libThatIsVndk",

    vendor_available: true,

    vndk: {

        enabled: true,

    }

    ...

}

同时存在vendor_available和vnd.enable属性


2.5 vndk-sp library:


被vendor直接使用,被system镜像间接使用的library,其二进制在system镜像中

其bp中的格式为

cc_library {

    name: "libThatIsVndkSp",

    vendor_available: true,

    vndk: {

        enabled: true,

        support_system_process: true,

    }

    ...

}

需要配置support_system_process属性


2.6 llndk library:


由Google维护的被system和vendor镜像共同使用的library,可double load。其二进制在system镜像

其bp中的格式为

llndk_library {

    name: "libThatIsLlndk",

}


Naive库划分与依赖关系


VNDK使能后的编译依赖关系


3.VSDK基本概念


VSDK其实是包含了VNDK部分,同时也包含Vendor Snapshot。


Vendor Snapshot的范围是由系统源码维护的用于Vendor编译或者集成用到的Native模块的集合,它主要由下面几个类型的产物构成

  • vendor: true或者vendor_available: true的动态/静态库或者是头文件库

  • vendor_available: true的静态VNDK库

  • vendor: true或者vendor_available: true的可执行文件或者目标文件

对于vendor_snapshot和vndk里面到底打包的是哪些模块,先看下表,对模块vendor变体的划分。


vndk :true的模块全部都安装在VNDK中,只有另外带了vendor_available:true的vndk模块才可以被vendor模块直接使用,不带的private的vndk只能被VNDK自有模块使用间接的被vendor模块使用。


总得来说:VSDK包括VNDK + vendor Snapshot + recoverySnapshot + host Snapshot。


4.Snapshot设计


上面两章分别给出了VNDK/VSDK的基础概念,内容划分和构建支持。回到最初的问题,在面对system和vendor不同时间不同版本编译的搭配问题上,VNDK/VSDK在工程上的处理流程如何?Snapshot的方案是从system侧预构建出vendor所需的内容,使用这部分而不是源码用于vendor构建。具体内容和实现接下来依次介绍。


4.1Snapshot简介


VNDK/VSDK的Snapshot(snapshot)是指从当前system侧按一定规则生成预构建的一组库,这些库将用于后面vendor侧的编译。



上图中给出了首发项目和vendor freeze项目两种情况system和vendor的搭配,由于Android大版本升级中vendor是固定的,vendor对应依赖的部分也需要有匹配的版本。在工程中我们有两种实现方法:


1、vendor侧manifest文件中包含system的仓库,例如framework/av,framework/base,framework/native这些热点仓库。然后这些仓库的使用前一个android版本的代码。


2、使用google的Snapshot设计,Vendor Image v27依赖的这部分v27版本的vndk/vsdk库将由System Image v27版本预构建生成,这些库将独立用于vendor侧的编译,以此vendor侧就能摆脱对system侧源码的依赖。


两种方法各有优缺点:1的方法简单直接,但是vendor的代码量更多,vendor编译时间更长;2vendor侧代码精简,编译时间短,但是工程中落地则需要额外的一套预构建系统进行支持。


4.2 Snapshot生成流程


生成Snapshot实际就是生成VSDK二进制及其编译配置逻辑,最终引用Snapshot产物的一套流程,可以分为三个阶段:



1、Generate Phrase:按照一定的规则,从系统侧源代码中产生出vendor image编译依赖的预置编译模块产物(称为prebuilt snapshots)的过程。


2、Install Phrase:通过py脚本将Generation阶段中生成的prebuilt模块安装到制定的源码目录,并生成对应的Android.bp文件的过程。


3、Use Phrase:通过设置BOARD_VNDK_VERSION为具体的某个版本号(如31),触发编译系统使用预先生成的Snapshot参与编译(对应地将屏蔽相关模块的源码编译逻辑)的过程。


4.3 VNDK Snapshot生成流程


以AOSP的设备为例,对应VNDK Snapshot包为android-vndk-arm64.zip,其内容为:

android-vndk-arm64.zip

├── arch-arm64-armv8-a

│   └── shared

│       ├── vndk-core  -> *.so files, *.json files

│       └── vndk-sp    -> *.so files, *.json files

├── arch-arm-armv8-a   -> (same as arch-arm64-armv8-a)

├── configs            -> *.libraries.txt, module_paths.txt, module_names.txt

├── include            -> exported header files (*.h, *.hh, etc.)

└── NOTICE_FILES       -> license txt files


Generate Phrase:

vndk Snapshot的生成逻辑在文件soong/cc/vndk.go通过定义VndkSnapshotSingleton来实现。

func init() {

android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)

}


func VndkSnapshotSingleton() android.Singleton {

return &vndkSnapshotSingleton{}

}


type vndkSnapshotSingleton struct {

vndkLibrariesFile   android.OutputPath

vndkSnapshotZipFile android.OptionalPath

}

其中vndkSnapshotZipFile定义了vndk-snapshot.zip文件的路径。在vndkSnapshotSingleton的GenerateBuildActions方法中生成vndkSnapshot


Install Phrase:

VNDK包的安装是通过/development/vndk/snapshot/update.py实现的,流程为:


最终生成的bp文件中的

vndk_prebuilt_shared {

    name: "android.hardware.wifi.hostapd-V1-ndk",

    version: "33",

    target_arch: "arm64",

    vendor_available: true,

    vndk: {

        enabled: true,

    },

    arch: {

        arm: {

            export_include_dirs: [

                "include/frameworks/native/libs/binder/ndk/include_cpp",

...

            ],

            srcs: ["arch-arm-armv8-a/shared/vndk-core/android.hardware.wifi.hostapd-V1-ndk.so"],

        },

        arm64: {

            export_include_dirs: [

                "include/frameworks/native/libs/binder/ndk/include_cpp",

...

            ],

            srcs: ["arch-arm64-armv8-a/shared/vndk-core/android.hardware.wifi.hostapd-V1-ndk.so"],

        },

    },

}

Use Phrase:

通过在device.mk中设置BOARD_VNDK_VERSION变量为具体版本值,然后对vendor侧进行编译。


4.4 VSDK Snapshot生成流程


以AOSP的设备为例,vsdkSnapshot包内容为:

vendor-$(TARGET_DEVICE).zip

├── arch-arm64-armv8-a

│   ├── binary         -> binary files, *.json files

│   ├── header         -> *.json files

│   ├── object         -> *.o files, *.json files

│   ├── shared         -> *.so files, *.json files

│   └── static         -> *.a files, *.json files

├── arch-arm-armv8-a   -> (arch-arm64-armv8-a)

├── configs            -> *.rc files, *.xml files

├── include            -> exported header files (*.h, *.hh, etc.)

└── NOTICE_FILES       -> license txt files


Generate Phrase:

vsdkSnapshot的生成逻辑在vendor_snapshot.go的GenerateBuildActions中:


Install Phrase:

vsdkSnapshot安装使用了/development/vendor_snapshot/update.py文件:


Use Phrase:

通过在device.mk中设置BOARD_VNDK_VERSION变量为具体版本值,然后对vendor侧进行编译。


5.总结


VNDK/VSDK Snapshot可进一步减少system/vendor组件之间的源码依赖、编译依赖,更容易形成Treble基线。


收益总结为三点:

  • 提高了vendor组件的编译效率

  • 提高了代码认知管理,解耦后的仓库,可以删除vendor组件中的耦合仓,只保留system组件中的源码

  • 更有利于支撑system/vendor组件的独立开发


参考资料

[1]https://source.android.com/devices/architecture/vndk/snapshot-vendor

[2]https://source.android.com/devices/architecture/vndk/snapshot-generate

[3] Bootcamp 2021 VSDK.pdf

[4]https://source.android.com/devices/architecture/vndk/enabling

[5]https://source.android.com/docs/core/architecture/vndk/build-system

[6]https://source.android.com/docs/core/architecture/vndk/snapshot-design

[7] 深入剖析VNDK/VSDK Snapshot编译框架




2023年Arm最新处理器架构分析——X4、A720和A520

Chromium多进程架构,你知道多少?

论好名字的重要性:Linux内核page到folio的变迁


长按关注内核工匠微信

Linux内核黑科技| 技术文章| 精选教程


继续滑动看下一个
OPPO内核工匠
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存