Pembaruan Sistem Dinamis

Pembaruan Sistem Dinamis (DSU) memungkinkan Anda membuat citra sistem Android yang dapat diunduh pengguna dari internet dan mencobanya tanpa risiko merusak citra sistem saat ini. Dokumen ini menjelaskan cara mendukung DSU.

Persyaratan kernel

Lihat Menerapkan Partisi Dinamis untuk persyaratan kernel.

Selain itu, DSU mengandalkan fitur kernel device-mapper-verity (dm-verity) untuk memverifikasi citra sistem Android. Jadi, Anda harus mengaktifkan konfigurasi kernel berikut:

  • CONFIG_DM_VERITY=y
  • CONFIG_DM_VERITY_FEC=y

Persyaratan partisi

Mulai Android 11, DSU memerlukan partisi /data untuk menggunakan sistem file F2FS atau ext4. F2FS memberikan kinerja yang lebih baik dan direkomendasikan, tetapi perbedaannya seharusnya tidak signifikan.

Berikut adalah beberapa contoh waktu yang dibutuhkan pembaruan sistem dinamis dengan perangkat Pixel:

  • Menggunakan F2FS:
    • 109s, pengguna 8G, sistem 867M, jenis sistem file: F2FS: enkripsi=aes-256-xts:aes-256-cts
    • 104s, pengguna 8G, sistem 867M, tipe sistem file: F2FS: enkripsi=es
  • Menggunakan ext4:
    • 135s, pengguna 8G, sistem 867M, jenis sistem file: ext4: enkripsi=aes-256-xts:aes-256-cts

Jika membutuhkan waktu lebih lama pada platform Anda, Anda mungkin ingin memeriksa apakah flag mount berisi flag yang membuat penulisan “sync”, atau Anda dapat menentukan flag “async” secara eksplisit untuk mendapatkan kinerja yang lebih baik.

Partisi metadata (16 MB atau lebih besar) diperlukan untuk menyimpan data yang terkait dengan gambar yang diinstal. Itu harus dipasang selama pemasangan tahap pertama.

Partisi userdata harus menggunakan sistem file F2FS atau ext4. Saat menggunakan F2FS, sertakan semua patch terkait F2FS yang tersedia di kernel umum Android .

DSU dikembangkan dan diuji dengan kernel/common 4.9. Disarankan untuk menggunakan kernel 4.9 dan yang lebih tinggi untuk fitur ini.

Perilaku vendor HAL

Penenun HAL

HAL penenun menyediakan sejumlah slot untuk menyimpan kunci pengguna. DSU menggunakan dua slot kunci tambahan. Jika OEM memiliki HAL penenun, ia harus memiliki slot yang cukup untuk citra sistem generik (GSI) dan citra host.

Penjaga gerbang HAL

Gatekeeper HAL perlu mendukung nilai USER_ID yang besar, karena GSI mengimbangi UID ke HAL sebesar +1000000.

Verifikasi boot

Jika Anda ingin mendukung booting Gambar GSI Pengembang dalam keadaan TERKUNCI tanpa menonaktifkan boot yang diverifikasi, sertakan kunci GSI Pengembang dengan menambahkan baris berikut ke file device/<device_name>/device.mk :

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

Perlindungan rollback

Saat menggunakan DSU, citra sistem Android yang diunduh harus lebih baru dari citra sistem saat ini di perangkat. Ini dilakukan dengan membandingkan tingkat patch keamanan di deskriptor properti Android Verified Boot (AVB) AVB dari kedua citra sistem: Prop: com.android.build.system.security_patch -> '2019-04-05' .

Untuk perangkat yang tidak menggunakan AVB, masukkan tingkat patch keamanan dari citra sistem saat ini ke dalam cmdline kernel atau bootconfig dengan bootloader: androidboot.system.security_patch=2019-04-05 .

Persyaratan perangkat keras

Saat Anda meluncurkan instans DSU, dua file sementara dialokasikan:

  • Partisi logis untuk menyimpan GSI.img (1~1,5 G)
  • Partisi /data kosong 8 GB sebagai kotak pasir untuk menjalankan GSI

Kami merekomendasikan untuk memesan setidaknya 10 GB ruang kosong sebelum meluncurkan instans DSU. DSU juga mendukung alokasi dari kartu SD. Ketika kartu SD hadir, itu memiliki prioritas tertinggi untuk alokasi. Dukungan kartu SD sangat penting untuk perangkat berdaya rendah yang mungkin tidak memiliki cukup penyimpanan internal. Saat kartu SD ada, pastikan itu tidak diadopsi. DSU tidak mendukung kartu SD yang diadopsi .

