Google cam kết thúc đẩy công bằng chủng tộc cho Cộng đồng người da đen. Xem cách thực hiện.

Định dạng tệp APEX

Định dạng vùng chứa Android Pony EXpress (APEX) đã được giới thiệu trong Android 10 và nó được sử dụng trong quy trình cài đặt cho các mô-đun hệ thống cấp thấp hơn. Định dạng này tạo điều kiện thuận lợi cho việc cập nhật các thành phần hệ thống không phù hợp với mô hình ứng dụng Android tiêu chuẩn. Một số thành phần ví dụ là dịch vụ bản địa và các thư viện, các lớp trừu tượng phần cứng ( Hals ), thời gian chạy ( ART ), và thư viện lớp.

Thuật ngữ "APEX" cũng có thể đề cập đến một tệp APEX.

Tiểu sử

Mặc dù Android hỗ trợ cập nhật các mô-đun phù hợp với mô hình ứng dụng tiêu chuẩn (ví dụ: dịch vụ, hoạt động) thông qua ứng dụng trình cài đặt gói (chẳng hạn như ứng dụng Cửa hàng Google Play), việc sử dụng mô hình tương tự cho các thành phần hệ điều hành cấp thấp hơn có những hạn chế sau:

  • Không thể sử dụng mô-đun dựa trên APK sớm trong trình tự khởi động. Trình quản lý gói là kho lưu trữ trung tâm của thông tin về các ứng dụng và chỉ có thể được khởi động từ trình quản lý hoạt động, sẽ sẵn sàng trong giai đoạn sau của quy trình khởi động.
  • Định dạng APK (đặc biệt là tệp kê khai) được thiết kế cho các ứng dụng Android và mô-đun hệ thống không phải lúc nào cũng phù hợp.

Thiết kế

Phần này mô tả thiết kế cấp cao của định dạng tệp APEX và trình quản lý APEX, là một dịch vụ quản lý tệp APEX.

Để biết thêm thông tin về lý do tại sao thiết kế này cho APEX đã được lựa chọn, xem Alternatives xem xét khi phát triển APEX .

Định dạng APEX

Đây là định dạng của tệp APEX.

Định dạng tệp APEX

Định dạng tập tin hình 1. APEX

Ở cấp cao nhất, tệp APEX là tệp zip trong đó tệp được lưu trữ không nén và nằm ở ranh giới 4 KB.

Bốn tệp trong một tệp APEX là:

  • apex_manifest.json
  • AndroidManifest.xml
  • apex_payload.img
  • apex_pubkey

Các apex_manifest.json tập tin chứa tên gói và phiên bản, trong đó xác định một tập tin APEX.

Các AndroidManifest.xml tập tin cho phép các tập tin APEX đến việc sử dụng các công cụ apk liên quan đến cơ sở hạ tầng như ADB, PackageManager, và các ứng dụng gói cài đặt (chẳng hạn như Play Store). Ví dụ, các tập tin APEX có thể sử dụng một công cụ hiện có như aapt kiểm tra siêu dữ liệu cơ bản từ tập tin. Tệp chứa tên gói và thông tin phiên bản. Những thông tin này thường là cũng có sẵn trong apex_manifest.json .

apex_manifest.json được khuyến khích hơn AndroidManifest.xml cho mã mới và hệ thống mà đối phó với APEX. AndroidManifest.xml có thể chứa thông tin nhắm mục tiêu bổ sung có thể được sử dụng bởi các công cụ xuất bản ứng dụng hiện tại.

apex_payload.img là một hình ảnh hệ thống tập tin ext4 được hỗ trợ bởi dm-verity. Hình ảnh được gắn trong thời gian chạy thông qua thiết bị lặp lại. Cụ thể, cây băm và khối siêu dữ liệu được tạo ra bằng cách sử dụng libavb thư viện. Tải trọng hệ thống tệp không được phân tích cú pháp (vì hình ảnh phải được gắn tại chỗ). Tập tin thông thường được bao gồm bên trong apex_payload.img tập tin.

apex_pubkey là khóa công khai sử dụng để đăng các hình ảnh hệ thống tập tin. Trong thời gian chạy, khóa này đảm bảo rằng APEX đã tải xuống được ký với cùng một thực thể ký cùng một APEX trong các phân vùng tích hợp sẵn.

