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 parametrodisplayId
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:
- Utilizza l'API
WallpaperManager
per impostare gli sfondi. -
WallpaperManager
è ottenuto da un oggettoContext
e ciascun oggettoContext
contiene informazioni sulla visualizzazione corrispondente (Context#getDisplay()/getDisplayId()
). Pertanto, puoi otteneredisplayId
da un'istanzaWallpaperManager
senza aggiungere nuovi metodi. - Dal punto di vista del framework, utilizza
displayId
ottenuto da un oggettoContext
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