Overlay delle risorse di runtime (RRO)

Un overlay delle risorse di runtime (RRO) è un pacchetto che modifica i valori delle risorse di un pacchetto di destinazione in fase di esecuzione. Ad esempio, un'app installata sull'immagine di sistema potrebbe modificare il proprio comportamento in base al valore di una risorsa. Anziché codificare il valore della risorsa in fase di compilazione, un RRO installato su una partizione diversa può modificare i valori delle risorse dell'app in fase di esecuzione.

Gli RRO possono essere abilitati o disabilitati. È possibile impostare a livello di codice lo stato di abilitazione/disabilitazione per attivare o disattivare la capacità di un RRO di modificare i valori delle risorse. RROs sono disabilitate per default (tuttavia, RROs statici sono abilitate di default).

Risorse sovrapposte

Gli overlay funzionano mappando le risorse definite nel pacchetto overlay alle risorse definite nel pacchetto di destinazione. Quando un'app tenta di risolvere il valore di una risorsa nel pacchetto di destinazione, viene restituito il valore della risorsa di sovrapposizione a cui è mappata la risorsa di destinazione.

Impostazione del manifesto

Un pacchetto è considerato un pacchetto di ORP se contiene un <overlay> tag da usare come figlio del <manifest> tag.

  • Il valore delle richieste android:targetPackage specifica di attributo il nome del pacchetto ORP intende sovrapposizione.

  • Il valore delle opzionali android:targetName attributo specifica il nome del sottoinsieme sovrapponibili delle risorse del pacchetto di destinazione ORP intende sovrapporre. Se la destinazione non definisce un insieme di risorse sovrapponibili, questo attributo non dovrebbe essere presente.

Di seguito viene mostrato un esempio di codice di sovrapposizione 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>

Gli overlay non possono sovrapporre il codice, quindi non possono avere file DEX. Inoltre, l' android:hasCode attributo del <application > tag nel manifesto deve essere impostata su false .

Definire la mappa delle risorse

In Android 11 o superiore, il meccanismo raccomandato per definire la mappa delle risorse di sovrapposizione è quello di creare un file nella res/xml directory del pacchetto di sovrapposizione, enumerare le risorse di destinazione che dovrebbero essere sovrapposti ed i loro valori di sostituzione, quindi impostare il valore della android:resourcesMap attributo del <overlay> tag manifesto a un riferimento al file di mapping di risorse.

Di seguito viene mostrato un esempio di codice res/xml/overlays.xml file.

<?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>

Il codice seguente mostra un manifesto di sovrapposizione di esempio.

<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>

Costruire il pacchetto

Android 11 o superiore supporta una regola di accumulo Soong per le sovrapposizioni che impedisce Android Asset Packaging Tool 2 (AAPT2) dal tentativo di configurazioni dedupe di risorse con lo stesso valore ( --no-resource-deduping ) e dalla rimozione risorse senza configurazioni di default ( --no-resource-removal ). Il codice seguente mostra un esempio Android.bp file.

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

Risorse risolutive

Se una risorsa di destinazione o una risorsa di sovrapposizione ha più configurazioni definite per la risorsa che viene interrogata, il runtime delle risorse restituisce il valore della configurazione che meglio corrisponde alla configurazione della configurazione del dispositivo. Per determinare quale configurazione è la migliore configurazione corrispondente, unire l'insieme delle configurazioni delle risorse di sovrapposizione nel set di configurazioni delle risorse di destinazione e quindi seguire il flusso risoluzione risorsa regolare (per i dettagli, vedere come Android trova la risorsa migliore-matching ).

Ad esempio, se un overlay definisce un valore per la drawable-en configurazione e la porta definisce un valore per drawable-en-port , drawable-en-port ha una migliore corrispondenza modo che il valore della configurazione nominale drawable-en-port è scelto in fase di esecuzione. Sovrapporre tutti drawable-en configurazioni, la sovrapposizione deve definire un valore per ciascun drawable-en configurazione le definisce bersaglio.

