Compatibilité avec les décorations système

Les mises à jour apportées à ces zones spécifiques à l'affichage sont fournies sur cette page.

Décorations système

Android 10 permet de configurer les écrans secondaires pour afficher certaines décorations système, telles que le fond d'écran, la barre de navigation et le lanceur d'applications. Par défaut, l'écran principal affiche toutes les décorations système, et les écrans secondaires affichent celles qui sont activées de manière facultative. Vous pouvez définir la compatibilité avec un éditeur de méthode d'entrée (IME) séparément des autres décorations système.

Utilisez DisplayWindowSettings#setShouldShowSystemDecorsLocked pour ajouter la compatibilité avec les décorations système sur un écran spécifique ou fournir une valeur par défaut dans /data/system/display_settings.xml. Pour obtenir des exemples, consultez Paramètres de la fenêtre d'affichage.

Implémentation

DisplayWindowSettings#setShouldShowSystemDecorsLocked est également exposé dans WindowManager#setShouldShowSystemDecors à des fins de test. Le déclenchement de cette méthode dans le but d'activer les décorations système n'ajoute pas les fenêtres de décoration qui manquaient auparavant et ne les supprime pas si elles étaient présentes. Dans la plupart des cas, la modification de la compatibilité avec les décorations système ne prend pleinement effet qu'après le redémarrage de l'appareil.

Les vérifications de la compatibilité avec les décorations système dans la base de code WindowManager passent généralement par DisplayContent#supportsSystemDecorations, tandis que les vérifications des services externes (tels que l'UI du système pour vérifier si la barre de navigation doit être affichée) utilisent WindowManager#shouldShowSystemDecors. Pour comprendre ce qui est contrôlé par ce paramètre, explorez les points d'appel de ces méthodes.

Fenêtres de décoration de l'UI du système

Android 10 ajoute la compatibilité avec les fenêtres de décoration système uniquement pour la barre de navigation, car elle est essentielle pour naviguer entre les activités et les applications. Par défaut, la barre de navigation affiche les options "Retour" et "Accueil". La barre de navigation n'est incluse que si l'écran cible est compatible avec les décorations système (voir DisplayWindowSettings).

La barre d'état est une fenêtre système plus complexe, car elle contient également le volet des notifications, les réglages rapides et l'écran de verrouillage. Dans Android 10, la barre d'état n'est pas compatible avec les écrans secondaires. Par conséquent, les notifications, les paramètres et un écran de verrouillage complet ne sont disponibles que sur l'écran principal.

La fenêtre système Vue d'ensemble ou Éléments récents n'est pas compatible avec les écrans secondaires. Dans Android 10, AOSP n'affiche les éléments récents que sur l'écran par défaut et contient les activités de tous les écrans. Lorsqu'une activité qui se trouvait sur un écran secondaire est lancée à partir des éléments récents, elle est affichée au premier plan sur cet écran, par défaut. Cette approche présente certains problèmes connus, comme le fait de ne pas se mettre à jour immédiatement lorsque des applications apparaissent sur d'autres écrans.

Implémentation

Pour implémenter des fonctionnalités supplémentaires de l'UI du système, les fabricants d'appareils doivent utiliser un seul composant d'UI du système qui écoute l'ajout ou la suppression d'écrans et présente le contenu approprié.

Un composant d'interface utilisateur du système compatible avec l'affichage multiple doit gérer les cas suivants :

  • Initialisation de plusieurs écrans au démarrage
  • Écran ajouté au moment de l'exécution
  • Écran supprimé au moment de l'exécution

Lorsque l'UI du système détecte l'ajout d'un écran avant WindowManager, elle crée une condition de concurrence. Pour éviter cela, implémentez un rappel personnalisé de WindowManager à l'UI du système lorsqu'un écran est ajouté au lieu de vous abonner aux événements DisplayManager.DisplayListener. Pour obtenir une implémentation de référence, consultez CommandQueue.Callbacks#onDisplayAddSystemDecorations pour la compatibilité avec la barre de navigation et WallpaperManagerInternal#onDisplayAddSystemDecorations pour les fonds d'écran.

