Hamparan Sumber Daya Waktu Proses (RRO)

Overlay sumber daya runtime (RRO) adalah paket yang mengubah nilai sumber daya dari paket target saat runtime. Misalnya, aplikasi yang diinstal pada citra sistem mungkin mengubah perilakunya berdasarkan nilai sumber daya. Daripada melakukan hardcoding nilai sumber daya pada waktu pembuatan, RRO yang diinstal pada partisi yang berbeda dapat mengubah nilai sumber daya aplikasi pada waktu proses.

RRO dapat diaktifkan atau dinonaktifkan. Anda dapat secara terprogram mengatur status aktifkan/nonaktifkan untuk mengaktifkan kemampuan RRO untuk mengubah nilai sumber daya. RRO dinonaktifkan secara default (namun, RRO statis diaktifkan secara default).

Sumber daya tumpang tindih

Overlay bekerja dengan memetakan sumber daya yang ditentukan dalam paket overlay ke sumber daya yang ditentukan dalam paket target. Saat aplikasi mencoba menyelesaikan nilai sumber daya dalam paket target, nilai sumber daya overlay tempat sumber daya target dipetakan akan dikembalikan.

Menyiapkan manifes

Sebuah paket dianggap sebagai paket RRO jika berisi tag <overlay> sebagai anak dari tag <manifest> .

  • Nilai atribut android:targetPackage yang diperlukan menentukan nama paket yang ingin dilapis oleh RRO.

  • Nilai atribut android:targetName opsional menentukan nama subset resource yang dapat di-overlay dari paket target yang ingin di-overlay oleh RRO. Jika target tidak menentukan kumpulan sumber daya yang dapat dihamparkan, atribut ini tidak boleh ada.

Kode berikut menunjukkan contoh overlay AndroidManifest.xml .

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.overlay">
    <application android:hasCode="false" />
    <overlay android:targetPackage="com.example.target"
                   android:targetName="OverlayableResources"/>
</manifest>

Hamparan tidak dapat melapisi kode, sehingga tidak dapat memiliki file DEX. Selain itu, atribut android:hasCode dari tag <application > dalam manifes harus disetel ke false .

Mendefinisikan peta sumber daya

Di Android 11 atau lebih tinggi, mekanisme yang direkomendasikan untuk mendefinisikan peta sumber daya overlay adalah membuat file di direktori res/xml dari paket overlay, menghitung sumber daya target yang harus di-overlay dan nilai penggantinya, lalu menyetel nilai atribut android:resourcesMap dari tag manifes <overlay> ke referensi ke file pemetaan sumber daya.

Kode berikut menunjukkan contoh file res/xml/overlays.xml .

<?xml version="1.0" encoding="utf-8"?>
<overlay xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- Overlays string/config1 and string/config2 with the same resource. -->
    <item target="string/config1" value="@string/overlay1" />
    <item target="string/config2" value="@string/overlay1" />

    <!-- Overlays string/config3 with the string "yes". -->
    <item target="string/config3" value="@android:string/yes" />

    <!-- Overlays string/config4 with the string "Hardcoded string". -->
    <item target="string/config4" value="Hardcoded string" />

    <!-- Overlays integer/config5 with the integer "42". -->
    <item target="integer/config5" value="42" />
</overlay>

Kode berikut menunjukkan contoh manifes overlay.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.overlay">
    <application android:hasCode="false" />
    <overlay android:targetPackage="com.example.target"
                   android:targetName="OverlayableResources"
                   android:resourcesMap="@xml/overlays"/>
</manifest>

Membangun paket

Android 11 atau yang lebih tinggi mendukung aturan build Soong untuk overlay yang mencegah Android Asset Packaging Tool 2 (AAPT2) mencoba menghapus konfigurasi sumber daya dengan nilai yang sama ( --no-resource-deduping ) dan menghapus sumber daya tanpa konfigurasi default ( --no-resource-removal ). Kode berikut menunjukkan contoh file Android.bp .

runtime_resource_overlay {
    name: "ExampleOverlay",
    sdk_version: "current",
}

Menyelesaikan sumber daya

Jika sumber daya target atau sumber daya overlay memiliki beberapa konfigurasi yang ditentukan untuk sumber daya yang dikueri, waktu proses sumber daya mengembalikan nilai konfigurasi yang paling cocok dengan konfigurasi konfigurasi perangkat. Untuk menentukan konfigurasi mana yang merupakan konfigurasi yang paling cocok, gabungkan kumpulan konfigurasi sumber daya overlay ke dalam kumpulan konfigurasi sumber daya target, lalu ikuti alur resolusi sumber daya reguler (untuk detailnya, lihat Cara Android menemukan sumber daya yang paling cocok ).

Misalnya, jika hamparan menentukan nilai untuk konfigurasi drawable-en dan target menentukan nilai untuk drawable-en-port , drawable-en-port memiliki kecocokan yang lebih baik sehingga nilai konfigurasi target drawable-en-port adalah dipilih saat runtime. Untuk melapisi semua konfigurasi drawable-en , overlay harus menentukan nilai untuk setiap konfigurasi drawable-en yang ditentukan target.

