Compatibilité avec les annonces display

Vous trouverez ci-dessous les modifications apportées à ces zones spécifiques au Réseau Display:

Redimensionner les activités et les écrans

Pour indiquer qu'une appli peut ne pas prendre en charge le mode multifenêtre ou le redimensionnement, les activités utilisent l'attribut resizeableActivity=false. Commun Voici quelques problèmes rencontrés par les applications lorsque les activités sont redimensionnées:

  • Une activité peut avoir une configuration différente de celle de l'application ou d'une autre un composant non visuel. Une erreur courante consiste à lire les métriques d'affichage à partir de l'application. le contexte. Les valeurs renvoyées ne seront pas ajustées en fonction des métriques sur les zones visibles dans où une activité est affichée.
  • Une activité peut ne pas gérer le redimensionnement et le plantage, afficher une UI déformée, ou perdre l'état suite à un redémarrage sans enregistrer l'état de l'instance.
  • Une application peut tenter d'utiliser des coordonnées d'entrée absolues (au lieu de par rapport à la position de la fenêtre), ce qui peut interrompre l'entrée le mode multifenêtre.

Sous Android 7 (ou version ultérieure), vous pouvez définir une application resizeableActivity=false pour toujours s'exécuter en mode plein écran. Dans dans ce cas, la plate-forme empêche les activités non redimensionnables d'être divisées l'écran. Si l'utilisateur tente d'appeler une activité non redimensionnable à partir du lanceur d'applications lorsqu'elle est déjà en mode Écran partagé, la plate-forme quitte le mode Écran partagé et lance l'activité non redimensionnable en mode plein écran.

Les applications qui définissent explicitement cet attribut sur false dans le fichier manifeste ne doit pas être lancé en mode multifenêtre, à moins que le fichier est appliqué:

  • La même configuration est appliquée au processus, qui contient toutes les activités et hors activité.
  • La configuration appliquée respecte les exigences du CDD pour la compatibilité avec les applications s'affiche.

Sous Android 10, la plate-forme empêche toujours les activités non redimensionnables de passer en mode Écran partagé, mais elles peuvent être temporairement mis à l'échelle si l'activité a déclaré une orientation ou un aspect fixe le ratio. Sinon, l'activité est redimensionnée pour remplir tout l'écran, comme dans Android. 9 et versions antérieures.

L'implémentation par défaut applique la règle suivante:

Lorsqu'une activité déclarée incompatible avec le mode multifenêtre via utiliser l'attribut android:resizeableActivity. s'applique à l'une des conditions décrites ci-dessous, puis lorsque la requête la configuration de l'écran doit changer, l'activité et le processus sont enregistrés configuration d'origine et l'utilisateur reçoit une affordance pour le relancer processus d'application pour utiliser la configuration d'écran mise à jour.

  • Est à orientation fixe via l'application android:screenOrientation
  • L'application utilise un format maximal ou minimal par défaut en fonction du niveau d'API ciblé ou déclare explicitement le format

Cette figure montre une activité non redimensionnable dont le format a été déclaré. Lorsque vous pliez l'appareil, la fenêtre est réduite pour s'adapter à la zone tout en en conservant les proportions en utilisant le format letterbox approprié. De plus, un l'option "redémarrer l'activité" est proposée à l'utilisateur chaque fois que la zone d'affichage de l'activité est modifiée.

Lorsque vous dépliez l'appareil, la configuration, la taille et le format activité ne change pas, mais l’option pour redémarrer l’activité s’affiche.

Lorsque resizeableActivity n'est pas défini (ou est défini sur true), l'application est entièrement compatible avec le redimensionnement.

Implémentation

Une activité non redimensionnable avec une orientation ou un format fixe est appelée le mode de compatibilité de taille (SCM) dans le code. La condition est définie dans ActivityRecord#shouldUseSizeCompatMode() Lorsqu'une activité SCM est la configuration liée à l'écran (comme la taille ou la densité) est fixe. dans la configuration de remplacement demandée, de sorte que l'activité ne dépend plus sur la configuration d'affichage actuelle.

Si l'activité SCM ne peut pas remplir tout l'écran, elle est alignée en haut et centré horizontalement. Les limites d'activité sont calculées AppWindowToken#calculateCompatBoundsTransformation()

Lorsqu'une activité SCM utilise une configuration d'écran différente de celle conteneur (par exemple, l'écran est redimensionné ou l'activité est déplacée vers une autre display), ActivityRecord#inSizeCompatMode() est "true" et SizeCompatModeActivityController (dans l'UI du système) reçoit les rappel pour afficher le bouton de redémarrage du processus.

