启用 VNDK

为了区隔供应商模块与系统模块,您在启用 VNDK 前需要对代码库进行一些更改。请按照以下指南在供应商/OEM 代码库中启用 VNDK。

编译系统库

编译系统包含多种类型的对象,其中包括库(共享、静态或标头)和二进制文件:

图 1. 编译系统库。
  • core:位于系统映像中,由系统映像使用。vendorvendor_availablevndkvndk-sp 库不能使用此类库。
    cc_library {
        name: "libThatIsCore",
        ...
    }
    
  • vendor-only(或 proprietary):位于供应商映像中,由供应商映像使用。
    cc_library {
        name: "libThatIsVendorOnly",
        proprietary: true,
        # or: vendor: true, # (for things in AOSP)
        ...
    }
    
    
  • vendor_available:位于供应商映像中,由供应商映像使用(可能包含 core 的重复项)。
    cc_library {
        name: "libThatIsVendorAvailable",
        vendor_available: true,
        ...
    }
    
  • vndk:位于系统映像中,由供应商映像使用(vendor_available 的子集)。
    cc_library {
        name: "libThatIsVndk",
        vendor_available: true,
        vndk: {
            enabled: true,
        }
        ...
    }
    
  • vndk-sp:位于系统映像中,由系统映像间接使用(core 的子集)。
    cc_library {
        name: "libThatIsVndkSp",
        vendor_available: true,
        vndk: {
            enabled: true,
            support_system_process: true,
        }
        ...
    }
    
  • llndk:同时由系统映像和供应商映像使用。
    llndk_library {
        name: "libThasIsLlndk",
    }
    

当一个库被标记为 vendor_available:true 时,它将编译两次:

  • 一次是为平台编译(因此被安装到 /system/lib 中)。
  • 一次是为供应商编译(因此被安装到 /vendor/lib/system/lib/vndk/system/lib/vndk-sp 中)。

库的供应商版本使用 -D__ANDROID_VNDK__ 标记编译。您可以使用此标记停用在 Android 未来版本中可能会发生显著变化的专用系统组件。此外,不同的库会导出一组不同的标头(例如 liblog)。可以在 Android.bp 文件中指定相应目标的供应商变体特有的选项:

target: { vendor: { … } }

为代码库启用 VNDK

要为代码库启用 VNDK,请执行以下操作:

  1. 通过计算 vendor.imgsystem.img 分区的所需大小来确定是否符合条件。
  2. 启用 BOARD_VNDK_VERSION=current。您可以将其添加到 BoardConfig.mk,也可以直接使用此选项来编译组件(即 m -j BOARD_VNDK_VERSION=current MY-LIB)。

在启用 BOARD_VNDK_VERSION=current 后,编译系统会强制执行以下依赖项和标头要求。

管理依赖项

如果 vendor 对象依赖的 core 组件在 vndk 中不存在或未以 vendor 对象的形式存在,则必须通过以下某种方式解决该问题:

  • 可以移除该依赖项。
  • 如果该 core 组件归 vendor 所有,则可将其标记为 vendor_availablevendor
  • 可以在上游向 Google 提交更改请求,以便将此核心对象列入 vndk

此外,如果有 core 组件依赖于 vendor 组件,则必须使此 vendor 组件成为 core 组件,或者以其他方式移除此依赖项(例如,通过移除依赖项或将其移到 vendor 组件中)。

管理标头

必须移除全局标头依赖项,编译系统才能知道在编译标头时是否带 -D__ANDROID_VNDK__。例如,您仍然可以使用标头库 libutils_headers 来访问 utils/StrongPointer.h 等 libutils 标头。

某些标头(例如 unistd.h)无法再以传递方式包含在内,但可以包含在本地。

最后,private/android_filesystem_config.h 的公共部分已移至 cutils/android_filesystem_config.h。要管理这些标头,请执行下列操作之一:

  • 通过将所有 AID_* 宏替换为 getgrnam/getpwnam 调用(如果可能),移除对 private/android_filesystem_config.h 的依赖。例如:
    • (uid_t)AID_WIFI 会变为 getpwnam("wifi")->pw_uid
    • (gid_t)AID_SDCARD_R 会变为 getgrnam("sdcard_r")->gr_gid
    如需了解详情,请参阅 private/android_filesystem_config.h
  • 对于硬编码的 AIS,请包含 cutils/android_filesystem_config.h