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. Nó cho phép xây dựng 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, chương trình 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 tự động cài đặt trong phân vùng /vendor và được kích hoạt khi chạy bởi apexd giống như APEX trong các phân vùng khác.

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

Mô-đun hóa hình ảnh nhà cung cấp

APEX tạo điều kiện thuận lợi cho việc đóng gói và mô-đun hóa việc triển khai tính năng trên hình ảnh của nhà cung cấp một cách tự nhiên.

Khi hình ảnh nhà cung cấp được xây dựng dưới dạng kết hợp các APEX của nhà cung cấp được xây dựng độc lập, nhà sản xuất thiết bị có thể dễ dàng chọn cách triển khai nhà cung cấp cụ thể mong muốn trên thiết bị của họ. Các nhà sản xuất thậm chí có thể tạo APEX của 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 tùy chỉnh hoàn toàn mới.

Ví dụ: OEM có thể chọn kết hợp thiết bị của họ với APEX triển khai wifi AOSP, APEX triển khai bluetooth SoC và APEX triển khai điện thoại OEM tùy chỉnh.

Nếu không có APEX của nhà cung cấp, việc triển khai có rất nhiều sự phụ thuộc giữa các thành phần của nhà cung cấp đòi hỏi phải có sự 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 tệp cấu hình và thư viện bổ sung) vào APEX với giao diện được xác định rõ ràng tại bất kỳ điểm giao tiếp giữa các tính năng nào, các thành phần khác nhau có thể thay thế cho nhau.

Lặp lại của nhà phát triển

APEX của nhà cung cấp giúp các 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 gói toàn bộ triển khai tính năng, như HAL wifi, bên trong APEX của nhà cung cấp. Sau đó, các nhà phát triển có thể xây dựng và đẩy APEX của nhà cung cấp riêng lẻ để kiểm tra các thay đổi, thay vì xây dựng lại toàn bộ hình ảnh nhà cung cấp.

Điều này giúp đơn giản hóa và tăng tốc chu trình lặp lại của nhà phát triển đối với những nhà phát triển chủ yếu làm việc trong một lĩnh vực tính năng và chỉ muốn lặp lại trên lĩnh vực tính năng đó.

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

Việc gộp một vùng tính năng vào APEX cũng giúp đơn giản hóa việc gỡ lỗi hoặc hoàn nguyên khi phát hiện thấy hành vi xấu của thiết bị. Ví dụ: nếu hệ thống điện thoại hoạt động kém trong bản dựng mới thì nhà phát triển có thể thử cài đặt triển khai điện thoại cũ hơn APEX trên một thiết bị (không cần flash toàn bộ bản dựng) và xem liệu hoạt động 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ụ

Khái niệm cơ bản

Xem trang Định dạng Tệp APEX chính để biết thông tin chung về APEX, bao gồm các yêu cầu về thiết bị, chi tiết về đị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ẽ làm cho mô-đun APEX trở thành APEX của nhà cung cấp.

apex {
  ..
  vendor: true,
  ..
}

Thư viện nhị phân và chia sẻ

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

Các giao diện gốc ổn định dành cho các phần phụ thuộc APEX của nhà cung cấp bao gồm cc_librarystubs , ndk_library hoặc llndk_library . Những phần phụ thuộc này được loại trừ khỏi quá trình đóng gói và các phần phụ thuộc được ghi lại trong tệp kê khai APEX. Tệp kê khai được xử lý bởi linkerconfig để các phần phụ thuộc gốc bên ngoài có sẵn trong thời gian chạy.

Không giống như các APEX trong phân vùng /system , các APEX của nhà cung cấp thường được gắn với một phiên bản VNĐK cụ thể. Thư viện VNDK đảm bảo tính ổn định của ABI trong bản phát hành, vì vậy chúng tôi có thể coi thư viện VNDK là ổn định và giảm kích thước APEX của nhà cung cấp bằng cách loại trừ chúng khỏi APEX bằng thuộc tính use_vndk_as_stable .

