Extensions WindowManager

La bibliothèque Jetpack WindowManager permet aux développeurs d'applications d'exploiter de nouveaux facteurs de forme d'appareil et de nouveaux environnements multifenêtres.

WindowManager Extensions (Extensions) est un module de plate-forme Android activable qui permet d'utiliser diverses fonctionnalités de Jetpack WindowManager. Le module est implémenté dans AOSP dans frameworks/base/libs/WindowManager/Jetpack et fourni sur les appareils compatibles avec les fonctionnalités WindowManager.

Distribution du module d'extensions

Les extensions sont compilées dans une bibliothèque .jar et placées dans la partition system_ext d'un appareil si les extensions sont activées dans le fichier make de l'appareil.

Pour activer les extensions sur un appareil, ajoutez les éléments suivants au fichier makefile de l'appareil :

$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)

Cela active les packages androidx.window.extensions et androidx.window.sidecar sur l'appareil et définit la propriété persist.wm.extensions.enabled. L'inclusion de ces packages dans le fichier makefile place également des déclarations dans etc/permissions/, ce qui les rend disponibles pour les processus d'application. Normalement, les modules sont chargés et exécutés dans le cadre du processus d'application au moment de l'exécution lorsqu'ils sont utilisés par la bibliothèque Jetpack WindowManager, ce qui rend leur fonctionnement semblable au code du framework côté client, comme illustré dans la figure suivante :

Figure 1 : Les extensions WindowManager sont chargées dans le processus d'application de la même manière que le code de plate-forme.

Le module androidx.window.extensions est le module d'extensions actuel en cours de développement. Le module androidx.window.sidecar est un ancien module inclus pour assurer la compatibilité avec les premières versions de Jetpack WindowManager, mais le side-car n'est plus activement maintenu.

La figure suivante illustre la logique permettant de déterminer l'utilisation de androidx.window.extensions ou androidx.window.sidecar.

Figure 2 : Arbre de décision pour accéder à androidx.window.extensions ou androidx.window.sidecar.

Modules d'extension

Les extensions fournissent des fonctionnalités de fenêtrage pour les appareils pliables à grand écran et les appareils compatibles avec le fenêtrage sur des écrans externes. Voici les domaines concernés :

Les implémentations OEM des extensions peuvent fournir des composants nuls ou des composants avec des implémentations par défaut ou de stub des méthodes dans l'interface WindowExtensions si le matériel de l'appareil ne prend pas en charge les fonctionnalités correspondantes, sauf si la fonctionnalité est spécifiquement demandée dans le document de définition de compatibilité (CDD) 7.1.1.1.

Extensions et API Jetpack

Le module WindowManager Extensions fournit sa propre surface d'API en plus des API de plate-forme publiques. Le module Extensions est développé publiquement dans une bibliothèque Jetpack androidx.window.extensions non destinée aux développeurs, afin que Jetpack WindowManager (androidx.window) puisse s'y associer au moment de la compilation. La surface de l'API Extensions fournit généralement des API de niveau inférieur.

Les API fournies par les extensions sont destinées à être utilisées uniquement par la bibliothèque Jetpack WindowManager. Les API Extensions ne sont pas conçues pour être appelées directement par les développeurs d'applications. Pour garantir un fonctionnement correct, la bibliothèque Extensions ne doit pas être ajoutée en tant que dépendance pour une application dans le fichier de compilation Gradle. Évitez de précompiler la bibliothèque Extensions directement dans une application. Au lieu de cela, reposez-vous sur le chargement au moment de l'exécution pour éviter de charger un mélange de classes Extensions précompilées et fournies au moment de l'exécution.

Jetpack WindowManager (androidx.window) est conçu pour être ajouté en tant que dépendance d'application et fournit les API publiques destinées aux développeurs, y compris celles pour les fonctionnalités des extensions WindowManager. La bibliothèque WindowManager charge automatiquement les extensions dans le processus d'application et encapsule les API d'extensions de niveau inférieur dans des abstractions de niveau supérieur et des interfaces plus ciblées. Les API Jetpack WindowManager suivent les normes de développement d'applications Android modernes et sont conçues pour offrir une interopérabilité pratique en s'intégrant bien aux bases de code qui utilisent d'autres bibliothèques AndroidX.

