À partir d'Android 13, les nouveaux framesbuffers, utilisés lors de la composition du client, sont alloués chaque fois que la résolution d'affichage change. Cette allocation est effectuée par SurfaceFlinger lors du prochain cycle invalidate après un changement de résolution.
Gestion du framebuffer lors des changements de résolution
Les modifications de résolution se produisent dans l'un des deux scénarios suivants:
Événement de hotplug, initié par le Hardware Composer (HWC), qui se produit lors du passage d'un écran externe à un autre écran externe dont la résolution par défaut est différente.
Lors d'un événement hotplug, les poignées des anciens framebuffers sont libérées lorsque les anciennes données d'affichage sont désallouées.
Changement de mode d'affichage initié par SurfaceFlinger, qui se produit lorsque l'utilisateur modifie la résolution avec les paramètres utilisateur ou qu'une application modifie la résolution avec
preferredDisplayModeId
.Lors d'un changement de mode d'affichage, les poignées des framebuffers client existants sont libérées par SurfaceFlinger avant d'appeler
setActiveConfig
ousetActiveConfigWithConstraints
.
Pour éviter des problèmes catastrophiques, tels que la fragmentation de la mémoire, sur les appareils qui ne réservent pas assez de mémoire pour les anciens et nouveaux framebuffers, il est essentiel que le HWC cesse d'utiliser les anciens framebuffers et libère tous les identifiants dans ces tampons de frame, comme indiqué dans les cas suivants:
Pour les événements hotplug, immédiatement avant d'appeler
onHotplug
.Pour les changements de mode, immédiatement après l'appel de
setActiveConfig
ou desetActiveConfigWithConstraints
.
Libérer les descripteurs permet de désallouer complètement la mémoire du framebuffer avant l'allocation de nouveaux framebuffers que SurfaceFlinger effectue lors du prochain cycle d'invalidation.
Recommandations pour la gestion du framebuffer
Si le HWC ne libère pas les poignées des anciens framebuffers à temps, l'allocation du nouveau framebuffer a lieu avant la désallocation de l'ancien framebuffer. 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 ces handle, une fuite de mémoire peut se produire.
Pour éviter les échecs d'allocation catastrophiques, suivez ces recommandations:
Si le HWC doit continuer à utiliser les anciens framebuffers client jusqu'à ce que les 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 du framebuffer.
Allouez un pool de mémoire dédié aux framebuffers, distinct du reste de la mémoire du tampon graphique. Cela est important, car entre la désallocation et la réallocation des framebuffers, un processus tiers peut tenter d'allouer de la mémoire graphique. Si le même pool de mémoire graphique est utilisé par le framebuffer et si la mémoire graphique est saturée, le processus tiers peut occuper la mémoire graphique précédemment allouée par un framebuffer, laissant ainsi une mémoire insuffisante pour la réallocation du framebuffer ou, éventuellement, fragmentant l'espace mémoire.
Tester la gestion du framebuffer
Nous recommandons aux OEM de vérifier la gestion appropriée de la mémoire du framebuffer client sur les commutateurs de résolution de leur appareil, comme suit:
Pour les événements de hotplug, il vous suffit de débrancher et de reconnecter deux écrans différents avec des résolutions différentes.
Pour les changements de mode, utilisez le test
ModeSwitchingTestActivity
du vérificateur CTS 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 de manière programmatique.