Hamparan dapat mereferensikan sumber dayanya sendiri, dengan perilaku yang berbeda di antara rilis Android.

  • Di Android 11 atau lebih tinggi, setiap hamparan memiliki ruang ID sumber daya cadangannya sendiri yang tidak tumpang tindih dengan ruang ID sumber daya target atau ruang ID sumber daya hamparan lainnya, sehingga hamparan yang mereferensikan sumber dayanya sendiri berfungsi seperti yang diharapkan.

  • Di Android 10 atau lebih rendah, overlay dan paket target berbagi ruang ID sumber daya yang sama, yang dapat menyebabkan tabrakan dan perilaku tak terduga saat mereka mencoba mereferensikan sumber daya mereka sendiri menggunakan sintaks @type/name .

Mengaktifkan/menonaktifkan overlay

Gunakan OverlayManager API untuk mengaktifkan dan menonaktifkan overlay yang dapat diubah (ambil antarmuka API menggunakan Context#getSystemService(Context.OVERLAY_SERVICE) ). Overlay hanya dapat diaktifkan oleh paket yang ditargetkannya atau oleh paket dengan izin android.permission.CHANGE_OVERLAY_PACKAGES . Saat overlay diaktifkan atau dinonaktifkan, peristiwa perubahan konfigurasi menyebar ke paket target dan aktivitas target diluncurkan kembali.

Membatasi sumber daya yang dapat dihamparkan

Di Android 10 atau yang lebih tinggi, tag XML <overlayable> memperlihatkan sekumpulan sumber daya yang diizinkan untuk dihamparkan oleh RRO. Dalam contoh file res/values/overlayable.xml , string/foo dan integer/bar adalah sumber daya yang digunakan untuk memberi tema pada tampilan perangkat; untuk melapisi sumber daya ini, hamparan harus secara eksplisit menargetkan kumpulan sumber daya yang dapat dilapis berdasarkan nama.

<!-- The collection of resources for theming the appearance of the device -->
<overlayable name="ThemeResources">
       <policy type="public">
               <item type="string" name="foo/" />
               <item type="integer" name="bar/" />
       </policy>
       ...
</overlayable>

APK dapat menentukan beberapa <overlayable> , tetapi setiap tag harus memiliki nama unik di dalam paket. Misalnya adalah:

  • OK untuk dua paket berbeda untuk keduanya mendefinisikan <overlayable name="foo"> .

  • Tidak boleh untuk satu APK memiliki dua <overlayable name="foo"> .

Kode berikut menunjukkan contoh overlay di file AndroidManifest.xml .

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.my.theme.overlay">
       <application android:hasCode="false" />
       <!-- This overlay will override the ThemeResources resources -->
       <overlay android:targetPackage="android" android:targetName="ThemeResources">
</manifest>

Saat aplikasi mendefinisikan tag <overlayable> , overlay menargetkan aplikasi tersebut:

  • Harus menentukan targetName .

  • Hanya dapat melapisi sumber daya yang tercantum dalam tag <overlayable> .

  • Hanya dapat menargetkan satu nama <overlayable> .

Anda tidak dapat mengaktifkan hamparan yang menargetkan paket yang memperlihatkan sumber daya yang dapat dihamparkan tetapi tidak menggunakan android:targetName untuk menargetkan tag <overlayable> tertentu.

Membatasi kebijakan

Gunakan tag <policy> untuk menerapkan pembatasan pada resource yang dapat di-overlay. Atribut type menentukan kebijakan mana yang harus dipenuhi overlay untuk mengganti resource yang disertakan. Jenis yang didukung meliputi berikut ini.

  • public . Hamparan apa pun dapat menimpa sumber daya.
  • system . Overlay apa pun pada partisi sistem dapat menimpa sumber daya.
  • vendor . Overlay apa pun pada partisi vendor dapat menimpa sumber daya.
  • product . Hamparan apa pun pada partisi produk dapat menimpa sumber daya.
  • signature . Overlay apa pun yang ditandatangani dengan tanda tangan yang sama dengan APK target dapat menggantikan resource.

Kode berikut menunjukkan contoh <policy> pada file res/values/overlayable.xml .

<overlayable name="ThemeResources">
   <policy type="vendor" >
       <item type="string" name="foo" />
   </policy>
   <policy type="product|signature"  >
       <item type="string" name="bar" />
       <item type="string" name="baz" />
   </policy>
</overlayable>

Untuk menentukan beberapa kebijakan, gunakan bilah vertikal (|) sebagai karakter pemisah. Saat beberapa kebijakan ditentukan, hamparan hanya perlu memenuhi satu kebijakan untuk mengganti sumber daya yang tercantum dalam tag <policy> .

Mengonfigurasi overlay

Android mendukung mekanisme yang berbeda untuk mengonfigurasi mutabilitas, status default, dan prioritas overlay bergantung pada versi rilis Android.

  • Perangkat yang menjalankan Android 11 atau lebih tinggi dapat menggunakan file OverlayConfig ( config.xml ) alih-alih atribut manifes. Menggunakan file overlay adalah metode yang disarankan untuk overlay.

  • Semua perangkat dapat menggunakan atribut manifes ( android:isStatic dan android:priority ) untuk mengonfigurasi RRO statis.

Menggunakan OverlayConfig

Di Android 11 atau lebih tinggi, Anda dapat menggunakan OverlayConfig untuk mengonfigurasi mutabilitas, status default, dan prioritas overlay. Untuk mengkonfigurasi overlay, buat atau ubah file yang terletak di partition/overlay/config/config.xml , di mana partition adalah partisi overlay yang akan dikonfigurasi. Untuk dikonfigurasi, overlay harus berada di direktori overlay/ dari partisi tempat overlay dikonfigurasi. Kode berikut menunjukkan contoh product/overlay/config/config.xml .

<config>
    <merge path="OEM-common-rros-config.xml" />
    <overlay package="com.oem.overlay.device" mutable="false" enabled="true" />
    <overlay package="com.oem.green.theme" enabled="true" />
</config>"

Tag <overlay> memerlukan atribut package yang menunjukkan paket overlay mana yang sedang dikonfigurasi. Atribut enabled opsional mengontrol apakah hamparan diaktifkan atau tidak secara default (default adalah false ). Atribut opsional yang mutable mengontrol apakah overlay dapat diubah atau tidak dan dapat mengubah status aktifnya secara terprogram saat runtime (default adalah true ). Hamparan yang tidak tercantum dalam file konfigurasi dapat diubah dan dinonaktifkan secara default.

Prioritas overlay

Saat beberapa hamparan menimpa sumber daya yang sama, urutan hamparan itu penting. Overlay memiliki prioritas yang lebih besar daripada overlay dengan konfigurasi yang mendahului konfigurasinya sendiri. Urutan prioritas overlay di partisi yang berbeda (dari prioritas terkecil hingga terbesar) adalah sebagai berikut.

  • system
  • vendor
  • oem
  • odm
  • product
  • system_ext

Menggabungkan file

Menggunakan <merge> memungkinkan file konfigurasi lain digabungkan pada posisi yang ditentukan ke dalam file konfigurasi. Atribut path dari tag mewakili jalur file untuk digabungkan relatif terhadap direktori yang berisi file konfigurasi overlay.

Menggunakan atribut manifes (RRO statis)

Di Android 10 atau lebih rendah, kekekalan dan prioritas overlay dikonfigurasi menggunakan atribut manifes berikut.

  • android:isStatic . Ketika nilai atribut boolean ini disetel ke true , overlay diaktifkan secara default dan tidak dapat diubah, yang mencegah overlay dinonaktifkan.

  • android:priority . Nilai atribut numerik ini (yang hanya memengaruhi hamparan statis) mengonfigurasi prioritas hamparan saat beberapa hamparan statis menargetkan nilai sumber daya yang sama. Angka yang lebih tinggi menunjukkan prioritas yang lebih tinggi.

Kode berikut menunjukkan contoh AndroidManifest.xml .

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.overlay">
    <application android:hasCode="false" />
    <overlay android:targetPackage="com.example.target"
                   android:isStatic="true"
                   android:priority="5"/>
</manifest>

Perubahan di Android 11

Di Android 11 atau lebih tinggi, jika file konfigurasi terletak di partition/overlay/config/config.xml , overlay dikonfigurasi menggunakan file tersebut dan android:isStatic dan android:priority tidak berpengaruh pada overlay yang terletak di partisi. Mendefinisikan file konfigurasi overlay di partisi mana pun akan memberlakukan prioritas partisi overlay.

Selain itu, Android 11 atau lebih tinggi menghapus kemampuan untuk menggunakan hamparan statis untuk memengaruhi nilai sumber daya yang dibaca selama penginstalan paket. Untuk kasus penggunaan umum dalam menggunakan overlay statis untuk mengubah nilai boolean yang mengonfigurasi status aktif komponen, gunakan <component-override> SystemConfig (baru di Android 11).

Debug overlay

Untuk mengaktifkan, menonaktifkan, dan membuang overlay secara manual, gunakan perintah shell manager overlay berikut.

adb shell cmd overlay

OverlayManagerService menggunakan idmap2 untuk memetakan ID sumber daya dalam paket target ke ID sumber daya dalam paket hamparan. Pemetaan ID yang dihasilkan disimpan di /data/resource-cache/ . Jika overlay Anda tidak berfungsi dengan benar, temukan file idmap yang sesuai untuk overlay Anda di /data/resource-cache/ , lalu jalankan perintah berikut.

adb shell idmap2 dump --idmap-path [file]

Perintah ini mencetak pemetaan sumber daya seperti yang ditunjukkan di bawah ini.

[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType