Ab Android 13 werden neue Framebuffer, die bei der Clientkomposition verwendet werden, immer dann zugewiesen, wenn sich die Displayauflösung ändert. Diese Zuweisung wird von SurfaceFlinger im nächsten invalid-Zyklus nach einer Auflösungsänderung durchgeführt.
Framebuffer-Verwaltung bei Auflösungswechseln
Änderungen der Auflösung treten in einem der folgenden beiden Szenarien auf:
Ein Hotplug-Ereignis, das vom Hardware Composer (HWC) initiiert wird, wenn von einem externen Display zu einem anderen externen Display mit einer anderen Standardauflösung gewechselt wird.
Bei einem Hotplug-Ereignis werden die Handles zu den alten Framebuffern freigegeben, wenn die alten Displaydaten deallociert werden.
Ein von SurfaceFlinger initiierter Wechsel des Anzeigemodus, der auftritt, wenn der Nutzer die Auflösung über die Nutzereinstellungen ändert oder eine App die Auflösung über
preferredDisplayModeId
ändert.Während eines Displaymoduswechsels werden die Handles zu vorhandenen Client-Framebuffern von SurfaceFlinger freigegeben, bevor
setActiveConfig
odersetActiveConfigWithConstraints
aufgerufen wird.
Um katastrophale Probleme wie Speicherfragmentierung auf Geräten zu vermeiden, die nicht genügend Speicher für die alten und neuen Framebuffer reservieren, ist es wichtig, dass HWC die alten Framebuffer nicht mehr verwendet und alle Handles für diese Framebuffer freigibt, wie in den folgenden Fällen gezeigt:
Bei Hotplug-Ereignissen unmittelbar vor dem Aufruf von
onHotplug
.Bei Moduswechsel direkt nach dem Aufruf von
setActiveConfig
odersetActiveConfigWithConstraints
.
Durch das Freigeben der Handles kann der Framebuffer-Speicher vollständig deallociert werden, bevor neue Framebuffer zugewiesen werden, die SurfaceFlinger während des nächsten invalidate-Zyklus ausführt.
Empfehlungen für die Framebufferverwaltung
Wenn HWC die Handles für alte Framebuffer nicht rechtzeitig freigibt, erfolgt die neue Framebufferzuweisung vor der Deaktivierung des alten Framebuffers. Dies kann zu katastrophalen Problemen führen, wenn die neue Zuweisung aufgrund von Fragmentierung oder anderen Problemen fehlschlägt. Schlimmer noch: Wenn HWC diese Handles überhaupt nicht freigibt, kann es zu einem Speicherleck kommen.
Folgen Sie diesen Empfehlungen, um schwerwiegende Zuweisungsfehler zu vermeiden:
Wenn HWC die alten Client-Framebuffer weiterhin verwenden muss, bis die neuen Client-Framebuffer bereitgestellt werden, ist es wichtig, sowohl für die alten als auch für die neuen Framebuffer genügend Arbeitsspeicher zu reservieren und gegebenenfalls Defragmentierungsalgorithmen auf dem Framebuffer-Speicherplatz auszuführen.
Weisen Sie den Framebuffern einen separaten Speicherpool zu, der vom Rest des Grafikbuffer-Speichers getrennt ist. Dies ist wichtig, da ein Drittanbieterprozess zwischen der Neuzuweisung und der Neuzuweisung der Framebuffer versuchen kann, Grafikspeicher zuzuweisen. Wenn derselbe Grafikspeicherpool vom Framebuffer verwendet wird und der Grafikspeicher voll ist, kann der Drittanbieterprozess den Grafikspeicher belegen, der zuvor einem Framebuffer zugewiesen wurde. Dadurch bleibt nicht genügend Arbeitsspeicher für die Neuzuweisung des Framebuffers übrig oder der Arbeitsspeicher wird möglicherweise fragmentiert.
Verwaltung des Framebuffers testen
OEMs wird empfohlen, die ordnungsgemäße Verwaltung des Framebuffer-Speichers des Clients über Auflösungsschalter für ihr Gerät hinweg zu testen. Dies wird so beschrieben:
Für Hotplug-Ereignisse ziehen Sie einfach zwei verschiedene Displays mit unterschiedlichen Auflösungen ab und schließen Sie sie wieder an.
Verwenden Sie für Moduswechsel den
ModeSwitchingTestActivity
CTS-Verifier-Test, um einen Moduswechsel zum Testen des Framebuffer-Speicherverhaltens auszulösen. Mit diesem Test können Probleme visuell erkannt werden, die sich programmatisch nur schwer erkennen lassen.