APEX của nhà cung cấp

Bạn có thể sử dụng định dạng tệp APEX để đóng gói và cài đặt các mô-đun hệ điều hành Android cấp thấp hơn. Công cụ này cho phép tạo và cài đặt độc lập các thành phần như dịch vụ và thư viện gốc, triển khai HAL, phần mềm cơ sở, tệp cấu hình, v.v.

APEX của nhà cung cấp được hệ thống xây dựng cài đặt tự động trong /vendor được apexd kích hoạt trong thời gian chạy, giống như các APEX trong các nền tảng khác phân vùng.

Trường hợp sử dụng

Mô-đun hoá hình ảnh của nhà cung cấp

APEX hỗ trợ việc đóng gói và mô-đun hoá tự nhiên các hoạt động triển khai tính năng trên hình ảnh của nhà cung cấp.

Khi hình ảnh của nhà cung cấp được tạo bằng cách kết hợp các nhà cung cấp được tạo độc lập APEX, nhà sản xuất thiết bị có thể dễ dàng chọn cách triển khai của nhà cung cấp mà họ muốn trên thiết bị của họ. Nhà sản xuất thậm chí có thể tạo một APEX nhà cung cấp mới nếu không có APEX nào được cung cấp phù hợp với nhu cầu của họ hoặc họ có phần cứng tuỳ chỉnh hoàn toàn mới.

Ví dụ: OEM có thể chọn thiết lập thiết bị của họ bằng AOSP wifi APEX triển khai, APEX triển khai Bluetooth SoC và OEM tuỳ chỉnh APEX triển khai điện thoại.

Nếu không có APEX của nhà cung cấp, việc triển khai với quá nhiều phần phụ thuộc giữa các thành phần của nhà cung cấp sẽ đòi hỏi bạn phải phối hợp và theo dõi cẩn thận. Bằng cách gói tất cả các thành phần (bao gồm cả tệp cấu hình và thư viện bổ sung) trong APEX với giao diện được xác định rõ ràng tại bất kỳ điểm giao tiếp nào giữa các tính năng, các thành phần khác nhau sẽ có thể hoán đổi cho nhau.

Lặp lại dành cho nhà phát triển

APEX của nhà cung cấp giúp nhà phát triển lặp lại nhanh hơn trong khi phát triển các mô-đun của nhà cung cấp bằng cách đóng gói toàn bộ quá trình triển khai tính năng, chẳng hạn như HAL wifi, bên trong APEX của nhà cung cấp. Sau đó, nhà phát triển có thể tạo và đẩy riêng APEX của nhà cung cấp để kiểm thử các thay đổi, thay vì tạo lại toàn bộ hình ảnh của nhà cung cấp.

Điều này giúp đơn giản hoá và đẩy nhanh chu kỳ lặp lại của nhà phát triển cho những nhà phát triển đang chủ yếu hoạt động trong một lĩnh vực tính năng và muốn lặp lại chỉ tính năng đó .

Việc tự nhiên gói một khu vực tính năng vào APEX cũng đơn giản hoá quy trình tạo, đẩy và kiểm thử các thay đổi cho khu vực tính năng đó. Ví dụ: Việc cài đặt lại APEX sẽ tự động cập nhật mọi tệp cấu hình hoặc thư viện đi kèm APEX bao gồm.

Việc gói một khu vực tính năng vào APEX cũng đơn giản hoá việc gỡ lỗi hoặc quay lại khi nhận thấy hành vi xấu của thiết bị. Ví dụ: nếu điện thoại hoạt động kém trong một bản dựng mới, thì nhà phát triển có thể thử cài đặt phiên bản điện thoại APEX triển khai trên thiết bị (mà không cần cài đặt ROM bản dựng đầy đủ) và xem hành vi tốt có được khôi phục hay không.

Ví dụ về quy trình làm việc:

# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w

# Test the device.
... testing ...

# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...

# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...

Ví dụ

Thông tin cơ bản

Xem trang Định dạng tệp APEX chính để biết APEX chung thông tin, bao gồm yêu cầu về thiết bị, chi tiết định dạng tệp và các bước cài đặt.

