Unterstützung von Systemdekorationen

Aktualisierungen dieser anzeigenspezifischen Bereiche werden auf dieser Seite bereitgestellt.

Systemverzierungen

In Android 10 können sekundäre Displays so konfiguriert werden, dass bestimmte Systemdekorationen wie Hintergrundbild, Navigationsleiste und Launcher angezeigt werden. Standardmäßig werden auf dem primären Display alle Systemdekorationen angezeigt, auf sekundären Displays nur die optional aktivierten. Sie können die Unterstützung für einen Eingabemethoden-Editor (IME) separat von anderen Systemdekorationen festlegen.

Verwenden Sie DisplayWindowSettings#setShouldShowSystemDecorsLocked, um Unterstützung für Systemdekorationen auf einem bestimmten Display hinzuzufügen oder einen Standardwert in /data/system/display_settings.xml anzugeben. Beispiele finden Sie unter Einstellungen für das Displayfenster.

Implementierung

DisplayWindowSettings#setShouldShowSystemDecorsLocked wird auch in WindowManager#setShouldShowSystemDecors für Tests bereitgestellt. Wenn Sie diese Methode auslösen, um Systemdekorationen zu aktivieren, werden keine Dekorfenster hinzugefügt, die zuvor gefehlt haben, und keine entfernt, die zuvor vorhanden waren. In den meisten Fällen wird die Änderung der Unterstützung für Systemdekorationen erst nach einem Neustart des Geräts vollständig wirksam.

Prüfungen zur Unterstützung von Systemdekorationen in der WindowManager-Codebasis erfolgen in der Regel über DisplayContent#supportsSystemDecorations, während Prüfungen für externe Dienste (z. B. System-UI, um zu prüfen, ob die Navigationsleiste angezeigt werden soll) WindowManager#shouldShowSystemDecors verwenden. Um zu verstehen, was durch diese Einstellung gesteuert wird, sehen Sie sich die Aufrufstellen dieser Methoden an.

Dekorfenster der System-UI

In Android 10 wird die Unterstützung für System-Decor-Fenster nur für die Navigationsleiste hinzugefügt, da sie für die Navigation zwischen Aktivitäten und Apps unerlässlich ist. Standardmäßig werden in der Navigationsleiste die Schaltflächen „Zurück“ und „Home“ angezeigt. Die Navigationsleiste ist nur enthalten, wenn das Zieldisplay Systemdekorationen unterstützt (siehe DisplayWindowSettings).

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

Das Systemfenster Übersichten oder Letzte Apps wird auf sekundären Bildschirmen nicht unterstützt. In Android 10 werden in AOSP nur die zuletzt verwendeten Apps auf dem Standarddisplay angezeigt und Aktivitäten von allen Displays enthalten. Wenn eine Aktivität, die auf einem sekundären Display angezeigt wurde, über „Letzte“ gestartet wird, wird sie standardmäßig auf diesem Display in den Vordergrund geholt. Dieser Ansatz hat einige bekannte Probleme, z. B. dass er nicht sofort aktualisiert wird, wenn Apps auf anderen Bildschirmen angezeigt werden.

Implementierung

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

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

  • Initialisierung mehrerer Displays beim Start
  • Display zur Laufzeit hinzugefügt
  • Display zur Laufzeit entfernt

Wenn die System-UI das Hinzufügen eines Displays vor dem WindowManager erkennt, entsteht eine Race-Bedingung. Sie können dies vermeiden, indem Sie einen benutzerdefinierten Callback von WindowManager zur System-UI implementieren, wenn ein Display hinzugefügt wird, anstatt DisplayManager.DisplayListener-Ereignisse zu abonnieren. Eine Referenzimplementierung finden Sie unter CommandQueue.Callbacks#onDisplayAddSystemDecorations für die Unterstützung der Navigationsleiste und unter WallpaperManagerInternal#onDisplayAddSystemDecorations für Hintergrundbilder.