De plus, Android 10 fournit les mises à jour suivantes :

  • La classe NavigationBarController contrôle toutes les fonctionnalités spécifiques aux barres de navigation.
  • Pour afficher une barre de navigation personnalisée, consultez CarStatusBar.
  • TYPE_NAVIGATION_BAR n'est plus limité à une seule instance et peut être utilisé par écran.
  • IWindowManager#hasNavigationBar est mis à jour pour n'inclure que le paramètre displayId pour l'UI du système.

Lanceur d'applications

Dans Android 10, chaque écran configuré pour prendre en charge les décorations système dispose d'une pile d'accueil dédiée pour les activités de lancement de type WindowConfiguration#ACTIVITY_TYPE_HOME, par défaut. Chaque écran utilise une instance distincte de l'activité de lancement :

Figure 1. Exemple de lanceur d'applications multi-écran pour platform/development/samples/MultiDisplay.

La plupart des lanceurs d'applications existants ne sont pas compatibles avec plusieurs instances et ne sont pas optimisés pour les grands écrans. De plus, une expérience différente est souvent attendue sur les écrans secondaires/externes. Pour fournir une activité dédiée aux écrans secondaires, Android 10 a introduit la catégorie SECONDARY_HOME dans les filtres d'intent. Les instances de cette activité sont utilisées sur tous les écrans compatibles avec les décorations système, à raison d'une par écran.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

L'activité doit avoir un mode de lancement qui n'empêche pas plusieurs instances et qui doit s'adapter à différentes tailles d'écran. Le mode de lancement ne peut pas être singleInstance ni singleTask.

Implémentation

Dans Android 10, RootActivityContainer#startHomeOnDisplay sélectionne automatiquement le composant et l'intent souhaités en fonction de l'écran sur lequel l'écran d'accueil est lancé. RootActivityContainer#resolveSecondaryHomeActivity contient la logique permettant de rechercher le composant d'activité de lancement en fonction du lanceur d'applications actuellement sélectionné et peut utiliser la valeur par défaut du système si nécessaire (voir ActivityTaskManagerService#getSecondaryHomeIntent).

Restrictions de sécurité

En plus des restrictions qui s'appliquent aux activités sur les écrans secondaires, pour éviter qu'une application malveillante ne crée un écran virtuel avec des décorations système activées et ne lise des informations sensibles de l'utilisateur à partir de la surface, le lanceur d'applications n'apparaît que sur les écrans virtuels appartenant au système. Le lanceur d'applications n'affiche pas de contenu sur les écrans virtuels non système.

Fonds d'écran

Dans Android 10 et versions ultérieures, les fonds d'écran sont compatibles avec les écrans secondaires :

Figure 2. Fond d'écran animé sur les écrans interne (en haut) et externe (en bas).

Les développeurs peuvent déclarer la compatibilité avec la fonctionnalité de fond d'écran en fournissant android:supportsMultipleDisplays="true" dans la définition XML WallpaperInfo. Les développeurs de fonds d'écran doivent également charger des éléments à l'aide du contexte d'affichage dans WallpaperService.Engine#getDisplayContext.

Le framework crée une instance WallpaperService.Engine par écran. Chaque moteur possède donc sa propre surface et son propre contexte d'affichage. Le développeur doit s'assurer que chaque moteur peut dessiner indépendamment, à des fréquences d'images différentes, en respectant VSync.

Sélectionner des fonds d'écran pour des écrans individuels

Android 10 ne fournit pas de compatibilité directe avec la plate-forme pour la sélection de fonds d'écran pour des écrans individuels. Pour ce faire, un identifiant d'écran stable est nécessaire pour conserver les paramètres de fond d'écran par écran. Display#getDisplayId est dynamique. Il n'est donc pas garanti qu'un écran physique ait le même ID après le redémarrage.