Frontend yang tersedia

Anda dapat meluncurkan DSU menggunakan adb , aplikasi OEM, atau pemuat DSU sekali klik (di Android 11 atau lebih tinggi).

Meluncurkan DSU menggunakan adb

Untuk meluncurkan DSU menggunakan adb, masukkan perintah ini:

$ 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

Meluncurkan DSU menggunakan aplikasi

Titik masuk utama ke DSU adalah android.os.image.DynamicSystemClient.java API:

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);
    }

Anda harus membundel/memprainstal aplikasi ini di perangkat. Karena DynamicSystemClient adalah API sistem, Anda tidak dapat membuat aplikasi dengan API SDK biasa dan tidak dapat memublikasikannya di Google Play. Tujuan dari aplikasi ini adalah:

  1. Ambil daftar gambar dan URL yang sesuai dengan skema yang ditentukan vendor.
  2. Cocokkan gambar dalam daftar dengan perangkat dan tampilkan gambar yang kompatibel untuk dipilih pengguna.
  3. Aktifkan DynamicSystemClient.start seperti ini:

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

URL menunjuk ke file gambar sistem yang di-gzip, tidak jarang, yang dapat Anda buat dengan perintah berikut:

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

Nama file harus mengikuti format ini:

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

Contoh:

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

Pemuat DSU sekali klik

Android 11 memperkenalkan pemuat DSU sekali klik, yang merupakan antarmuka di setelan pengembang.

Meluncurkan pemuat DSU

Gambar 1. Meluncurkan pemuat DSU

Saat pengembang mengeklik tombol DSU Loader , ia mengambil deskriptor DSU JSON yang telah dikonfigurasi sebelumnya dari web dan menampilkan semua gambar yang berlaku di menu mengambang. Pilih gambar untuk memulai instalasi DSU, dan kemajuan ditampilkan di bilah notifikasi.

Kemajuan instalasi gambar DSU

Gambar 2. Kemajuan instalasi gambar DSU

Secara default, pemuat DSU memuat deskriptor JSON yang berisi gambar GSI. Bagian berikut menunjukkan cara membuat paket DSU yang ditandatangani OEM dan memuatnya dari pemuat DSU.

Bendera fitur

Fitur DSU berada di bawah bendera fitur settings_dynamic_android . Sebelum menggunakan DSU, pastikan tanda fitur yang sesuai diaktifkan.

Mengaktifkan tanda fitur.

Gambar 3. Mengaktifkan flag fitur

UI flag fitur mungkin tidak tersedia di perangkat yang menjalankan build pengguna. Dalam hal ini, gunakan perintah adb sebagai gantinya:

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

Gambar sistem host vendor di GCE (opsional)

Salah satu kemungkinan lokasi penyimpanan untuk image sistem adalah bucket Google Compute Engine (GCE). Administrator rilis menggunakan konsol penyimpanan GCP untuk menambahkan/menghapus/mengubah image sistem yang dirilis.

Gambar harus akses publik, seperti yang ditunjukkan di sini:

Akses publik di GCE

Gambar 4. Akses publik di GCE

Prosedur untuk membuat item menjadi publik tersedia di dokumentasi Google Cloud .

DSU multi-partisi dalam file ZIP

Mulai Android 11, DSU dapat memiliki lebih dari satu partisi. Misalnya, dapat berisi product.img selain system.img . Saat perangkat melakukan booting, init tahap pertama mendeteksi partisi DSU yang terinstal dan mengganti partisi di perangkat untuk sementara, saat DSU yang diinstal diaktifkan. Paket DSU mungkin berisi partisi yang tidak memiliki partisi yang sesuai pada perangkat.

Proses DSU dengan banyak partisi

Gambar 5. Proses DSU dengan banyak partisi

DSU yang ditandatangani OEM

Untuk memastikan semua gambar yang berjalan pada perangkat diotorisasi oleh produsen perangkat, semua gambar dalam paket DSU harus ditandatangani. Misalnya, asumsikan ada paket DSU yang berisi dua gambar partisi seperti di bawah ini:

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

Baik system.img dan product.img harus ditandatangani oleh kunci OEM sebelum dimasukkan ke dalam file ZIP. Praktik umum adalah menggunakan algoritma asimetris, misalnya RSA, di mana kunci rahasia digunakan untuk menandatangani paket dan kunci publik digunakan untuk memverifikasinya. Ramdisk tahap pertama harus menyertakan kunci publik pengupas, misalnya /avb/*.avbpubkey . Jika perangkat sudah mengadopsi AVB, prosedur penandatanganan yang ada sudah cukup. Bagian berikut mengilustrasikan proses penandatanganan dan menyoroti penempatan kunci pub AVB yang digunakan untuk memverifikasi gambar dalam paket DSU.

Deskriptor DSU JSON

Deskriptor DSU JSON menjelaskan paket DSU. Ini mendukung dua primitif. Pertama, include primitif menyertakan deskriptor JSON tambahan atau mengalihkan pemuat DSU ke lokasi baru. Sebagai contoh:

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

Kedua, image primitif digunakan untuk menggambarkan paket DSU yang dirilis. Di dalam gambar primitif ada beberapa atribut:

  • Atribut name dan details adalah string yang ditampilkan pada dialog untuk dipilih pengguna.

  • cpu_api , vndk , dan os_version digunakan untuk pemeriksaan kompatibilitas, yang akan dijelaskan di bagian berikutnya.

  • Atribut pubkey opsional menjelaskan kunci publik yang berpasangan dengan kunci rahasia yang digunakan untuk menandatangani paket DSU. Jika ditentukan, layanan DSU dapat memeriksa apakah perangkat memiliki kunci yang digunakan untuk memverifikasi paket DSU. Ini menghindari penginstalan paket DSU yang tidak dikenal, misalnya menginstal DSU yang ditandatangani oleh OEM-A ke perangkat yang dibuat oleh OEM-B.

  • Atribut tos opsional menunjuk ke file teks yang menjelaskan persyaratan layanan untuk paket DSU terkait. Ketika pengembang memilih paket DSU dengan persyaratan atribut layanan yang ditentukan, kotak dialog yang ditunjukkan pada Gambar 6 terbuka, meminta pengembang untuk menerima persyaratan layanan sebelum menginstal paket DSU.

    Kotak dialog persyaratan layanan

    Gambar 6. Kotak dialog persyaratan layanan

Untuk referensi, inilah deskriptor DSU JSON untuk 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"
      }
   ]
}

Manajemen kompatibilitas

Beberapa atribut digunakan untuk menentukan kompatibilitas antara paket DSU dan perangkat lokal:

  • cpu_api adalah string yang menjelaskan arsitektur perangkat. Atribut ini wajib dan dibandingkan dengan properti sistem ro.product.cpu.abi . Nilai-nilai mereka harus sama persis.

  • os_version adalah bilangan bulat opsional yang menentukan rilis Android. Misalnya, untuk Android 10, os_version adalah 10 dan untuk Android 11, os_version adalah 11 . Ketika atribut ini ditentukan, itu harus sama dengan atau lebih besar dari properti sistem ro.system.build.version.release . Pemeriksaan ini digunakan untuk mencegah booting image Android 10 GSI pada perangkat vendor Android 11, yang saat ini tidak didukung. Mem-boot image Android 11 GSI pada perangkat Android 10 diperbolehkan.

  • vndk adalah larik opsional yang menentukan semua VNDK yang disertakan dalam paket DSU. Saat ditentukan, pemuat DSU memeriksa apakah nomor yang diekstrak dari properti sistem ro.vndk.version disertakan.

Mencabut kunci DSU untuk keamanan

Dalam kasus yang sangat jarang terjadi ketika pasangan kunci RSA yang digunakan untuk menandatangani gambar DSU disusupi, ramdisk harus diperbarui sesegera mungkin untuk menghapus kunci yang disusupi. Selain memperbarui partisi boot, Anda dapat memblokir kunci yang disusupi menggunakan daftar pencabutan kunci DSU (daftar hitam kunci) dari URL HTTPS.

Daftar pencabutan kunci DSU berisi daftar kunci publik AVB yang dicabut. Selama instalasi DSU, kunci publik di dalam gambar DSU divalidasi dengan daftar pencabutan. Jika gambar ditemukan berisi kunci publik yang dicabut, proses penginstalan DSU berhenti.

URL daftar pencabutan kunci harus berupa URL HTTPS untuk memastikan kekuatan keamanan, dan ditentukan dalam string sumber daya:

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

Nilai string adalah https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json , yang merupakan daftar pencabutan untuk kunci GSI yang dirilis Google. String sumber daya ini dapat dilapis dan dikustomisasi, sehingga OEM yang mengadopsi fitur DSU dapat menyediakan dan memelihara daftar hitam kunci mereka sendiri. Ini menyediakan cara bagi OEM untuk memblokir kunci publik tertentu tanpa memperbarui gambar ramdisk perangkat.

Format daftar pencabutan adalah:

{
   "entries":[
      {
         "public_key":"bf14e439d1acf231095c4109f94f00fc473148e6",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      },
      {
         "public_key":"d199b2f29f3dc224cca778a7544ea89470cbef46",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      }
   ]
}
  • public_key adalah intisari SHA-1 dari kunci yang dicabut, dalam format yang dijelaskan di bagian pembuatan pubkey AVB .
  • status menunjukkan status pencabutan kunci. Saat ini, satu-satunya nilai yang didukung adalah REVOKED .
  • reason adalah string opsional yang menjelaskan alasan pencabutan.

prosedur DSU

Bagian ini menjelaskan cara melakukan beberapa prosedur konfigurasi DSU.

Menghasilkan pasangan kunci baru

Gunakan perintah openssl untuk menghasilkan pasangan kunci privat/publik RSA dalam format .pem (misalnya, dengan ukuran 2048 bit):

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

Kunci pribadi mungkin tidak dapat diakses dan hanya disimpan dalam modul keamanan perangkat keras (HSM) . Dalam hal ini, mungkin ada sertifikat kunci publik x509 yang tersedia setelah pembuatan kunci. Lihat bagian Menambahkan pubkey pasangan ke ramdisk untuk petunjuk membuat kunci publik AVB dari sertifikat x509.

Untuk mengonversi sertifikat x509 ke format PEM:

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

Lewati langkah ini jika sertifikat sudah menjadi file PEM.

Menambahkan pubkey pasangan ke ramdisk

oem_cert.avbpubkey harus diletakkan di bawah /avb/*.avbpubkey untuk memverifikasi paket DSU yang ditandatangani. Pertama, konversi kunci publik dalam format PEM ke format kunci publik AVB:

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

Kemudian masukkan kunci publik di ramdisk tahap pertama dengan langkah-langkah berikut.

  1. Tambahkan modul bawaan untuk menyalin avbpubkey . Misalnya, tambahkan device/<company>/<board>/oem_cert.avbpubkey dan device/<company>/<board>/avb/Android.mk dengan konten seperti ini:

    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. Jadikan target droidcore bergantung pada oem_cert.avbpubkey yang ditambahkan:

    droidcore: oem_cert.avbpubkey
    

Membuat atribut pubkey AVB di deskriptor JSON

oem_cert.avbpubkey dalam format biner kunci publik AVB. Gunakan SHA-1 untuk membuatnya dapat dibaca sebelum memasukkannya ke dalam deskriptor JSON:

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

Ini akan menjadi konten atribut pubkey dari deskriptor JSON.

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

Menandatangani paket DSU

Gunakan salah satu metode berikut untuk menandatangani paket DSU:

  • Metode 1: Gunakan kembali artefak yang dibuat oleh proses penandatanganan AVB asli untuk membuat paket DSU. Pendekatan alternatif adalah mengekstrak gambar yang sudah ditandatangani dari paket rilis dan menggunakan gambar yang diekstraksi untuk membuat file ZIP secara langsung.

  • Metode 2: Gunakan perintah berikut untuk menandatangani partisi DSU jika kunci pribadi tersedia. Setiap img dalam paket DSU (file ZIP) ditandatangani secara terpisah:

    $ 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
    

Untuk informasi selengkapnya tentang menambahkan add_hashtree_footer menggunakan avbtool , lihat Menggunakan avbtool .

Memverifikasi paket DSU secara lokal

Disarankan untuk memverifikasi semua gambar lokal terhadap kunci publik yang dipasangkan dengan perintah berikut:


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

Output yang diharapkan terlihat seperti ini:

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

Membuat paket DSU

Contoh berikut membuat paket DSU yang berisi system.img dan product.img :

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

Setelah kedua gambar ditandatangani, gunakan perintah berikut untuk membuat file ZIP:

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

Menyesuaikan DSU sekali klik

Secara default, pemuat DSU menunjuk ke metadata gambar GSI yaitu https://...google.com/.../gsi-src.json .

OEM dapat menimpa daftar dengan mendefinisikan properti persist.sys.fflag.override.settings_dynamic_system.list yang menunjuk ke deskriptor JSON mereka sendiri. Misalnya, OEM dapat menyediakan metadata JSON yang menyertakan GSI serta gambar milik OEM seperti ini:

{
    "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"
      },

}

Mungkin bagi OEM untuk merantai metadata DSU yang dipublikasikan seperti yang ditunjukkan pada Gambar 7.

Merantai metadata DSU yang diterbitkan

Gambar 7. Merangkai metadata DSU yang diterbitkan