免费资源网,https://freexyz.cn/
目录
  • 为何要使用 VNDK?
  • VNDK相关概念
    • 供应商模块
    • Framework共享库
    • LL-NDK
    • Same-Process HAL (SP-HAL)
  • VNDK 库简介
    • 目录
    • VNDK 电子表格
  • VNDK 快照
    • 启用 VNDK
      • 编译选项
      • 供应商变体库
      • 条件编译
    • VNDK 扩展
      • 规则和Sepolicy
        • VNDK 规则
        • sepolicy
        • same_process_hal_file 标签

      为何要使用 VNDK?

      VNDK的全称是Vendor Native Development Kit,是Android 8.0引入的一种新技术。它表现一系列库的合集,用于让供应商开发自己的HALs。VNDK 包含在 system.img 中,并在运行时与供应商代码动态关联。

      官方文档的解释给我的感觉其目的就是收敛Android的碎片化。不仅仅VNDK,Android 8.0引入许多的技术都是为了将System与Vendor分割开来。这样可以保持Android核心系统的纯净性,而将碎片化扔给供应商维护。渐渐的芯片供应商和设备厂商可以无需关心Android系统的实现,仅仅使用VNDK就可以完成产品开发。

      VNDK相关概念

      供应商模块

      供应商模块是特定于供应商的可执行文件或共享库,这些模块将安装到供应商分区中。

      • 在 Android.bp 文件中,供应商模块必须将vendor或proprietary属性设置为 true
      • 在 Android.mk 文件中,供应商模块必须将 LOCAL_VENDOR_MODULE 或 LOCAL_PROPRIETARY_MODULE 设置为 true

      Framework共享库

      在理想的Android 8.0及更高版本环境中,Framework进程不加载供应商共享库,而供应商进程仅加载供应商共享库(和一部分Framework共享库)。Framework进程与供应商进程之间的通信由HIDL和hardware binder控制。

      供应商进程需要使用Framework共享库可能随系统的更新而发生变化。为了保证供应商模块在多个Android版本上皆可正常工作,根据Framework共享库的特性不同,将其三个子类别:

      • LL-NDK库:已知稳定的Framework共享库,它们的开发者致力于保持其 API/ABI 稳定性。LL-NDK 包含以下库:libEGL.solibGLESv1_CM.solibGLESv2.solibGLESv3.solibandroid_net.solibc.solibdl.soliblog.solibm.solibnativewindow.solibneuralnetworks.solibsync.solibvndksupport.so 和 libvulkan.so
      • 合格的 VNDK 库 (VNDK):可以安全复制两次的Framework共享库。Framework模块和供应商模块可以与其各自的库副本相关联。Framework共享库只有满足以下条件才能成为合格的 VNDK 库:

        • 不向Framework发送或从Framework接收 IPC。
        • 与 ART 虚拟机无关。
        • 不读写文件格式不稳定的文件/分区。
        • 没有需要法律审查的特殊软件许可。
        • 其代码所有者不反对供应商使用该库。
      • 框架专用库 (FWK-ONLY) :不属于上述类别的Framework共享库。此类库具有以下特点:

        • 被视为Framework内部实现细节。
        • 不得由供应商模块访问。
        • 具有不稳定的 ABI/API,无 API/ABI 兼容性保证。
        • 不会被复制。

      LL-NDK

      LL-NDK 共享库是具有稳定 ABI 的共享库。框架模块和供应商模块均具有相同的最新实现。对于每个 LL-NDK 共享库,Android.bp 都包含一个 llndk_library 模块定义:

      llndk_library {
          name: "libvndksupport",
          symbol_file: "libvndksupport.map.txt",
      }

      该模块定义指定了模块名称和符号文件,后者描述了对供应商模块可见的符号。例如:

      LIBVNDKSUPPORT {
        global:
          android_load_sphal_library; # vndk
          android_unload_sphal_library; # vndk
        local:
          *;
      };

      Same-Process HAL (SP-HAL)

      Same-Process HAL (SP-HAL) 是预定义的的一组HAL,作为供应商共享库进行实现,并被加载到Framework进程中。SP-HAL 必须仅依赖于 LL-NDK 和 VNDK-SP。VNDK-SP 是一部分预定义的符合条件的 VNDK 库。VNDK-SP 库会被仔细审查,以确保将 VNDK-SP 库双重加载到Framework进程中不会导致问题。SP-HAL 和 VNDK-SP 均由 Google 定义,并通过链接器命名空间进行隔离。

      以下库是经过批准的 SP-HAL:

      • libGLESv1_CM_${driver}.so
      • libGLESv2_${driver}.so
      • libGLESv3_${driver}.so
      • libEGL_${driver}.so
      • vulkan.${driver}.so
      • android.hardware.renderscript@1.0-impl.so
      • android.hardware.graphics.mapper@2.0-impl.so

      以下库是 SP-HAL 可以访问的 VNDK-SP 库:

      • android.hardware.graphics.common@1.0.so
      • android.hardware.graphics.mapper@2.0.so
      • android.hardware.renderscript@1.0.so (Renderscript)
      • libRS_internal.so (Renderscript)
      • libbase.so
      • libc++.so
      • libcutils.so
      • libhardware.so
      • libhidlbase.so
      • libhidltransport.so
      • libhwbinder.so
      • libion.so
      • libutils.so
      • libz.so

      以下 VNDK-SP 依赖项 (VNDK-SP-Private) 对 SP-HAL 来说是不可见的:

      • libRSCpuRef.so (Renderscript)
      • libRSDriver.so (Renderscript)
      • libbacktrace.so
      • libblas.so (Renderscript)
      • libbcinfo.so (Renderscript)
      • liblzma.so
      • libunwind.so

      以下是具有 RS 例外的框架专用库 (FWK-ONLY-RS):

      • libft2.so (Renderscript)
      • libmediandk.so (Renderscript)

      VNDK 库简介

      VNDK 定义了可与供应商代码相关联的库集:VNDK-core、VNDK-SP 和 LL-NDK,并阻止供应商使用不在 VNDK 集内的库。

      VNDK-core 库安装在 /system/lib[64]/vndk-${VER} 中,仅适用于 API 级别为 ${VER} 的供应商进程。${VER} 可以通过/vendor/default.prop中的系统属性ro.vndk.version获取。系统进程不得使用这些库,而必须使用安装在 /system/lib[64] 中的库。由于每个进程都具有严格的命名空间限制,因此不会造成重复加载 VNDK-core 库。要在 VNDK-core 中添加库,请将以下内容添加到 Android.bp 中:

      vendor_available: true,
      vndk: {
          enabled: true,
      },

      VNDK-SP 库安装在 /system/lib[64]/vndk-sp-${VER} 中,可以被供应商进程和系统进程(通过安装在供应商分区中的 SP-HAL 库)使用。VNDK-SP 库可以重复加载。要在 VNDK-SP 中添加库,请将以下内容添加到 Android.bp 中:

      vendor_available: true,
      vndk: {
          enabled: true,
          support_system_process: true,
      },

      LL-NDK 库安装在 /system/lib[64] 中。供应商模块可以使用 LL-NDK stub访问 LL-NDK 库的预选符号。LL-NDK 库必须支持向后兼容,且具有 ABI 稳定性,以便旧版供应商模块使用新版 LL-NDK 库。由于 LL-NDK 具有 ABI 稳定特性,VNDK 快照无需包含旧版供应商映像的 LL-NDK 库。

      目录

      VNDK库可以大致划分为以下目录:

      • /system/lib[64] 包含所有Framework共享库,具体包括 LL-NDK、VNDK 和Framework专用库(包括 LL-NDK-Private 和一些与 VNDK-SP 中的库同名的库)。
      • /system/lib[64]/vndk-sp 包含适用于 Same-Process HAL 的 VNDK-SP 库。
      • /vendor/lib[64] 包含供应商扩展的 VNDK 库(DXUA 库或 DXUX VNDK 库)、Same-Process HAL 实现,以及其他供应商共享库。
      • /vendor/lib[64]/vndk-sp 可能包含供应商扩展的 VNDK-SP 库。

      供应商模块从 /system/lib[64] 中加载 VNDK 库。

      VNDK 电子表格

      Google 会提供一个符合条件的 VNDK 电子表格(例如 eligible-list.csv),该电子表格会标记可由供应商模块使用的框架共享库:

      标记 说明
      LL-NDK 可由框架模块和供应商模块使用的共享库(具有稳定的 ABI/API)。
      LL-NDK-Private LL-NDK 库的私有依赖项。供应商模块不得直接访问此类库。
      VNDK-SP SP-HAL 框架共享库依赖项。
      VNDK-SP-Private 所有供应商模块都无法直接访问的 VNDK-SP 依赖项。
      VNDK 面向供应商模块(SP-HAL 和 SP-HAL-Dep 除外)提供的框架共享库。
      VNDK-Private 所有供应商模块都无法直接访问的 VNDK 依赖项。
      FWK-ONLY 供应商模块不得(直接或间接)访问、仅限框架使用的共享库。
      FWK-ONLY-RS 供应商模块不得访问(RS 用途除外)、仅限框架使用的共享库。

      下表描述了适用于供应商共享库的标记:

      标记 说明
      SP-HAL Same-Process HAL 实现共享库。
      SP-HAL-Dep SP-HAL 供应商共享库依赖项(也称为 SP-HAL 依赖项,不包括 LL-NDK 和 VNDK-SP)。
      VND-ONLY 框架模块不可见且不得访问的共享库。所复制的扩展后 VNDK 库也将被标记为 VND-ONLY。

      标记之间的关系:

      Android VNDK使用及原理深入探究

      VNDK 快照

      VNDK 快照就是一组预编译的库文件和配置文件的集合。因为VNDK的实质就是要规范供应商的开发,如果保证VNDK接口稳定的标准化,供应商就无需修改VNDK库。系统只要提供所有VNDK版本的二进制文件,就可以满足供应商的开发。这些需求的文件就是VNDK快照需要提供的内容。

      VNDK 快照包含以下文件:

      • VNDK-core 和 VNDK-SP 共享库的供应商变体。

        • 无需 LL-NDK 共享库,因为这类库是向后兼容的。
        • 对于 64 位目标,TARGET_ARCH 和 TARGET_2ND_ARCH 库都将被编译并包含在内。
      • VNDK-core、VNDK-SP、LL-NDK 和 VNDK-private 库的列表,文件为 [vndkcore|vndksp|llndk|vndkprivate].libraries.txt
      • 链接器配置文件为 ld.config.txt
      • 许可文件。
      • module_paths.txt。记录所有 VNDK 库的模块路径;检查 GPL 项目是否已在指定 Android 源代码树中发布源代码时,需要用到这种文件。

      以下示例展示了 arm64 (TARGET_ARCH=arm64) VNDK 快照 ZIP 文件 (android-vndk-arm64.zip) 的目录结构。

      Android VNDK使用及原理深入探究

      供应商镜像会依赖于特定版本的VNDK,所以系统镜像中应该提供供应商需求的VNDK版本的镜像。即使系统镜像与供应商镜像使用不同版本的Android进行编译,但是只要保证系统镜像能够提供正确的VNDK就保证正常运行。下图展示了Android P系统镜像使用Android O供应商镜像的场景。

      Android VNDK使用及原理深入探究

      启用 VNDK

      编译选项

      在 BoardConfig.mk添加BOARD_VNDK_VERSION=current可以在编译过程开启VNDK。也可以在编译模块时传递该编译选项,例如: m -j BOARD_VNDK_VERSION=current MY-LIB)。

      当启用 BOARD_VNDK_VERSION=current 后,编译系统会检查库的依赖性和头文件的合法性。

      • 确保vendor对象仅依赖于VNDK库集:VNDK-core、VNDK-SP 和 LL-NDK。确保core组件不依赖与vendor组件。
      • 移除全局头文件的依赖项,以便编译器可以明确是否使用-D__ANDROID_VNDK__来编译头文件。就是说全局头文件无法再使用传递方式包含在头文件内。

      启用 BOARD_VNDK_VERSION后,系统会移除多个默认的全局头文件搜索路径。模块使用这些路径下的头文件时,需要明确指定与 header_libsstatic_libs 和/或 shared_libs 的依赖关系。这些路径中包括:

      • frameworks/av/include
      • frameworks/native/include
      • frameworks/native/opengl/include
      • hardware/libhardware/include
      • hardware/libhardware_legacy/include
      • hardware/ril/include
      • libnativehelper/include
      • libnativehelper/include_deprecated
      • system/core/include
      • system/media/audio/include

      供应商变体库

      在 Android.bp 文件中,cc_librarycc_library_staticcc_library_shared 和 cc_library_headers 模块定义支持三个与 VNDK 相关的属性:vendor_availablevndk.enabled 和 vndk.support_system_process

      如果 一个库标记为vendor_available 或 vndk.enabled 为 true,则可能被编译两次,生成两种变体:核心变体和供应商变体。

      • 核心变体被视为Framework模块,将安装到 /system/lib[64] 中。
      • 而供应商变体应被视为供应商模块。系统根据模块依赖性来决定是否编译变体,并进行依赖性检查。供应商变体安装路径会根据 Android.bp中的属性来决定。

      下表总结了编译系统如何处理供应商变体,

      vendor_available vndk .enabled vndk. support_system_process 供应商变体说明
      true false false 供应商变体为 VND-ONLY。共享库将安装到 /vendor/lib[64] 中。
      true false true 无效(编译错误)
      true true false 供应商变体为 VNDK。共享库将安装到 /system/lib[64]/vndk-${VER} 中。
      true true true 供应商变体为 VNDK-SP。共享库将安装到 /system/lib[64]/vndk-sp-${VER} 中。
      false false false 没有供应商变体。此模块为 FWK-ONLY。
      false false true 无效(编译错误)
      false true false 供应商变体为 VNDK-Private。共享库将安装到 /system/lib[64]/vndk-${VER} 中。供应商模块不得直接使用这些变体。
      false true true 供应商变体为 VNDK-SP-Private。共享库将安装到 /system/lib[64]/vndk-sp-${VER} 中。供应商模块不得直接使用这些变体。

      注意:供应商可以为其模块设置 vendor_available,但不得设置 vndk.enabled 和 vndk.support_system_process,因为供应商模块无法在通用系统映像 (GSI) 中找到它们。

      条件编译

      默认情况下,Android 编译系统会为供应商变体和 VNDK 扩展定义 __ANDROID_VNDK__。您可以使用 C 预处理器防护程序保护代码:

      void all() { }
      
      #if !defined(__ANDROID_VNDK__)
      void framework_only() { }
      #endif
      
      #if defined(__ANDROID_VNDK__)
      void vndk_only() { }
      #endif

      除了 __ANDROID_VNDK__,还可以在 Android.bp 中指定不同的 cflags 或 cppflags。在 target.vendor 中指定的 cflags 或 cppflags 是专门针对供应商变体的。

      例如,以下 Android.bp 定义了 libexample 和 libexample_ext。它为libexample的供应商变体定义了"LIBEXAMPLE_ENABLE_VNDK=1",为libexample的扩展库定义了 "LIBEXAMPLE_ENABLE_VNDK=1" 和"LIBEXAMPLE_ENABLE_VNDK_EXT=1"。

      cc_library {
          name: "libexample",
          srcs: ["src/example.c"],
          vendor_available: true,
          vndk: {
              enabled: true,
          },
          target: {
              vendor: {
                  cflags: ["-DLIBEXAMPLE_ENABLE_VNDK=1"],
              },
          },
      }
      
      cc_library {
          name: "libexample_ext",
          srcs: ["src/example.c"],
          vendor: true,
          vndk: {
              enabled: true,
              extends: "libexample",
          },
          cflags: [
              "-DLIBEXAMPLE_ENABLE_VNDK=1",
              "-DLIBEXAMPLE_ENABLE_VNDK_EXT=1",
          ],
      }

      VNDK 扩展

      Android还提供了VNDK扩展的方法,就是使用自己修改的VNDK共享库来替换原始的VNDK共享库。因为供应商很可能根据自己的需求来更改AOSP库的源码,可能是为了提高性能,或者添加新钩子、新 API 或新功能。VNDK 扩展库会安装到 /vendor/lib[64]/vndk[-sp] 中,并在系统运行时会替换原始的 VNDK 共享库。

      在 Android 9 及更高版本中,Android.bp 本身支持 VNDK 扩展。要编译 VNDK 扩展,请定义另一个具有 vendor:true 和 extends 属性的模块:

      cc_library {
          name: "libvndk",
          vendor_available: true,
          vndk: {
              enabled: true,
          },
      }
      
      cc_library {
          name: "libvndk_ext",
          vendor: true,
          vndk: {
              enabled: true,
              extends: "libvndk",
          },
      }

      具有 vendor:truevndk.enabled:true 和 extends 属性的模块可定义 VNDK 扩展:

      • extends 属性必须指定基础 VNDK 共享库名称(或 VNDK-SP 共享库名称)。
      • VNDK 扩展(或 VNDK-SP 扩展)以扩展时所基于的基础模块名称命名。例如,libvndk_ext 的输出二进制文件是 libvndk.so,而非 libvndk_ext.so
      • VNDK 扩展将安装到 /vendor/lib[64]/vndk 中。
      • VNDK-SP 扩展将安装到 /vendor/lib[64]/vndk-sp 中。
      • 基础共享库必须同时具有 vndk.enabled:true 和 vendor_available:true

      VNDK-SP 扩展必须从 VNDK-SP 共享库进行扩展,就是说在定义时必须包含相同的vndk.support_system_process 。VNDK 扩展(或 VNDK-SP 扩展)也可以依赖于其他供应商共享库:

      cc_library {
          name: "libvndk_sp",
          vendor_available: true,
          vndk: {
              enabled: true,
              support_system_process: true,
          },
      }
      
      cc_library {
          name: "libvndk_sp_ext",
          vendor: true,
          vndk: {
              enabled: true,
              extends: "libvndk_sp",
              support_system_process: true,
          shared_libs: [
              "libvendor",
          ],
      }
      
      cc_library {
          name: "libvendor",
          vendor: true,
      }

      如果供应商模块依赖于由 VNDK 扩展定义的其他 API,则该模块必须在其 shared_libs 属性中指定 VNDK 扩展的名称:

      // A vendor shared library example
      cc_library {
          name: "libvendor",
          vendor: true,
          shared_libs: [
              "libvndk_ext",
          ],
      }
      
      // A vendor executable example
      cc_binary {
          name: "vendor-example",
          vendor: true,
          shared_libs: [
              "libvndk_ext",
          ],
      }

      如果供应商模块依赖于 VNDK 扩展,则这些 VNDK 扩展将自动安装到 /vendor/lib[64]/vndk[-sp] 中。如果某个模块不再依赖于 VNDK 扩展,请向 CleanSpec.mk 添加一个清理步骤,以移除共享库。例如:

      $(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)

      规则和Sepolicy

      VNDK 规则

      完整的 VNDK 规则列表如下。

      • 框架进程不得从供应商分区中加载非 SP-HAL 共享库(此规则从 Android 8.1 开始严格地强制实施)。
      • 供应商进程不得从系统分区中加载非 LL-NDK 库、非 VNDK-SP 库和非 VNDK 库(Android O 中并未严格地强制实施此规则,但未来版本中会这么做)。
      • 注意:要想从未来版本(比 Android 8.0 更高的版本)仅针对框架的 OTA 中受益,就不得在搭载 Android 8.0 出厂的设备中违反此规则。
      • 已安装的 VNDK 库必须是由 Google 定义的合格 VNDK 库的子集。
      • SP-HAL 和 SP-HAL-Dep 的外部依赖项必须仅限于 LL-NDK 库或由 Google 定义的 VNDK-SP 库。

        • SP-HAL 共享库的依赖项必须仅限于 LL-NDK 库、由 Google 定义的 VNDK-SP 库、其他 SP-HAL 库和/或可标记为 SP-HAL-Dep 库的其他供应商共享库。
        • 只有当供应商共享库不是 AOSP 库,且其依赖项仅限于 LL-NDK 库、由 Google 定义的 VNDK-SP 库、SP-HAL 库和/或其他 SP-HAL-Dep 库时,才可标记为 SP-HAL-Dep 库。
      • VNDK-SP 必须保持独立。在 Android 8.0 中,系统以一种特殊方式处理 libRS_internal.so,但在未来版本中,其处理方式会被重新考虑。
      • 不得通过非 HIDL 接口(包括但不限于 Binder、套接字、共享内存、文件等)进行框架-供应商通信。
      • 系统分区必须足够大,以便容纳所有符合条件的 VNDK 库的两个副本,以及不符合条件的框架共享库的一个副本。

      sepolicy

      本部分中介绍的框架进程对应于 sepolicy 中的 coredomain,而供应商进程对应于 non-coredomain。例如,/dev/binder 只能在 coredomain 中被访问,而 /dev/vndbinder 只能在非 coredomain 中被访问。

      类似政策会限制对系统分区和供应商分区上的共享库的访问。下表列出了访问不同类别的共享库时所需的权限:

      类别 分区 是否可从 coredomain 访问 是否可从 非 coredomain 访问
      LL-NDK 系统
      LL-NDK-Private 系统
      VNDK-SP/VNDK-SP-Private 系统
      VNDK-SP-Ext 供应商
      VNDK 系统
      VNDK-Ext 供应商
      FWK-ONLY 系统
      FWK-ONLY-RS 系统
      SP-HAL 供应商
      SP-HAL-Dep 供应商
      VND-ONLY 供应商

      LL-NDK-Private 和 VNDK-SP-Private 必须从这两个域中都可访问,因为非 coredomain 会间接访问这些库。同样,SP-HAL-Dep 必须可从 coredomain 访问,因为 SP-HAL 依赖该域。

      same_process_hal_file 标签

      供应商分区中包含下面几个库。确保这些库既可以从 coredomain 访问,又可以从非 coredomain 访问。

      • VNDK-SP-Ext,位于 /vendor/lib[64]/vndk-sp
      • SP-HAL,位于 /vendor/lib[64] 或 /vendor/lib[64]/hw
      • SP-HAL-Dep,位于 /vendor/lib[64] 或 /vendor/lib[64]/hw

      将这些文件明确标记为 same_process_hal_file。因为在默认情况下,从 coredomain 无法访问 vendor 分区中的任何内容。请向供应商特定的 file_contexts 文件中添加与以下命令行类似的命令行:

      /vendor/lib(64)?/hw/libMySpHal\.so        u:object_r:same_process_hal_file:s0
      /vendor/lib(64)?/vndk-sp/libBase\.so      u:object_r:same_process_hal_file:s0
      /vendor/lib(64)?/libBaseInternal\.so      u:object_r:same_process_hal_file:s0

      参考文档:

      Android Source: VNDK

      以上就是Android VNDK使用及原理深入探究的详细内容,更多关于Android VNDK使用原理的资料请关注其它相关文章!

      免费资源网,https://freexyz.cn/
      声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。