Người quản lý APEX

Người quản lý APEX (hoặc apexd ) là một độc lập quá trình bản địa chịu trách nhiệm kiểm tra, cài đặt, và gỡ bỏ cài đặt các file APEX. Quá trình này được khởi chạy và sẵn sàng sớm trong trình tự khởi động. File APEX thường được cài đặt sẵn trên thiết bị dưới /system/apex . Trình quản lý APEX mặc định sử dụng các gói này nếu không có bản cập nhật nào.

Quá trình cập nhật của một APEX sử dụng lớp PackageManager và là như sau.

  1. Tệp APEX được tải xuống qua ứng dụng trình cài đặt gói, ADB hoặc nguồn khác.
  2. Trình quản lý gói bắt đầu quy trình cài đặt. Khi nhận ra rằng tệp là APEX, trình quản lý gói chuyển giao quyền kiểm soát cho trình quản lý APEX.
  3. Người quản lý APEX xác minh tệp APEX.
  4. Nếu tệp APEX được xác minh, cơ sở dữ liệu nội bộ của trình quản lý APEX được cập nhật để phản ánh rằng tệp APEX được kích hoạt ở lần khởi động tiếp theo.
  5. Người yêu cầu cài đặt nhận được một chương trình phát sóng khi xác minh gói thành công.
  6. Để tiếp tục cài đặt, hệ thống phải được khởi động lại.
  7. Ở lần khởi động tiếp theo, trình quản lý APEX khởi động, đọc cơ sở dữ liệu nội bộ và thực hiện các thao tác sau đối với từng tệp APEX được liệt kê:

    1. Xác minh tệp APEX.
    2. Tạo thiết bị lặp lại từ tệp APEX.
    3. Tạo thiết bị chặn trình ánh xạ thiết bị trên đầu thiết bị lặp lại.
    4. Gắn kết các thiết bị khối thiết bị mapper vào một con đường duy nhất (ví dụ, /apex/ name @ ver ).

Khi tất cả các tệp APEX được liệt kê trong cơ sở dữ liệu nội bộ được gắn kết, trình quản lý APEX cung cấp dịch vụ liên kết cho các thành phần hệ thống khác để truy vấn thông tin về các tệp APEX đã cài đặt. Ví dụ: các thành phần hệ thống khác có thể truy vấn danh sách các tệp APEX được cài đặt trong thiết bị hoặc truy vấn đường dẫn chính xác nơi một APEX cụ thể được gắn kết, để các tệp có thể được truy cập.

Tệp APEX là tệp APK

File APEX là các tập tin apk hợp lệ vì họ đã đăng zip lưu trữ (sử dụng sơ đồ chữ ký APK) chứa một AndroidManifest.xml file. Điều này cho phép các tệp APEX sử dụng cơ sở hạ tầng cho các tệp APK, chẳng hạn như ứng dụng trình cài đặt gói, tiện ích ký và trình quản lý gói.

Các AndroidManifest.xml tập tin bên trong một tập tin APEX là tối thiểu, bao gồm các gói name , versionCode , và tùy chọn targetSdkVersion , minSdkVersion , và maxSdkVersion để nhắm mục tiêu hạt mịn. Thông tin này cho phép phân phối tệp APEX qua các kênh hiện có như ứng dụng trình cài đặt gói và ADB.

Các loại tệp được hỗ trợ

Định dạng APEX hỗ trợ các loại tệp sau:

  • Các lib được chia sẻ tự nhiên
  • Các tệp thực thi gốc
  • Tệp JAR
  • Hồ sơ dữ liệu
  • Định cấu hình tệp

Điều này không có nghĩa là APEX có thể cập nhật tất cả các loại tệp này. Việc một loại tệp có thể được cập nhật hay không phụ thuộc vào nền tảng và mức độ ổn định của các định nghĩa về giao diện cho các loại tệp.

Đang ký

Các tệp APEX được ký theo hai cách. Thứ nhất, apex_payload.img (đặc biệt là các mô tả vbmeta nối vào apex_payload.img ) tập tin được ký kết với một chìa khóa. Sau đó, toàn bộ APEX được ký kết bằng cách sử dụng sơ đồ chữ ký APK v3 . Hai khóa khác nhau được sử dụng trong quá trình này.