Gli overlay possono fare riferimento alle proprie risorse, con comportamenti diversi tra le versioni di Android.

  • In Android 11 o versioni successive, ogni overlay ha il proprio spazio ID risorsa riservato che non si sovrappone allo spazio ID risorsa di destinazione o ad altri spazi ID risorsa overlay, quindi gli overlay che fanno riferimento alle proprie risorse funzionano come previsto.

  • In Android 10 o inferiore, sovrapposizioni e pacchetti di destinazione condividono lo stesso spazio ID risorsa, che può causare collisioni e un comportamento imprevisto quando si tenta di fare riferimento le proprie risorse utilizzando il @type/name sintassi.

Abilitare/disabilitare gli overlay

Utilizzare OverlayManager API per attivare e disattivare gli overlay mutabili (recuperare l'interfaccia API utilizzando Context#getSystemService(Context.OVERLAY_SERVICE) ). Un overlay può essere attivato solo dal pacchetto si rivolge o da un pacchetto con android.permission.CHANGE_OVERLAY_PACKAGES permesso. Quando un overlay è abilitato o disabilitato, gli eventi di modifica della configurazione si propagano al pacchetto di destinazione e le attività di destinazione vengono riavviate.

Limitazione delle risorse sovrapponibili

In Android 10 o superiore, il <overlayable> tag XML espone una serie di risorse che RROs sono autorizzati a sovrapposizione. Nel seguente esempio res/values/overlayable.xml di file, string/foo e integer/bar sono risorse utilizzate per tematizzazione l'aspetto del dispositivo; per sovrapporre queste risorse, un overlay deve indirizzare esplicitamente la raccolta di risorse sovrapponibili per nome.

<!-- 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>

Un APK possibile definire più <overlayable> tag, ma ogni tag deve avere un nome univoco all'interno del pacchetto. Ad esempio, è:

  • OK per due diversi pacchetti per entrambi definiscono <overlayable name="foo"> .

  • Non OK per un singolo APK avere due <overlayable name="foo"> blocchi.

Il codice seguente mostra un esempio di una sovrapposizione nel AndroidManifest.xml file.

<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>

Quando un'applicazione definisce un <overlayable> tag, sovrappone targeting app:

  • È necessario specificare targetName .

  • Possibile sovrapporre solo le risorse elencate all'interno del <overlayable> tag.

  • Può avere come bersaglio un solo <overlayable> nome.

Non è possibile attivare un overlay mira un pacchetto che espone le risorse sovrapponibili, ma non fa uso di android:targetName di indirizzare una specifica <overlayable> tag.

Politiche di restrizione

Utilizzare il <policy> tag per imporre restrizioni sulle risorse sovrapponibili. I type specifica degli attributi che le politiche un overlay deve avere per la priorità sulle risorse inclusi. I tipi supportati includono i seguenti.

  • public . Qualsiasi sovrapposizione può sovrascrivere la risorsa.
  • system . Qualsiasi sovrapposizione sulla partizione di sistema può sovrascrivere le risorse.
  • vendor . Qualsiasi sovrapposizione sulla partizione del fornitore può sovrascrivere le risorse.
  • product . Qualsiasi sovrapposizione sulla partizione del prodotto può sovrascrivere le risorse.
  • signature . Qualsiasi overlay firmato con la stessa firma dell'APK di destinazione può sovrascrivere le risorse.

Di seguito viene mostrato un esempio di codice <policy> tag nella res/values/overlayable.xml di file.

<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>

Per specificare più criteri, utilizzare le barre verticali (|) come caratteri separatori. Quando vengono specificati più criteri, una sovrapposizione deve soddisfare un solo criterio per sostituire le risorse elencate all'interno del <policy> tag.

Configurazione degli overlay

Android supporta diversi meccanismi per configurare la mutabilità, lo stato predefinito e la priorità degli overlay a seconda della versione di Android.

  • Dispositivi con Android 11 o superiore possono utilizzare un OverlayConfig del file ( config.xml ) al posto di attributi manifeste. L'utilizzo di un file overlay è il metodo consigliato per gli overlay.

  • Tutti i dispositivi possono utilizzare gli attributi si manifestano ( android:isStatic e android:priority ) a RROs configurare statici.

Utilizzo di OverlayConfig

In Android 11 o superiore, è possibile utilizzare OverlayConfig per configurare la mutevolezza, stato di default, e la priorità di sovrapposizioni. Per configurare un overlay, creare o modificare il file che si trova a partition/overlay/config/config.xml , dove partition è la partizione della sovrapposizione da configurare. Per essere configurato, una sovrapposizione deve risiedere nella overlay/ directory della partizione in cui la sovrapposizione è configurato. Di seguito viene mostrato un esempio di codice 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>"

Il <overlay> tag richiede un package attributo che indica quale pacchetto di sovrapposizione viene configurato. L'invio facoltativo enabled controlli di attributo se la sovrapposizione è abilitato di default (il valore predefinito è false ). Gli optional mutable controlli di attributo se la sovrapposizione è mutevole e può avere il suo stato abilitato cambiato programatically a tempo di esecuzione (di default è true ). Gli overlay non elencati in un file di configurazione sono modificabili e disabilitati per impostazione predefinita.

Sovrapposizione precedenza

Quando più overlay sovrascrivono le stesse risorse, l'ordine degli overlay è importante. Un overlay ha una precedenza maggiore rispetto agli overlay con configurazioni che precedono la propria configurazione. L'ordine di precedenza degli overlay nelle diverse partizioni (dalla minima alla massima precedenza) è il seguente.

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

Unione di file

Usando <merge> tag permette di altri file di configurazione per essere uniti nella posizione specificata nel file di configurazione. Il path attributo del tag rappresenta il percorso del file da unire relativo alla directory contenente i file di configurazione di sovrapposizione.

Utilizzo degli attributi manifest (RRO statici)

In Android 10 o versioni precedenti, l'immutabilità e la precedenza dell'overlay vengono configurate utilizzando i seguenti attributi manifest.

  • android:isStatic . Quando il valore di questo attributo booleano è impostato su true , la sovrapposizione è abilitato di default ed è immutabile, che impedisce la sovrapposizione di essere disabilitato.

  • android:priority . Il valore di questo attributo numerico (che ha effetto solo sugli overlay statici) configura la precedenza dell'overlay quando più overlay statici hanno come target lo stesso valore di risorsa. Un numero più alto indica una precedenza più alta.

Il codice seguente mostra un esempio 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>

Modifiche ad Android 11

In Android 11 o superiore, se un file di configurazione si trova nella partition/overlay/config/config.xml , sovrapposizioni sono configurati utilizzando quel file e android:isStatic e android:priority non hanno un effetto sulla sovrapposizioni situati nella partizione. La definizione di un file di configurazione dell'overlay in qualsiasi partizione impone la precedenza della partizione dell'overlay.

Inoltre, Android 11 o versioni successive rimuove la possibilità di utilizzare sovrapposizioni statiche per influenzare i valori delle risorse lette durante l'installazione del pacchetto. Per il caso d'uso comune di utilizzare le sovrapposizioni statici per modificare il valore di booleani quella componente configurare lo stato abilitato, utilizzare il <component-override> SystemConfig tag (di nuovo in Android 11).

Debug degli overlay

Per abilitare, disabilitare e scaricare manualmente gli overlay, utilizzare il seguente comando shell del gestore degli overlay.

adb shell cmd overlay

OverlayManagerService usi idmap2 per mappare gli ID risorse nel pacchetto di destinazione agli ID di risorsa nel pacchetto di sovrapposizione. Le mappature ID generati sono memorizzati in /data/resource-cache/ . Se la sovrapposizione non funziona correttamente, trovare il corrispondente idmap file per il sovrapposizione in /data/resource-cache/ , quindi eseguire il seguente comando.

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

Questo comando stampa la mappatura delle risorse come mostrato di seguito.

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