Unterstützung für Systemdekorationen

Nachfolgend finden Sie Aktualisierungen, die an diesen anzeigespezifischen Bereichen vorgenommen wurden:

Systemdekorationen

Android 10 bietet Unterstützung für die Konfiguration sekundärer Displays, um bestimmte Systemdekorationen wie Hintergrundbild, Navigationsleiste und Launcher anzuzeigen. Standardmäßig zeigt die primäre Anzeige alle Systemdekorationen an und die sekundären Anzeigen zeigen die optional aktivierten Dekorationen an. Die Unterstützung für einen Input Method Editor (IME) kann getrennt von anderen Systemdekorationen eingestellt werden.

Verwenden Sie DisplayWindowSettings#setShouldShowSystemDecorsLocked() , um Unterstützung für Systemdekorationen auf einer bestimmten Anzeige hinzuzufügen oder einen Standardwert in /data/system/display_settings.xml bereitzustellen. Beispiele finden Sie unter Anzeigefenstereinstellungen .

Implementierung

DisplayWindowSettings#setShouldShowSystemDecorsLocked() wird zu Testzwecken auch in WindowManager#setShouldShowSystemDecors() verfügbar gemacht. Durch das Auslösen dieser Methode mit der Absicht, Systemdekore zu aktivieren, werden zuvor fehlende Dekorfenster nicht hinzugefügt oder entfernt, wenn sie zuvor vorhanden waren. In den meisten Fällen wird die Änderung der Systemdekorationsunterstützung erst nach einem Neustart des Geräts vollständig wirksam.

Überprüfungen auf Unterstützung von Systemdekorationen in der WindowManager-Codebasis erfolgen normalerweise über DisplayContent#supportsSystemDecorations() , während Überprüfungen für externe Dienste (z. B. die System-Benutzeroberfläche, um zu überprüfen, ob die Navigationsleiste angezeigt werden soll) WindowManager#shouldShowSystemDecors() verwenden. Um zu verstehen, was durch diese Einstellung gesteuert wird, erkunden Sie die Aufrufpunkte dieser Methoden.

Dekorfenster der System-Benutzeroberfläche

Android 10 fügt Unterstützung für Systemdekorfenster nur für die Navigationsleiste hinzu, da die Navigationsleiste für die Navigation zwischen Aktivitäten und Apps unerlässlich ist. Standardmäßig werden in der Navigationsleiste die Angebote „Zurück“ und „Zuhause“ angezeigt. Dies ist nur enthalten, wenn die Zielanzeige Systemdekorationen unterstützt (siehe DisplayWindowSettings ).

Die Statusleiste ist ein komplizierteres Systemfenster, da sie auch Benachrichtigungsschatten, Schnelleinstellungen und Sperrbildschirm enthält. In Android 10 wird die Statusleiste auf sekundären Displays nicht unterstützt. Daher sind Benachrichtigungen, Einstellungen und eine vollständige Tastensperre nur auf dem primären Display verfügbar.

Das Systemfenster „Übersicht/Letzte“ wird auf sekundären Bildschirmen nicht unterstützt. In Android 10 zeigt AOSP nur „Letzte“ auf der Standardanzeige an und enthält Aktivitäten von allen Anzeigen. Beim Start über „Letzte“ wird eine Aktivität, die sich auf einem sekundären Bildschirm befand, standardmäßig auf diesem Bildschirm im Vordergrund angezeigt. Bei diesem Ansatz treten einige bekannte Probleme auf, z. B. die Tatsache, dass Apps nicht sofort aktualisiert werden, wenn sie auf anderen Bildschirmen angezeigt werden.

Implementierung

Um zusätzliche System-UI-Funktionen zu implementieren, sollten Gerätehersteller eine einzelne System-UI-Komponente verwenden, die auf das Hinzufügen/Entfernen von Anzeigen wartet und entsprechende Inhalte präsentiert.

Eine System-UI-Komponente, die Multi-Display (MD) unterstützt, sollte die folgenden Fälle verarbeiten:

  • Mehrfache Display-Initialisierung beim Start
  • Anzeige zur Laufzeit hinzugefügt
  • Anzeige zur Laufzeit entfernt