Trong đoạn mã bên dưới, APEX sẽ chứa cả tệp nhị phân ( my_service ) và các phần phụ thuộc không ổn định của nó ( tệp *.so ). Nó sẽ không chứa các thư viện VNĐK, ngay cả khi my_service được xây dựng với các thư viện VNĐK như libbase . Thay vào đó, khi chạy my_service sẽ sử dụng libbase từ thư viện VNĐK do hệ thống cung cấp.

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

Trong đoạn mã bên dưới, APEX sẽ 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 nó (như được mô tả ở trên).

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

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:

Để gói gọn đầy đủ việc triển khai HAL, APEX cũng phải chỉ định mọi đoạn VINTF và tập lệnh init có liên quan.

mảnh VINTF

Các đoạn VINTF có thể được cung cấp từ APEX của nhà cung cấp khi các đoạn này nằm trong etc/vintf của APEX.

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

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

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

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

APEX có thể bao gồm tập lệnh init theo hai cách: (A) tệp văn bản dựng sẵn trong tải trọng APEX hoặc (B) 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"],
  ..
}

Các tập lệnh init trong APEX chỉ có thể có định nghĩa service . Các tập lệnh khởi tạo trong APEX của nhà cung cấp cũng có thể có các lệnh on <property> .

Hãy cẩn thận khi sử dụng on thị. Vì các tập lệnh init 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ể sử dụng được. Sử dụng apex.all.ready=true để thực hiện hành động càng sớm càng tốt.

Phần sụn

Ví dụ:

Nhúng chương trình cơ sở vào APEX của nhà cung cấp với loại mô-đun prebuilt_firmware như sau.

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
  ..
}

Các mô-đun prebuilt_firmware được cài đặt trong thư mục <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 sụn.

file_contexts của APEX phải gắn nhãn chính xác cho bất kỳ mục tải trọng chương trình cơ sở nào để đảm bảo rằng các tệp này có thể được truy cập bởi ueventd khi chạy; thông thường, nhãn vendor_file là đủ. Ví dụ:

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

Mô-đun hạt 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 dựng 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 chính xác cho bất kỳ mục tải trọng mô-đun hạt nhân nào. Ví dụ:

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

Các mô-đun hạt nhân phải được cài đặt rõ ràng. Tập lệnh init ví dụ sau trong phân vùng của nhà cung cấp hiển thị quá trình 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 vào APEX của nhà cung cấp bằ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 tin 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 tìm thấy trên phân vùng của nhà cung cấp dưới dạng các tệp dựng sẵn bên trong APEX của nhà cung cấp và nhiều tệp khác đang được thêm vào.

Ví dụ:

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

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

Ví dụ:

Các 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 có chung tên và khóa APEX, sau đó chọn phiên bản nào được kích hoạt trong mỗi lần khởi động bằng cách sử dụng sysprop 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 việc cài đặt bản sao APEX mới bằng cách sử dụng adb install .

Các trường hợp sử dụng ví dụ:

  • Cài đặt 3 phiên bản của nhà cung cấp wifi HAL APEX: Đội QA có thể chạy thử nghiệm thủ công hoặc tự động bằng một phiên bản, sau đó khởi động lại vào phiên bản khác và chạy lại thử nghiệm, sau đó so sánh kết quả cuối cùng.
  • Cài đặt 2 phiên bản máy ảnh APEX của nhà cung cấp HAL, hiện tạithử nghiệm : Dogfooders 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 để có thể dễ dàng trao đổi lại.

Trong quá trình khởi động, apexd tìm kiếm sysprop theo định dạng cụ thể để kích hoạt phiên bản APEX phù hợp.

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

  • Cấu hình khởi động
    • Được sử dụng để đặt giá trị mặc định, trong BoardConfig.mk .
    • androidboot.vendor.apex.<apex name>
  • Sysprop liên tục
    • Được sử dụng để thay đổi giá trị mặc định, được đặt trên 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 được 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 cấu hình bằ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 thiết bị được khởi động, hãy thay đổi phiên bản đã kích hoạt bằng cách đặt sysprop liên tục:

$ 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ợ cập nhật bootconfig sau khi flash (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";
,

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. Nó cho phép xây dựng 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, chương trình 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 tự động cài đặt trong phân vùng /vendor và được kích hoạt khi chạy bởi apexd giống như APEX trong các phân vùng khác.

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

Mô-đun hóa hình ảnh nhà cung cấp

APEX tạo điều kiện thuận lợi cho việc đóng gói và mô-đun hóa việc triển khai tính năng trên hình ảnh của nhà cung cấp một cách tự nhiên.

Khi hình ảnh nhà cung cấp được xây dựng dưới dạng kết hợp các APEX của nhà cung cấp được xây dựng độc lập, nhà sản xuất thiết bị có thể dễ dàng chọn cách triển khai nhà cung cấp cụ thể mong muốn trên thiết bị của họ. Các nhà sản xuất thậm chí có thể tạo APEX của 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 tùy chỉnh hoàn toàn mới.

Ví dụ: OEM có thể chọn kết hợp thiết bị của họ với APEX triển khai wifi AOSP, APEX triển khai bluetooth SoC và APEX triển khai điện thoại OEM tùy chỉnh.

Nếu không có APEX của nhà cung cấp, việc triển khai có rất nhiều sự phụ thuộc giữa các thành phần của nhà cung cấp đòi hỏi phải có sự 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 tệp cấu hình và thư viện bổ sung) vào APEX với giao diện được xác định rõ ràng tại bất kỳ điểm giao tiếp giữa các tính năng nào, các thành phần khác nhau có thể thay thế cho nhau.

Lặp lại của nhà phát triển

APEX của nhà cung cấp giúp các 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 gói toàn bộ triển khai tính năng, như wifi HAL, bên trong APEX của nhà cung cấp. Sau đó, các nhà phát triển có thể xây dựng và đẩy APEX của nhà cung cấp riêng lẻ để kiểm tra các thay đổi, thay vì xây dựng lại toàn bộ hình ảnh nhà cung cấp.

Điều này giúp đơn giản hóa và tăng tốc chu trình lặp lại của nhà phát triển đối với những nhà phát triển chủ yếu làm việc trong một lĩnh vực tính năng và chỉ muốn lặp lại trên lĩnh vực tính năng đó.

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

Việc gộp một vùng tính năng vào APEX cũng giúp đơn giản hóa việc gỡ lỗi hoặc hoàn nguyên khi phát hiện thấy hành vi xấu của thiết bị. Ví dụ: nếu hệ thống điện thoại hoạt động kém trong bản dựng mới thì nhà phát triển có thể thử cài đặt triển khai điện thoại cũ hơn APEX trên một thiết bị (không cần flash toàn bộ bản dựng) và xem liệu hoạt động 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ụ

Khái niệm cơ bản

Xem trang Định dạng Tệp APEX chính để biết thông tin chung về APEX, bao gồm các yêu cầu về thiết bị, chi tiết về đị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ẽ làm cho mô-đun APEX trở thành APEX của nhà cung cấp.

apex {
  ..
  vendor: true,
  ..
}

Thư viện nhị phân và chia sẻ

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

Các giao diện gốc ổn định dành cho các phần phụ thuộc APEX của nhà cung cấp bao gồm cc_librarystubs , ndk_library hoặc llndk_library . Những phần phụ thuộc này được loại trừ khỏi quá trình đóng gói và các phần phụ thuộc được ghi lại trong tệp kê khai APEX. Tệp kê khai được xử lý bởi linkerconfig để các phần phụ thuộc gốc bên ngoài có sẵn trong thời gian chạy.

Không giống như các APEX trong phân vùng /system , các APEX của nhà cung cấp thường được gắn với một phiên bản VNĐK cụ thể. Thư viện VNDK đảm bảo tính ổn định của ABI trong bản phát hành, vì vậy chúng tôi có thể coi thư viện VNDK là ổn định và giảm kích thước APEX của nhà cung cấp bằng cách loại trừ chúng khỏi APEX bằng thuộc tính use_vndk_as_stable .