Tailles et formats d'affichage

Android 10 est compatible avec de nouveaux formats des rapports élevés d'écrans longs et fins à des rapports 1:1. Les applications peuvent définir ApplicationInfo#maxAspectRatio et le ApplicationInfo#minAspectRatio de l'écran à gérer.

formats d'application dans Android 10

Figure 1 : Exemples de formats d'application compatibles avec Android 10.

Les implémentations d'appareils peuvent avoir des écrans secondaires avec des tailles et inférieures à celles requises par Android 9 ou inférieures (minimum 2, 5 en largeur ou en hauteur, minimale de 320 DP pour smallestScreenWidth), mais seules les activités compatibles avec ces petits écrans peuvent être placées ici.

Les applications peuvent l'activer en déclarant une taille minimale prise en charge inférieure à ou égal à la taille d'affichage cible. Utiliser android:minHeight et Attributs de mise en page de l'activité android:minWidth dans AndroidManifest.

Règles d'affichage

Android 10 sépare et déplace certains écrans de l'implémentation par défaut de WindowManagerPolicy dans PhoneWindowManager à des classes par écran, telles que:

  • État et rotation de l'écran
  • Quelques touches et suivi des événements de mouvement
  • UI du système et fenêtres de décoration

Sous Android 9 (et versions antérieures), la classe PhoneWindowManager gérait règles d'affichage, état et paramètres, rotation, cadre de la fenêtre de décoration le suivi, etc. Android 10 migre la majeure partie la classe DisplayPolicy, à l'exception du suivi de la rotation, qui a été déplacé vers DisplayRotation.

Paramètres de la fenêtre d'affichage