Versions et mises à jour des extensions

Le module Extensions peut être mis à jour en même temps que la plate-forme Android lors des mises à jour annuelles ou trimestrielles. Les mises à jour trimestrielles permettent d'augmenter le niveau de l'API Extensions entre les mises à jour de l'API de la plate-forme Android, ce qui permet une itération plus rapide et offre aux OEM la possibilité d'ajouter un accès officiel à l'API pour les nouvelles fonctionnalités proches des lancements de matériel.

Le tableau suivant répertorie les versions de l'API androidx.window.extensions pour différentes versions d'Android.

Version de la plate-forme Android Niveau d'API des extensions WindowManager Version de l'API androidx.window.extensions
Android 15 6 1.5.0 (bientôt disponible)
Android 14 QPR3 5 1.4.0 (bientôt disponible)
Android 14 QPR1 4 1.3.0
Android 14 3 1.2.0
Android 13 QPR3 2 1.1.0
Android 13 1 1.0.0
Android 12L 1 1.0.0

Le niveau de l'API Extensions (colonne du milieu) augmente chaque fois qu'un élément est ajouté à la surface de l'API stable existante (colonne de droite).

Compatibilité ascendante et descendante

Jetpack WindowManager gère la complexité des mises à jour fréquentes du niveau d'API, l'évolution rapide de l'API et la rétrocompatibilité. Lorsque le code de la bibliothèque est exécuté dans le processus d'application, la bibliothèque vérifie le niveau d'API Extensions déclaré et fournit l'accès aux fonctionnalités en fonction du niveau déclaré.

Pour éviter qu'une application plante lors de l'exécution, WindowManager effectue également une vérification de la réflexion Java au moment de l'exécution des API Extensions disponibles en fonction du niveau d'API Extensions déclaré. En cas d'incohérence, WindowManager peut désactiver l'utilisation des extensions (partiellement ou complètement) et signaler les fonctionnalités concernées comme non disponibles pour l'application.

Les extensions WindowManager sont implémentées en tant que module system_ext qui utilise des API de plate-forme privées pour appeler le cœur de WindowManager, DeviceStateManager et d'autres services système dans l'implémentation des fonctionnalités des extensions.

La compatibilité peut ne pas être maintenue avec les versions préliminaires d'Extensions antérieures à la version correspondante de la plate-forme Android (trimestrielle ou annuelle) avec laquelle les versions sont finalisées. L'historique complet des API Extensions est disponible dans les fichiers texte de l'API de la branche de publication window:extensions:extensions.

Les versions plus récentes d'Extensions doivent continuer à fonctionner avec les anciennes versions de WindowManager compilées dans les applications pour maintenir la compatibilité ascendante. Pour ce faire, chaque nouvelle version de l'API Extensions ajoute de nouvelles API sans supprimer les anciennes. Par conséquent, les applications avec des versions plus anciennes de WindowManager peuvent continuer à utiliser les anciennes API Extensions avec lesquelles elles ont été compilées.

La validation CTS garantit que, pour toute version déclarée des API Extensions sur l'appareil, toutes les API pour cette version et les versions précédentes sont présentes et fonctionnelles.

Performances

Le module Extensions est mis en cache dans les chargeurs de classe système non bootclasspath par défaut à partir d'Android 14 (niveau d'API 34). Il n'y a donc aucun impact sur les performances dû au chargement du module en mémoire au démarrage de l'application. L'utilisation de fonctionnalités de modules individuels peut avoir une légère incidence sur les caractéristiques de performances des applications lorsque des appels IPC supplémentaires sont effectués entre le client et le serveur.

Modules

Intégration d'activités