Trong đoạn mã bên dưới, APEX sẽ chứa cả tệp nhị phân ( my_service ) và các phần phụ thuộc không ổn định của nó ( tệp *.so ). Nó sẽ không chứa các thư viện VNĐK, ngay cả khi my_service được xây dựng với các thư viện VNĐK như libbase . Thay vào đó, khi chạy my_service sẽ sử dụng libbase từ thư viện VNĐK do hệ thống cung cấp.

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

Trong đoạn mã bên dưới, APEX sẽ 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 nó (như được mô tả ở trên).

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

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:

Để gói gọn đầy đủ việc triển khai HAL, APEX cũng phải chỉ định mọi đoạn VINTF và tập lệnh init có liên quan.

mảnh VINTF

Các đoạn VINTF có thể được cung cấp từ APEX của nhà cung cấp khi các đoạn này nằm trong etc/vintf của APEX.

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

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

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

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

APEX có thể bao gồm tập lệnh init theo hai cách: (A) tệp văn bản dựng sẵn trong tải trọng APEX hoặc (B) 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"],
  ..
}

Các tập lệnh init trong APEX chỉ có thể có định nghĩa service . Các tập lệnh khởi tạo trong APEX của nhà cung cấp cũng có thể có các lệnh on <property> .

Hãy cẩn thận khi sử dụng on thị. Vì các tập lệnh init 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ể sử dụng được. Sử dụng apex.all.ready=true để thực hiện hành động càng sớm càng tốt.

Phần sụn

Ví dụ:

Nhúng chương trình cơ sở vào APEX của nhà cung cấp với loại mô-đun prebuilt_firmware như sau.

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
  ..
}

Các mô-đun prebuilt_firmware được cài đặt trong thư mục <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 sụn.

file_contexts của APEX phải gắn nhãn chính xác cho bất kỳ mục tải trọng chương trình cơ sở nào để đảm bảo rằng các tệp này có thể được truy cập bởi ueventd khi chạy; thông thường, nhãn vendor_file là đủ. Ví dụ:

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

Mô-đun hạt 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 dựng 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 chính xác cho bất kỳ mục tải trọng mô-đun hạt nhân nào. Ví dụ:

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

Các mô-đun hạt nhân phải được cài đặt rõ ràng. Tập lệnh init ví dụ sau trong phân vùng của nhà cung cấp hiển thị quá trình 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 vào APEX của nhà cung cấp bằ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 tin 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 tìm thấy trên phân vùng của nhà cung cấp dưới dạng các tệp dựng sẵn bên trong APEX của nhà cung cấp và nhiều tệp khác đang được thêm vào.

Ví dụ:

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

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

Ví dụ:

Các 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 có chung tên và khóa APEX, sau đó chọn phiên bản nào được kích hoạt trong mỗi lần khởi động bằng cách sử dụng sysprop 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 việc cài đặt bản sao APEX mới bằng cách sử dụng adb install .

Các trường hợp sử dụng ví dụ:

  • Cài đặt 3 phiên bản của nhà cung cấp wifi HAL APEX: Đội QA có thể chạy thử nghiệm thủ công hoặc tự động bằng một phiên bản, sau đó khởi động lại vào phiên bản khác và chạy lại thử nghiệm, sau đó so sánh kết quả cuối cùng.
  • Cài đặt 2 phiên bản máy ảnh APEX của nhà cung cấp HAL, hiện tạithử nghiệm : Dogfooders 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 để có thể dễ dàng trao đổi lại.

Trong quá trình khởi động, apexd tìm kiếm sysprop theo định dạng cụ thể để kích hoạt phiên bản APEX phù hợp.

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

  • Cấu hình khởi động
    • Được sử dụng để đặt giá trị mặc định, trong BoardConfig.mk .
    • androidboot.vendor.apex.<apex name>
  • Sysprop liên tục
    • Được sử dụng để thay đổi giá trị mặc định, được đặt trên 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 được 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 cấu hình bằ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 thiết bị được khởi động, hãy thay đổi phiên bản đã kích hoạt bằng cách đặt sysprop liên tục:

$ 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ợ cập nhật bootconfig sau khi flash (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";
,

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. Nó cho phép xây dựng 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, chương trình 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 tự động cài đặt trong phân vùng /vendor và được kích hoạt khi chạy bởi apexd giống như APEX trong các phân vùng khác.

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

Mô-đun hóa hình ảnh nhà cung cấp

APEX tạo điều kiện thuận lợi cho việc đóng gói và mô-đun hóa việc triển khai tính năng trên hình ảnh của nhà cung cấp một cách tự nhiên.

Khi hình ảnh nhà cung cấp được xây dựng dưới dạng kết hợp các APEX của nhà cung cấp được xây dựng độc lập, nhà sản xuất thiết bị có thể dễ dàng chọn cách triển khai nhà cung cấp cụ thể mong muốn trên thiết bị của họ. Các nhà sản xuất thậm chí có thể tạo APEX của 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 tùy chỉnh hoàn toàn mới.

Ví dụ: OEM có thể chọn kết hợp thiết bị của họ với APEX triển khai wifi AOSP, APEX triển khai bluetooth SoC và APEX triển khai điện thoại OEM tùy chỉnh.

Nếu không có APEX của nhà cung cấp, việc triển khai có rất nhiều sự phụ thuộc giữa các thành phần của nhà cung cấp đòi hỏi phải có sự 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 tệp cấu hình và thư viện bổ sung) vào APEX với giao diện được xác định rõ ràng tại bất kỳ điểm giao tiếp giữa các tính năng nào, các thành phần khác nhau có thể thay thế cho nhau.

Lặp lại của nhà phát triển

APEX của nhà cung cấp giúp các 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 gói toàn bộ triển khai tính năng, như wifi HAL, bên trong APEX của nhà cung cấp. Sau đó, các nhà phát triển có thể xây dựng và đẩy APEX của nhà cung cấp riêng lẻ để kiểm tra các thay đổi, thay vì xây dựng lại toàn bộ hình ảnh nhà cung cấp.

Điều này giúp đơn giản hóa và tăng tốc chu trình lặp lại của nhà phát triển đối với những nhà phát triển chủ yếu làm việc trong một lĩnh vực tính năng và chỉ muốn lặp lại trên lĩnh vực tính năng đó.

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

Việc gộp một vùng tính năng vào APEX cũng giúp đơn giản hóa việc gỡ lỗi hoặc hoàn nguyên khi phát hiện thấy hành vi xấu của thiết bị. Ví dụ: nếu hệ thống điện thoại hoạt động kém trong bản dựng mới thì nhà phát triển có thể thử cài đặt triển khai điện thoại cũ hơn APEX trên một thiết bị (không cần flash toàn bộ bản dựng) và xem liệu hoạt động 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ụ

Khái niệm cơ bản

Xem trang Định dạng Tệp APEX chính để biết thông tin chung về APEX, bao gồm các yêu cầu về thiết bị, chi tiết về đị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ẽ làm cho mô-đun APEX trở thành APEX của nhà cung cấp.

apex {
  ..
  vendor: true,
  ..
}

Thư viện nhị phân và chia sẻ

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

Các giao diện gốc ổn định dành cho các phần phụ thuộc APEX của nhà cung cấp bao gồm cc_librarystubs , ndk_library hoặc llndk_library . Những phần phụ thuộc này được loại trừ khỏi quá trình đóng gói và các phần phụ thuộc được ghi lại trong tệp kê khai APEX. Tệp kê khai được xử lý bởi linkerconfig để các phần phụ thuộc gốc bên ngoài có sẵn trong thời gian chạy.

Không giống như các APEX trong phân vùng /system , các APEX của nhà cung cấp thường được gắn với một phiên bản VNĐK cụ thể. Thư viện VNDK đảm bảo tính ổn định của ABI trong bản phát hành, vì vậy chúng tôi có thể coi thư viện VNDK là ổn định và giảm kích thước APEX của nhà cung cấp bằng cách loại trừ chúng khỏi APEX bằng thuộc tính use_vndk_as_stable .

