Android 设备制造商出于各种原因更改 AOSP 库的源代码。一些供应商重新实现 AOSP 库中的函数以提高性能,而另一些供应商则向 AOSP 库添加新的钩子、新的 API 或新功能。本节提供了扩展 AOSP 库的指南,扩展方式应不会破坏 CTS/VTS。
直接替换
所有修改后的共享库都必须是 AOSP 对应库的二进制兼容、直接替换。所有现有的 AOSP 用户都必须能够使用修改后的共享库,而无需重新编译。此要求意味着以下几点:
- 不得移除 AOSP 函数。
- 如果结构体向其用户公开,则不得更改结构体。
- 不得加强函数的前提条件。
- 函数必须提供等效的功能。
- 不得削弱函数的后置条件。
扩展模块分类
按模块定义和使用的功能对模块进行分类。
注意:此处使用功能而不是 API/ABI,因为有可能在不更改任何 API/ABI 的情况下添加功能。
根据模块中定义的功能,模块可以分为 DA 模块和 DX 模块
-
仅定义 AOSP 模块 (DA 模块) 不定义 AOSP 对应库中没有的新功能。
- 示例 1. 完好无损的未修改 AOSP 库是 DA 模块。
- 示例 2. 如果供应商使用 SIMD 指令重写
libcrypto.so
中的函数(不添加新函数),则修改后的libcrypto.so
将是 DA 模块。
-
定义扩展模块 (DX 模块) 定义新功能,或者没有 AOSP 对应库。
- 示例 1. 如果供应商向
libjpeg.so
添加一个辅助函数以访问某些内部数据,则修改后的libjpeg.so
将是 DX 库,而新添加的函数将是库的扩展部分。 - 示例 2. 如果供应商定义一个名为
libfoo.so
的非 AOSP 库,则libfoo.so
将是 DX 库。
- 示例 1. 如果供应商向
根据模块使用的功能,模块可以分为 UA 模块和 UX 模块。
-
仅使用 AOSP 模块 (UA 模块) 仅在其实现中使用 AOSP 功能。它们不依赖于任何非 AOSP 扩展。
- 示例 1. 完好无损的未修改 AOSP 库是 UA 模块。
- 示例 2. 如果修改后的共享库
libjpeg.so
仅依赖于其他 AOSP API,则它将是 UA 模块。
-
使用扩展模块 (UX 模块) 在其实现中依赖于某些非 AOSP 功能。
- 示例 1. 如果修改后的
libjpeg.so
依赖于另一个名为libjpeg_turbo2.so
的非 AOSP 库,则修改后的libjpeg.so
将是 UX 模块。 - 示例 2. 如果供应商向其修改后的
libexif.so
添加一个新函数,并且他们修改后的libjpeg.so
使用来自libexif.so
的新添加函数,则他们修改后的libjpeg.so
将是 UX 模块。
- 示例 1. 如果修改后的
定义和用法彼此独立
使用的功能 | |||
---|---|---|---|
仅 AOSP (UA) | 扩展 (UX) | ||
定义的功能 | 仅 AOSP (DA) | DAUA | DAUX |
扩展 (DX) | DXUA | DXUX |
VNDK 扩展机制
依赖于扩展功能的供应商模块将无法工作,因为具有相同名称的 AOSP 库不具有扩展功能。如果供应商模块直接或间接依赖于扩展功能,则供应商应将 DAUX、DXUA 和 DXUX 共享库复制到供应商分区(供应商进程始终首先在供应商分区中查找共享库)。但是,不得复制 LL-NDK 库,因此供应商模块不得依赖于修改后的 LL-NDK 库定义的功能。
如果相应的 AOSP 库可以提供相同的功能,并且当系统分区被通用系统映像 (GSI) 覆盖时供应商模块继续工作,则 DAUA 共享库可以保留在系统分区上。
直接替换非常重要,因为 GSI 中未修改的 VNDK 库将与名称冲突时修改后的共享库链接。如果 AOSP 库以 API/ABI 不兼容的方式修改,则 GSI 中的 AOSP 库可能无法链接或导致未定义的行为。