Ở phía thiết bị, một khóa công khai tương ứng với khóa cá nhân được sử dụng để ký bộ mô tả vbmeta được cài đặt. Trình quản lý APEX sử dụng khóa công khai để xác minh các APEX được yêu cầu cài đặt. Mỗi APEX phải được ký bằng các khóa khác nhau và được thực thi cả tại thời điểm xây dựng và thời gian chạy.

APEX trong các phân vùng tích hợp

File APEX có thể được đặt trong xây dựng trong các phân vùng như /system . Phân vùng đã vượt quá dm-verity, vì vậy các tệp APEX được gắn trực tiếp qua thiết bị loopback.

Nếu APEX có trong phân vùng dựng sẵn, APEX có thể được cập nhật bằng cách cung cấp gói APEX có cùng tên gói và lớn hơn hoặc bằng mã phiên bản. APEX mới được lưu trữ trong /data và, tương tự như gói ứng dụng, phiên bản mới được cài đặt phiên bản bóng đã hiện diện trong phân vùng built-in. Nhưng không giống như APK, phiên bản APEX mới được cài đặt chỉ được kích hoạt sau khi khởi động lại.

Yêu cầu về nhân

Để hỗ trợ mô-đun dòng chính APEX trên thiết bị Android, cần có các tính năng nhân Linux sau: trình điều khiển vòng lặp và dm-verity. Trình điều khiển loopback gắn hình ảnh hệ thống tệp trong mô-đun APEX và dm-verity xác minh mô-đun APEX.

Hiệu suất của trình điều khiển loopback và dm-verity rất quan trọng trong việc đạt được hiệu suất hệ thống tốt khi sử dụng mô-đun APEX.

Các phiên bản hạt nhân được hỗ trợ

Các mô-đun dòng chính APEX được hỗ trợ trên các thiết bị sử dụng phiên bản hạt nhân 4.4 trở lên. Các thiết bị mới khởi chạy với Android 10 trở lên phải sử dụng phiên bản hạt nhân 4.9 trở lên để hỗ trợ mô-đun APEX.

Các bản vá nhân bắt buộc

Các bản vá lỗi hạt nhân cần thiết để hỗ trợ mô-đun APEX được bao gồm trong cây chung của Android. Để nhận các bản vá hỗ trợ APEX, hãy sử dụng phiên bản mới nhất của cây chung Android.

Phiên bản hạt nhân 4.4

Phiên bản này chỉ được hỗ trợ cho các thiết bị được nâng cấp từ Android 9 lên Android 10 và muốn hỗ trợ mô-đun APEX. Để có được các bản vá lỗi cần thiết, một xuống merge từ android-4.4 chi nhánh được khuyến khích mạnh mẽ. Sau đây là danh sách các bản vá lỗi riêng lẻ cần thiết cho phiên bản hạt nhân 4.4.

  • THƯỢNG LƯU: loop: thêm ioctl để thay đổi kích thước khối logic ( 4.4 )
  • Backport: block / loop: set hw_sectors ( 4.4 )
  • THƯỢNG LƯU: loop: Add LOOP_SET_BLOCK_SIZE trong compat ioctl ( 4.4 )
  • ANDROID: mnt: Fix next_descendent ( 4.4 )
  • ANDROID: mnt: remount nên tuyên truyền để nô lệ nô lệ ( 4.4 )
  • ANDROID: mnt: Tuyên truyền đi ngược lại một cách chính xác ( 4.4 )
  • Hoàn nguyên "ANDROID: dm verity: thêm kích thước prefetch tối thiểu" ( 4.4 )
  • THƯỢNG LƯU: loop: thả cache nếu bù đắp hoặc BLOCK_SIZE được thay đổi ( 4.4 )

Phiên bản hạt nhân 4.9 / 4.14 / 4.19

Để có được các bản vá lỗi cần thiết cho các phiên bản kernel 4.9 / 4.14 / 4.19, xuống-merge từ android-common chi nhánh.

Các tùy chọn cấu hình hạt nhân bắt buộc

Danh sách sau đây hiển thị các yêu cầu cấu hình cơ bản để hỗ trợ mô-đun APEX đã được giới thiệu trong Android 10. Các mục có dấu hoa thị (*) là các yêu cầu hiện có từ Android 9 trở xuống.

(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support

Yêu cầu tham số dòng lệnh nhân

Để hỗ trợ APEX, hãy đảm bảo các tham số dòng lệnh hạt nhân đáp ứng các yêu cầu sau:

  • loop.max_loop KHÔNG phải thiết lập
  • loop.max_part phải <= 8

Xây dựng APEX

Phần này mô tả cách tạo APEX bằng hệ thống xây dựng Android. Sau đây là một ví dụ về Android.bp cho một APEX tên apex.test .

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    // libc.so and libcutils.so are included in the apex
    native_shared_libs: ["libc", "libcutils"],
    binaries: ["vold"],
    java_libs: ["core-all"],
    prebuilts: ["my_prebuilt"],
    compile_multilib: "both",
    key: "apex.test.key",
    certificate: "platform",
}

apex_manifest.json dụ:

{
  "name": "com.android.example.apex",
  "version": 1
}

file_contexts dụ:

(/.*)?           u:object_r:system_file:s0
/sub(/.*)?       u:object_r:sub_file:s0
/sub/file3       u:object_r:file3_file:s0

Loại tệp và vị trí trong APEX

Loại tệp Vị trí ở APEX
Thư viện được chia sẻ /lib/lib64 ( /lib/arm cho cánh tay dịch trong x86)
Thực thi /bin
Thư viện Java /javalib
Bản dựng sẵn /etc

Phụ thuộc bắc cầu

Các tệp APEX tự động bao gồm các phụ thuộc bắc cầu của các lib hoặc tệp thực thi được chia sẻ gốc. Ví dụ, nếu libFoo phụ thuộc vào libBar , hai libs được bao gồm khi chỉ libFoo được liệt kê trong native_shared_libs tài sản.

Xử lý nhiều ABI

Cài đặt native_shared_libs tài sản cho cả hai giao diện ứng dụng nhị phân tiểu học và trung (Abis) của thiết bị. Nếu APEX nhắm mục tiêu đến các thiết bị có một ABI duy nhất (nghĩa là chỉ 32 bit hoặc chỉ 64 bit), thì chỉ các thư viện có ABI tương ứng mới được cài đặt.

Cài đặt binaries tài sản duy nhất cho ABI chính của thiết bị như mô tả dưới đây:

  • Nếu thiết bị chỉ là 32 bit, thì chỉ có biến thể 32 bit của nhị phân được cài đặt.
  • Nếu thiết bị chỉ là 64 bit, thì chỉ có biến thể 64 bit của nhị phân được cài đặt.

Để thêm kiểm soát hạt mịn trên Abis của các thư viện nguồn gốc và mã nhị phân, sử dụng multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] tài sản.

  • first : Phù hợp với ABI chính của thiết bị. Đây là mặc định cho mã nhị phân.
  • lib32 : Phù hợp với 32-bit ABI của thiết bị, nếu được hỗ trợ.
  • lib64 : Phù hợp với 64-bit ABI của thiết bị, nó hỗ trợ.
  • prefer32 : Phù hợp với 32-bit ABI của thiết bị, nếu được hỗ trợ. Nếu ABI 32 bit không được hỗ trợ, hãy khớp với ABI 64 bit.
  • both : Trận cả Abis. Đây là mặc định cho native_shared_libraries .

Các java , libraries , và prebuilts tính là ABI-agnostic.

Ví dụ này dành cho thiết bị hỗ trợ 32/64 và không thích 32:

apex {
    // other properties are omitted
    native_shared_libs: ["libFoo"], // installed for 32 and 64
    binaries: ["exec1"], // installed for 64, but not for 32
    multilib: {
        first: {
            native_shared_libs: ["libBar"], // installed for 64, but not for 32
            binaries: ["exec2"], // same as binaries without multilib.first
        },
        both: {
            native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
            binaries: ["exec3"], // installed for 32 and 64
        },
        prefer32: {
            native_shared_libs: ["libX"], // installed for 32, but not for 64
        },
        lib64: {
            native_shared_libs: ["libY"], // installed for 64, but not for 32
        },
    },
}

