À partir d'Android 13, le système alloue de nouveaux framebuffers, utilisés lors de la composition client, chaque fois que la résolution de l'écran change. SurfaceFlinger effectue cette allocation lors du prochain cycle invalidate après un changement de résolution.
Gestion du framebuffer lors des changements de résolution
Les changements de résolution se produisent dans l'un des deux scénarios suivants :
Un événement de branchement à chaud, initié par le Hardware Composer (HWC), qui se produit lors du passage d'un écran externe à un autre écran externe ayant une résolution par défaut différente.
Lors d'un événement de branchement à chaud, HWC libère les handles des anciens tampons de frame lorsqu'il libère les anciennes données d'affichage.
Il s'agit d'un changement de mode d'affichage initié par SurfaceFlinger, qui se produit lorsque vous modifiez la résolution à l'aide des paramètres utilisateur ou lorsqu'une application modifie la résolution à l'aide de
preferredDisplayModeId
.Lors d'un changement de mode d'affichage, SurfaceFlinger libère les handles des framebuffers client existants avant d'appeler
setActiveConfig
ousetActiveConfigWithConstraints
.
Pour éviter les problèmes catastrophiques tels que la fragmentation de la mémoire sur les appareils dont la mémoire du tampon de frame est insuffisante, HWC doit libérer les handles des anciens tampons de frame. Cette étape est essentielle dans les cas suivants :
Pour les événements de branchement à chaud, immédiatement avant d'appeler
onHotplug
.Pour les changements de mode, immédiatement après l'appel de
setActiveConfig
ousetActiveConfigWithConstraints
.
La libération des handles permet de désallouer complètement la mémoire du framebuffer avant que SurfaceFlinger n'alloue de nouveaux framebuffers lors du prochain cycle invalidate.
Recommandations pour la gestion des framebuffers
Si HWC ne libère pas les handles des anciens framebuffers à temps, une nouvelle allocation de framebuffer se produit avant la désallocation des anciens framebuffers. Cela peut entraîner des problèmes catastrophiques lorsque la nouvelle allocation échoue en raison d'une fragmentation ou d'autres problèmes. Pire encore, si HWC ne libère pas du tout ces handles, une fuite de mémoire peut se produire.
Pour éviter les échecs d'allocation catastrophiques, suivez ces recommandations :
Si HWC doit continuer à utiliser les anciens framebuffers client jusqu'à ce que de nouveaux framebuffers client soient fournis, il est essentiel de réserver suffisamment de mémoire pour les anciens et les nouveaux framebuffers, et éventuellement d'exécuter des algorithmes de défragmentation sur l'espace mémoire des framebuffers.
Allouez un pool de mémoire dédié aux tampons de frame, distinct du reste de la mémoire tampon graphique. Cette étape est importante, car un processus tiers peut tenter d'allouer de la mémoire graphique entre la désallocation et la réallocation du framebuffer. Si la mémoire tampon de trame utilise le même pool de mémoire graphique et si la mémoire graphique est pleine, le processus tiers peut occuper la mémoire précédemment allouée par une mémoire tampon de trame. Cela peut entraîner une mémoire insuffisante pour la réallocation du framebuffer ou la fragmentation de la mémoire.
Tester la gestion du framebuffer
Nous conseillons aux OEM de tester la bonne gestion de la mémoire du framebuffer client lors des changements de résolution de leur appareil, comme décrit ci-dessous :
Pour les événements de branchement à chaud, débranchez et rebranchez deux écrans différents ayant des résolutions différentes.
Pour les changements de mode, utilisez le test
ModeSwitchingTestActivity
CTS Verifier pour lancer un changement de mode afin de tester le comportement de la mémoire du framebuffer. Ce test peut identifier visuellement les problèmes difficiles à détecter par programmation.