Le composant activity embedding permet aux applications d'optimiser leur UI pour les appareils à grand écran et les écrans externes. L'intégration d'activités permet de présenter deux activités côte à côte dans une mise en page à plusieurs volets, ce qui facilite le développement d'applications adaptatives pour les anciennes applications.

Le composant d'intégration d'activité doit être disponible sur tous les appareils dotés d'un écran intégré d'une taille égale ou supérieure à sw600dp. L'intégration d'activités doit également être activée sur les appareils compatibles avec les connexions d'écrans externes, car l'application peut s'afficher dans une taille plus grande lorsque des écrans externes sont connectés au moment de l'exécution.

Configuration de l'appareil

Aucune configuration spécifique de l'appareil n'est nécessaire, à l'exception de l'activation du module Extensions, comme décrit dans la section Distribution du module Extensions. Il est judicieux d'activer les extensions sur tous les appareils compatibles avec le mode multifenêtre. Il est probable que les futures versions d'Android rendent les extensions obligatoires sur les configurations d'appareils portables et à grand écran courants.

Informations sur la mise en page des fenêtres

Le composant d'informations sur la mise en page des fenêtres identifie la position et l'état de la charnière sur un appareil pliable lorsque celle-ci traverse une fenêtre d'application. Les informations sur la mise en page des fenêtres permettent aux applications de répondre et d'afficher des mises en page optimisées en mode Table sur les appareils pliables. Pour en savoir plus sur l'utilisation, consultez Rendre votre application pliable.

Les appareils Android pliables qui incluent une charnière reliant des zones de panneau d'affichage distinctes ou continues doivent mettre les informations sur la charnière à la disposition des applications via WindowLayoutComponent.

La position et les limites de la charnière doivent être indiquées par rapport à la fenêtre d'application identifiée par un Context transmis à l'API. Si les limites de la fenêtre d'application ne croisent pas les limites de la charnière, la charnière DisplayFeature ne doit pas être signalée. Il est également acceptable de ne pas signaler les caractéristiques d'affichage lorsque leur position ne peut pas être signalée de manière fiable, par exemple lorsqu'une fenêtre d'application peut être déplacée librement par l'utilisateur en mode multifenêtre ou en mode letterbox de compatibilité.

Pour les fonctionnalités de pliage, les mises à jour de l'état doivent être signalées lorsque la position de la charnière change entre les états stables. Par défaut, dans un état d'affichage à plat, l'API doit signaler FoldingFeature.State.FLAT. Si le matériel de l'appareil peut être laissé à moitié plié dans un état stable, l'API doit signaler FoldingFeature.State.HALF_OPENED. Il n'existe pas d'état fermé dans l'API, car dans ce cas, la fenêtre de l'application ne serait pas visible ou ne franchirait pas les limites de la charnière.

Configuration de l'appareil

Pour prendre en charge l'implémentation de la fonctionnalité de pliage, les OEM doivent procéder comme suit :

  • Configurez les états de l'appareil dans device_state_configuration.xml pour qu'ils soient utilisés par DeviceStateManagerService. Pour en savoir plus, consultez la documentation de référence sur DeviceStateProviderImpl.java.

    Si les implémentations par défaut de DeviceStateProvider ou DeviceStatePolicy ne conviennent pas à l'appareil, une implémentation personnalisée peut être utilisée.

  • Activez le module Extensions comme décrit dans la section Distribution du module Extensions.

  • Spécifiez l'emplacement des fonctionnalités d'affichage dans la ressource de chaîne com.android.internal.R.string.config_display_features (généralement dans frameworks/base/core/res/res/values/config.xml dans la superposition d'appareil).

    Le format attendu pour la chaîne est le suivant :

    <type>-[<left>,<top>,<right>,<bottom>]

    type peut correspondre à fold ou hinge. Les valeurs de left, top, right et bottom sont des coordonnées de pixels entiers dans l'espace de coordonnées de l'écran dans l'orientation naturelle de l'écran. La chaîne de configuration peut contenir plusieurs fonctionnalités d'affichage séparées par des points-virgules.

    Exemple :

    <!-- Jetpack WindowManager display features -->
    <string name="config_display_features" translatable="false">fold-[1000,0,1000,2000]</string>
    
  • Définissez le mappage entre les identifiants d'état de l'appareil interne utilisés dans DeviceStateManager et les constantes d'état publiques envoyées aux développeurs dans com.android.internal.R.array.config_device_state_postures.

    Le format attendu pour chaque entrée est le suivant :

    <device_specific_state_identifier>:<Jetpack WindowManager state identifier>

    Les identifiants d'état acceptés sont les suivants :

    • COMMON_STATE_NO_FOLDING_FEATURES = 1 : l'état n'a aucune fonctionnalité de pliage à signaler. Par exemple, il peut s'agir de l'état fermé de l'appareil pliable typique avec l'écran principal à l'intérieur.
    • COMMON_STATE_HALF_OPENED = 2 : la fonctionnalité de pliage est à moitié ouverte.
    • COMMON_STATE_FLAT = 3 : le téléphone est à plat. Par exemple, il peut s'agir de l'état ouvert de l'appareil pliable typique avec l'écran principal sur la face intérieure.
    • COMMON_STATE_USE_BASE_STATE = 1000 : dans Android 14, valeur pouvant être utilisée pour les états émulés où l'état de la charnière est dérivé de l'état de base, tel que défini dans CommonFoldingFeature.java.

    Pour en savoir plus, consultez DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int).

    Exemple :

    <!-- Map of System DeviceState supplied by DeviceStateManager to WindowManager posture.-->
    <string-array name="config_device_state_postures" translatable="false">
      <item>0:1</item>    <!-- CLOSED       : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>1:2</item>    <!-- HALF_OPENED  : COMMON_STATE_HALF_OPENED -->
      <item>2:3</item>    <!-- OPENED       : COMMON_STATE_FLAT -->
      <item>3:1</item>    <!-- REAR_DISPLAY : COMMON_STATE_NO_FOLDING_FEATURES -->
      <item>4:1000</item> <!-- CONCURRENT   : COMMON_STATE_USE_BASE_STATE -->
    </string-array>
    

Zone de la fenêtre

Le composant de zone de fenêtre fournit un ensemble de fonctionnalités qui permettent aux applications d'accéder à des écrans et des zones d'affichage supplémentaires sur certains appareils pliables et multi-écrans.