ký vbmeta

Ký mỗi APEX bằng các khóa khác nhau. Khi một khoá mới là cần thiết, tạo ra một công-tư cặp khóa và thực hiện một apex_key module. Sử dụng key tài sản ký APEX sử dụng chìa khóa. Khóa công khai được tự động đưa vào APEX với tên avb_pubkey .

# create an rsa key pair
openssl genrsa -out foo.pem 4096

# extract the public key from the key pair
avbtool extract_public_key --key foo.pem --output foo.avbpubkey

# in Android.bp
apex_key {
    name: "apex.test.key",
    public_key: "foo.avbpubkey",
    private_key: "foo.pem",
}

Trong ví dụ trên, tên của khóa công khai ( foo ) trở thành ID của chìa khóa. ID của khóa được sử dụng để ký APEX được viết trong APEX. Khi chạy, apexd thẩm tra các APEX sử dụng một khóa công khai với cùng một ID trong thiết bị.

Ký ZIP

Ký các APEX giống như cách bạn ký các APK. Ký APEXes hai lần; một lần cho các hệ thống tập tin nhỏ ( apex_payload.img tập tin) và một lần cho toàn bộ tập tin.

Để đăng ký một APEX tại file-level, thiết lập các certificate sở hữu trong một trong ba cách sau:

  • Không được thiết lập: Nếu không có giá trị được thiết lập, APEX được ký với chứng tọa lạc tại PRODUCT_DEFAULT_DEV_CERTIFICATE . Nếu không có lá cờ được thiết lập, giá trị mặc định đường dẫn đến build/target/product/security/testkey .
  • <name> : Các APEX được ký với <name> Giấy chứng nhận trong cùng thư mục với PRODUCT_DEFAULT_DEV_CERTIFICATE .
  • :<name> : Các APEX được ký với chứng chỉ được xác định bởi các module Soong tên <name> . Mô-đun chứng chỉ có thể được định nghĩa như sau.
android_app_certificate {
    name: "my_key_name",
    certificate: "dir/cert",
    // this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}

Cài đặt APEX

Để cài đặt APEX, hãy sử dụng ADB.

adb install apex_file_name
adb reboot

Sử dụng APEX

Sau khi khởi động lại, APEX được gắn vào /apex/<apex_name>@<version> thư mục. Nhiều phiên bản của cùng một APEX có thể được gắn cùng một lúc. Trong số những người gắn kết những con đường, một trong đó tương ứng với phiên bản mới nhất là ràng buộc gắn vào /apex/<apex_name> .

Khách hàng có thể sử dụng đường dẫn được gắn kết để đọc hoặc thực thi các tệp từ APEX.

Các APEX thường được sử dụng như sau:

  1. Một OEM hay ODM sự cài đặt trước một APEX dưới /system/apex khi thiết bị được vận chuyển.
  2. File trong APEX được truy cập thông qua /apex/<apex_name>/ con đường.
  3. Khi một phiên bản cập nhật của APEX được cài đặt trong /data/apex , các điểm đường dẫn đến APEX mới sau khi khởi động lại.

Cập nhật dịch vụ bằng APEX

Để cập nhật một dịch vụ bằng APEX:

  1. Đánh dấu dịch vụ trong phân vùng hệ thống là có thể cập nhật được. Thêm tùy chọn updatable định nghĩa dịch vụ.

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. Tạo mới .rc tập tin cho dịch vụ cập nhật. Sử dụng override tùy chọn để xác định lại các dịch vụ hiện có.

    /apex/my.apex@1/etc/init.rc:
    
    service myservice /apex/my.apex@1/bin/myservice
        class core
        user system
        ...
        override
    

Định nghĩa dịch vụ chỉ có thể được xác định trong .rc tập tin của một APEX. Trình kích hoạt hành động không được hỗ trợ trong APEX.

Nếu một dịch vụ được đánh dấu là có thể cập nhật bắt đầu trước khi các APEX được kích hoạt, thì việc khởi động sẽ bị trì hoãn cho đến khi quá trình kích hoạt các APEX hoàn tất.

Cấu hình hệ thống để hỗ trợ cập nhật APEX

Thiết lập thuộc tính hệ thống sau đây để true để hỗ trợ cập nhật tập tin APEX.

<device.mk>:

PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true

BoardConfig.mk:
TARGET_FLATTEN_APEX := false

hoặc chỉ

<device.mk>:

$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)

