| <html devsite><head> |
| <title>供应商原生开发套件 (VNDK)</title> |
| <meta name="project_path" value="/_project.yaml"/> |
| <meta name="book_path" value="/_book.yaml"/> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p>供应商原生开发套件 (VNDK) 是专门用来让供应商实现其 HAL 的一组库。VNDK 包含在 <code>system.img</code> 中,并在运行时与供应商代码动态关联。</p> |
| |
| <h2 id="why-vndk">为何要使用 VNDK?</h2> |
| <p>Android 8.0 及更高版本支持框架专用更新,在此类更新中,系统分区可以升级到最新版本,而供应商分区保持不变。这意味着在不同时间编译的二进制文件必须能够相互配合使用;VNDK 为 Android 版本迭代时发生的 API/ABI 变更所导致的问题提供了解决途径。</p> |
| |
| <p>框架专用更新面临着以下挑战:</p> |
| |
| <ul> |
| <li><strong>框架模块与供应商模块之间的依赖关系</strong>。在 Android 8.0 之前的版本中,两种模块可以互相关联。但是,来自供应商模块的依赖关系对框架模块开发施加了不必要的限制。</li> |
| <li><strong>AOSP 库的扩展</strong>。Android 8.0 及更高版本要求所有 Android 设备在系统分区被替换为标准常规系统映像 (GSI) 时,都可以通过 CTS 测试。不过,当供应商扩展 AOSP 库以提高性能或为其 HIDL 实现添加额外的功能时,使用标准 GSI 来刷写系统分区可能会破坏供应商的 HIDL 实现(有关如何防止此类破坏的指南,请参阅 <a href="/devices/architecture/vndk/extensions.html">VNDK 扩展</a>)。</li> |
| </ul> |
| |
| <p>为了克服这些挑战,Android 8.0 引入了一些技术,例如 VNDK(本部分对其进行了介绍)、<a href="/devices/architecture/hidl/index.html">HIDL</a>、hwbinder、<a href="/devices/architecture/dto/index.html">设备树叠加层</a>和 sepolicy 叠加层。</p> |
| |
| <h2 id="resources">VNDK 资源</h2> |
| <p>本部分包含以下 VNDK 资源:</p> |
| <ul> |
| <li><em><a href="#vndk-concepts">VNDK 概念</a></em>:(请参阅下文)介绍了框架共享库、Same-Process HAL (SP-HAL) 和 VNDK 术语。 |
| </li> |
| <li><em><a href="/devices/architecture/vndk/extensions.html">VNDK 扩展</a></em>:对专门针对供应商的更改进行了分类。例如,具有供应商模块所依赖的扩展功能的库必须复制到供应商分区中,但禁止进行 ABI 不兼容的更改。</li> |
| <li><em><a href="/devices/architecture/vndk/build-system.html">VNDK 编译系统支持</a></em>:介绍了与 VNDK 相关的编译系统配置和模块定义语法。</li> |
| <li><em><a href="/devices/architecture/vndk/deftool.html">VNDK 定义工具</a></em>:可协助您将源代码树迁移到 Android 8.0 及更高版本。</li> |
| <li><em><a href="/devices/architecture/vndk/linker-namespace.html">链接器命名空间</a></em>:提供对共享库关联的精细控制。 |
| </li> |
| <li><em><a href="/devices/architecture/vndk/dir-rules-sepolicy.html">目录、规则和 sepolicy</a></em>:定义了搭载 Android 8.0 及更高版本的设备的目录结构,以及 VNDK 规则和关联的 sepolicy。</li> |
| <li><em><a href="../images/vndk_design_android_o.pdf">Android O 中的 VDNK 设计</a></em>演示文稿:阐述了 Android O 中使用的 VDNK 基本概念。</li> |
| </ul> |
| |
| <h2 id="concepts">VNDK 概念</h2> |
| <p>在理想的 Android 8.0 及更高版本环境中,框架进程不加载供应商共享库,所有供应商进程仅加载供应商共享库(和一部分框架共享库),而框架进程与供应商进程之间的通信由 HIDL 和硬件 binder 控制。</p> |
| |
| <p>这样的环境存在以下可能:来自框架共享库的稳定、公共 API 可能不足以满足供应商模块开发者的需求(尽管 API 在不同的 Android 版本之间会有所变化),要防止出现这种情况,供应商进程需要能够访问一部分框架共享库。此外,由于性能要求可能会导致折中方案,因此必须区别对待某些对响应时间要求严格的 HAL。</p> |
| |
| <p>以下部分详细介绍了 VNDK 如何处理适用于供应商的框架共享库以及 Same-Process HAL (SP-HAL)。</p> |
| |
| <h3 id="framework-shared-libraries">适用于供应商的框架共享库</h3> |
| <p>本部分介绍了供应商进程可访问的共享库的分类标准。要让供应商模块在多个 Android 版本上皆可正常工作,有以下两种方法:</p> |
| |
| <ol> |
| <li><strong>让框架共享库的 ABI/API 保持稳定</strong>。新的框架模块和旧的供应商模块可以使用同一共享库,以减少内存占用和存储空间占用。此外,通过使用同一共享库,还可以避免一些双重加载问题。不过,保持稳定的 ABI/API 的开发成本很高,因此让每个框架共享库导出的所有 ABI/API 都保持稳定是不现实的。</li> |
| <li><strong>复制旧的框架共享库</strong>。此方法会严重限制边信道,即在框架模块与供应商模块之间进行通信的所有机制,包括(但不限于)binder、套接字、管道、共享内存、共享文件和系统属性。除非通信协议被冻结且保持稳定(例如通过 hwbinder 的 HIDL),否则不能进行通信。双重加载共享库也可能会导致出现问题;例如,如果将新库创建的对象传递到旧库的函数中,则可能会出错,因为这些库可能会以不同的方式解读该对象。</li> |
| </ol> |
| |
| <p>根据共享库的特性不同,使用的方法也有差异。因此,框架共享库可分为以下三个子类别:</p> |
| |
| <ul> |
| <li><em></em><em></em>LL-NDK 库是已知稳定的框架共享库。它们的开发者致力于保持其 API/ABI 稳定性。 |
| <ul> |
| <li>LL-NDK 包含以下库:<code>libEGL.so</code>、<code>libGLESv1_CM.so</code>、<code>libGLESv2.so</code>、<code>libGLESv3.so</code>、<code>libandroid_net.so</code>、<code>libc.so</code>、<code>libdl.so</code>、<code>liblog.so</code>、<code>libm.so</code>、<code>libnativewindow.so</code>、<code>libneuralnetworks.so</code>、<code>libsync.so</code>、<code>libvndksupport.so</code> 和 <code>libvulkan.so</code>。 |
| </li> |
| </ul> |
| </li> |
| <li><em></em><em></em>符合条件的 VNDK 库 (VNDK) 是指可以安全复制两次的框架共享库。<em></em><em></em>框架模块和供应商模块可以与其各自的库副本相关联。框架共享库只有满足以下条件才能成为符合条件的 VNDK 库: |
| <ul> |
| <li>不向框架发送或从框架接收 IPC。</li> |
| <li>与 ART 虚拟机无关。</li> |
| <li>不读取/写入文件格式不稳定的文件/分区。</li> |
| <li>没有需要法律审查的特殊软件许可。</li> |
| <li>其代码所有者不反对供应商使用该库。</li> |
| </ul> |
| </li> |
| <li><em></em><em></em>框架专用库 (FWK-ONLY) 是指不属于上述类别的框架共享库。此类库具有以下特点: |
| <ul> |
| <li>被视为框架内部实现细节。</li> |
| <li>不得由供应商模块访问。</li> |
| <li>具有不稳定的 ABI/API,无 API/ABI 兼容性保证。</li> |
| <li>不会被复制。</li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h3 id="sp-hal">Same-Process HAL (SP-HAL)</h3> |
| <p> |
| <em></em><em></em><em></em><em></em>Same-Process HAL (SP-HAL) 是一组预先确定的 HAL,作为供应商共享库进行实现,并被加载到框架进程中。SP-HAL 由链接器命名空间(控制共享库可见的库和符号)进行隔离。SP-HAL 必须仅依赖于 LL-NDK 和 VNDK-SP<em></em><em></em>。</p> |
| |
| <p>VNDK-SP 是一部分预定义的符合条件的 VNDK 库。我们会仔细审查 VNDK-SP 库,以确保将 VNDK-SP 库双重加载到框架进程中不会导致问题。SP-HAL 和 VNDK-SP 均由 Google 定义。</p> |
| |
| <p>以下库是经过批准的 SP-HAL:</p> |
| |
| <ul> |
| <li><code>libGLESv1_CM_${driver}.so</code></li> |
| <li><code>libGLESv2_${driver}.so</code></li> |
| <li><code>libGLESv3_${driver}.so</code></li> |
| <li><code>libEGL_${driver}.so</code></li> |
| <li><code>vulkan.${driver}.so</code></li> |
| <li><code>[email protected]</code></li> |
| <li><code>[email protected]</code></li> |
| </ul> |
| |
| <p>以下库是 SP-HAL 可以访问的 VNDK-SP 库: |
| </p> |
| |
| <ul> |
| <li><code>[email protected]</code></li> |
| <li><code>[email protected]</code></li> |
| <li><code>[email protected]</code> (Renderscript)</li> |
| <li><code>libRS_internal.so</code> (Renderscript)</li> |
| <li><code>libbase.so</code></li> |
| <li><code>libc++.so</code></li> |
| <li><code>libcutils.so</code></li> |
| <li><code>libhardware.so</code></li> |
| <li><code>libhidlbase.so</code></li> |
| <li><code>libhidltransport.so</code></li> |
| <li><code>libhwbinder.so</code></li> |
| <li><code>libion.so</code></li> |
| <li><code>libutils.so</code></li> |
| <li><code>libz.so</code></li> |
| </ul> |
| |
| <p> |
| 以下 VNDK-SP 依赖项 (VNDK-SP-Private) 对 SP-HAL 来说是不可见的:<em></em><em></em> |
| </p> |
| |
| <ul> |
| <li><code>libRSCpuRef.so</code> (Renderscript)</li> |
| <li><code>libRSDriver.so</code> (Renderscript)</li> |
| <li><code>libbacktrace.so</code></li> |
| <li><code>libblas.so</code> (Renderscript)</li> |
| <li><code>libbcinfo.so</code> (Renderscript)</li> |
| <li><code>liblzma.so</code></li> |
| <li><code>libunwind.so</code></li> |
| </ul> |
| |
| <p>以下是具有 RS 例外的框架专用库 (FWK-ONLY-RS):<em></em></p> |
| <ul> |
| <li><code>libft2.so</code> (Renderscript)</li> |
| <li><code>libmediandk.so</code> (Renderscript)</li> |
| </ul> |
| |
| <h2 id="vndk-terminology">VNDK 术语</h2> |
| <ul> |
| <li><em></em><em></em><em></em>模块是指共享库或可执行文件。</li> |
| <li><em></em><em></em>进程是指可执行文件产生的操作系统任务。</li> |
| <li>以“框架”打头的术语是指与<strong>系统</strong>分区相关的概念。<em></em></li> |
| <li>以“供应商”打头的术语是指与<strong>供应商</strong>分区相关的概念。<em></em></li> |
| </ul> |
| |
| <p>例如:</p> |
| <ul> |
| <li>框架可执行文件是指 <code>/system/bin</code> 或 <code>/system/xbin</code> 中的可执行文件。<em></em></li> |
| <li>框架共享库是指 <code>/system/lib[64]</code> 下的共享库。<em></em></li> |
| <li><em></em><em></em><em></em>框架模块是指框架共享库和框架可执行文件。</li> |
| <li>框架进程是指从框架可执行文件衍生而来的进程(例如 <code>/system/bin/app_process</code>)。<em></em><em></em></li> |
| <li>供应商可执行文件是指 <code>/vendor/bin</code> 中的可执行文件<em></em>。 |
| </li><li>供应商共享库是指 <code>/vendor/lib[64]</code> 下的共享库。<em></em></li> |
| <li><em></em><em></em><em></em>供应商模块是指供应商可执行文件和供应商共享库。</li> |
| <li><em></em><em></em>供应商进程是指供应商可执行文件(例如 </li> |
| <code>/vendor/bin/[email protected]</code>)产生的进程。 |
| </ul> |
| |
| <aside class="note"><strong>注意</strong>:常规系统映像 (GSI) 是指根据相应分支(与版本分支类似,但更正了一些错误或进行了一些泛化)编译并由 Google 发布的标准 Android 系统映像。<em></em></aside> |
| |
| <h2 id="vndk-versioning">VNDK 版本编号</h2> |
| |
| <p>在 Android P 中,VNDK 共享库带有版本编号:</p> |
| |
| <ul> |
| <li><code>ro.vndk.version</code> 系统属性将自动添加到 <code>/vendor/default.prop</code>。</li> |
| |
| <li>VNDK 共享库将安装到 <code>/system/lib[64]/vndk-${ro.vndk.version}</code> 中。</li> |
| |
| <li>VNDK-SP 共享库将安装到 <code>/system/lib[64]/vndk-sp-${ro.vndk.version}</code> 中。</li> |
| |
| <li>动态链接器配置文件将安装到 <code>/system/etc/ld.config.${ro.vndk.version}.txt</code> 中。</li> |
| </ul> |
| |
| <p>系统将按以下算法选择 <code>ro.vndk.version</code> 的值:</p> |
| |
| <ul> |
| <li>如果 <code>BOARD_VNDK_VERSION</code> 不等于 <code>current</code>,则使用 <code>BOARD_VNDK_VERSION</code>。<em></em></li> |
| |
| <li>如果 <code>BOARD_VNDK_VERSION</code> 等于 <code>current</code>:<em></em></li> |
| |
| <ul> |
| <li>如果 <code>PLATFORM_VERSION_CODENAME</code> 为 <code>REL</code>,则使用 <code>PLATFORM_SDK_VERSION</code>(例如 <code>28</code>)。</li> |
| |
| <li>否则使用 <code>PLATFORM_VERSION_CODENAME</code>(例如 <code>P</code>)。</li> |
| </ul> |
| </ul> |
| |
| <h3 id="upgrading-devices">升级设备</h3> |
| |
| <p>如果 Android 8.x 设备停用了 VNDK 运行时增强功能(即,编译时未使用 <code>BOARD_VNDK_VERSION</code> 或使用了 <code>BOARD_VNDK_RUNTIME_DISABLE</code>),则在升级到 Android P 时,可能会将 <code>PRODUCT_USE_VNDK_OVERRIDE := false</code> 添加 <code>BoardConfig.mk</code>。</p> |
| |
| <p>如果 <code>PRODUCT_USE_VNDK_OVERRIDE</code> 为 <code>false</code>,则 <code>ro.vndk.lite</code> 属性将自动添加到 <code>/vendor/default.prop</code>,且其值将为 <code>true</code>。因此,动态链接器将加载 <code>/system/etc/ld.config.vndk_lite.txt</code> 中的链接器命名空间配置,这仅会隔离 SP-HAL 和 VNDK-SP。</p> |
| |
| <p>如果要将搭载 Android 7.0(或更低版本)的设备升级到 Android P,请将 <code>PRODUCT_TREBLE_LINKER_NAMESPACES_OVERRIDE := false</code> 添加到 <code>BoardConfig.mk</code>。</p> |
| |
| <h3 id="vendor-test-suite">供应商测试套件 (VTS)</h3> |
| |
| <p>Android P 供应商测试套件 (VTS) 强制要求存在非空 <code>ro.vndk.version</code> 属性。新发布的设备和升级设备都必须定义 <code>ro.vndk.version</code>。一些 VNDK 测试用例(例如 <code>VtsVndkFilesTest</code> 和 <code>VtsVndkDependencyTest</code>)依赖于 <code>ro.vndk.version</code> 属性来加载符合条件且匹配的 VNDK 库数据集。</p> |
| |
| <p>如果 <code>ro.product.first_api_level</code> 属性大于 27,则不能定义 <code>ro.vndk.lite</code> 属性。 |
| 如果在新推出的 Android P 设备中定义了 <code>ro.vndk.lite</code>,则 <code>VtsTreblePlatformVersionTest</code> 将失败。</p> |
| |
| <h2 id="document-history">文档历史记录</h2> |
| |
| <p>本部分跟踪了对 VNDK 文档进行的更改。</p> |
| |
| <h3 id="changes-p">Android P 的变化</h3> |
| |
| <ul> |
| <li>添加了“VNDK 版本编号”部分。</li> |
| |
| <li>添加了“VTS”部分。</li> |
| |
| <li>更改了部分 VNDK 类别的名称:</li> |
| <ul> |
| <li>LL-NDK-Indirect 已改名为 LL-NDK-Private。</li> |
| <li>VNDK-Indirect 已改名为 VNDK-Private。</li> |
| <li>VNDK-SP-Indirect-Private 已改名为 VNDK-SP-Private。</li> |
| <li>移除了 VNDK-SP-Indirect。</li> |
| </ul> |
| </ul> |
| |
| <h3 id="changes-81">Android 8.1 的变化</h3> |
| |
| <ul> |
| <li>SP-NDK 库已合并到 LL-NDK 库中。</li> |
| |
| <li>在 RS 命名空间部分中将 <code>libui.so</code> 替换为 <code>libft2.so</code>。包含 <code>libui.so</code> 会出错。</li> |
| |
| <li>将 <code>libGLESv3.so</code> 和 <code>libandroid_net.so</code> 添加到 LL-NDK 库中。</li> |
| |
| <li>将 <code>libion.so</code> 添加到 VNDK-SP 库中。</li> |
| |
| <li>从 LL-NDK 库中移除 <code>libstdc++.so</code>。改用 <code>libc++.so</code>。某些版本的独立工具链可以将 <code>-lstdc++</code> 添加到默认链接器标记中。要停用默认设置,请将 <code>-nodefaultlibs -lc -lm -ldl</code> 添加到 <code>LDFLAGS</code> 中。</li> |
| |
| <li>将 <code>libz.so</code> 从 LL-NDK 移到 VNDK-SP 库中。在某些配置中,<code>libz.so</code> 可能仍是 LL-NDK。但是,应该没有明显的差异。</li> |
| </ul> |
| |
| </body></html> |