Le mode écran arrière permet à une application d'afficher l'aperçu de l'appareil photo sur l'écran extérieur d'un appareil pliable pour permettre l'utilisation de l'appareil photo principal de l'appareil pour les selfies et les vidéos. Les appareils compatibles avec Android (tels que définis par le CDD Android en termes d'attributs tels que la taille, la densité et les affordances de navigation disponibles) qui couvrent un écran aligné sur les caméras arrière de l'appareil doivent fournir un accès au mode d'écran arrière.

Sur Android 14, le mode Dual Screen permet aux applications qui s'exécutent sur l'écran intérieur d'un appareil pliable d'afficher du contenu supplémentaire sur l'écran de couverture face aux autres utilisateurs. Par exemple, l'écran de couverture peut afficher l'aperçu de la caméra à la personne photographiée ou filmée.

Configuration de l'appareil

Pour prendre en charge l'implémentation de la fonctionnalité de pliage, les OEM doivent procéder comme suit :

  • Configurez les états de l'appareil dans device_state_configuration.xml pour qu'ils soient utilisés par DeviceStateManagerService. Pour en savoir plus, consultez DeviceStateProviderImpl.java.

    Si l'implémentation par défaut de DeviceStateProvider ou DeviceStatePolicy ne convient pas à l'appareil, une implémentation personnalisée peut être utilisée.

  • Pour les appareils pliables compatibles avec le mode ouvert ou plat, spécifiez les identifiants d'état correspondants dans com.android.internal.R.array.config_openDeviceStates.

  • Pour les appareils pliables qui prennent en charge les états pliés, listez les identifiants d'état correspondants dans com.android.internal.R.array.config_foldedDeviceStates.

  • Pour les appareils pliables vers l'intérieur qui prennent en charge un état semi-plié (charnière à moitié ouverte comme un ordinateur portable), listez les états correspondants dans com.android.internal.R.array.config_halfFoldedDeviceStates.

  • Pour les appareils compatibles avec le mode d'affichage arrière :

    • Listez les états correspondants dans com.android.internal.R.array.config_rearDisplayDeviceStates pour DeviceStateManager.
    • Spécifiez l'adresse d'affichage physique de l'écran arrière dans com.android.internal.R.string.config_rearDisplayPhysicalAddress.
    • Spécifiez l'identifiant d'état dans com.android.internal.R.integer.config_deviceStateRearDisplay pour qu'il soit utilisé par les extensions.
    • Ajoutez l'identifiant d'état dans com.android.internal.R.array.config_deviceStatesAvailableForAppRequests pour le rendre disponible pour les applications.
  • Sur Android 14, pour les appareils compatibles avec le mode double affichage (simultané) :

    • Définissez com.android.internal.R.bool.config_supportsConcurrentInternalDisplays sur true.
    • Spécifiez l'adresse d'affichage physique de l'écran arrière dans com.android.internal.R.config_deviceStateConcurrentRearDisplay.
    • Spécifiez l'identifiant d'état dans com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay à utiliser par les extensions si l'identifiant est destiné à être mis à la disposition des applications.
    • Ajoutez l'identifiant d'état dans com.android.internal.R.array.config_deviceStatesAvailableForAppRequests pour le rendre disponible pour les applications.

Validation

Les OEM doivent valider leurs implémentations pour s'assurer du comportement attendu dans les scénarios courants. Les tests CTS et les tests utilisant Jetpack WindowManager sont disponibles pour les OEM afin de tester les implémentations.

Tests CTS

Pour exécuter les tests CTS, consultez Exécuter les tests CTS. Les tests CTS liés à Jetpack WindowManager se trouvent sous cts/tests/framework/base/windowmanager/jetpack/. Le nom du module de test est CtsWindowManagerJetpackTestCases.

Tests WindowManager

Pour télécharger les tests Jetpack WindowManager, suivez les instructions Android Jetpack. Les tests se trouvent dans la bibliothèque de fenêtres, sous le module window:window : window/window/src/androidTest/.

Pour exécuter les tests de l'appareil pour le module window:window à partir de la ligne de commande, procédez comme suit :

  1. Branchez un appareil sur lequel les options pour les développeurs et le débogage USB sont activés.
  2. Autorisez l'ordinateur à déboguer l'appareil.
  3. Ouvrez un shell dans le répertoire racine du dépôt androidx.
  4. Remplacez le répertoire par framework/support.
  5. Exécutez la commande suivante : ./gradlew window:window:connectedAndroidTest.
  6. Analysez les résultats.

Pour exécuter les tests à partir d'Android Studio, procédez comme suit :

  1. Ouvrez Android Studio.
  2. Branchez un appareil sur lequel les options pour les développeurs et le débogage USB sont activés.
  3. Autorisez l'ordinateur à déboguer l'appareil.
  4. Accédez à un test dans la bibliothèque de fenêtres du module de fenêtres.
  5. Ouvrez une classe de test et exécutez-la à l'aide des flèches vertes sur la droite de l'éditeur.

Vous pouvez également créer une configuration dans Android Studio pour exécuter une méthode de test, une classe de test ou tous les tests d'un module.

Les résultats peuvent être analysés manuellement en examinant la sortie du shell. Certains tests sont ignorés si l'appareil ne répond pas à certaines hypothèses. Les résultats sont enregistrés dans un emplacement standard, et les analystes peuvent écrire un script pour automatiser leur analyse.