Les modifications apportées à ces zones spécifiques à l'affichage sont indiquées ci-dessous :
- Décorations du système
- Fenêtres de décoration de l'UI du système
- Lanceur d'applications
- Fonds d'écran
Décorations système
Android 10 permet de configurer des é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 éventuellement activées. La prise en charge d'un éditeur de méthode d'entrée (IME) peut être définie séparément des autres décorations système.
Utilisez DisplayWindowSettings#setShouldShowSystemDecorsLocked()
pour ajouter la prise en charge des décorations système sur un écran spécifique ou pour fournir une valeur par défaut dans /data/system/display_settings.xml
. Pour obtenir des exemples, consultez la section 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 avec l'intention d'activer les décors système n'ajoute pas de fenêtres de décoration qui étaient auparavant manquantes, ni ne les supprime si elles étaient auparavant présentes. Dans la plupart des cas, la modification de la prise en charge des décorations système ne prend pleinement effet qu'après le redémarrage de l'appareil.
Les vérifications de la prise en charge des 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 (telles que l'UI 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 la fenêtre de décoration du système pour la barre de navigation uniquement, car la barre de navigation est essentielle pour naviguer entre les activités et les applications. Par défaut, la barre de navigation affiche les affordances "Retour" et "Accueil". Cette valeur 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. Sous Android 10, la barre d'état n'est pas compatible avec les écrans secondaires. Par conséquent, les notifications, les paramètres et un clavier complet ne sont disponibles que sur l'écran principal.
La fenêtre système Vue d'ensemble/Éléments récents n'est pas compatible avec les écrans secondaires. Dans Android 10, AOSP n'affiche que les éléments récents sur l'écran par défaut et contient les activités de tous les écrans. Lorsqu'elle est lancée à partir de "Récents", une activité qui se trouvait sur un écran secondaire est mise en avant sur cet écran, par défaut. Cette approche présente certains problèmes connus, par exemple, elle ne s'actualise pas immédiatement lorsque des applications apparaissent sur d'autres écrans.
Implémentation
Pour implémenter des fonctionnalités d'UI système supplémentaires, les fabricants d'appareils doivent utiliser un seul composant d'UI système qui écoute l'ajout/la suppression d'écrans et présente le contenu approprié.
Un composant d'UI système compatible avec le multi-écran (MD) doit gérer les cas suivants:
- Initialisation de plusieurs écrans au démarrage
- Écran ajouté au moment de l'exécution
- Affichage supprimé au moment de l'exécution
Lorsque l'UI système détecte l'ajout d'un écran avant WindowManager, une condition de course est créée. Pour éviter cela, implémentez un rappel personnalisé de WindowManager à l'UI système lorsqu'un écran est ajouté au lieu de vous abonner aux événements DisplayManager.DisplayListener
. Pour une implémentation de référence, consultez CommandQueue.Callbacks#onDisplayReady
pour la prise en charge de la barre de navigation et WallpaperManagerInternal#onDisplayReady
pour les fonds d'écran.
En outre, Android 10 apporte 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 inclure le paramètredisplayId
pour l'UI du système uniquement.
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 du lanceur d'applications de type WindowConfiguration#ACTIVITY_TYPE_HOME
, par défaut. Chaque écran utilise une instance distincte d'activité du lanceur d'applications.
Figure 1 : Exemple de lanceur multi-écran pour platform/development/samples/MultiDisplay
La plupart des lanceurs existants ne sont pas compatibles avec plusieurs instances et ne sont pas optimisés pour les grands écrans. De plus, un type d'expérience différent est souvent attendu sur les écrans secondaires/externes. Pour fournir une activité dédiée aux écrans secondaires, Android 10 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 doit s'adapter à différentes tailles d'écran. Le mode de lancement ne peut pas être singleInstance
ni singleTask
.
Implémentation
Sous 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é du lanceur en fonction du lanceur 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 les décorations système activées et ne lise des informations sensibles à 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
Sous 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 internes (ci-dessus) et externes (ci-dessous)
Les développeurs peuvent déclarer la prise en charge de 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 dispose donc de sa propre surface et de son propre contexte d'affichage. Le développeur doit s'assurer que chaque moteur peut dessiner indépendamment, à différentes fréquences d'images, en respectant VSYNC.
Sélectionner des fonds d'écran pour des écrans individuels
Android 10 ne prend pas en charge directement 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 du fond d'écran par écran.
Display#getDisplayId()
étant dynamique, rien ne garantit qu'un écran physique aura le même ID après le redémarrage.
Cependant, 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:
- Utilisez l'API
WallpaperManager
pour définir les fonds d'écran. WallpaperManager
est obtenu à partir d'un objetContext
, et chaque objetContext
contient des informations sur l'écran correspondant (Context#getDisplay()/getDisplayId()
). Par conséquent, vous pouvez obtenirdisplayId
à partir d'une instanceWallpaperManager
sans ajouter de nouvelles méthodes.- Côté framework, utilisez
displayId
à partir d'un objetContext
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 les implémentations existantes pour les sélecteurs de fond d'écran. S'il a été ouvert sur un écran spécifique et qu'il utilise le bon contexte, le système peut identifier automatiquement l'écran lorsqu'il appelle la méthode pour définir un fond d'écran.
Si vous devez définir un fond d'écran pour un écran autre que l'écran actuel, créez un 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 dont il n'est pas propriétaire. Cela est dû à un problème de sécurité, car une application malveillante pourrait créer un écran virtuel avec la prise en charge des décorations système activée et lire des informations sensibles à l'utilisateur à partir de la surface (telles qu'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 et une connexion de fond d'écran par écran. Dans WindowManager, des contrôleurs de fond d'écran sont créés pour chaque objet DisplayContent
lors de la création au lieu d'un seul WallpaperController
pour tous les écrans.
Certaines implémentations de méthodes WallpaperManager
publiques (telles que WallpaperManager#getDesiredMinimumWidth()
) ont été mises à jour pour calculer et fournir des informations pour les affichages correspondants.
WallpaperInfo#supportsMultipleDisplays()
et un attribut de ressource correspondant ont été ajoutés afin que les développeurs d'applications puissent indiquer les fonds d'écran 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