Supporto per decorazioni di sistema

Gli aggiornamenti apportati a queste aree specifiche del display sono forniti di seguito:

Decorazioni di sistema

Android 10 aggiunge il supporto per la configurazione dei display secondari per mostrare alcune decorazioni di sistema, come sfondo, barra di navigazione e launcher. Per impostazione predefinita, il display principale mostra tutte le decorazioni del sistema e i display secondari mostrano quelle abilitate facoltativamente. Il supporto per un Input Method Editor (IME) può essere impostato separatamente dalle altre decorazioni di sistema.

Utilizza DisplayWindowSettings#setShouldShowSystemDecorsLocked() per aggiungere il supporto per le decorazioni di sistema su uno schermo specifico o fornire un valore predefinito in /data/system/display_settings.xml . Per esempi, vedere Impostazioni della finestra di visualizzazione .

Implementazione

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

I controlli per il supporto delle decorazioni di sistema nella base di codice WindowManager in genere passano attraverso DisplayContent#supportsSystemDecorations() mentre i controlli per i servizi esterni (come l'interfaccia utente di sistema per verificare se la barra di navigazione deve essere visualizzata) utilizzano WindowManager#shouldShowSystemDecors() . Per comprendere cosa viene controllato da questa impostazione, esplorare i punti di chiamata di questi metodi.

Finestre decorative dell'interfaccia utente del sistema

Android 10 aggiunge il supporto della finestra di decorazione del sistema solo per la barra di navigazione, poiché la barra di navigazione è essenziale per spostarsi tra attività e app. Per impostazione predefinita, la barra di navigazione mostra le offerte Indietro e Home. Questo è incluso solo se il display di destinazione supporta le decorazioni di sistema (vedi DisplayWindowSettings ).

La barra di stato è una finestra di sistema più complicata, perché contiene anche l'Ombra notifiche, le Impostazioni rapide e la Schermata di blocco. In Android 10, la barra di stato non è supportata sui display secondari. Pertanto, notifiche, impostazioni e uno scudo tastiera completo sono disponibili solo sul display principale.

La finestra di sistema Panoramica/Recenti non è supportata nelle schermate secondarie. In Android 10, AOSP visualizza solo i Recenti sul display predefinito e contiene le attività di tutti i display. Quando viene avviata da Recenti, un'attività che era su un display secondario viene portata in primo piano su quel display, per impostazione predefinita. Questo approccio presenta alcuni problemi noti, come il mancato aggiornamento immediato quando le app vengono visualizzate su altri schermi.

Implementazione

Per implementare funzionalità aggiuntive dell'interfaccia utente di sistema, i produttori di dispositivi dovrebbero utilizzare un singolo componente dell'interfaccia utente di sistema che rileva l'aggiunta/rimozione di display e presenta contenuto appropriato.

Un componente dell'interfaccia utente di sistema che supporta Multi-Display (MD) dovrebbe gestire i seguenti casi:

  • Inizializzazione di più display all'avvio
  • Visualizzazione aggiunta in fase di esecuzione
  • Visualizzazione rimossa in fase di esecuzione

Quando l'interfaccia utente del sistema rileva l'aggiunta di uno schermo prima di WindowManager, crea una race condition. Ciò può essere evitato implementando un callback personalizzato da WindowManager all'interfaccia utente di sistema quando viene aggiunto un display invece di sottoscrivere gli eventi DisplayManager .DisplayListener . Per un'implementazione di riferimento, vedere CommandQueue.Callbacks#onDisplayReady per il supporto della barra di navigazione e WallpaperManagerInternal#onDisplayReady 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, vedere CarStatusBar .
  • TYPE_NAVIGATION_BAR non è più limitato a una singola istanza e può essere utilizzato per display.
  • IWindowManager#hasNavigationBar() è stato aggiornato per includere il parametro displayId solo per l'interfaccia utente del sistema.

Lanciatore

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

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

La maggior parte dei launcher esistenti non supporta più istanze e non è ottimizzata per schermi di grandi dimensioni. Inoltre, spesso ci si aspetta un diverso tipo di esperienza sui display secondari/esterni. Per fornire un'attività dedicata per gli schermi secondari, Android 10 introduce la categoria SECONDARY_HOME nei filtri di intenti. 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 alle 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'intento desiderati in base al display in cui viene avviata la schermata iniziale. RootActivityContainer#resolveSecondaryHomeActivity() contiene la logica per cercare il componente dell'attività del programma di avvio in base al programma di avvio attualmente selezionato e può utilizzare l'impostazione predefinita del sistema, se necessario (vedere ActivityTaskManagerService#getSecondaryHomeIntent() ).

Restrizioni di sicurezza

Oltre alle restrizioni che si applicano alle attività sui display secondari, per evitare la possibilità che un'app dannosa crei un display virtuale con decorazioni di sistema abilitate e legga informazioni sensibili dell'utente dalla superficie, il launcher viene visualizzato solo sui display virtuali di proprietà del sistema. Il programma di avvio non visualizza il contenuto su 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 (sopra) ed esterni (sotto)

Gli sviluppatori possono dichiarare il supporto per la funzionalità dello sfondo fornendo android:supportsMultipleDisplays="true" nella definizione XML WallpaperInfo . È inoltre previsto che gli sviluppatori di sfondi carichino le risorse utilizzando il contesto di visualizzazione 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 ciascun motore possa disegnare in modo indipendente, a frame rate diversi, rispettando VSYNC.

Seleziona gli sfondi per i singoli schermi

Android 10 non fornisce il supporto diretto della piattaforma per la selezione degli sfondi per i singoli schermi. A tale scopo, è necessario un identificatore di visualizzazione stabile per mantenere le impostazioni dello sfondo per display. Display#getDisplayId() è dinamico, quindi non esiste alcuna garanzia che uno schermo fisico avrà lo stesso ID dopo il riavvio.

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

  1. Utilizza l'API WallpaperManager per impostare gli sfondi.
  2. WallpaperManager è ottenuto da un oggetto Context e ciascun oggetto Context contiene informazioni sulla visualizzazione corrispondente ( Context#getDisplay()/getDisplayId() ). Pertanto, puoi ottenere displayId da un'istanza WallpaperManager senza aggiungere nuovi metodi.
  3. Dal punto di vista del framework, utilizza displayId ottenuto da un oggetto Context e mappalo su un identificatore statico (come una porta di un display fisico). Utilizza l'identificatore statico per rendere persistente 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 richiede di impostare uno sfondo, il sistema può identificare automaticamente il display.

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

Restrizioni di sicurezza

Il sistema non mostrerà gli sfondi sui display virtuali di cui non è proprietario. Ciò è dovuto a un problema di sicurezza dovuto al fatto che un'app dannosa potrebbe creare un display virtuale con il supporto delle decorazioni di sistema abilitato e leggere informazioni sensibili dell'utente dalla superficie (come 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 di sfondo e una connessione per display. In WindowManager, i controller dello sfondo vengono creati per ciascun oggetto DisplayContent durante la costruzione invece di un singolo WallpaperController per tutti i display.

Alcune delle implementazioni pubbliche del metodo WallpaperManager (come WallpaperManager#getDesiredMinimumWidth() ) sono state aggiornate per calcolare e fornire informazioni per le visualizzazioni 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 sfondi visualizzato 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