天天看點

Android VNDK/VSDK Snapshot編譯架構

作者:核心工匠

1.背景

背景一:

為解決Android版本碎片化問題,引入Treble架構,它提供了穩定的新SoC供應商接口,引入HAL 接口定義語言(HIDL/Stable AIDL,技術棧依然是Binder),它指定了 vendor HAL 和system framework的接口, 解耦system Framework 與Vendor HAL, system/vendor元件功能互相獨立,進而使得Vendor Freeze成為可能。

Android VNDK/VSDK Snapshot編譯架構

背景二:

經過調查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方案落地的一個重要環節和基礎支撐。

Android VNDK/VSDK Snapshot編譯架構

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",

}

Android VNDK/VSDK Snapshot編譯架構

Naive庫劃分與依賴關系

Android VNDK/VSDK Snapshot編譯架構

VNDK使能後的編譯依賴關系

3.VSDK基本概念

Android VNDK/VSDK Snapshot編譯架構

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變體的劃分。

Android VNDK/VSDK Snapshot編譯架構

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側的編譯。

Android VNDK/VSDK Snapshot編譯架構

上圖中給出了首發項目和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産物的一套流程,可以分為三個階段:

Android VNDK/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

Android VNDK/VSDK Snapshot編譯架構

Install Phrase:

VNDK包的安裝是通過/development/vndk/snapshot/update.py實作的,流程為:

Android VNDK/VSDK Snapshot編譯架構

最終生成的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中:

Android VNDK/VSDK Snapshot編譯架構

Install Phrase:

vsdkSnapshot安裝使用了/development/vendor_snapshot/update.py檔案:

Android VNDK/VSDK Snapshot編譯架構

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編譯架構

本文首發在“核心工匠”微信公衆号,歡迎關注公衆号擷取最新Linux技術分享。

繼續閱讀