APEX phẳng

Đối với các thiết bị cũ, đôi khi không thể hoặc không thể cập nhật hạt nhân cũ để hỗ trợ đầy đủ APEX. Ví dụ, hạt nhân có thể đã được xây dựng mà không CONFIG_BLK_DEV_LOOP=Y , mà là rất quan trọng để gắn hình ảnh hệ thống tập tin bên trong một APEX.

APEX phẳng là một APEX được xây dựng đặc biệt có thể được kích hoạt trên các thiết bị có nhân kế thừa. Các tệp trong APEX phẳng được cài đặt trực tiếp vào một thư mục trong phân vùng tích hợp sẵn. Ví dụ, lib/libFoo.so trong một phẳng APEX my.apex được cài đặt để /system/apex/my.apex/lib/libFoo.so .

Việc kích hoạt APEX phẳng không liên quan đến thiết bị vòng lặp. Toàn bộ thư mục /system/apex/my.apex được trực tiếp ràng buộc gắn vào /apex/name@ver .

Không thể cập nhật các APEX đã làm phẳng bằng cách tải xuống các phiên bản cập nhật của APEX từ mạng vì không thể làm phẳng các APEX đã tải xuống. Các APEX phẳng chỉ có thể được cập nhật thông qua OTA thông thường.

APEX phẳng là cấu hình mặc định. Điều này có nghĩa là tất cả các APEX đều được làm phẳng theo mặc định trừ khi bạn định cấu hình thiết bị của mình một cách rõ ràng để tạo các APEX không phẳng để hỗ trợ cập nhật APEX (như đã giải thích ở trên).

KHÔNG hỗ trợ trộn các APEX phẳng và không phẳng trong một thiết bị. Các APEX trong một thiết bị phải là tất cả không phẳng hoặc tất cả đều phẳng. Điều này đặc biệt quan trọng khi vận chuyển các bản dựng sẵn APEX đã ký trước cho các dự án như Mainline. Các APEX không được chỉ định trước (nghĩa là được xây dựng từ nguồn) cũng phải không được làm phẳng và được ký bằng các khóa thích hợp. Thiết bị này nên kế thừa từ updatable_apex.mk như được giải thích trong Cập nhật một dịch vụ với một APEX .

APEX được nén

Android 12 trở lên có tính năng nén APEX để giảm tác động lưu trữ của các gói APEX có thể cập nhật. Sau khi bản cập nhật cho APEX được cài đặt, mặc dù phiên bản cài đặt sẵn của nó không được sử dụng nữa nhưng nó vẫn chiếm cùng một lượng dung lượng. Không gian bị chiếm dụng đó vẫn không có sẵn.

APEX nén giảm thiểu tác động lưu trữ này bằng cách sử dụng một bộ nén cao của file APEX trên phân vùng chỉ đọc (chẳng hạn như /system phân vùng). Android 12 trở lên sử dụng thuật toán nén zip DEFLATE.

Nén không cung cấp tối ưu hóa cho những điều sau:

  • Bootstrap APEXes được yêu cầu gắn rất sớm trong trình tự khởi động.

  • APEXes không thể cập nhật. Nén là chỉ có lợi nếu một phiên bản cập nhật của một APEX được cài đặt trên /data phân vùng. Một danh sách đầy đủ của các đỉnh có thể cập nhật có sẵn trên Modular hệ thống Components trang.

  • APEXes libs được chia sẻ động. Kể từ apexd luôn kích hoạt cả hai phiên bản của các đỉnh như vậy (cài đặt sẵn và nâng cấp), nén chúng không thêm giá trị.

Định dạng tệp APEX được nén

Đây là định dạng của tệp APEX nén.

Diagram shows the format of a compressed APEX file

Định dạng tập tin hình 2. Nén APEX