Trong Android.bp, việc đặt thuộc tính vendor: true sẽ biến mô-đun APEX thành APEX của nhà cung cấp.

apex {
  ..
  vendor: true,
  ..
}

Tệp nhị phân và thư viện dùng chung

APEX bao gồm các phần phụ thuộc bắc cầu bên trong tải trọng APEX, trừ phi các phần phụ thuộc đó có giao diện ổn định.

Các giao diện gốc ổn định cho các phần phụ thuộc APEX của nhà cung cấp bao gồm cc_library với thư viện stubs và LLNDK. Các phần phụ thuộc này bị loại trừ khỏi việc đóng gói và phần phụ thuộc đều được ghi lại trong tệp kê khai APEX. Tệp kê khai là được linkerconfig xử lý để các phần phụ thuộc gốc bên ngoài có sẵn trong thời gian chạy.

Trong đoạn mã sau, APEX chứa cả tệp nhị phân (my_service) và các phần phụ thuộc không ổn định (tệp *.so).

apex {
  ..
  vendor: true,
  binaries: ["my_service"],
  ..
}

Trong đoạn mã sau, APEX chứa thư viện dùng chung my_standalone_lib và mọi phần phụ thuộc không ổn định của thư viện đó (như mô tả ở trên).

apex {
  ..
  vendor: true,
  native_shared_libs: ["my_standalone_lib"],
  ..
}

Thu nhỏ APEX

APEX có thể lớn hơn vì gói các phần phụ thuộc không ổn định. Bạn nên sử dụng tính năng liên kết tĩnh. Các thư viện phổ biến như libc++.solibbase.so có thể có dạng liên kết tĩnh với tệp nhị phân HAL. Tạo phần phụ thuộc để cung cấp phiên bản ổn định giao diện có thể là một tuỳ chọn khác. Phần phụ thuộc sẽ không được đóng gói trong APEX.

Triển khai HAL

Để xác định cách triển khai HAL, hãy cung cấp các tệp nhị phân và thư viện tương ứng bên trong APEX của nhà cung cấp tương tự như các ví dụ sau:

Để đóng gói hoàn toàn việc triển khai HAL, APEX cũng phải chỉ định bất kỳ các mảnh VINTF và tập lệnh init có liên quan.

Mảnh VINTF

Mảnh VINTF có thể được phân phát qua APEX của nhà cung cấp khi các mảnh nằm trong etc/vintf của APEX.

Sử dụng thuộc tính prebuilts để nhúng các mảnh VINTF vào APEX.

apex {
  ..
  vendor: true,
  prebuilts: ["fragment.xml"],
  ..
}

prebuilt_etc {
  name: "fragment.xml",
  src: "fragment.xml",
  sub_dir: "vintf",
}

API truy vấn

Khi các mảnh VINTF được thêm vào APEX, hãy sử dụng API libbinder_ndk để nhận bản đồ ánh xạ của giao diện HAL và tên APEX.

  • AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default") : true nếu thực thể HAL được xác định trong APEX.
  • AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...) : lấy tên APEX xác định thực thể HAL.
  • AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...) : hãy sử dụng tính năng này để mở HAL truyền qua.

Tập lệnh khởi tạo

APEX có thể chứa các tập lệnh khởi tạo theo 2 cách: (A) một tệp văn bản tạo sẵn trong tải trọng APEX hoặc (B) một tập lệnh init thông thường trong /vendor/etc. Bạn có thể đặt cả hai cho cùng một APEX.

Tập lệnh khởi tạo trong APEX:

prebuilt_etc {
  name: "myinit.rc",
  src: "myinit.rc"
}

apex {
  ..
  vendor: true,
  prebuilts: ["myinit.rc"],
  ..
}

Tập lệnh khởi tạo trong APEX của nhà cung cấp có thể có service định nghĩa và lệnh on <property or event>.

Hãy đảm bảo rằng định nghĩa service trỏ đến một tệp nhị phân trong cùng một APEX. Ví dụ: APEX com.android.foo có thể xác định một dịch vụ có tên là foo-service.

on foo-service /apex/com.android.foo/bin/foo
  ...

Hãy cẩn thận khi sử dụng các lệnh on. Vì các tập lệnh khởi tạo trong APEX được phân tích cú pháp và thực thi sau khi APEX được kích hoạt, nên một số sự kiện hoặc thuộc tính không thể được sử dụng. Sử dụng apex.all.ready=true để kích hoạt các hành động càng sớm càng tốt. Bootstrap APEX có thể sử dụng on init, nhưng không thể sử dụng on early-init.

Chương trình cơ sở

Ví dụ:

Nhúng chương trình cơ sở vào APEX của nhà cung cấp bằng loại mô-đun prebuilt_firmware, như theo dõi.

prebuilt_firmware {
  name: "my.bin",
  src: "path_to_prebuilt_firmware",
  vendor: true,
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.bin"],  // installed inside APEX as /etc/firmware/my.bin
  ..
}

prebuilt_firmware mô-đun được cài đặt trong <apex name>/etc/firmware của APEX. ueventd quét các thư mục /apex/*/etc/firmware để tìm các mô-đun phần mềm.

file_contexts của APEX phải gắn nhãn mọi mục trong phần tải trọng của chương trình cơ sở đúng cách để đảm bảo rằng ueventd có thể truy cập vào các tệp này trong thời gian chạy; thường, chỉ cần nhãn vendor_file là đủ. Ví dụ:

(/.*)? u:object_r:vendor_file:s0

Mô-đun nhân

Nhúng các mô-đun hạt nhân vào APEX của nhà cung cấp dưới dạng các mô-đun tạo sẵn, như sau.

prebuilt_etc {
  name: "my.ko",
  src: "my.ko",
  vendor: true,
  sub_dir: "modules"
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.ko"],  // installed inside APEX as /etc/modules/my.ko
  ..
}

file_contexts của APEX phải gắn nhãn cho mọi mục nhập tải trọng mô-đun nhân đúng cách. Ví dụ:

/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0

Bạn phải cài đặt rõ ràng các mô-đun hạt nhân. Tập lệnh init mẫu sau trong phân vùng nhà cung cấp hiển thị bản cài đặt qua insmod:

my_init.rc:

on early-boot
  insmod /apex/myapex/etc/modules/my.ko
  ..

Lớp phủ tài nguyên thời gian chạy

Ví dụ:

Nhúng lớp phủ tài nguyên thời gian chạy trong APEX của nhà cung cấp bằng cách sử dụng thuộc tính rros.

runtime_resource_overlay {
    name: "my_rro",
    soc_specific: true,
}


apex {
  ..
  vendor: true,
  rros: ["my_rro"],  // installed inside APEX as /overlay/my_rro.apk
  ..
}

Các tệp cấu hình khác

APEX của nhà cung cấp hỗ trợ nhiều tệp cấu hình khác thường có trên nhà cung cấp phân vùng dưới dạng được tạo sẵn bên trong APEX của nhà cung cấp và nhiều tính năng khác đang được thêm vào.

Ví dụ:

APEX của nhà cung cấp theo phương thức tự thân khởi nghiệp

Một số dịch vụ HAL (Lớp trừu tượng phần cứng) như keymint cần hoạt động trước khi có APEX đã kích hoạt. Các HAL đó thường đặt early_hal trong phần định nghĩa dịch vụ trong tập lệnh init. Một ví dụ khác là lớp animation thường được bắt đầu sớm hơn sự kiện post-fs-data. Khi dịch vụ HAL (Lớp trừu tượng phần cứng) sớm như vậy được được đóng gói trong APEX của nhà cung cấp, tạo đỉnh "vendorBootstrap": true trong APEX của nó Tệp kê khai để có thể kích hoạt sớm hơn. Xin lưu ý rằng bạn chỉ có thể kích hoạt APEX khởi động từ vị trí tạo sẵn như /vendor/apex, chứ không phải từ /data/apex.

Thuộc tính hệ thống

Đây là các thuộc tính hệ thống mà khung đọc để hỗ trợ nhà cung cấp CÁC PHƯƠNG ÁN:

  • input_device.config_file.apex=<apex name> – khi được đặt, các tệp cấu hình đầu vào (*.idc, *.kl*.kcm) sẽ được tìm kiếm từ thư mục /etc/usr của APEX.
  • ro.vulkan.apex=<apex name> – khi được đặt, trình điều khiển Vulkan sẽ được tải từ APEX. Vì trình điều khiển Vulkan được các HAL đời đầu sử dụng, hãy tạo APEX Bootstrap APEX và định cấu hình không gian tên của trình liên kết đó hiển thị.

Đặt các thuộc tính hệ thống trong tập lệnh init bằng setprop .

Các tính năng phát triển bổ sung

Lựa chọn APEX khi khởi động

Ví dụ:

Nhà phát triển cũng có thể cài đặt nhiều phiên bản APEX của nhà cung cấp dùng chung cùng tên và khoá APEX, sau đó chọn phiên bản sẽ được kích hoạt trong mỗi lần khởi động bằng sysprops liên tục. Đối với một số trường hợp sử dụng nhất định của nhà phát triển, việc này có thể đơn giản hơn so với việc cài đặt bản sao mới của APEX bằng adb install.

Ví dụ về trường hợp sử dụng:

  • Cài đặt 3 phiên bản APEX của nhà cung cấp Wi-Fi HAL: Nhóm đảm bảo chất lượng có thể chạy hướng dẫn hoặc kiểm thử tự động bằng một phiên bản, sau đó khởi động lại để chuyển sang một phiên bản khác và chạy lại kiểm thử, sau đó so sánh kết quả cuối cùng.
  • Cài đặt 2 phiên bản APEX của nhà cung cấp HAL máy ảnh, hiện tạithử nghiệm: Người dùng thử nghiệm có thể sử dụng phiên bản thử nghiệm mà không cần tải xuống và cài đặt tệp bổ sung, nhờ đó, họ có thể dễ dàng hoán đổi trở lại.

Trong khi khởi động, apexd tìm các sysprops theo một định dạng cụ thể để kích hoạt đúng phiên bản APEX.

Các định dạng dự kiến cho khoá thuộc tính là:

  • Bootconfig
    • Dùng để đặt giá trị mặc định trong BoardConfig.mk.
    • androidboot.vendor.apex.<apex name>
  • sysprop ổn định
    • Dùng để thay đổi giá trị mặc định, được đặt trên một thiết bị đã khởi động.
    • Ghi đè giá trị bootconfig nếu có.
    • persist.vendor.apex.<apex name>

Giá trị của thuộc tính phải là tên tệp của APEX cần kích hoạt.

// Default version.
apex {
  name: "com.oem.camera.hal.my_apex_default",
  vendor: true,
  ..
}

// Non-default version.
apex {
  name: "com.oem.camera.hal.my_apex_experimental",
  vendor: true,
  ..
}

Phiên bản mặc định cũng phải được định cấu hình bằng cách sử dụng bootconfig trong BoardConfig.mk:

# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
    androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default

Sau khi khởi động thiết bị, hãy thay đổi phiên bản đã kích hoạt bằng cách đặt sysprop ổn định:

$ adb root;
$ adb shell setprop \
    persist.vendor.apex.com.oem.camera.hal \
    com.oem.camera.hal.my_apex_experimental;
$ adb reboot;

Nếu thiết bị hỗ trợ việc cập nhật bootconfig sau khi cài đặt ROM (chẳng hạn như thông qua các lệnh fastboot oem), thì việc thay đổi thuộc tính bootconfig cho APEX được cài đặt nhiều lần cũng sẽ thay đổi phiên bản được kích hoạt khi khởi động.

Đối với các thiết bị tham chiếu ảo dựa trên Cuttlefish, bạn có thể sử dụng lệnh --extra_bootconfig_args để đặt trực tiếp thuộc tính bootconfig trong khi khởi chạy. Ví dụ:

launch_cvd --noresume \
  --extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";