Wenn die System-Benutzeroberfläche das Hinzufügen einer Anzeige vor WindowManager erkennt, wird eine Race-Bedingung erstellt. Dies kann vermieden werden, indem ein benutzerdefinierter Rückruf von WindowManager an die Systembenutzeroberfläche implementiert wird, wenn eine Anzeige hinzugefügt wird, anstatt DisplayManager .DisplayListener Ereignisse zu abonnieren. Eine Referenzimplementierung finden Sie unter CommandQueue.Callbacks#onDisplayReady für die Navigationsleistenunterstützung und WallpaperManagerInternal#onDisplayReady für Hintergrundbilder.

Darüber hinaus bietet Android 10 diese Updates:

  • Die NavigationBarController Klasse steuert alle für Navigationsleisten spezifischen Funktionen.
  • Informationen zum Anzeigen einer angepassten Navigationsleiste finden Sie unter CarStatusBar .
  • TYPE_NAVIGATION_BAR ist nicht mehr auf eine einzelne Instanz beschränkt und kann pro Anzeige verwendet werden.
  • IWindowManager#hasNavigationBar() wurde aktualisiert und enthält jetzt nur noch den displayId Parameter für die System-Benutzeroberfläche.

Startprogramm

In Android 10 verfügt jede Anzeige, die für die Unterstützung von Systemdekorationen konfiguriert ist, standardmäßig über einen dedizierten Home-Stack für Launcher-Aktivitäten mit dem Typ WindowConfiguration#ACTIVITY_TYPE_HOME . Jede Anzeige verwendet eine separate Instanz der Launcher-Aktivität.

Abbildung 1. Beispiel für einen Multi-Display-Launcher für platform/development/samples/MultiDisplay

Die meisten vorhandenen Launcher unterstützen nicht mehrere Instanzen und sind nicht für große Bildschirmgrößen optimiert. Außerdem wird auf sekundären/externen Displays oft ein anderes Erlebnis erwartet. Um eine dedizierte Aktivität für sekundäre Bildschirme bereitzustellen, führt Android 10 die Kategorie SECONDARY_HOME in Intent-Filtern ein. Instanzen dieser Aktivität werden auf allen Displays verwendet, die Systemdekorationen unterstützen, eine pro Display.

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

Die Aktivität muss über einen Startmodus verfügen, der mehrere Instanzen nicht verhindert und sich voraussichtlich an unterschiedliche Bildschirmgrößen anpasst. Der Startmodus kann nicht singleInstance oder singleTask sein.

Implementierung

In Android 10 wählt RootActivityContainer#startHomeOnDisplay() automatisch die gewünschte Komponente und Absicht aus, abhängig von der Anzeige, auf der der Startbildschirm gestartet wird. RootActivityContainer#resolveSecondaryHomeActivity() enthält die Logik zum Nachschlagen der Launcher-Aktivitätskomponente abhängig vom aktuell ausgewählten Launcher und kann bei Bedarf den Systemstandard verwenden (siehe ActivityTaskManagerService#getSecondaryHomeIntent() ).

Sicherheitsbeschränkungen

Zusätzlich zu den Einschränkungen, die für Aktivitäten auf sekundären Displays gelten, wird der Launcher nur auf virtuellen Displays angezeigt, die dem System gehören, um zu vermeiden, dass eine bösartige App eine virtuelle Anzeige mit aktivierten Systemdekorationen erstellt und benutzersensible Informationen von der Oberfläche liest. Der Launcher zeigt keine Inhalte auf virtuellen Displays an, die nicht zum System gehören.

Hintergrundbilder

In Android 10 (und höher) werden Hintergrundbilder auf sekundären Displays unterstützt:

Abbildung 2. Live-Hintergrundbild auf internen (oben) und externen Displays (unten)

Entwickler können die Unterstützung für die Hintergrundfunktion erklären, indem sie android:supportsMultipleDisplays="true" in der WallpaperInfo XML-Definition angeben. Von Wallpaper-Entwicklern wird außerdem erwartet, dass sie Assets mithilfe des Anzeigekontexts in WallpaperService.Engine#getDisplayContext() laden.

Das Framework erstellt eine WallpaperService.Engine Instanz pro Anzeige, sodass jede Engine über eine eigene Oberfläche und einen eigenen Anzeigekontext verfügt. Der Entwickler muss sicherstellen, dass jede Engine unabhängig voneinander mit unterschiedlichen Bildraten und unter Berücksichtigung von VSYNC zeichnen kann.

Wählen Sie Hintergrundbilder für einzelne Bildschirme aus

Android 10 bietet keine direkte Plattformunterstützung für die Auswahl von Hintergrundbildern für einzelne Bildschirme. Um dies zu erreichen, ist eine stabile Anzeigekennung erforderlich, um die Hintergrundeinstellungen pro Anzeige beizubehalten. Display#getDisplayId() ist dynamisch, daher gibt es keine Garantie dafür, dass eine physische Anzeige nach dem Neustart dieselbe ID hat.

Allerdings wurde mit Android 10 DisplayInfo.mAddress hinzugefügt, das stabile Kennungen für physische Displays enthält und in Zukunft für eine vollständige Implementierung verwendet werden kann. Leider ist es zu spät, die Logik für Android 10 zu implementieren. Die vorgeschlagene Lösung:

  1. Verwenden Sie die WallpaperManager API, um die Hintergrundbilder festzulegen.
  2. WallpaperManager wird von einem Context Objekt abgerufen, und jedes Context Objekt verfügt über Informationen zur entsprechenden Anzeige ( Context#getDisplay()/getDisplayId() ). Daher können Sie displayId von einer WallpaperManager Instanz abrufen, ohne neue Methoden hinzuzufügen.
  3. Verwenden Sie auf der Framework-Seite die von einem Context erhaltene displayId und ordnen Sie sie einer statischen Kennung zu (z. B. einem Port einer physischen Anzeige). Verwenden Sie die statische Kennung, um das ausgewählte Hintergrundbild beizubehalten.

Bei dieser Problemumgehung werden vorhandene Implementierungen für die Hintergrundauswahl verwendet. Wenn es auf einem bestimmten Display geöffnet wurde und den richtigen Kontext verwendet, kann das System beim Aufruf zum Festlegen eines Hintergrundbilds das Display automatisch identifizieren.

Wenn ein Hintergrundbild für eine andere Anzeige als die aktuelle Anzeige festgelegt werden muss, erstellen Sie ein neues Context für die Zielanzeige ( Context#createDisplayContext ) und rufen Sie die WallpaperManager Instanz von dieser Anzeige ab.

Sicherheitsbeschränkungen

Das System zeigt keine Hintergrundbilder auf virtuellen Displays an, die es nicht besitzt. Dies ist auf Sicherheitsbedenken zurückzuführen, dass eine bösartige App bei aktivierter Systemdekorationsunterstützung eine virtuelle Anzeige erstellen und benutzersensible Informationen (z. B. ein persönliches Foto) von der Oberfläche lesen könnte.

Implementierung

In Android 10 akzeptieren die Schnittstellen IWallpaperConnection#attachEngine() und IWallpaperService#attach() den Parameter displayId , um Verbindungen pro Anzeige zu erstellen. WallpaperManagerService.DisplayConnector kapselt eine Hintergrund-Engine und -Verbindung pro Anzeige. In WindowManager werden beim Erstellen für jedes DisplayContent Objekt Hintergrund-Controller anstelle eines einzelnen WallpaperController für alle Anzeigen erstellt.

Einige der öffentlichen WallpaperManager Methodenimplementierungen (z. B. WallpaperManager#getDesiredMinimumWidth() ) wurden aktualisiert, um Informationen für entsprechende Anzeigen zu berechnen und bereitzustellen. WallpaperInfo#supportsMultipleDisplays() und ein entsprechendes Ressourcenattribut wurden hinzugefügt, damit App-Entwickler melden können, welche Hintergrundbilder für mehrere Bildschirme bereit sind.

Wenn der auf dem Standarddisplay angezeigte Hintergrunddienst nicht mehrere Displays unterstützt, zeigt das System das Standardhintergrundbild auf den sekundären Displays an.

Abbildung 3. Hintergrund-Fallback-Logik für sekundäre Displays