Công cụ định nghĩa VNDK

Công cụ định nghĩa VNDK giúp nhà cung cấp di chuyển cây nguồn của họ sang môi trường Android 8.0. Công cụ này quét các tệp nhị phân trong hệ thống và hình ảnh nhà cung cấp, sau đó phân giải các phần phụ thuộc. Dựa trên biểu đồ phần phụ thuộc mô-đun, công cụ này cũng có thể phát hiện các lỗi vi phạm các khái niệm VNDK và đưa ra thông tin chi tiết/đề xuất để di chuyển các mô-đun giữa các phân vùng. Nếu bạn chỉ định Hình ảnh hệ thống chung (GSI), thì công cụ định nghĩa VNDK có thể so sánh hình ảnh hệ thống của bạn với GSI và xác định các thư viện mở rộng.

Phần này trình bày 3 lệnh thường dùng cho công cụ định nghĩa VNDK:

  • vndk. Tính toán VNDK_SP_LIBRARIES, VNDK_SP_EXT_LIBRARIES và EXTRA_VENDOR_LIBRARIES để khắc phục sự cố hệ thống xây dựng trong Android 8.0 trở lên.
  • check-dep. Kiểm tra các phần phụ thuộc mô-đun vi phạm từ mô-đun nhà cung cấp đến thư viện dùng chung khung không đủ điều kiện.
  • deps. In các phần phụ thuộc giữa thư viện dùng chung và tệp thực thi.

Để biết thêm thông tin chi tiết về cách sử dụng lệnh nâng cao, hãy tham khảo tệp README.md trong kho lưu trữ Công cụ định nghĩa VNDK.

vndk

Lệnh con vndk tải các thư viện dùng chung và tệp thực thi từ phân vùng hệ thống và phân vùng nhà cung cấp, sau đó phân giải các phần phụ thuộc mô-đun để xác định các thư viện phải được sao chép vào /system/lib[64]/vndk-sp-${VER}/vendor/lib[64]. Các tuỳ chọn cho lệnh con vndk bao gồm:

Lựa chọn Mô tả
--system Chỉ đến một thư mục chứa các tệp nằm trong phân vùng hệ thống.
--vendor Chỉ đến một thư mục chứa các tệp nằm trong phân vùng của nhà cung cấp.
--aosp-system Chỉ đến một thư mục chứa các tệp nằm trong hình ảnh hệ thống chung (GSI).
--load-extra-deps Chỉ đến một tệp mô tả các phần phụ thuộc ngầm ẩn, chẳng hạn như dlopen().

Ví dụ: để tính toán các nhóm thư viện VNDK, hãy chạy lệnh con vndk sau:

./vndk_definition_tool.py vndk \
    --system ${ANDROID_PRODUCT_OUT}/system \
    --vendor ${ANDROID_PRODUCT_OUT}/vendor \
    --aosp-system ${ANDROID_PRODUCT_OUT}/../generic_arm64_ab/system\
    --load-extra-deps dlopen.dep

Chỉ định các phần phụ thuộc bổ sung bằng định dạng tệp đơn giản. Mỗi dòng đại diện cho một mối quan hệ, trong đó tệp trước dấu hai chấm phụ thuộc vào tệp sau dấu hai chấm. Ví dụ:

/system/lib/libart.so: /system/lib/libart-compiler.so

Dòng này cho phép công cụ định nghĩa VNDK biết rằng libart.so phụ thuộc vào libart-compiler.so.

Đích đến cài đặt

Công cụ định nghĩa VNDK liệt kê các thư viện và thư mục cài đặt tương ứng cho các danh mục sau:

Danh mục Thư mục
vndk_sp Phải cài đặt vào /system/lib[64]/vndk-sp-${VER}
vndk_sp_ext Phải cài đặt vào /vendor/lib[64]/vndk-sp
extra_vendor_libs Phải cài đặt vào /vendor/lib[64]

Tạo mẫu hệ thống

Sau khi thu thập kết quả từ công cụ định nghĩa VNDK, nhà cung cấp có thể tạo Android.mk và điền vào VNDK_SP_LIBRARIES, VNDK_SP_EXT_LIBRARIESEXTRA_VENDOR_LIBRARIES để tự động hoá quá trình sao chép thư viện vào đích cài đặt được chỉ định.

ifneq ($(filter $(YOUR_DEVICE_NAME),$(TARGET_DEVICE)),)
VNDK_SP_LIBRARIES := ##_VNDK_SP_##
VNDK_SP_EXT_LIBRARIES := ##_VNDK_SP_EXT_##
EXTRA_VENDOR_LIBRARIES := ##_EXTRA_VENDOR_LIBS_##

#-------------------------------------------------------------------------------
# VNDK Modules
#-------------------------------------------------------------------------------
LOCAL_PATH := $(call my-dir)

define define-vndk-lib
include $$(CLEAR_VARS)
LOCAL_MODULE := $1.$2
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_PREBUILT_MODULE_FILE := $$(TARGET_OUT_INTERMEDIATE_LIBRARIES)/$1.so
LOCAL_STRIP_MODULE := false
LOCAL_MULTILIB := first
LOCAL_MODULE_TAGS := optional
LOCAL_INSTALLED_MODULE_STEM := $1.so
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE_RELATIVE_PATH := $3
LOCAL_VENDOR_MODULE := $4
include $$(BUILD_PREBUILT)

ifneq ($$(TARGET_2ND_ARCH),)
ifneq ($$(TARGET_TRANSLATE_2ND_ARCH),true)
include $$(CLEAR_VARS)
LOCAL_MODULE := $1.$2
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_PREBUILT_MODULE_FILE := $$($$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)/$1.so
LOCAL_STRIP_MODULE := false
LOCAL_MULTILIB := 32
LOCAL_MODULE_TAGS := optional
LOCAL_INSTALLED_MODULE_STEM := $1.so
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE_RELATIVE_PATH := $3
LOCAL_VENDOR_MODULE := $4
include $$(BUILD_PREBUILT)
endif  # TARGET_TRANSLATE_2ND_ARCH is not true
endif  # TARGET_2ND_ARCH is not empty
endef

$(foreach lib,$(VNDK_SP_LIBRARIES),\
    $(eval $(call define-vndk-lib,$(lib),vndk-sp-gen,vndk-sp,)))
$(foreach lib,$(VNDK_SP_EXT_LIBRARIES),\
    $(eval $(call define-vndk-lib,$(lib),vndk-sp-ext-gen,vndk-sp,true)))
$(foreach lib,$(EXTRA_VENDOR_LIBRARIES),\
    $(eval $(call define-vndk-lib,$(lib),vndk-ext-gen,,true)))


#-------------------------------------------------------------------------------
# Phony Package
#-------------------------------------------------------------------------------

include $(CLEAR_VARS)
LOCAL_MODULE := $(YOUR_DEVICE_NAME)-vndk
LOCAL_MODULE_TAGS := optional
LOCAL_REQUIRED_MODULES := \
    $(addsuffix .vndk-sp-gen,$(VNDK_SP_LIBRARIES)) \
    $(addsuffix .vndk-sp-ext-gen,$(VNDK_SP_EXT_LIBRARIES)) \
    $(addsuffix .vndk-ext-gen,$(EXTRA_VENDOR_LIBRARIES))
include $(BUILD_PHONY_PACKAGE)

endif  # ifneq ($(filter $(YOUR_DEVICE_NAME),$(TARGET_DEVICE)),)

check-dep

Lệnh con check-dep quét các mô-đun của nhà cung cấp và kiểm tra các phần phụ thuộc của chúng. Nếu phát hiện lỗi vi phạm, công cụ này sẽ in thư viện phụ thuộc và cách sử dụng ký hiệu vi phạm:

./vndk_definition_tool.py check-dep \
    --system ${ANDROID_PRODUCT_OUT}/system \
    --vendor ${ANDROID_PRODUCT_OUT}/vendor \
    --tag-file eligible-list.csv \
    --module-info ${ANDROID_PRODUCT_OUT}/module-info.json \
    1> check_dep.txt \
    2> check_dep_err.txt

Ví dụ: kết quả mẫu sau đây cho thấy một phần phụ thuộc vi phạm từ libRS_internal.so đến libmediandk.so:

/system/lib/libRS_internal.so
        MODULE_PATH: frameworks/rs
        /system/lib/libmediandk.so
                AImageReader_acquireNextImage
                AImageReader_delete
                AImageReader_getWindow
                AImageReader_new
                AImageReader_setImageListener

Các tuỳ chọn cho lệnh con check-dep bao gồm:

Lựa chọn Mô tả
--tag-file Phải tham chiếu đến một tệp thẻ thư viện đủ điều kiện (như mô tả bên dưới). Đây là một bảng tính do Google cung cấp, mô tả các danh mục thư viện dùng chung khung.
--module-info Chỉ đến module-info.json do hệ thống bản dựng Android tạo. Tệp này giúp công cụ định nghĩa VNDK liên kết các mô-đun nhị phân với mã nguồn.

Tệp thẻ thư viện đủ điều kiện

Google cung cấp một bảng tính VNDK đủ điều kiện (ví dụ: eligible-list.csv) gắn thẻ các thư viện dùng chung khung mà các mô-đun của nhà cung cấp có thể sử dụng:

Thẻ Mô tả
LL-NDK Thư viện dùng chung có ABI/API ổn định mà cả mô-đun khung và mô-đun nhà cung cấp đều có thể sử dụng.
LL-NDK-Private Các phần phụ thuộc riêng tư của thư viện LL-NDK. Mô-đun của nhà cung cấp không được truy cập trực tiếp vào các thư viện này.
VNDK-SP Phần phụ thuộc thư viện dùng chung của khung SP-HAL.
VNDK-SP-Private Các phần phụ thuộc VNDK-SP mà không phải tất cả mô-đun của nhà cung cấp đều có thể truy cập trực tiếp.
VNDK Thư viện dùng chung khung có sẵn cho các mô-đun của nhà cung cấp (ngoại trừ SP-HAL và SP-HAL-Dep).
VNDK-Private Các phần phụ thuộc VNDK mà không phải tất cả mô-đun của nhà cung cấp đều có thể truy cập trực tiếp.
FWK-ONLY Thư viện dùng chung chỉ dành cho khung mà các mô-đun của nhà cung cấp không được truy cập (không trực tiếp cũng không gián tiếp).
FWK-ONLY-RS Thư viện dùng chung chỉ dành cho khung mà các mô-đun của nhà cung cấp không được truy cập (ngoại trừ trường hợp sử dụng RS).

Bảng sau đây mô tả các thẻ dùng cho thư viện dùng chung của nhà cung cấp:

Thẻ Mô tả
SP-HAL Thư viện dùng chung triển khai HAL cùng quy trình.
SP-HAL-Dep Phần phụ thuộc thư viện dùng chung của nhà cung cấp SP-HAL (còn gọi là phần phụ thuộc SP-HAL, ngoại trừ LL-NDK và VNDK-SP).
CHỈ DÀNH CHO VND Các thư viện dùng chung không hiển thị trong khung mà các mô-đun khung không được truy cập. Các thư viện VNDK mở rộng đã sao chép cũng được gắn thẻ là VND-ONLY.

Mối quan hệ giữa các thẻ:

Mối quan hệ giữa các thẻ.

Hình 1. Mối quan hệ giữa các thẻ.

phần phụ thuộc

Để gỡ lỗi các phần phụ thuộc thư viện, lệnh con deps sẽ in các phần phụ thuộc mô-đun:

./vndk_definition_tool.py deps \
    --system ${ANDROID_PRODUCT_OUT}/system \
    --vendor ${ANDROID_PRODUCT_OUT}/vendor

Kết quả sẽ bao gồm nhiều dòng. Dòng không có ký tự tab sẽ bắt đầu một phần mới. Dòng có ký tự tab phụ thuộc vào phần trước đó. Ví dụ:

/system/lib/ld-android.so
/system/lib/libc.so
        /system/lib/libdl.so

Kết quả này cho thấy ld-android.so không có phần phụ thuộc và libc.so phụ thuộc vào libdl.so.

Khi chỉ định tuỳ chọn --revert, lệnh con deps sẽ in các cách sử dụng thư viện (phần phụ thuộc đảo ngược):

./vndk_definition_tool.py deps \
    --revert \
    --system ${ANDROID_PRODUCT_OUT}/system \
    --vendor ${ANDROID_PRODUCT_OUT}/vendor

Ví dụ:

/system/lib/ld-android.so
        /system/lib/libdl.so
        

Kết quả này cho thấy ld-android.so được libdl.so sử dụng, hay nói cách khác, libdl.so phụ thuộc vào ld-android.so. Ngoài ra, kết quả này cho thấy rằng libdl.so là người dùng duy nhất của ld-android.so.

Khi chỉ định tuỳ chọn --symbol, lệnh con deps sẽ in các ký hiệu đang được sử dụng:

./vndk_definition_tool.py deps \
    --symbol \
    --system ${ANDROID_PRODUCT_OUT}/system \
    --vendor ${ANDROID_PRODUCT_OUT}/vendor
    

Ví dụ:

/system/lib/libc.so
        /system/lib/libdl.so
                android_get_application_target_sdk_version
                dl_unwind_find_exidx
                dlclose
                dlerror
                dlopen
                dlsym

Kết quả này cho thấy libc.so phụ thuộc vào 6 hàm được xuất từ libdl.so. Nếu bạn chỉ định cả tuỳ chọn --symbol và tuỳ chọn --revert, thì các ký hiệu mà người dùng sử dụng sẽ được in.