Sous Android 10, le paramètre configurable par écran Le paramètre de fenêtrage a été étendu pour inclure:

  • Mode de fenêtrage d'affichage par défaut
  • Valeurs de surbalayage
  • Rotation et mode de rotation des utilisateurs
  • Taille, densité et mode de scaling imposés
  • Mode de suppression de contenu (lorsque l'écran est retiré)
  • Prise en charge des décorations système et IME

La classe DisplayWindowSettings contient des paramètres pour ces options. Ils sont conservés sur le disque dans la partition /data dans display_settings.xml chaque fois qu'un paramètre est modifié. Pour détails, consultez DisplayWindowSettings.AtomicFileStorage et DisplayWindowSettings#writeSettings() Les fabricants d'appareils peuvent fournissent des valeurs par défaut dans display_settings.xml pour leur appareil configuration. Toutefois, comme le fichier est stocké dans /data, une logique supplémentaire peut être nécessaire pour restaurer le fichier s'il est effacé par un effacement de données.

Par défaut, Android 10 utilise DisplayInfo#uniqueId en tant qu'identifiant d'un écran lorsqu'il est persistant les paramètres. uniqueId doit être renseigné pour tous les écrans. Dans De plus, il est stable pour les écrans physiques et réseau. Il est également possible de utiliser le port d'un écran physique comme identifiant, qui peut être défini dans DisplayWindowSettings#mIdentifier À chaque écriture, tous les paramètres sont écrites afin de pouvoir mettre à jour sans risque la clé utilisée pour une entrée d'affichage dans stockage. Pour en savoir plus, consultez Identifiants d'affichage statique.

Les paramètres sont conservés dans le répertoire /data pour l'historique raisons. À l'origine, ils étaient utilisés pour conserver les paramètres définis par l'utilisateur, tels que la rotation de l'écran.

Identifiants d'affichage statique

Android 9 (et versions antérieures) ne fournissait pas d'identifiants stables pour les écrans dans d'infrastructure. Lorsqu'un écran a été ajouté au système, Display#mDisplayId ou DisplayInfo#displayId était généré pour cet affichage en incrémentant un compteur statique. Si le système ajouté et supprimé le même affichage, un ID différent est généré.

Si plusieurs écrans sont disponibles au démarrage sur un appareil, il est possible qu'ils soient des identifiants différents, selon le moment. Bien qu'Android 9 (et précédemment) incluait DisplayInfo#uniqueId, qui n'en contenait pas assez pour différencier les écrans, car les supports physiques étaient identifié comme local:0 ou local:1, pour représenter l'écran intégré et l'écran externe.

Modifications apportées à Android 10 DisplayInfo#uniqueId d'ajouter un identifiant stable et de différencier écrans virtuels.

Type d'affichage Format
Local
local:<stable-id>
Réseau
network:<mac-address>
Virtuel
virtual:<package-name-and-name>

En plus des modifications apportées à uniqueId, DisplayInfo.address contient DisplayAddress, un un identifiant d'affichage stable entre les redémarrages. Sur Android 10, DisplayAddress prend en charge les et les affichages du réseau. DisplayAddress.Physical contient un élément stable ID display (identique à uniqueId) et peuvent être créés avec DisplayAddress#fromPhysicalDisplayId()

Android 10 constitue également une méthode pratique informations sur le port (Physical#getPort()). Cette méthode peut être utilisée le framework d'identifier les écrans de manière statique. Par exemple, il est utilisé dans DisplayWindowSettings). DisplayAddress.Network contient l'adresse MAC et peut être créé avec DisplayAddress#fromMacAddress()

Ces ajouts permettent aux fabricants d'appareils d'identifier les écrans dans des images configurations multi-écrans, et pour configurer différents paramètres et fonctionnalités système à l'aide d'identifiants d'affichage statiques, tels que les ports d'écrans physiques. Ces méthodes sont masquées et ne sont destinées qu'à être utilisées system_server

Avec un identifiant d'affichage HWC (qui peut être opaque et pas toujours stable), cela renvoie le numéro de port 8 bits (spécifique à la plate-forme) qui identifie un connecteur physique pour la sortie d'affichage, ainsi que le blob EDID de l'écran. SurfaceFlinger extrait les informations sur le fabricant ou le modèle de l'EDID pour générer les ID d'affichage 64 bits stables exposés au framework. Si cette méthode n'est pas pris en charge ou des erreurs, SurfaceFlinger revient à l'ancien mode MD, où DisplayInfo#address est nul et DisplayInfo#uniqueId est codé en dur, comme décrit ci-dessus.

Pour vérifier que cette fonctionnalité est compatible, exécutez la commande suivante:

$ dumpsys SurfaceFlinger --display-id
# Example output.
Display 21691504607621632 (HWC display 0): port=0 pnpId=SHP displayName="LQ123P1JX32"
Display 9834494747159041 (HWC display 2): port=1 pnpId=HWP displayName="HP Z24i"
Display 1886279400700944 (HWC display 1): port=2 pnpId=AUS displayName="ASUS MB16AP"

Utiliser plus de deux écrans

Sous Android 9 (et versions antérieures), SurfaceFlinger et DisplayManagerService a supposé l'existence de deux écrans physiques au maximum avec des ID 0 codés en dur et 1.

À partir d'Android 10, SurfaceFlinger pouvait exploiter L'API Hardware Composer (HWC) pour générer des ID d'affichage stables, ce qui lui permet de gérer un nombre arbitraire d'écrans physiques. Pour en savoir plus, consultez Identifiants d'affichage statique.

Le framework peut rechercher le jeton IBinder pour un jeton physique afficher via SurfaceControl#getPhysicalDisplayToken après avoir obtenu l'ID d'affichage 64 bits de SurfaceControl#getPhysicalDisplayIds ou à partir d'un événement de connexion à chaud DisplayEventReceiver.

Sous Android 10 (et versions antérieures), l'écran interne principal est TYPE_INTERNAL et tous les écrans secondaires sont signalés comme TYPE_EXTERNAL quel que soit le type de connexion. Par conséquent, tout écran interne supplémentaire est considéré comme externe. Pour contourner ce problème, le code spécifique à l'appareil peut émettre des hypothèses sur DisplayAddress.Physical#getPort si le HWC est connu et l'allocation de ports est prévisible.

Cette limitation a été supprimée dans Android 11 (et versions ultérieures).

  • Dans Android 11, le premier écran signalé au démarrage est l'écran principal. Le type de connexion (interne ou externe) n'a pas d'importance. Cependant, il reste vrai que l'écran principal ne peut pas être déconnecté et suit ce qui suit : il doit s'agir d'un affichage interne. Notez que certains téléphones pliables possèdent plusieurs écrans internes.
  • Les écrans secondaires sont classés correctement dans la catégorie Display.TYPE_INTERNAL ou Display.TYPE_EXTERNAL (anciennement Display.TYPE_BUILT_IN et Display.TYPE_HDMI, respectivement) en fonction de leur type de connexion.

Implémentation

Sous Android 9 et versions antérieures, les écrans sont identifiés par des ID 32 bits, où 0 correspond à l'écran interne, 1 à l'écran externe, [2, INT32_MAX] sont des écrans virtuels HWC, et "-1" représente un écran non valide ou un écran virtuel non HWC.

À partir d'Android 10, les écrans sont stables et persistants, ce qui permet à SurfaceFlinger et DisplayManagerService pour suivre plus de deux écrans et reconnaître ceux déjà vus. Si le matériel prend en charge IComposerClient.getDisplayIdentificationData et fournit des ressources d'affichage d'identification, SurfaceFlinger analyse la structure de l'EDID et attribue des valeurs ID d'affichage 64 bits pour les écrans virtuels physiques et physiques Les identifiants sont exprimés à l'aide de Un type d'option, où la valeur nulle représente un affichage non valide ou une VM l'écran. Sans compatibilité HWC, SurfaceFlinger revient à l'ancien comportement avec deux écrans physiques.

Sélection par écran

Pour prendre en charge plusieurs sources d'entrée qui ciblent à la fois des écrans individuels temps, Android 10 peut être configuré pour prendre en charge plusieurs pour chacune des fenêtres sélectionnées, au maximum une par écran. Ceci est destiné uniquement aux cas d'utilisation Types d'appareils lorsque plusieurs utilisateurs interagissent avec le même appareil à la fois et utilisent différents modes de saisie ou périphériques, comme Android Automobile.

Il est fortement recommandé de ne pas activer cette fonctionnalité pour Les appareils standards, y compris les appareils multi-écrans ou ceux utilisés pour les ordinateurs de bureau expériences. Cela est principalement dû à un problème de sécurité susceptible à se demander quelle fenêtre est sélectionnée en entrée.

Imaginez que l’utilisateur qui saisit des informations sécurisées dans un champ de saisie de texte, en se connectant à une application bancaire ou en saisissant du texte contenant des informations des informations. Une application malveillante pourrait créer un affichage virtuel hors écran avec exécuter une activité, également avec un champ de saisie de texte. Légalité et les activités malveillantes sont ciblées et affichent toutes deux un indicateur de saisie active (curseur clignotant).

Cependant, étant donné que la saisie à partir d'un clavier (matériel ou logiciel) est saisie dans l'activité la plus élevée uniquement (l'application la plus récemment lancée), par créant un affichage virtuel caché, une application malveillante pourrait capturer l'entrée utilisateur, lorsque vous utilisez un clavier virtuel sur l'écran principal de l'appareil.

Utiliser com.android.internal.R.bool.config_perDisplayFocusEnabled pour définir la sélection par écran.

Compatibilité

Problème:sur Android 9 ou version antérieure, une seule fenêtre au maximum dans la au système actif à un moment donné.

Solution:dans les rares cas où deux fenêtres du même processus serait ciblé, le système ne sélectionne que la fenêtre qui est plus haut dans l'ordre Z. Cette restriction est supprimée pour les applications qui ciblent Android 10, on s'attend à ce qu'ils puissent prendre en charge que plusieurs fenêtres soient sélectionnées simultanément.

Implémentation

WindowManagerService#mPerDisplayFocusEnabled contrôle les la disponibilité de cette fonctionnalité. Dans ActivityManager, ActivityDisplay#getFocusedStack() est désormais utilisé à la place de l'option globale le suivi dans une variable. ActivityDisplay#getFocusedStack() détermine l'objectif en fonction de l'ordre de plan au lieu de mettre en cache la valeur. Ainsi, une seule source, WindowManager, doit suivre l'ordre de plan des activités.

ActivityStackSupervisor#getTopDisplayFocusedStack() prend un une approche similaire pour les cas où la pile la plus ciblée du système doit être identifié. Les piles sont balayées de haut en bas, à la recherche de la première pile éligible.

InputDispatcher peut désormais avoir plusieurs fenêtres sélectionnées (un par écran). Si un événement d'entrée est spécifique à l'affichage, il est envoyé. à la fenêtre sélectionnée de l'écran correspondant. Sinon, il est envoyé à la fenêtre sélectionnée dans l'écran sélectionné, qui correspond à l'écran sur lequel l'utilisateur avez interagi le plus récemment.

Voir InputDispatcher::mFocusedWindowHandlesByDisplay et InputDispatcher::setFocusedDisplay() Les applis sélectionnées sont aussi mises à jour séparément dans InputManagerService, NativeInputManager::setFocusedApplication()

Dans WindowManager, les fenêtres sélectionnées font également l'objet d'un suivi séparé. Voir DisplayContent#mCurrentFocus et DisplayContent#mFocusedApp et leurs utilisations respectives. Thème connexe les méthodes de suivi et de mise à jour De WindowManagerService à DisplayContent.