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++.so
và libbase.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:
- HAL cảm biến
- Lớp trừu tượng phần cứng (HAL) cho bộ rung
- Lớp trừu tượng phần cứng (HAL) cho Wi-Fi
- Lớp trừu tượng phần cứng (HAL) cho điện thoại
Để đó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ụ:
- XML khai báo tính năng
- Cảm biến có các tệp XML dưới dạng tệp tạo sẵn trong APEX của nhà cung cấp HAL cảm biến
- Tệp cấu hình đầu vào
- Màn hình cảm ứng được định cấu hình là tích hợp sẵn trong APEX của nhà cung cấp chỉ có cấu hình
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
và*.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ại và thử 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>
- Dùng để đặt giá trị mặc định trong
- 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";