Bản cập nhật hệ thống động

Cập nhật hệ thống động (DSU) cho phép bạn tạo hình ảnh hệ thống Android mà người dùng có thể tải xuống từ Internet và dùng thử mà không có nguy cơ làm hỏng hình ảnh hệ thống hiện tại. Tài liệu này mô tả cách hỗ trợ DSU.

Yêu cầu hạt nhân

Xem Triển khai phân vùng động để biết các yêu cầu về kernel.

Ngoài ra, DSU còn dựa vào tính năng kernel-mapper-verity (dm-verity) để xác minh hình ảnh hệ thống Android. Vì vậy, bạn phải kích hoạt các cấu hình kernel sau:

  • CONFIG_DM_VERITY=y
  • CONFIG_DM_VERITY_FEC=y

Yêu cầu phân vùng

Bắt đầu từ Android 11, DSU yêu cầu phân vùng /data để sử dụng hệ thống tệp F2FS hoặc ext4. F2FS mang lại hiệu suất tốt hơn và được khuyên dùng, nhưng sự khác biệt sẽ không đáng kể.

Dưới đây là một số ví dụ về thời gian cập nhật hệ thống động với thiết bị Pixel:

  • Sử dụng F2FS:
    • 109s, người dùng 8G, hệ thống 867M, loại hệ thống tệp: F2FS: mã hóa=aes-256-xts:aes-256-cts
    • 104s, người dùng 8G, hệ thống 867M, loại hệ thống tệp: F2FS: mã hóa=ice
  • Sử dụng ext4:
    • 135s, người dùng 8G, hệ thống 867M, loại hệ thống tệp: ext4: mã hóa=aes-256-xts:aes-256-cts

Nếu nền tảng của bạn mất nhiều thời gian hơn, bạn có thể muốn kiểm tra xem cờ gắn kết có chứa bất kỳ cờ nào giúp ghi “đồng bộ hóa” hay không, hoặc bạn có thể chỉ định rõ ràng cờ “không đồng bộ” để có hiệu suất tốt hơn.

Cần có phân vùng metadata (16 MB hoặc lớn hơn) để lưu trữ dữ liệu liên quan đến hình ảnh đã cài đặt. Nó phải được gắn trong giai đoạn gắn kết đầu tiên.

Phân vùng userdata phải sử dụng hệ thống tệp F2FS hoặc ext4. Khi sử dụng F2FS, hãy bao gồm tất cả các bản vá liên quan đến F2FS có sẵn trong nhân chung của Android .

DSU được phát triển và thử nghiệm với kernel/common 4.9. Bạn nên sử dụng kernel 4.9 trở lên cho tính năng này.

Hành vi HAL của nhà cung cấp

Thợ dệt HAL

Weaver HAL cung cấp một số lượng khe cắm cố định để lưu trữ khóa người dùng. DSU sử dụng thêm hai khe khóa. Nếu OEM có HAL dệt, nó cần có đủ khe cắm cho hình ảnh hệ thống chung (GSI) và hình ảnh máy chủ.

Người gác cổng HAL

Gatekeeper HAL cần hỗ trợ các giá trị USER_ID lớn, vì GSI bù UID cho HAL bằng +1000000.

Xác minh khởi động

Nếu bạn muốn hỗ trợ khởi động Hình ảnh GSI của Nhà phát triểntrạng thái LOCKED mà không tắt khả năng khởi động đã được xác minh, hãy bao gồm các khóa GSI của Nhà phát triển bằng cách thêm dòng sau vào tệp device/<device_name>/device.mk :

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

Bảo vệ khôi phục

Khi sử dụng DSU, hình ảnh hệ thống Android được tải xuống phải mới hơn hình ảnh hệ thống hiện tại trên thiết bị. Điều này được thực hiện bằng cách so sánh các cấp độ bản vá bảo mật trong bộ mô tả thuộc tính AVB Khởi động được xác minh Android (AVB) của cả hai hình ảnh hệ thống: Prop: com.android.build.system.security_patch -> '2019-04-05' .