Toutefois, Android 10 a ajouté DisplayInfo.mAddress, qui contient des identifiants stables pour les écrans physiques et peut être utilisé pour une implémentation complète à l'avenir. Malheureusement, il est trop tard pour implémenter la logique pour Android 10. Solution suggérée :

  1. Utilisez la classe WallpaperManager pour définir les fonds d'écran.

    WallpaperManager est obtenu à partir d'un Context objet, et chaque objet Context contient des informations sur l'écran correspondant (Context#getDisplay/getDisplayId). Par conséquent, vous pouvez obtenir displayId à partir d'une instance WallpaperManager sans ajouter de nouvelles méthodes.

  2. Côté framework, utilisez displayId obtenu à partir d'un objet Context et mappez-le à un identifiant statique (tel qu'un port d'un écran physique). Utilisez l'identifiant statique pour conserver le fond d'écran choisi.

Cette solution de contournement utilise des implémentations existantes pour les sélecteurs de fonds d'écran. S'il a été ouvert sur un écran spécifique et utilise le bon contexte, le système peut identifier automatiquement l'écran lorsqu'il appelle pour définir un fond d'écran.

Si vous devez définir un fond d'écran pour un écran autre que l'écran actuel écran, créez un nouvel objet Context pour l'écran cible (Context#createDisplayContext) et obtenez l'instance WallpaperManager à partir de cet écran.

Restrictions de sécurité

Le système n'affiche pas de fonds d'écran sur les écrans virtuels qui ne lui appartiennent pas. Cela est dû à un problème de sécurité : une application malveillante pourrait créer un écran virtuel avec la compatibilité avec les décorations système activée et lire des informations sensibles de l'utilisateur à partir de la surface (comme une photo personnelle).

Implémentation

Dans Android 10, les interfaces IWallpaperConnection#attachEngine et IWallpaperService#attach acceptent le paramètre displayId pour créer des connexions par écran. WallpaperManagerService.DisplayConnector encapsule un moteur de fond d'écran et une connexion par écran. Dans WindowManager, les contrôleurs de fonds d'écran sont créés pour chaque objet DisplayContent lors de la construction au lieu d'un seul WallpaperController pour tous les écrans.

Certaines des implémentations de la méthode publique WallpaperManager (telles que WallpaperManager#getDesiredMinimumWidth) ont été mises à jour pour calculer et fournir des informations pour les écrans correspondants. WallpaperInfo#supportsMultipleDisplays et un attribut de ressource correspondant ont été ajoutés afin que les développeurs d'applications puissent indiquer quels fonds d'écran sont prêts pour plusieurs écrans.

Si le service de fond d'écran affiché sur l'écran par défaut n'est pas compatible avec plusieurs écrans, le système affiche le fond d'écran par défaut sur les écrans secondaires :

Figure 3. Logique de remplacement du fond d'écran pour les écrans secondaires.

Activer la compatibilité avec les fonds d'écran animés

Dans Android 10 et versions ultérieures (API 29), les développeurs peuvent utiliser l'attribut android:supportsMultipleDisplays pour indiquer si leur fond d'écran peut s'étendre sur plusieurs écrans. Dans les environnements de fenêtrage de bureau, où le multitâche est dense, le rendu de fonds d'écran animés sur des écrans externes peut avoir un impact significatif sur la surcharge du GPU et de la mémoire.

Pour préserver les ressources système, le système ne rend pas les fonds d'écran animés sur les écrans connectés par défaut. Lorsqu'un fond d'écran animé est limité par la configuration du système ou le fichier manifeste de l'application, le système affiche un fond d'écran statique de remplacement.

Les OEM peuvent ajuster cette expérience en activant la compatibilité avec les fonds d'écran animés pour le matériel haut de gamme ou en personnalisant le remplacement statique pour un aspect de marque.

Si votre matériel peut afficher plusieurs instances de fonds d'écran animés, remplacez la configuration suivante :

Chemin d'accès à la ressource frameworks/base/core/res/res/values/config.xml
Config Name (Nom de la configuration) config_isLiveWallpaperSupportedInDesktopExperience

Personnaliser le fond d'écran de remplacement

Si les fonds d'écran animés sont désactivés ou non compatibles avec le fournisseur, le système utilise un composant par défaut. Vous pouvez le rediriger vers votre propre fournisseur de fonds d'écran statiques :

Chemin d'accès à la ressource frameworks/base/core/res/res/values/config.xml
Config Name (Nom de la configuration) fallback_wallpaper_component

Implémenter la compatibilité avec les fonds d'écran

Pour appliquer ces modifications, utilisez une superposition de ressources au moment de la compilation dans le dossier spécifique à votre appareil, qui est généralement device/<vendor>/<product>/overlay/frameworks/base/core/res/res/values/.