Ở cấp cao nhất, tệp APEX được nén là tệp zip chứa tệp đỉnh ban đầu ở dạng xì hơi với mức nén là 9 và với các tệp khác được lưu trữ không nén.

Bốn tệp bao gồm một tệp APEX:

  • original_apex : xì hơi với mức độ nén của 9 Đây là bản gốc, không nén tập tin APEX .
  • apex_manifest.pb : lưu trữ chỉ
  • AndroidManifest.xml : lưu trữ chỉ
  • apex_pubkey : lưu trữ chỉ

Các apex_manifest.pb , AndroidManifest.xml , và apex_pubkey file là bản sao các tập tin tương ứng của họ trong original_apex .

Xây dựng APEX nén

Nén APEX thể được xây dựng bằng cách sử dụng apex_compression_tool.py công cụ nằm ở system/apex/tools .

Một số tham số liên quan đến nén APEX có sẵn trong hệ thống xây dựng.

Trong Android.bp liệu một tập tin APEX là nén được điều khiển bởi compressible bất động sản:

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    compressible: true,
}

Một PRODUCT_COMPRESSED_APEX điều khiển cờ sản phẩm cho dù a system image xây dựng từ nguồn phải chứa các tập tin nén APEX.

Đối với thí nghiệm địa phương bạn có thể buộc một xây dựng để các đỉnh nén bằng cách thiết lập OVERRIDE_PRODUCT_COMPRESSED_APEX= để true .

Nén APEX tập tin được tạo bởi hệ thống xây dựng có .capex mở rộng. Phần mở rộng giúp bạn dễ dàng phân biệt giữa các phiên bản nén và không nén của tệp APEX.

Các thuật toán nén được hỗ trợ

Android 12 chỉ hỗ trợ nén deflate-zip.

Kích hoạt tệp APEX nén trong khi khởi động

Trước khi một APEX nén có thể được kích hoạt, original_apex tập tin bên trong nó giải nén vào /data/apex/decompressed thư mục. Kết quả giải nén tập tin APEX được cứng liên quan đến /data/apex/active thư mục.

Hãy coi ví dụ sau như một minh họa của quá trình được mô tả ở trên.

Cân nhắc /system/apex/com.android.foo.capex như một APEX nén được kích hoạt, với mã phiên bản 37.

  1. Các original_apex tập tin bên trong /system/apex/com.android.foo.capex được giải nén vào /data/apex/decompressed/com.android.foo@37.apex .
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex được thực hiện để xác minh rằng nó có một nhãn SELinux đúng.
  3. Xác minh kiểm tra được thực hiện trên /data/apex/decompressed/com.android.foo@37.apex để đảm bảo tính hợp lệ của nó: apexd kiểm tra khóa công khai gói trong /data/apex/decompressed/com.android.foo@37.apex để xác minh rằng nó tương đương với một gói trong /system/apex/com.android.foo.capex .
  4. Các /data/apex/decompressed/com.android.foo@37.apex tập tin là khó khăn liên quan đến /data/apex/active/com.android.foo@37.apex thư mục.
  5. Sự hoạt Logic thường xuyên cho các tập tin nén APEX được thực hiện trên /data/apex/active/com.android.foo@37.apex .

Tương tác với OTA

Các tệp APEX được nén có tác động đến việc phân phối và ứng dụng OTA. Vì bản cập nhật OTA có thể chứa tệp APEX nén với cấp phiên bản cao hơn so với những gì đang hoạt động trên thiết bị, nên phải dành một lượng dung lượng trống nhất định trước khi thiết bị được khởi động lại để áp dụng bản cập nhật OTA.

Để hỗ trợ các hệ thống OTA, apexd cho thấy hai API binder:

  • calculateSizeForCompressedApex - tính toán kích thước cần thiết để giải nén file APEX trong một gói OTA. Điều này có thể được sử dụng để xác minh rằng một thiết bị có đủ dung lượng trước khi một OTA được tải xuống.
  • reserveSpaceForCompressedApex - dự trữ không gian trên đĩa để sử dụng trong tương lai bằng apexd cho giải nén file APEX nén bên trong gói OTA.

Trong trường hợp của một bản cập nhật A / B OTA, apexd nỗ lực giải nén ở chế độ nền như một phần của postinstall OTA thói quen. Nếu giải nén bị lỗi, apexd thực hiện việc giải nén trong khi khởi động áp dụng bản cập nhật OTA.

