Supporto delle decorazioni di sistema

Gli aggiornamenti apportati a queste aree specifiche del display sono forniti in questa pagina.

Decorazioni di sistema

Android 10 aggiunge il supporto per la configurazione dei display secondari in modo da mostrare determinate decorazioni di sistema, come sfondo, barra di navigazione e avvio applicazioni. Per impostazione predefinita, il display principale mostra tutte le decorazioni di sistema, mentre i display secondari mostrano quelle abilitate facoltativamente. Puoi impostare il supporto per un editor del metodo di input (IME) separatamente dalle altre decorazioni di sistema.

Utilizza DisplayWindowSettings#setShouldShowSystemDecorsLocked per aggiungere il supporto per le decorazioni di sistema su un display specifico o fornire un valore predefinito in /data/system/display_settings.xml. Per visualizzare alcuni esempi, consulta Impostazioni della finestra di visualizzazione.

In Android 17 e versioni successive, il supporto di un display per le decorazioni di sistema può cambiare in modo dinamico. Se un display ha il flag FLAG_ALLOWS_CONTENT_MODE_SWITCH, il sistema consente all'utente di decidere se il display ospita le app o esegue il mirroring di un altro display. Il sistema utilizza le decorazioni di sistema solo se l'utente decide di utilizzare il display per ospitare le app. I componenti di sistema, come l'UI di sistema e gli avvio app OEM, sono responsabili della creazione e della visualizzazione delle decorazioni di sistema. Per aggiungere o rimuovere dinamicamente le decorazioni di sistema e per inizializzare o liberare le strutture per display, questi componenti devono registrare un'istanza IDisplayWindowListener e implementare i metodi IDisplayWindowListener.onDisplayAddSystemDecorations e IDisplayWindowListener.onDisplayRemoveSystemDecorations. IDisplayWindowListener è un'API nascosta disponibile solo per i componenti di sistema.

Implementazione

DisplayWindowSettings#setShouldShowSystemDecorsLocked viene esposto anche in WindowManager#setShouldShowSystemDecors per i test. L'attivazione di questo metodo con l'intento di abilitare le decorazioni di sistema non aggiunge le finestre di decorazione mancanti in precedenza né le rimuove se erano presenti in precedenza. Nella maggior parte dei casi, la modifica del supporto delle decorazioni di sistema diventa completamente effettiva solo dopo il riavvio del dispositivo.

I controlli per il supporto delle decorazioni di sistema nella codebase di WindowManager di solito passano attraverso DisplayContent#supportsSystemDecorations, mentre i controlli per i servizi esterni (come l'UI di sistema per verificare se la barra di navigazione deve essere mostrata) utilizzano WindowManager#shouldShowSystemDecors. Per capire cosa viene controllato da questa impostazione, esplora i punti di chiamata di questi metodi.

Finestre di decorazione dell'UI di sistema

Android 10 aggiunge il supporto delle finestre di decorazione di sistema solo per la barra di navigazione, perché è essenziale per spostarsi tra attività e app. Per impostazione predefinita, la barra di navigazione mostra le affordance Indietro e Home. La barra di navigazione è inclusa solo se il display di destinazione supporta le decorazioni di sistema (vedi DisplayWindowSettings).

La barra di stato è una finestra di sistema più complessa, perché contiene anche l'area notifiche, le impostazioni rapide e la schermata di blocco. In Android 10, la barra di stato non è supportata sui display secondari. Di conseguenza, le notifiche, le impostazioni e una schermata di blocco completa sono disponibili solo sul display principale.

La finestra di sistema Panoramiche o Recenti non è supportata sugli schermi secondari. In Android 10, AOSP mostra Recenti solo sul display predefinito e contiene le attività di tutti i display. Quando viene avviata da Recenti, un'attività presente su un display secondario viene portata in primo piano su quel display, per impostazione predefinita. Questo approccio presenta alcuni problemi noti, ad esempio non si aggiorna immediatamente quando le app vengono visualizzate su altri schermi.

Implementazione

Per implementare funzionalità aggiuntive dell'UI di sistema, i produttori di dispositivi devono utilizzare un singolo componente dell'UI di sistema che rimane in ascolto dell'aggiunta o della rimozione dei display e presenta i contenuti appropriati.

Un componente dell'UI di sistema che supporta più display (MD) deve gestire i seguenti casi:

  • Inizializzazione di più display all'avvio
  • Display aggiunto in fase di runtime
  • Display rimosso in fase di runtime

Quando l'UI di sistema rileva l'aggiunta di un display prima di WindowManager, si verifica una race condition. Puoi evitare questo problema implementando un callback personalizzato da WindowManager all'UI di sistema quando viene aggiunto un display anziché sottoscrivere gli eventi DisplayManager.DisplayListener. Per un'implementazione di riferimento, vedi CommandQueue.Callbacks#onDisplayAddSystemDecorations per il supporto della barra di navigazione e WallpaperManagerInternal#onDisplayAddSystemDecorations per gli sfondi.

Inoltre, Android 10 fornisce questi aggiornamenti:

  • La classe NavigationBarController controlla tutte le funzionalità specifiche delle barre di navigazione.
  • Per visualizzare una barra di navigazione personalizzata, vedi CarStatusBar.
  • TYPE_NAVIGATION_BAR non è più limitato a una singola istanza e può essere utilizzato per display.
  • IWindowManager#hasNavigationBar viene aggiornato per includere il parametro displayId solo per la UI di sistema.

Avvio applicazioni

In Android 10, per impostazione predefinita, ogni display configurato per supportare le decorazioni di sistema ha uno stack home dedicato per le attività di avvio applicazioni con tipo WindowConfiguration#ACTIVITY_TYPE_HOME. Ogni display utilizza un'istanza separata dell'attività di avvio applicazioni:

Figura 1. Esempio di avvio applicazioni multi-display per platform/development/samples/MultiDisplay.

La maggior parte degli avvio applicazioni esistenti non supporta più istanze e non è ottimizzata per le dimensioni dello schermo di grandi dimensioni. Inoltre, spesso ci si aspetta un'esperienza diversa sui display secondari/esterni. Per fornire un'attività dedicata per gli schermi secondari, Android 10 ha introdotto la categoria SECONDARY_HOME nei filtri di intent. Le istanze di questa attività vengono utilizzate su tutti i display che supportano le decorazioni di sistema, una per display.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

L'attività deve avere una modalità di avvio che non impedisca più istanze e che si adatti a diverse dimensioni dello schermo. La modalità di avvio non può essere singleInstance o singleTask.

Implementazione

In Android 10, RootActivityContainer#startHomeOnDisplay seleziona automaticamente il componente e l'intent desiderati a seconda del display in cui viene avviata la schermata Home. RootActivityContainer#resolveSecondaryHomeActivity contiene la logica per cercare il componente dell'attività di avvio applicazioni a seconda dell'avvio applicazioni attualmente selezionato e può utilizzare il valore predefinito del sistema, se necessario (vedi ActivityTaskManagerService#getSecondaryHomeIntent).

Limitazioni di sicurezza

Oltre alle limitazioni che si applicano alle attività sui display secondari, per evitare la possibilità che un'app dannosa crei un display virtuale con le decorazioni di sistema abilitate e legga informazioni sensibili dell'utente dalla superficie, l'avvio applicazioni viene visualizzato solo sui display virtuali di proprietà del sistema. L'avvio applicazioni non mostra contenuti sui display virtuali non di sistema.

Sfondi

In Android 10 e versioni successive, gli sfondi sono supportati sui display secondari:

Figura 2. Sfondo animato su display interni (in alto) ed esterni (in basso).

Gli sviluppatori possono dichiarare il supporto per la funzionalità dello sfondo fornendo android:supportsMultipleDisplays="true" nella definizione XML WallpaperInfo. Gli sviluppatori di sfondi devono anche caricare le risorse utilizzando il contesto del display in WallpaperService.Engine#getDisplayContext.

Il framework crea un'istanza WallpaperService.Engine per display, quindi ogni motore ha la propria superficie e il proprio contesto di visualizzazione. Lo sviluppatore deve assicurarsi che ogni motore possa disegnare in modo indipendente, a frame rate diversi, rispettando VSync.

Selezionare gli sfondi per i singoli schermi

Android 10 non fornisce il supporto diretto della piattaforma per la selezione degli sfondi per i singoli schermi. Per farlo, è necessario un identificatore di display stabile per conservare le impostazioni dello sfondo per display. Display#getDisplayId è dinamico, quindi non è garantito che un display fisico abbia lo stesso ID dopo il riavvio.

Tuttavia, Android 10 ha aggiunto DisplayInfo.mAddress, che contiene identificatori stabili per i display fisici e può essere utilizzato per un'implementazione completa in futuro. Purtroppo, è troppo tardi per implementare la logica per Android 10. La soluzione suggerita:

  1. Utilizza la classe WallpaperManager per impostare gli sfondi.

    WallpaperManager viene ottenuto da un oggetto Context e ogni oggetto Context contiene informazioni sul display corrispondente (Context#getDisplay/getDisplayId). Di conseguenza, puoi ottenere displayId da un'istanza WallpaperManager senza aggiungere nuovi metodi.

  2. Sul lato del framework, utilizza displayId ottenuto da un oggetto Context e mappalo a un identificatore statico (ad esempio una porta di un display fisico). Utilizza l'identificatore statico per conservare lo sfondo scelto.

Questa soluzione alternativa utilizza le implementazioni esistenti per i selettori di sfondi. Se è stato aperto su un display specifico e utilizza il contesto corretto, quando chiama per impostare uno sfondo, il sistema può identificare automaticamente il display.

Se è necessario impostare lo sfondo per un display diverso da quello attuale display, crea un nuovo oggetto Context per il display di destinazione (Context#createDisplayContext) e ottieni l'istanza WallpaperManager da quel display.

Limitazioni di sicurezza

Il sistema non mostrerà gli sfondi sui display virtuali di cui non è proprietario. Questo è dovuto a un problema di sicurezza: un'app dannosa potrebbe creare un display virtuale con il supporto delle decorazioni di sistema abilitato e leggere informazioni sensibili dell'utente dalla superficie (ad esempio una foto personale).

Implementazione

In Android 10, le interfacce IWallpaperConnection#attachEngine e IWallpaperService#attach accettano il parametro displayId per creare connessioni per display. WallpaperManagerService.DisplayConnector incapsula un motore e una connessione di sfondi per display. In WindowManager, i controller degli sfondi vengono creati per ogni oggetto DisplayContent durante la costruzione anziché un singolo WallpaperController per tutti i display.

Alcune delle implementazioni del metodo pubblico WallpaperManager (ad esempio WallpaperManager#getDesiredMinimumWidth) sono state aggiornate per calcolare e fornire informazioni per i display corrispondenti. Sono stati aggiunti WallpaperInfo#supportsMultipleDisplays e un attributo di risorsa corrispondente, in modo che gli sviluppatori di app possano segnalare quali sfondi sono pronti per più schermi.

Se il servizio di sfondi mostrato sul display predefinito non supporta più display, il sistema mostra lo sfondo predefinito sui display secondari:

Figura 3. Logica di fallback dello sfondo per i display secondari.

Abilitare il supporto degli sfondi animati

In Android 10 e versioni successive (API 29), gli sviluppatori possono utilizzare l'android:supportsMultipleDisplays attributo per indicare se il loro sfondo può estendersi su più display. Negli ambienti di finestre desktop, in cui il multitasking è intenso, il rendering degli sfondi animati sui display esterni può influire in modo significativo sul sovraccarico della GPU e della memoria.

Per preservare le risorse di sistema, il sistema non esegue il rendering degli sfondi animati sui display collegati per impostazione predefinita. Quando uno sfondo animato è limitato dalla configurazione di sistema o dal manifest dell'app, il sistema esegue il rendering di uno sfondo statico di fallback.

Gli OEM possono ottimizzare questa esperienza abilitando il supporto degli sfondi animati per l'hardware di fascia alta o personalizzando il fallback statico per un aspetto brandizzato.

Se l'hardware può eseguire il rendering di più istanze di sfondi animati, sostituisci la seguente configurazione:

Percorso della risorsa frameworks/base/core/res/res/values/config.xml
Nome configurazione config_isLiveWallpaperSupportedInDesktopExperience

Personalizzare lo sfondo di fallback

Se gli sfondi animati sono disattivati o non sono supportati dal provider, il sistema utilizza un componente predefinito. Puoi indirizzare questo componente al tuo provider di sfondi statici:

Percorso della risorsa frameworks/base/core/res/res/values/config.xml
Nome configurazione fallback_wallpaper_component

Implementare il supporto degli sfondi

Per applicare queste modifiche, utilizza una sovrapposizione di risorse in fase di compilazione nella cartella specifica del dispositivo, che in genere è device/<vendor>/<product>/overlay/frameworks/base/core/res/res/values/.