Außerdem bietet Android 10 folgende Updates:

  • Die Klasse NavigationBarController steuert alle Funktionen, die für Navigationsleisten spezifisch sind.
  • Informationen zum Anpassen der Navigationsleiste finden Sie unter CarStatusBar.
  • TYPE_NAVIGATION_BAR ist nicht mehr auf eine einzelne Instanz beschränkt und kann pro Display verwendet werden.
  • IWindowManager#hasNavigationBar wurde aktualisiert und enthält jetzt den Parameter displayId nur für die System-UI.

Launcher

In Android 10 hat jeder Bildschirm, der für die Unterstützung von Systemdekorationen konfiguriert ist, standardmäßig einen dedizierten Home-Stack für Launcher-Aktivitäten mit dem Typ WindowConfiguration#ACTIVITY_TYPE_HOME. Für jeden Bildschirm wird eine separate Instanz der Launcher-Aktivität verwendet:

Abbildung 1. Beispiel für einen Launcher für mehrere Displays für platform/development/samples/MultiDisplay.

Die meisten vorhandenen Launcher unterstützen keine mehreren Instanzen und sind nicht für große Displays optimiert. Außerdem wird auf sekundären/externen Displays oft eine andere Art von Nutzererfahrung erwartet. Um eine spezielle Aktivität für sekundäre Displays bereitzustellen, wurde in Android 10 die Kategorie SECONDARY_HOME in Intent-Filtern eingeführt. 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 einen Startmodus haben, der mehrere Instanzen zulässt, und sich an verschiedene Bildschirmgrößen anpassen. Der Startmodus darf nicht singleInstance oder singleTask sein.

Implementierung

In Android 10 wird die gewünschte Komponente und der gewünschte Intent automatisch ausgewählt, je nachdem, auf welchem Display der Startbildschirm gestartet wird.RootActivityContainer#startHomeOnDisplay RootActivityContainer#resolveSecondaryHomeActivity enthält die Logik zum Suchen der Launcher-Aktivitätskomponente in Abhängigkeit vom aktuell ausgewählten Launcher und kann bei Bedarf den Systemstandard verwenden (siehe ActivityTaskManagerService#getSecondaryHomeIntent).

Sicherheitseinschrä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. So soll verhindert werden, dass eine schädliche App ein virtuelles Display mit aktivierten Systemdekorationen erstellt und nutzersensible Informationen von der Oberfläche liest. Der Launcher zeigt keine Inhalte auf virtuellen Displays an, die nicht zum System gehören.

Hintergründe

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

Abbildung 2: Live-Hintergrund auf dem inneren (oben) und äußeren Display (unten).

Entwickler können die Unterstützung für die Hintergrundbildfunktion deklarieren, indem sie android:supportsMultipleDisplays="true" in der XML-Definition WallpaperInfo angeben. Hintergrundbildentwickler müssen Assets auch über den Anzeige-Kontext in WallpaperService.Engine#getDisplayContext laden.

Das Framework erstellt eine WallpaperService.Engine-Instanz pro Display. Jede Engine hat also ihren eigenen Surface- und Displaykontext. Der Entwickler muss dafür sorgen, dass jede Engine unabhängig voneinander mit unterschiedlichen Framerates zeichnen kann und dabei VSync berücksichtigt.

Hintergründe für einzelne Displays auswählen

Android 10 bietet keine direkte Plattformunterstützung für die Auswahl von Hintergrundbildern für einzelne Bildschirme. Dazu ist eine stabile Display-Kennung erforderlich, um die Hintergrundeinstellungen pro Display beizubehalten. Display#getDisplayId ist dynamisch. Es gibt daher keine Garantie, dass ein physisches Display nach einem Neustart dieselbe ID hat.