Các giải pháp thay thế được xem xét khi phát triển APEX

Dưới đây là một số tùy chọn mà AOSP đã xem xét khi thiết kế định dạng tệp APEX và tại sao chúng được bao gồm hoặc loại trừ.

Hệ thống quản lý gói thông thường

Bản phân phối Linux có hệ thống quản lý gói như dpkgrpm , đó là mạnh mẽ, trưởng thành, và mạnh mẽ. Tuy nhiên, chúng không được sử dụng cho APEX vì chúng không thể bảo vệ các gói sau khi cài đặt. Việc xác minh chỉ được thực hiện khi các gói đang được cài đặt. Những kẻ tấn công có thể phá vỡ tính toàn vẹn của các gói đã cài đặt, không được chú ý. Đây là một hồi quy dành cho Android trong đó tất cả các thành phần hệ thống được lưu trữ trong các hệ thống tệp chỉ đọc có tính toàn vẹn được bảo vệ bởi dm-verity cho mọi I / O. Mọi hành vi giả mạo thành phần hệ thống đều phải bị cấm hoặc có thể phát hiện được để thiết bị có thể từ chối khởi động nếu bị xâm phạm.

dm-crypt cho tính toàn vẹn

Các tập tin trong một container APEX là từ tích hợp các phân vùng (ví dụ, các /system phân vùng) được bảo vệ bởi dm-verity, nơi bất kỳ sửa đổi để các tập tin bị cấm ngay cả sau khi phân vùng được gắn kết. Để cung cấp cùng một mức độ bảo mật cho các tệp, tất cả các tệp trong APEX được lưu trữ trong một hình ảnh hệ thống tệp được ghép nối với cây băm và bộ mô tả vbmeta. Nếu không có dm-verity, một APEX trong /data phân vùng dễ bị thay đổi ngoài ý muốn được thực hiện sau khi nó được xác minh và cài đặt.

Trong thực tế, các /data phân vùng cũng được bảo vệ bởi lớp mã hóa như dm-crypt. Mặc dù điều này cung cấp một số mức độ bảo vệ chống lại sự giả mạo, mục đích chính của nó là quyền riêng tư, không phải tính toàn vẹn. Khi một tăng tấn công truy cập vào các /data phân vùng, có thể có không có bảo vệ hơn nữa, và điều này một lần nữa là một hồi quy so với tất cả các thành phần hệ thống đang trong /system phân vùng. Cây băm bên trong tệp APEX cùng với dm-verity cung cấp cùng một mức độ bảo vệ nội dung.

Chuyển hướng đường dẫn từ / system đến / apex

Hệ thống file thành phần đóng gói trong một APEX có thể truy cập thông qua con đường mới như /apex/<name>/lib/libfoo.so . Khi các tập tin là một phần của /system phân vùng, họ đã truy cập qua đường dẫn như /system/lib/libfoo.so . Ứng dụng khách của tệp APEX (tệp APEX khác hoặc nền tảng) phải sử dụng các đường dẫn mới. Bạn có thể cần cập nhật mã hiện có do thay đổi đường dẫn.

Mặc dù là một cách để tránh những thay đổi đường dẫn là để che phủ các nội dung tập tin trong một tập tin APEX vào /system phân vùng, nhóm Android đã quyết định không để các tệp lớp phủ trên /system phân vùng vì điều này có thể ảnh hưởng đến hiệu suất như số lượng file được overlayed ( thậm chí có thể xếp chồng lên nhau) tăng lên.

Một lựa chọn khác là để chiếm quyền điều khiển các chức năng tập tin truy cập như open , stat , và readlink , do đó đường dẫn bắt đầu với /system đã được chuyển hướng đến đường dẫn tương ứng của họ dưới /apex . Nhóm Android đã loại bỏ tùy chọn này vì không thể thay đổi tất cả các chức năng chấp nhận đường dẫn. Ví dụ: một số ứng dụng liên kết tĩnh Bionic, ứng dụng này thực hiện các chức năng. Trong những trường hợp như vậy, những ứng dụng đó không được chuyển hướng.