Đối với các thiết bị không sử dụng AVB, hãy đưa mức vá bảo mật của image hệ thống hiện tại vào kernel cmdline hoặc bootconfig bằng bootloader: androidboot.system.security_patch=2019-04-05 .

Yêu cầu phần cứng

Khi bạn khởi chạy một phiên bản DSU, hai tệp tạm thời sẽ được phân bổ:

  • Phân vùng hợp lý để lưu trữ GSI.img (1~1,5 G)
  • Phân vùng /data trống 8 GB làm hộp cát để chạy GSI

Chúng tôi khuyên bạn nên đặt trước ít nhất 10 GB dung lượng trống trước khi khởi chạy phiên bản DSU. DSU cũng hỗ trợ phân bổ từ thẻ SD. Khi có thẻ SD, thẻ này có mức độ ưu tiên cao nhất để phân bổ. Hỗ trợ thẻ SD rất quan trọng đối với các thiết bị có công suất thấp hơn và có thể không có đủ bộ nhớ trong. Khi có thẻ SD, hãy đảm bảo thẻ đó không được chấp nhận. DSU không hỗ trợ thẻ SD được chấp nhận .

Giao diện người dùng có sẵn

Bạn có thể khởi chạy DSU bằng cách sử dụng adb , ứng dụng OEM hoặc trình tải DSU chỉ bằng một cú nhấp chuột (trong Android 11 trở lên).

Khởi chạy DSU bằng adb

Để khởi chạy DSU bằng adb, hãy nhập các lệnh sau:

$ simg2img out/target/product/.../system.img system.raw
$ gzip -c system.raw > system.raw.gz
$ adb push system.raw.gz /storage/emulated/0/Download
$ adb shell am start-activity \
-n com.android.dynsystem/com.android.dynsystem.VerificationActivity  \
-a android.os.image.action.START_INSTALL    \
-d file:///storage/emulated/0/Download/system.raw.gz  \
--el KEY_SYSTEM_SIZE $(du -b system.raw|cut -f1)  \
--el KEY_USERDATA_SIZE 8589934592

Khởi chạy DSU bằng ứng dụng

Điểm truy cập chính vào DSU là API android.os.image.DynamicSystemClient.java :

public class DynamicSystemClient {


...
...

     /**
     * Start installing DynamicSystem from URL with default userdata size.
     *
     * @param systemUrl A network URL or a file URL to system image.
     * @param systemSize size of system image.
     */
    public void start(String systemUrl, long systemSize) {
        start(systemUrl, systemSize, DEFAULT_USERDATA_SIZE);
    }

Bạn phải gói/cài đặt sẵn ứng dụng này trên thiết bị. Vì DynamicSystemClient là API hệ thống nên bạn không thể xây dựng ứng dụng bằng API SDK thông thường và không thể xuất bản ứng dụng đó trên Google Play. Mục đích của ứng dụng này là:

  1. Tìm nạp danh sách hình ảnh và URL tương ứng bằng sơ đồ do nhà cung cấp xác định.
  2. Hãy ghép các hình ảnh trong danh sách với thiết bị và hiển thị hình ảnh tương thích để người dùng lựa chọn.
  3. Gọi DynamicSystemClient.start như thế này:

    DynamicSystemClient aot = new DynamicSystemClient(...)
       aot.start(
            ...URL of the selected image...,
            ...uncompressed size of the selected image...);
    
    

URL trỏ đến tệp hình ảnh hệ thống được nén, không thưa thớt mà bạn có thể thực hiện bằng các lệnh sau:

$ simg2img ${OUT}/system.img ${OUT}/system.raw
$ gzip ${OUT}/system.raw
$ ls ${OUT}/system.raw.gz

Tên tệp phải theo định dạng này:

<android version>.<lunch name>.<user defined title>.raw.gz

Ví dụ:

  • o.aosp_taimen-userdebug.2018dev.raw.gz
  • p.aosp_taimen-userdebug.2018dev.raw.gz

Trình tải DSU một cú nhấp chuột

Android 11 giới thiệu trình tải DSU chỉ bằng một cú nhấp chuột, đây là giao diện người dùng trong cài đặt của nhà phát triển.

Khởi chạy trình tải DSU

Hình 1. Khởi chạy trình tải DSU

Khi nhà phát triển nhấp vào nút Trình tải DSU , nó sẽ tìm nạp bộ mô tả DSU JSON được định cấu hình sẵn từ web và hiển thị tất cả các hình ảnh có thể áp dụng trong menu nổi. Chọn một hình ảnh để bắt đầu cài đặt DSU và tiến trình hiển thị trên thanh thông báo.

Tiến trình cài đặt hình ảnh DSU

Hình 2. Tiến trình cài đặt image DSU

Theo mặc định, trình tải DSU tải bộ mô tả JSON chứa hình ảnh GSI. Các phần sau đây trình bày cách tạo các gói DSU có chữ ký OEM và tải chúng từ trình tải DSU.

Cờ tính năng

Tính năng DSU nằm dưới cờ tính năng settings_dynamic_android . Trước khi sử dụng DSU, hãy đảm bảo cờ tính năng tương ứng được bật.

Kích hoạt cờ tính năng.

Hình 3. Kích hoạt cờ tính năng

Giao diện người dùng cờ tính năng có thể không khả dụng trên thiết bị đang chạy bản dựng người dùng. Trong trường hợp này, hãy sử dụng lệnh adb thay thế:

$ adb shell setprop persist.sys.fflag.override.settings_dynamic_system 1

Hình ảnh hệ thống máy chủ của nhà cung cấp trên GCE (tùy chọn)

Một trong những vị trí lưu trữ có thể có cho hình ảnh hệ thống là nhóm Google Computer Engine (GCE). Quản trị viên phát hành sử dụng bảng điều khiển lưu trữ GCP để thêm/xóa/thay đổi hình ảnh hệ thống đã phát hành.

Các hình ảnh phải được truy cập công khai, như được hiển thị ở đây:

Quyền truy cập công cộng vào GCE

Hình 4. Truy cập công cộng trong GCE

Quy trình công khai một mục có sẵn trong tài liệu của Google Cloud .

DSU nhiều phân vùng trong tệp ZIP

Bắt đầu từ Android 11, DSU có thể có nhiều phân vùng. Ví dụ: nó có thể chứa một product.img ngoài system.img . Khi thiết bị khởi động, giai đoạn đầu tiên init sẽ phát hiện các phân vùng DSU đã cài đặt và tạm thời thay thế phân vùng trên thiết bị khi DSU đã cài đặt được bật. Gói DSU có thể chứa một phân vùng không có phân vùng tương ứng trên thiết bị.

Quá trình DSU với nhiều phân vùng

Hình 5. Quá trình DSU với nhiều phân vùng

DSU có chữ ký OEM

Để đảm bảo tất cả hình ảnh chạy trên thiết bị đều được nhà sản xuất thiết bị cho phép, tất cả hình ảnh trong gói DSU phải được ký. Ví dụ: giả sử có gói DSU chứa hai hình ảnh phân vùng như bên dưới:

dsu.zip {
    - system.img
    - product.img
}

Cả system.imgproduct.img đều phải được ký bằng khóa OEM trước khi đưa vào tệp ZIP. Thực tế phổ biến là sử dụng thuật toán bất đối xứng, ví dụ như RSA, trong đó khóa bí mật được sử dụng để ký gói và khóa chung được sử dụng để xác minh nó. Đĩa RAM giai đoạn đầu tiên phải bao gồm khóa công khai ghép nối, ví dụ: /avb/*.avbpubkey . Nếu thiết bị đã sử dụng AVB thì quy trình ký hiện tại sẽ đủ. Các phần sau minh họa quá trình ký và nêu bật vị trí của khóa pubkey AVB được sử dụng để xác minh hình ảnh trong gói DSU.

Bộ mô tả JSON DSU

Bộ mô tả DSU JSON mô tả các gói DSU. Nó hỗ trợ hai nguyên thủy. Đầu tiên, include nguyên thủy bao gồm các bộ mô tả JSON bổ sung hoặc chuyển hướng trình tải DSU đến một vị trí mới. Ví dụ:

{
    "include": ["https://.../gsi-release/gsi-src.json"]
}

Thứ hai, image gốc được sử dụng để mô tả các gói DSU được phát hành. Bên trong hình ảnh nguyên thủy có một số thuộc tính:

  • Thuộc tính namedetails là các chuỗi được hiển thị trên hộp thoại để người dùng lựa chọn.

  • Các thuộc tính cpu_api , vndkos_version được sử dụng để kiểm tra tính tương thích, được mô tả trong phần tiếp theo.

  • Thuộc tính pubkey tùy chọn mô tả khóa chung kết hợp với khóa bí mật được sử dụng để ký gói DSU. Khi được chỉ định, dịch vụ DSU có thể kiểm tra xem thiết bị có khóa được sử dụng để xác minh gói DSU hay không. Điều này tránh cài đặt gói DSU không được nhận dạng, ví dụ như cài đặt DSU được OEM-A ký vào thiết bị do OEM-B sản xuất.

  • Thuộc tos tùy chọn trỏ đến một tệp văn bản mô tả các điều khoản dịch vụ cho gói DSU tương ứng. Khi nhà phát triển chọn gói DSU có thuộc tính điều khoản dịch vụ được chỉ định, hộp thoại hiển thị trong Hình 6 sẽ mở ra, yêu cầu nhà phát triển chấp nhận các điều khoản dịch vụ trước khi cài đặt gói DSU.

    Hộp thoại điều khoản dịch vụ

    Hình 6. Hộp thoại điều khoản dịch vụ

Để tham khảo, đây là bộ mô tả JSON DSU cho GSI:

{
   "images":[
      {
         "name":"GSI+GMS x86",
         "os_version":"10",
         "cpu_abi": "x86",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_x86-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI+GMS ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI x86_64",
         "os_version":"10",
         "cpu_abi": "x86_64",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_x86_64-exp-QP1A.190711.020.C4-5928301.zip"
      }
   ]
}

Quản lý tương thích

Một số thuộc tính được sử dụng để chỉ định khả năng tương thích giữa gói DSU và thiết bị cục bộ:

  • cpu_api là một chuỗi mô tả kiến ​​trúc thiết bị. Thuộc tính này là bắt buộc và được so sánh với thuộc tính hệ thống ro.product.cpu.abi . Giá trị của chúng phải khớp chính xác.

  • os_version là số nguyên tùy chọn chỉ định bản phát hành Android. Ví dụ: đối với Android 10, os_version10 và đối với Android 11, os_version11 . Khi thuộc tính này được chỉ định, nó phải bằng hoặc lớn hơn thuộc tính hệ thống ro.system.build.version.release . Kiểm tra này được sử dụng để ngăn chặn việc khởi động hình ảnh GSI Android 10 trên thiết bị của nhà cung cấp Android 11 hiện không được hỗ trợ. Cho phép khởi động hình ảnh Android 11 GSI trên thiết bị Android 10.

  • vndk là một mảng tùy chọn chỉ định tất cả các VNĐK có trong gói DSU. Khi được chỉ định, trình tải DSU sẽ kiểm tra xem số được trích xuất từ ​​thuộc tính hệ thống ro.vndk.version có được bao gồm hay không.

Thu hồi khóa DSU để bảo mật

Trong trường hợp cực kỳ hiếm gặp khi cặp khóa RSA dùng để ký các ảnh DSU bị xâm phạm, đĩa RAM phải được cập nhật càng sớm càng tốt để xóa khóa bị xâm phạm. Ngoài việc cập nhật phân vùng khởi động, bạn có thể chặn các khóa bị xâm phạm bằng cách sử dụng danh sách thu hồi khóa DSU (danh sách đen khóa) từ URL HTTPS.

Danh sách thu hồi khóa DSU chứa danh sách các khóa công khai AVB đã bị thu hồi. Trong quá trình cài đặt DSU, các khóa chung bên trong các ảnh DSU được xác thực bằng danh sách thu hồi. Nếu phát hiện thấy hình ảnh có chứa khóa chung bị thu hồi thì quá trình cài đặt DSU sẽ dừng lại.

URL danh sách thu hồi khóa phải là URL HTTPS để đảm bảo độ mạnh bảo mật và được chỉ định trong chuỗi tài nguyên:

frameworks/base/packages/DynamicSystemInstallationService/res/values/strings.xml@key_revocation_list_url

Giá trị của chuỗi là https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json , đây là danh sách thu hồi các khóa GSI do Google phát hành. Chuỗi tài nguyên này có thể được phủ và tùy chỉnh để các OEM áp dụng tính năng DSU có thể cung cấp và duy trì danh sách đen khóa của riêng họ. Điều này cung cấp một cách để OEM chặn một số khóa chung nhất định mà không cần cập nhật hình ảnh đĩa ram của thiết bị.

Định dạng của danh sách thu hồi là:

{
   "entries":[
      {
         "public_key":"bf14e439d1acf231095c4109f94f00fc473148e6",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      },
      {
         "public_key":"d199b2f29f3dc224cca778a7544ea89470cbef46",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      }
   ]
}
  • public_key là bản tóm tắt SHA-1 của khóa bị thu hồi, theo định dạng được mô tả trong phần tạo khóa pubkey AVB .
  • status cho biết trạng thái thu hồi của khóa. Hiện tại, giá trị được hỗ trợ duy nhất là REVOKED .
  • reason là một chuỗi tùy chọn mô tả lý do thu hồi.

thủ tục DSU

Phần này mô tả cách thực hiện một số thủ tục cấu hình DSU.

Tạo cặp khóa mới

Sử dụng lệnh openssl để tạo cặp khóa riêng/chung RSA ở định dạng .pem (ví dụ: với kích thước 2048 bit):

$ openssl genrsa -out oem_cert_pri.pem 2048
$ openssl rsa -in oem_cert_pri.pem -pubout -out oem_cert_pub.pem

Khóa riêng có thể không truy cập được và chỉ được lưu trong mô-đun bảo mật phần cứng (HSM) . Trong trường hợp này, có thể có chứng chỉ khóa công khai x509 sau khi tạo khóa. Xem phần Thêm khóa pubkey ghép nối vào đĩa ram để biết hướng dẫn tạo khóa chung AVB từ chứng chỉ x509.

Để chuyển đổi chứng chỉ x509 sang định dạng PEM:

$ openssl x509 -pubkey -noout -in oem_cert_pub.x509.pem > oem_cert_pub.pem

Bỏ qua bước này nếu chứng chỉ đã là tệp PEM.

Thêm pubkey ghép nối vào ramdisk

oem_cert.avbpubkey phải được đặt trong /avb/*.avbpubkey để xác minh gói DSU đã ký. Đầu tiên, chuyển đổi khóa chung ở định dạng PEM sang định dạng khóa chung AVB:

$ avbtool extract_public_key --key oem_cert_pub.pem --output oem_cert.avbpubkey

Sau đó đưa khóa chung vào đĩa ram giai đoạn đầu tiên bằng các bước sau.

  1. Thêm mô-đun dựng sẵn để sao chép avbpubkey . Ví dụ: thêm device/<company>/<board>/oem_cert.avbpubkeydevice/<company>/<board>/avb/Android.mk với nội dung như thế này:

    include $(CLEAR_VARS)
    
    LOCAL_MODULE := oem_cert.avbpubkey
    LOCAL_MODULE_CLASS := ETC
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
    LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
    else
    LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
    endif
    
    include $(BUILD_PREBUILT)
    
  2. Đặt mục tiêu droidcore phụ thuộc vào oem_cert.avbpubkey được thêm vào:

    droidcore: oem_cert.avbpubkey
    

Tạo thuộc tính pubkey AVB trong bộ mô tả JSON

oem_cert.avbpubkey có định dạng nhị phân khóa công khai AVB. Sử dụng SHA-1 để làm cho nó có thể đọc được trước khi đưa nó vào bộ mô tả JSON:

$ sha1sum oem_cert.avbpubkey | cut -f1 -d ' '
3e62f2be9d9d813ef5........866ac72a51fd20

Đây sẽ là nội dung của thuộc tính pubkey của bộ mô tả JSON.

   "images":[
      {
         ...
         "pubkey":"3e62f2be9d9d813ef5........866ac72a51fd20",
         ...
      },

Ký gói DSU

Sử dụng một trong các phương pháp sau để ký gói DSU:

  • Phương pháp 1: Sử dụng lại tạo phẩm được tạo bởi quy trình ký AVB ban đầu để tạo gói DSU. Một cách tiếp cận khác là trích xuất các hình ảnh đã được ký từ gói phát hành và sử dụng các hình ảnh được trích xuất để tạo trực tiếp tệp ZIP.

  • Phương pháp 2: Sử dụng các lệnh sau để ký phân vùng DSU nếu có khóa riêng. Mỗi img trong gói DSU (tệp ZIP) được ký riêng:

    $ key_len=$(openssl rsa -in oem_cert_pri.pem -text | grep Private-Key | sed -e 's/.*(\(.*\) bit.*/\1/')
    $ for partition in system product; do
        avbtool add_hashtree_footer \
            --image ${OUT}/${partition}.img \
            --partition_name ${partition} \
            --algorithm SHA256_RSA${key_len} \
            --key oem_cert_pri.pem
    done
    

Để biết thêm thông tin về cách thêm add_hashtree_footer bằng avbtool , hãy xem Sử dụng avbtool .

Xác minh gói DSU cục bộ

Bạn nên xác minh tất cả hình ảnh cục bộ dựa trên khóa chung ghép nối bằng các lệnh sau:


for partition in system product; do
    avbtool verify_image --image ${OUT}/${partition}.img  --key oem_cert_pub.pem
done

Đầu ra dự kiến ​​trông như thế này:

Verifying image dsu/system.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/system.img
: Successfully verified sha1 hashtree of dsu/system.img for image of 898494464 bytes

Verifying image dsu/product.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/product.img
: Successfully verified sha1 hashtree of dsu/product.img for image of 905830400 bytes

Tạo gói DSU

Ví dụ sau đây tạo một gói DSU chứa system.img và một product.img :

dsu.zip {
    - system.img
    - product.img
}

Sau khi cả hai hình ảnh được ký, hãy sử dụng lệnh sau để tạo tệp ZIP:

$ mkdir -p dsu
$ cp ${OUT}/system.img dsu
$ cp ${OUT}/product.img dsu
$ cd dsu && zip ../dsu.zip *.img && cd -

Tùy chỉnh DSU bằng một cú nhấp chuột

Theo mặc định, trình tải DSU trỏ đến siêu dữ liệu của hình ảnh GSI là https://...google.com/.../gsi-src.json .

Các OEM có thể ghi đè danh sách bằng cách xác định thuộc tính persist.sys.fflag.override.settings_dynamic_system.list trỏ đến bộ mô tả JSON của riêng họ. Ví dụ: OEM có thể cung cấp siêu dữ liệu JSON bao gồm GSI cũng như các hình ảnh độc quyền của OEM như thế này:

{
    "include": ["https://dl.google.com/.../gsi-src.JSON"]
    "images":[
      {
         "name":"OEM image",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"...",
         "vndk":[
            27,
            28,
            29
         ],
         "spl":"...",
         "pubkey":"",
         "uri":"https://.../....zip"
      },

}

OEM có thể xâu chuỗi siêu dữ liệu DSU đã xuất bản như trong Hình 7.

Xâu chuỗi siêu dữ liệu DSU được xuất bản

Hình 7. Xâu chuỗi siêu dữ liệu DSU đã xuất bản