Mit Android 10 wurde jedoch DisplayInfo.mAddress eingeführt, 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. Vorgeschlagene Lösung:

  1. Verwenden Sie die Klasse WallpaperManager, um die Hintergrundbilder festzulegen.

    WallpaperManager wird aus einem Context-Objekt abgerufen und jedes Context-Objekt enthält Informationen zum entsprechenden Display (Context#getDisplay/getDisplayId). Daher können Sie displayId aus einer WallpaperManager-Instanz abrufen, ohne neue Methoden hinzuzufügen.

  2. Verwenden Sie auf der Framework-Seite displayId, das von einem Context-Objekt abgerufen wird, und ordnen Sie es einer statischen Kennung zu (z. B. einem Port eines physischen Displays). Verwenden Sie die statische Kennung, um den ausgewählten Hintergrund beizubehalten.

Bei dieser Problemumgehung werden vorhandene Implementierungen für die Auswahl von Hintergrundbildern verwendet. Wenn die App auf einem bestimmten Display geöffnet wurde und den richtigen Kontext verwendet, kann das System das Display automatisch erkennen, wenn es aufgerufen wird, um ein Hintergrundbild festzulegen.

Wenn Sie das Hintergrundbild für ein anderes Display als das aktuelle festlegen müssen, erstellen Sie ein neues Context-Objekt für das Zieldisplay (Context#createDisplayContext) und rufen Sie die WallpaperManager-Instanz von diesem Display ab.

Sicherheitseinschränkungen

Das System zeigt keine Hintergrundbilder auf virtuellen Displays an, die nicht zum System gehören. Dies ist auf ein Sicherheitsrisiko zurückzuführen, da eine schädliche App ein virtuelles Display mit aktivierter Unterstützung für Systemdekorationen erstellen und vertrauliche Nutzerinformationen von der Oberfläche lesen könnte (z. B. ein persönliches Foto).

Implementierung

In Android 10 akzeptieren die Schnittstellen IWallpaperConnection#attachEngine und IWallpaperService#attach den Parameter displayId, um Verbindungen pro Display zu erstellen. WallpaperManagerService.DisplayConnector kapselt eine Wallpaper-Engine und ‑Verbindung pro Display. In WindowManager werden Wallpaper-Controller für jedes DisplayContent-Objekt bei der Erstellung erstellt, anstatt eines einzelnen WallpaperController für alle Displays.

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

Wenn der auf dem Standarddisplay angezeigte Hintergrunddienst keine Unterstützung für mehrere Displays bietet, wird auf den sekundären Displays der Standardhintergrund angezeigt:

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

Unterstützung für Live-Hintergründe aktivieren

In Android 10 und höher (API 29) können Entwickler mit dem Attribut android:supportsMultipleDisplays angeben, ob ihr Hintergrundbild auf mehreren Displays angezeigt werden kann. In Desktop-Freiform-Fenster-Umgebungen, in denen Multitasking intensiv genutzt wird, kann das Rendern von Live-Hintergründen auf externen Displays die GPU- und Arbeitsspeicher-Overheads erheblich beeinträchtigen.

Um Systemressourcen zu schonen, werden Live-Hintergründe auf angeschlossenen Displays standardmäßig nicht gerendert. Wenn ein Live-Hintergrund durch die Systemkonfiguration oder das App-Manifest eingeschränkt wird, rendert das System einen statischen Fallback-Hintergrund.

OEMs können diese Funktion anpassen, indem sie entweder die Unterstützung von Live-Hintergründen für High-End-Hardware aktivieren oder das statische Fallback für ein Branding anpassen.

Wenn Ihre Hardware mehrere Live-Hintergrundinstanzen rendern kann, überschreiben Sie die folgende Konfiguration:

Ressourcenpfad frameworks/base/core/res/res/values/config.xml
Konfigurationsname config_isLiveWallpaperSupportedInDesktopExperience

Fallback-Hintergrund anpassen

Wenn Live-Hintergründe deaktiviert sind oder vom Anbieter nicht unterstützt werden, verwendet das System eine Standardkomponente. Sie können dies auf Ihren eigenen Anbieter für statische Hintergrundbilder verweisen:

Ressourcenpfad frameworks/base/core/res/res/values/config.xml
Konfigurationsname fallback_wallpaper_component

Unterstützung für Hintergrundbilder implementieren

Um diese Änderungen anzuwenden, verwenden Sie ein Ressourcen-Overlay für die Build-Zeit in Ihrem gerätespezifischen Ordner, der in der Regel device/<vendor>/<product>/overlay/frameworks/base/core/res/res/values/ ist.