Une superposition de ressources d'exécution (RRO) est un package qui modifie les valeurs de ressources d'un package cible au moment de l'exécution. Par exemple, une application installée sur l'image système peut modifier son comportement en fonction de la valeur d'une ressource. Plutôt que de coder en dur la valeur de la ressource au moment de la compilation, un RRO installé sur une autre partition peut modifier les valeurs des ressources de l'application au moment de l'exécution.
Les RRO peuvent être activés ou désactivés. Vous pouvez définir de manière programmatique l'état d'activation/de désactivation pour activer ou désactiver la possibilité d'un RRO de modifier les valeurs de ressources. Les RRO sont désactivés par défaut (les RRO statiques sont toutefois activés par défaut).
Ressources superposées
Les superpositions fonctionnent en mappant les ressources définies dans le package de superposition aux ressources définies dans le package cible. Lorsqu'une application tente de résoudre la valeur d'une ressource dans le package cible, la valeur de la ressource de superposition à laquelle la ressource cible est mappée est renvoyée à la place.
Configurer le fichier manifeste
Un package est considéré comme un package RRO s'il contient une balise <overlay>
en tant qu'enfant de la balise <manifest>
.
La valeur de l'attribut
android:targetPackage
obligatoire spécifie le nom du package que le RRO entend superposer.La valeur de l'attribut
android:targetName
facultatif spécifie le nom du sous-ensemble de ressources superposables du package cible que le RRO a l'intention de superposer. Si la cible ne définit pas d'ensemble de ressources superposables, cet attribut ne doit pas être présent.
Le code suivant montre un exemple de AndroidManifest.xml
de superposition.
<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>
Les superpositions ne peuvent pas se superposer au code. Elles ne peuvent donc pas contenir de fichiers DEX. En outre, l'attribut android:hasCode
de la balise <application
> du fichier manifeste doit être défini sur false
.
Définir la carte des ressources
Sous Android 11 ou version ultérieure, le mécanisme recommandé pour définir la carte des ressources de superposition consiste à créer un fichier dans le répertoire res/xml
du package de superposition, à énumérer les ressources cibles à superposer et leurs valeurs de remplacement, puis à définir la valeur de l'attribut android:resourcesMap
de la balise manifeste <overlay>
sur une référence au fichier de mappage des ressources.
Le code suivant illustre un exemple de fichier 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>
Le code suivant illustre un exemple de fichier manifeste de superposition.
<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>
Créer le package
Android 11 ou version ultérieure est compatible avec une règle de compilation Soong pour les superpositions qui empêche Android Asset Packaging Tool 2 (AAPT2) de tenter de dédupliquer les configurations de ressources ayant la même valeur (--no-resource-deduping
) et de supprimer les ressources sans configurations par défaut (--no-resource-removal
). Le code suivant montre un exemple de fichier Android.bp
.
runtime_resource_overlay {
name: "ExampleOverlay",
sdk_version: "current",
}
Résoudre les ressources
Si une ressource cible ou une ressource de superposition comporte plusieurs configurations définies pour la ressource interrogée, l'environnement d'exécution des ressources renvoie la valeur de la configuration qui correspond le mieux à la configuration de l'appareil. Pour déterminer la configuration la plus pertinente, fusionnez l'ensemble des configurations de ressources en superposition avec l'ensemble des configurations de ressources cibles, puis suivez le flux de résolution de ressources standard (pour en savoir plus, consultez la section Comment Android détermine-t-il la ressource la plus pertinente ?).
Par exemple, si une superposition définit une valeur pour la configuration drawable-en
et que la cible définit une valeur pour drawable-en-port
, drawable-en-port
est une meilleure correspondance. La valeur de la configuration cible drawable-en-port
est donc choisie au moment de l'exécution. Pour superposer toutes les configurations drawable-en
, la superposition doit définir une valeur pour chaque configuration drawable-en
définie par la cible.
Les superpositions peuvent faire référence à leurs propres ressources, avec des comportements différents entre les versions d'Android.
Sous Android 11 ou version ultérieure, chaque superposition dispose de son propre espace d'ID de ressource réservé qui ne se chevauche pas avec l'espace d'ID de ressource cible ni avec d'autres espaces d'ID de ressource de superposition. Les superpositions qui font référence à leurs propres ressources fonctionnent donc comme prévu.
Sous Android 10 ou version antérieure, les superpositions et les packages cibles partagent le même espace d'ID de ressource, ce qui peut entraîner des collisions et un comportement inattendu lorsqu'ils tentent de référencer leurs propres ressources à l'aide de la syntaxe
@type/name
.
Activer/Désactiver les superpositions
Les superpositions peuvent être activées/désactivées manuellement et de manière programmatique.
Désactiver ou activer manuellement les superpositions
Pour activer et valider manuellement un RRO, exécutez la commande suivante:
adb shell cmd overlay enable --user current com.example.carrro
adb shell cmd overlay list --user current | grep -i com.example com.example.carrro
Cela active le RRO pour l'utilisateur système (userId = 0
) qui est propriétaire de SystemUI.
Cette instruction n'affecte pas les applications lancées par l'utilisateur de premier plan (userId = 10
). Pour activer le RRO pour l'utilisateur de premier plan, utilisez le paramètre -–user 10
:
adb shell cmd overlay enable --user 10 com.example.carrro
Activer ou désactiver des superpositions de manière programmatique
Utilisez l'API OverlayManager
pour activer et désactiver les superpositions modifiables (récupérez l'interface de l'API à l'aide de Context#getSystemService(Context.OVERLAY_SERVICE)
). Une superposition ne peut être activée que par le package qu'elle cible ou par un package disposant de l'autorisation android.permission.CHANGE_OVERLAY_PACKAGES
. Lorsqu'une superposition est activée ou désactivée, les événements de modification de la configuration se propagent au package cible et les activités cibles sont redémarrées.
Limiter les ressources superposables
Sous Android 10 ou version ultérieure, la balise XML <overlayable>
expose un ensemble de ressources que les RRO peuvent superposer. Dans l'exemple de fichier res/values/overlayable.xml
suivant, string/foo
et integer/bar
sont des ressources utilisées pour thématiser l'apparence de l'appareil. Pour superposer ces ressources, une superposition doit cibler explicitement la collection de ressources superposables par nom.
<!-- 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 peut définir plusieurs balises <overlayable>
, mais chaque balise doit avoir un nom unique dans le package. Par exemple:
Autorisez deux packages différents à définir
<overlayable name="foo">
.Un seul APK ne doit pas contenir deux blocs
<overlayable name="foo">
.
Le code suivant montre un exemple de superposition dans le fichier 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>
Lorsqu'une application définit une balise <overlayable>
, les superpositions ciblant cette application:
Vous devez spécifier
targetName
.Ne peut recouvrir que les ressources listées dans la balise
<overlayable>
.Ne peut cibler qu'un seul nom
<overlayable>
.
Vous ne pouvez pas activer une superposition ciblant un package qui expose des ressources superposables, mais qui n'utilise pas android:targetName
pour cibler une balise <overlayable>
spécifique.
Règles de restriction
Utilisez la balise <policy>
pour appliquer des restrictions aux ressources superposables. L'attribut type
spécifie les règles qu'une superposition doit respecter pour remplacer les ressources incluses. Les types acceptés sont les suivants :
public
. Toute superposition peut remplacer la ressource.system
. Toute superposition sur la partition système peut remplacer les ressources.vendor
. Toute superposition sur la partition du fournisseur peut remplacer les ressources.product
. Toute superposition sur la partition de produit peut remplacer les ressources.oem
. Toute superposition sur la partition OEM peut remplacer les ressources.odm
. Toute superposition sur la partition odm peut remplacer les ressources.signature
. Toute superposition signée avec la même signature que l'APK cible peut remplacer les ressources.actor
. Toute superposition signée avec la même signature que l'APK de l'acteur peut remplacer les ressources. L'acteur est déclaré dans la balise named-actor dans la configuration système.config_signature
. Toute superposition signée avec la même signature que l'APK overlay-config peut remplacer les ressources. La configuration de superposition est déclarée dans la balise overlay-config-signature dans la configuration système.
Le code suivant montre un exemple de balise <policy>
dans le fichier 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>
Pour spécifier plusieurs règles, utilisez des barres verticales (|) comme caractères séparateurs.
Lorsque plusieurs règles sont spécifiées, une superposition ne doit respecter qu'une seule règle pour remplacer les ressources listées dans la balise <policy>
.
Configurer des superpositions
Android propose différents mécanismes pour configurer la mutabilité, l'état par défaut et la priorité des superpositions en fonction de la version d'Android.
Les appareils équipés d'Android 11 ou version ultérieure peuvent utiliser un fichier
OverlayConfig
(config.xml
) au lieu d'attributs de fichier manifeste. La méthode recommandée pour les superpositions consiste à utiliser un fichier de superposition.Tous les appareils peuvent utiliser des attributs de fichier manifeste (
android:isStatic
etandroid:priority
) pour configurer des RRO statiques.
Utiliser OverlayConfig
Dans Android 11 ou version ultérieure, vous pouvez utiliser OverlayConfig
pour configurer la mutabilité, l'état par défaut et la priorité des superpositions. Pour configurer une superposition, créez ou modifiez le fichier situé à partition/overlay/config/config.xml
, où partition
est la partition de la superposition à configurer. Pour être configuré, un calque doit se trouver dans le répertoire overlay/
de la partition dans laquelle il est configuré. Le code suivant illustre un exemple de fichier 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>"
La balise <overlay>
nécessite un attribut package
qui indique le package de superposition en cours de configuration. L'attribut enabled
facultatif contrôle si la superposition est activée par défaut (false
par défaut). L'attribut mutable
facultatif contrôle si la superposition est modifiable et si son état activé peut être modifié par programmation au moment de l'exécution (true
par défaut). Les superpositions qui ne sont pas listées dans un fichier de configuration sont modifiables et désactivées par défaut.
Priorité des superpositions
Lorsque plusieurs superpositions remplacent les mêmes ressources, l'ordre des superpositions est important. Une superposition a une priorité plus élevée que les superpositions dont les configurations précèdent sa propre configuration. L'ordre de priorité des superpositions dans différentes partitions (de la priorité la plus faible à la priorité la plus élevée) est le suivant.
system
vendor
odm
oem
product
system_ext
Fusionner des fichiers
L'utilisation de balises <merge>
permet de fusionner d'autres fichiers de configuration à l'emplacement spécifié dans le fichier de configuration. L'attribut path
de la balise représente le chemin d'accès du fichier à fusionner par rapport au répertoire contenant les fichiers de configuration de superposition.
Utiliser des attributs de fichier manifeste/des RRO statiques
Sous Android 10 ou version antérieure, l'immuabilité et la priorité des superpositions sont configurées à l'aide des attributs de fichier manifeste suivants.
android:isStatic
. Lorsque la valeur de cet attribut booléen est définie surtrue
, la superposition est activée par défaut et est immuable, ce qui empêche sa désactivation.android:priority
. La valeur de cet attribut numérique (qui ne concerne que les superpositions statiques) configure la priorité de la superposition lorsque plusieurs superpositions statiques ciblent la même valeur de ressource. Plus le nombre est élevé, plus la priorité est élevée.
Le code suivant illustre un exemple de 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>
Modifications apportées à Android 11
Sous Android 11 ou version ultérieure, si un fichier de configuration se trouve dans partition/overlay/config/config.xml
, les superpositions sont configurées à l'aide de ce fichier, et android:isStatic
et android:priority
n'ont aucune incidence sur les superpositions situées dans la partition. La définition d'un fichier de configuration de superposition dans n'importe quelle partition applique la priorité de la partition de superposition.
De plus, Android 11 ou version ultérieure supprime la possibilité d'utiliser des superpositions statiques pour affecter les valeurs des ressources lues lors de l'installation du package. Pour le cas d'utilisation courant consistant à utiliser des superpositions statiques pour modifier la valeur des booléens qui configurent l'état d'activation du composant, utilisez la balise SystemConfig
<component-override>
(nouvelle dans Android 11).
Superpositions de débogage
Pour activer, désactiver et vider manuellement les superpositions, utilisez la commande shell du gestionnaire de superpositions suivante.
adb shell cmd overlay
L'utilisation de enable
sans spécifier d'utilisateur affecte l'utilisateur actuel, c'est-à-dire l'utilisateur système (userId = 0
), qui est propriétaire de l'UI système. Cela n'affecte pas l'utilisateur au premier plan (userId = 10
), qui est propriétaire des applications. Pour activer le RRO pour l'utilisateur au premier plan, utilisez le paramètre –-user 10
:
adb shell cmd overlay enable --user 10 com.example.carrro
OverlayManagerService
utilise idmap2
pour mapper les ID de ressources du package cible aux ID de ressources du package de superposition. Les mappages d'ID générés sont stockés dans /data/resource-cache/
. Si votre superposition ne fonctionne pas correctement, recherchez le fichier idmap
correspondant à votre superposition dans /data/resource-cache/
, puis exécutez la commande suivante.
adb shell idmap2 dump --idmap-path [file]
Cette commande affiche le mappage des ressources, comme illustré ci-dessous.
[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType