A partire da Android 13, i nuovi frame buffer, utilizzati durante la composizione client, vengono allocati ogni volta che cambia la risoluzione del display. Questa allocazione viene eseguita da SurfaceFlinger nel ciclo invalidate successivo a una modifica della risoluzione.
Gestione del frame buffer durante i cambi di risoluzione
Le modifiche alla risoluzione si verificano a causa di 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 display esterno 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 cambio di 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 cambio di modalità di visualizzazione, 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 smetta di utilizzare i framebuffer precedenti e rilasci tutti gli handle di 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 al numero
setActiveConfig
osetActiveConfigWithConstraints
.
Il rilascio degli handle consente di deallocare completamente la memoria framebuffer prima dell'allocazione di nuovi framebuffer eseguita da SurfaceFlinger durante il ciclo invalidate successivo.
Consigli per la gestione del framebuffer
Se HWC non rilascia gli handle ai vecchi frame buffer in tempo, la nuova allocazione del frame buffer avviene prima della deallocazione del vecchio frame buffer. Ciò può causare problemi catastrofici quando la nuova allocazione non riesce a causa della frammentazione o di altri problemi. Ancora peggio, se HWC non rilascia mai questi handle, può verificarsi una perdita di memoria.
Per evitare errori di allocazione catastrofici, segui questi consigli:
Se HWC deve continuare a utilizzare i vecchi framebuffer client finché non vengono forniti i nuovi, è fondamentale riservare memoria sufficiente sia per i vecchi che per i nuovi framebuffer ed eventualmente eseguire algoritmi di deframmentazione 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 frame buffer, 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, possibilmente, frammentando lo spazio di memoria.
Test della gestione del framebuffer
Si consiglia agli OEM di testare la corretta gestione della memoria del framebuffer del client in tutti i cambi di risoluzione per il 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 problemi difficili da rilevare a livello di programmazione.