Trong đoạn mã bên dưới, APEX sẽ chứa cả tệp nhị phân ( my_service ) và các phần phụ thuộc không ổn định của nó ( tệp *.so ). Nó sẽ không chứa các thư viện VNĐK, ngay cả khi my_service được xây dựng với các thư viện VNĐK như libbase . Thay vào đó, khi chạy my_service sẽ sử dụng libbase từ thư viện VNĐK do hệ thống cung cấp.

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

Trong đoạn mã bên dưới, APEX sẽ 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 nó (như được mô tả ở trên).

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

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:

Để gói gọn đầy đủ việc triển khai HAL, APEX cũng phải chỉ định mọi đoạn VINTF và tập lệnh init có liên quan.

mảnh VINTF

Các đoạn VINTF có thể được cung cấp từ APEX của nhà cung cấp khi các đoạn này nằm trong etc/vintf của APEX.

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

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

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

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

APEX có thể bao gồm tập lệnh init theo hai cách: (A) tệp văn bản dựng sẵn trong tải trọng APEX hoặc (B) 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"],
  ..
}

Các tập lệnh init trong APEX chỉ có thể có định nghĩa service . Các tập lệnh khởi tạo trong APEX của nhà cung cấp cũng có thể có các lệnh on <property> .

Hãy cẩn thận khi sử dụng on thị. Vì các tập lệnh init 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ể sử dụng được. Sử dụng apex.all.ready=true để thực hiện hành động càng sớm càng tốt.

Phần sụn

Ví dụ:

Nhúng chương trình cơ sở vào APEX của nhà cung cấp với loại mô-đun prebuilt_firmware như sau.

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
  ..
}

Các mô-đun prebuilt_firmware được cài đặt trong thư mục <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 sụn.

file_contexts của APEX phải gắn nhãn chính xác cho bất kỳ mục tải trọng chương trình cơ sở nào để đảm bảo rằng các tệp này có thể được truy cập bởi ueventd khi chạy; thông thường, nhãn vendor_file là đủ. Ví dụ:

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

Mô-đun hạt 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 dựng 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 chính xác cho bất kỳ mục tải trọng mô-đun hạt nhân nào. Ví dụ:

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

Các mô-đun hạt nhân phải được cài đặt rõ ràng. Tập lệnh init ví dụ sau trong phân vùng của nhà cung cấp hiển thị quá trình 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 vào APEX của nhà cung cấp bằ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 tin 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 tìm thấy trên phân vùng của nhà cung cấp dưới dạng các tệp dựng sẵn bên trong APEX của nhà cung cấp và nhiều tệp khác đang được thêm vào.

Ví dụ:

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

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

Ví dụ:

Các 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 có chung tên và khóa APEX, sau đó chọn phiên bản nào được kích hoạt trong mỗi lần khởi động bằng cách sử dụng sysprop 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 việc cài đặt bản sao APEX mới bằng cách sử dụng adb install .

Các trường hợp sử dụng ví dụ:

  • Cài đặt 3 phiên bản của nhà cung cấp wifi HAL APEX: Đội QA có thể chạy thử nghiệm thủ công hoặc tự động bằng một phiên bản, sau đó khởi động lại vào phiên bản khác và chạy lại thử nghiệm, sau đó so sánh kết quả cuối cùng.
  • Cài đặt 2 phiên bản máy ảnh APEX của nhà cung cấp HAL, hiện tạithử nghiệm : Dogfooders 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 để có thể dễ dàng trao đổi lại.

Trong quá trình khởi động, apexd tìm kiếm sysprop theo định dạng cụ thể để kích hoạt phiên bản APEX phù hợp.

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

  • Cấu hình khởi động
    • Được sử dụng để đặt giá trị mặc định, trong BoardConfig.mk .
    • androidboot.vendor.apex.<apex name>
  • Sysprop liên tục
    • Được sử dụng để thay đổi giá trị mặc định, được đặt trên 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 được 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 cấu hình bằ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 thiết bị được khởi động, hãy thay đổi phiên bản đã kích hoạt bằng cách đặt sysprop liên tục:

$ 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ợ cập nhật bootconfig sau khi flash (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";