A partire da Android 13, i nuovi framebuffer, utilizzati durante la composizione client, vengono allocati ogni volta che cambia la risoluzione del display. Questa allocazione viene eseguita da SurfaceFlinger al successivo ciclo di annullamento della convalida dopo una modifica della risoluzione.
Gestione del framebuffer durante i cambi di risoluzione
Le modifiche alla risoluzione si verificano in uno dei seguenti due scenari:
Un evento hotplug, avviato da Hardware Composer (HWC), che si verifica quando si passa da un display esterno a un altro con una risoluzione predefinita diversa.
Durante un evento hotplug, gli handle dei vecchi frame buffer vengono rilasciati quando i vecchi dati di visualizzazione vengono deallocati.
Un passaggio alla modalità di visualizzazione avviato da SurfaceFlinger, che si verifica quando l'utente modifica la risoluzione con le impostazioni utente o un'app modifica la risoluzione con
preferredDisplayModeId
.Durante il passaggio da una modalità di visualizzazione all'altra, gli handle dei framebuffer client esistenti vengono rilasciati da SurfaceFlinger prima di chiamare
setActiveConfig
osetActiveConfigWithConstraints
.
Per evitare problemi catastrofici, come la frammentazione della memoria, sui dispositivi che non riservano memoria sufficiente per i framebuffer vecchi e nuovi, è fondamentale che HWC cessi di utilizzare i framebuffer vecchi e rilasci gli eventuali handle a questi framebuffer come mostrato nei seguenti casi:
Per gli eventi hotplug, immediatamente prima di chiamare
onHotplug
.Per i cambi di modalità, immediatamente dopo la chiamata a
setActiveConfig
osetActiveConfigWithConstraints
.
Il rilascio degli handle consente di deallocare completamente la memoria del framebuffer prima dell'allocazione di nuovi framebuffer eseguita da SurfaceFlinger durante il successivo ciclo invalidate.
Consigli per la gestione del framebuffer
Se HWC non rilascia in tempo i handle per i vecchi frame buffer, la nuova allocazione del frame buffer avviene prima della deallocazione del vecchio frame buffer. Ciò può causare problemi catastrofici quando la nuova allocazione non va a buon fine a causa di frammentazione o altri problemi. Inoltre, se HWC non rilascia affatto questi handle, è possibile che si verifichi una perdita di memoria.
Per evitare errori di allocazione catastrofici, segui questi consigli:
Se l'HWC deve continuare a utilizzare i vecchi framebuffer client fino a quando non vengono forniti i nuovi framebuffer client, è fondamentale riservare memoria sufficiente sia per i framebuffer vecchi che per quelli nuovi ed eventualmente eseguire algoritmi di defragmentazione nello spazio di memoria del framebuffer.
Alloca un pool di memoria dedicato per i framebuffer separato dal resto della memoria del buffer grafico. Questo è importante perché tra la deallocazione e la riallocazione dei framebuffer, un processo di terze parti può tentare di allocare la memoria grafica. Se lo stesso pool di memoria grafica viene utilizzato dal framebuffer e se la memoria grafica è piena, il processo di terze parti può occupare la memoria grafica precedentemente allocata da un framebuffer, lasciando quindi una memoria insufficiente per la riallocazione del framebuffer o, eventualmente, frammentando lo spazio di memoria.
Testa la gestione del framebuffer
Gli OEM sono invitati a verificare la corretta gestione della memoria del framebuffer del client per gli switch di risoluzione del proprio dispositivo, come descritto di seguito:
Per gli eventi hotplug, scollega e ricollega due display diversi con risoluzioni diverse.
Per i cambi di modalità, utilizza il test
ModeSwitchingTestActivity
CTS Verifier per avviare un cambio di modalità per testare il comportamento della memoria del framebuffer. Questo test può identificare visivamente i problemi difficili da rilevare programmaticamente.