Die Aktualisierungen in diesen displayspezifischen Bereichen sind unten aufgeführt:
- Größenänderung von Aktivitäten und Displays
- Displaygrößen und Seitenverhältnisse
- Displayrichtlinien
- Einstellungen für Displayfenster
- Statische Display-IDs
- Verwendung von mehr als zwei Displays
- Fokus pro Display
Größenänderung von Aktivitäten und Displays
Um anzugeben, dass eine App den Mehrfenstermodus oder die Größenänderung möglicherweise nicht unterstützt, verwenden Aktivitäten das Attribut resizeableActivity=false. Häufige Probleme, die bei Apps auftreten, wenn die Größe von Aktivitäten geändert wird:
- Eine Aktivität kann eine andere Konfiguration als die App oder eine andere nicht visuelle Komponente haben. Ein häufiger Fehler besteht darin, Displaymesswerte aus dem App-Kontext zu lesen. Die zurückgegebenen Werte werden nicht an die Messwerte des sichtbaren Bereichs angepasst, in dem eine Aktivität angezeigt wird.
- Eine Aktivität kann die Größenänderung möglicherweise nicht verarbeiten und abstürzen, eine verzerrte Benutzeroberfläche anzeigen oder den Status verlieren, weil sie ohne Speichern des Instanzstatus neu gestartet wird.
- Eine App versucht möglicherweise, absolute Eingabekoordinaten zu verwenden (anstatt der Koordinaten relativ zur Fensterposition). Dadurch kann die Eingabe im Mehrfenstermodus unterbrochen werden.
Unter Android 7 (und höher) kann für eine App resizeableActivity=false festgelegt werden, damit sie immer im Vollbildmodus ausgeführt wird. In diesem Fall verhindert die Plattform, dass Aktivitäten mit nicht änderbarer Größe im Splitscreen-Modus ausgeführt werden. Wenn der Nutzer versucht, eine Aktivität mit nicht änderbarer Größe über den Launcher aufzurufen, während er sich bereits im Splitscreen-Modus befindet, beendet die Plattform den Splitscreen-Modus und startet die Aktivität mit nicht änderbarer Größe im Vollbildmodus.
Apps, bei denen dieses Attribut im Manifest explizit auf false gesetzt ist, dürfen nicht im Mehrfenstermodus gestartet werden, es sei denn, der Kompatibilitätsmodus wird angewendet:
- Dieselbe Konfiguration wird auf den Prozess angewendet, der alle Aktivitäten und nicht aktivitätsbezogenen Komponenten enthält.
- Die angewendete Konfiguration erfüllt die CDD-Anforderungen für mit Apps kompatible Displays.
Unter Android 10 verhindert die Plattform weiterhin, dass Aktivitäten mit nicht änderbarer Größe im Splitscreen-Modus ausgeführt werden. Sie können jedoch vorübergehend skaliert werden, wenn für die Aktivität eine feste Ausrichtung oder ein festes Seitenverhältnis deklariert wurde. Andernfalls wird die Größe der Aktivität so angepasst, dass sie den gesamten Bildschirm ausfüllt, wie unter Android 9 und niedriger.
Bei der Standardimplementierung wird die folgende Richtlinie angewendet:
Wenn eine Aktivität als nicht mit dem Mehrfenstermodus kompatibel deklariert wurde, indem das Attribut android:resizeableActivity verwendet wurde, und wenn diese Aktivität eine der unten beschriebenen Bedingungen erfüllt, werden die Aktivität und der Prozess mit der ursprünglichen Konfiguration gespeichert, wenn die angewendete Bildschirmkonfiguration geändert werden muss. Der Nutzer erhält die Möglichkeit, den App-Prozess neu zu starten, um die aktualisierte Bildschirmkonfiguration zu verwenden.
- Feste Ausrichtung über die Anwendung von
android:screenOrientation - Die App hat ein standardmäßiges maximales oder minimales Seitenverhältnis, indem sie auf das API-Level ausgerichtet ist oder das Seitenverhältnis explizit deklariert.
Diese Abbildung zeigt eine Aktivität mit nicht änderbarer Größe und einem deklarierten Seitenverhältnis. Wenn das Gerät zusammengeklappt wird, wird die Größe des Fensters so angepasst, dass es in den Bereich passt, wobei das Seitenverhältnis mithilfe des entsprechenden Letterboxing beibehalten wird. Außerdem wird dem Nutzer jedes Mal eine Option zum Neustart der Aktivität angezeigt, wenn der Anzeigebereich für die Aktivität geändert wird.
Wenn das Gerät aufgeklappt wird, ändern sich die Konfiguration, Größe und das Seitenverhältnis der Aktivität nicht. Es wird jedoch die Option zum Neustart der Aktivität angezeigt.
Wenn resizeableActivity nicht festgelegt ist (oder auf true gesetzt ist), unterstützt die App die Größenänderung vollständig.
Implementierung
Eine Aktivität mit nicht änderbarer Größe und fester Ausrichtung oder festem Seitenverhältnis wird im Code als Größenkompatibilitätsmodus (Size Compatibility Mode, SCM) bezeichnet. Die Bedingung ist in ActivityRecord#shouldUseSizeCompatMode() definiert. Wenn eine SCM-Aktivität gestartet wird, ist die bildschirmbezogene Konfiguration (z. B. Größe oder Dichte) in der angeforderten Überschreibungskonfiguration festgelegt, sodass die Aktivität nicht mehr von der aktuellen Displaykonfiguration abhängig ist.
Wenn die SCM-Aktivität nicht den gesamten Bildschirm ausfüllen kann, wird sie oben ausgerichtet und horizontal zentriert. Die Aktivitätsgrenzen werden von AppWindowToken#calculateCompatBoundsTransformation() berechnet.
Wenn eine SCM-Aktivität eine andere Bildschirmkonfiguration als ihr Container verwendet (z. B. wenn die Größe des Displays geändert oder die Aktivität auf ein anderes Display verschoben wird), ist ActivityRecord#inSizeCompatMode() auf „true“ gesetzt und SizeCompatModeActivityController (in der System-UI) erhält den Callback, um die Schaltfläche zum Neustart des Prozesses anzuzeigen.
Displaygrößen und Seitenverhältnisse
Android 10 unterstützt neue Seitenverhältnisse, von hohen Verhältnissen langer und schmaler Bildschirme bis hin zu 1:1-Verhältnissen. Apps können
ApplicationInfo#maxAspectRatio
und die ApplicationInfo#minAspectRatio des Bildschirms definieren, den sie
verarbeiten können.

Abbildung 1 : Beispiel für App-Verhältnisse, die unter Android 10 unterstützt werden
Geräteimplementierungen können sekundäre Displays mit Größen und Auflösungen haben, die kleiner sind als die von Android 9 und niedriger erforderlichen (mindestens 6,35 cm Breite oder Höhe, mindestens 320 DP für smallestScreenWidth). Dort können jedoch nur Aktivitäten platziert werden, die diese kleinen Displays unterstützen.
Apps können sich anmelden, indem sie eine unterstützte Mindestgröße deklarieren, die kleiner oder gleich der Ziel-Anzeigegröße ist. Verwenden Sie dazu die Layoutattribute android:minHeight und android:minWidth im AndroidManifest.
Displayrichtlinien
Unter Android 10 werden bestimmte Displayrichtlinien von der Standardimplementierung WindowManagerPolicy in PhoneWindowManager getrennt und in klassenspezifische Klassen verschoben, z. B.:
- Displaystatus und ‑ausrichtung
- Einige Tasten und Motion-Event-Tracking
- System-UI und Dekorationsfenster
Unter Android 9 (und niedriger) wurden Displayrichtlinien, Status und Einstellungen, Ausrichtung, Tracking von Dekorationsfensterrahmen und mehr von der Klasse PhoneWindowManager verarbeitet. Unter Android 10 wird das meiste davon in die Klasse DisplayPolicy verschoben, mit Ausnahme des Ausrichtungstrackings, das in DisplayRotation verschoben wurde.
Einstellungen für Displayfenster
Unter Android 10 wurde die konfigurierbare Einstellung für die Fensterverwaltung pro Display um Folgendes erweitert:
- Standardmodus für die Fensterverwaltung auf dem Display
- Overscan-Werte
- Nutzerrotation und Rotationsmodus
- Erzwungene Größe, Dichte und Skalierungsmodus
- Modus zum Entfernen von Inhalten (wenn das Display entfernt wird)
- Unterstützung für Systemdekorationen und IME
Die Klasse DisplayWindowSettings enthält Einstellungen für diese Optionen. Sie werden jedes Mal, wenn eine Einstellung geändert wird, in der Partition /data in display_settings.xml auf dem Laufwerk gespeichert. Weitere Informationen finden Sie unter DisplayWindowSettings.AtomicFileStorage und DisplayWindowSettings#writeSettings(). Gerätehersteller können in display_settings.xml Standardwerte für ihre Gerätekonfiguration angeben. Da die Datei jedoch in /data gespeichert ist, ist möglicherweise zusätzliche Logik erforderlich, um die Datei wiederherzustellen, wenn sie durch eine Bereinigung gelöscht wurde.
Standardmäßig verwendet Android 10 DisplayInfo#uniqueId als ID für ein Display, wenn die Einstellungen gespeichert werden. uniqueId sollte für alle Displays ausgefüllt sein. Außerdem ist sie für physische und Netzwerkdisplays stabil. Es ist auch möglich, den Port eines physischen Displays als ID zu verwenden. Dieser kann in DisplayWindowSettings#mIdentifier festgelegt werden. Bei jedem Schreibvorgang werden alle Einstellungen geschrieben. Daher ist es sicher, den Schlüssel zu aktualisieren, der für einen Displayeintrag im Speicher verwendet wird. Weitere Informationen finden Sie unter
Statische Display-IDs.
Die Einstellungen werden aus historischen Gründen im Verzeichnis /data gespeichert. Ursprünglich wurden sie verwendet, um vom Nutzer festgelegte Einstellungen wie die Displayausrichtung zu speichern.
Statische Display-IDs
Unter Android 9 (und niedriger) gab es im Framework keine stabilen IDs für Displays. Wenn dem System ein Display hinzugefügt wurde, wurde Display#mDisplayId oder DisplayInfo#displayId für dieses Display generiert, indem ein statischer Zähler erhöht wurde. Wenn dasselbe Display vom System hinzugefügt und entfernt wurde, ergab sich eine andere ID.
Wenn auf einem Gerät von Anfang an mehrere Displays verfügbar waren, konnten den Displays je nach Zeitpunkt unterschiedliche IDs zugewiesen werden. Unter Android 9 (und niedriger) war zwar DisplayInfo#uniqueId enthalten, aber nicht genügend Informationen, um zwischen Displays zu unterscheiden, da physische Displays entweder als local:0 oder local:1 identifiziert wurden, um das integrierte und das externe Display darzustellen.
Unter Android 10 wird DisplayInfo#uniqueId geändert, um eine stabile ID hinzuzufügen und zwischen lokalen, Netzwerk- und virtuellen Displays zu unterscheiden.
| Displaytyp | Format |
|---|---|
| Lokal | local:<stable-id> |
| Netzwerk | network:<mac-address> |
| Virtuell | virtual:<package-name-and-name> |
Zusätzlich zu den Aktualisierungen von uniqueId enthält DisplayInfo.address DisplayAddress, eine Display-ID, die über Neustarts hinweg stabil ist. Unter Android 10 unterstützt DisplayAddress physische und Netzwerkdisplays. DisplayAddress.Physical enthält eine stabile Display-ID (wie in uniqueId) und kann mit DisplayAddress#fromPhysicalDisplayId() erstellt werden.
Android 10 bietet auch eine praktische Methode zum Abrufen von Portinformationen (Physical#getPort()). Diese Methode kann im Framework verwendet werden, um Displays statisch zu identifizieren. Sie wird beispielsweise in DisplayWindowSettings verwendet. DisplayAddress.Network enthält die MAC-Adresse und kann mit DisplayAddress#fromMacAddress() erstellt werden.
Mit diesen Ergänzungen können Gerätehersteller Displays in statischen Multi-Display-Setups identifizieren und verschiedene Systemeinstellungen und ‑funktionen mithilfe statischer Display-IDs konfigurieren, z. B. Ports für physische Displays. Diese Methoden sind ausgeblendet und dürfen nur in system_server verwendet werden.
Bei einer HWC-Display-ID (die undurchsichtig und nicht immer stabil sein kann) gibt diese Methode die (plattformspezifische) 8-Bit-Portnummer zurück, die einen physischen Anschluss für die Displayausgabe identifiziert, sowie den EDID-Blob des Displays.
SurfaceFlinger extrahiert Hersteller- oder Modellinformationen aus der EDID, um die stabilen 64-Bit-Display-IDs zu generieren, die für das Framework verfügbar gemacht werden. Wenn diese Methode nicht unterstützt wird oder Fehler auftreten, greift SurfaceFlinger auf den Legacy-MD-Modus zurück, in dem DisplayInfo#address null und DisplayInfo#uniqueId fest codiert ist, wie oben beschrieben.
Führen Sie Folgendes aus, um zu prüfen, ob diese Funktion unterstützt wird:
$ dumpsys SurfaceFlinger --display-id # Example output. Display 21691504607621632 (HWC display 0): port=0 pnpId=SHP displayName="LQ123P1JX32" Display 9834494747159041 (HWC display 2): port=1 pnpId=HWP displayName="HP Z24i" Display 1886279400700944 (HWC display 1): port=2 pnpId=AUS displayName="ASUS MB16AP"
Verwendung von mehr als zwei Displays
Unter Android 9 (und niedriger) gingen SurfaceFlinger und DisplayManagerService von maximal zwei physischen Displays mit den fest codierten IDs 0 und 1 aus.
Ab Android 10 kann SurfaceFlinger eine Hardware Composer (HWC) API verwenden, um stabile Display-IDs zu generieren, mit denen eine beliebige Anzahl physischer Displays verwaltet werden kann. Weitere Informationen finden Sie unter Statische Display-IDs.
Das Framework kann das IBinder-Token für ein physisches Display über SurfaceControl#getPhysicalDisplayToken suchen, nachdem die 64-Bit-Display-ID von SurfaceControl#getPhysicalDisplayIds oder von einem DisplayEventReceiver-Hotplug-Ereignis abgerufen wurde.
Unter Android 10 (und niedriger) ist das primäre interne Display TYPE_INTERNAL und alle sekundären Displays werden unabhängig vom Verbindungstyp als TYPE_EXTERNAL gekennzeichnet. Daher werden zusätzliche interne Displays als extern behandelt.
Als Problemumgehung kann gerätespezifischer Code Annahmen zu DisplayAddress.Physical#getPort treffen, wenn der HWC bekannt ist und die Logik für die Portzuweisung vorhersehbar ist.
Diese Einschränkung wurde unter Android 11 (und höher) entfernt.
- Unter Android 11 ist das erste Display, das beim Start gemeldet wird, das primäre Display. Der Verbindungstyp (intern oder extern) ist irrelevant. Es gilt jedoch weiterhin, dass das primäre Display nicht getrennt werden kann und daher in der Praxis ein internes Display sein muss. Einige faltbare Smartphones haben mehrere interne Displays.
- Sekundäre Displays werden je nach Verbindungstyp korrekt als
Display.TYPE_INTERNALoderDisplay.TYPE_EXTERNAL(früherDisplay.TYPE_BUILT_INundDisplay.TYPE_HDMI, jeweils) kategorisiert.
Implementierung
Unter Android 9 und niedriger werden Displays durch 32-Bit-IDs identifiziert, wobei 0 für das interne Display, 1 für das externe Display, [2, INT32_MAX] für virtuelle HWC-Displays und -1 für ein ungültiges Display oder ein nicht HWC-virtuelles Display steht.
Ab Android 10 erhalten Displays stabile und dauerhafte IDs, mit denen SurfaceFlinger und DisplayManagerService mehr als zwei Displays verfolgen und zuvor gesehene Displays erkennen können. Wenn der HWC IComposerClient.getDisplayIdentificationData unterstützt und Display-Identifikationsdaten bereitstellt, parst SurfaceFlinger die EDID-Struktur und weist physischen und virtuellen HWC-Displays stabile 64-Bit-Display-IDs zu. Die IDs werden mit einem Optionstyp ausgedrückt, wobei der Nullwert ein ungültiges Display oder ein nicht HWC-virtuelles Display darstellt. Ohne HWC-Unterstützung greift SurfaceFlinger auf das Legacy-Verhalten mit maximal zwei physischen Displays zurück.
Fokus pro Display
Um mehrere Eingabequellen zu unterstützen, die gleichzeitig auf einzelne Displays ausgerichtet sind, kann Android 10 so konfiguriert werden, dass mehrere fokussierte Fenster unterstützt werden, maximal eines pro Display. Dies ist nur für spezielle Gerätetypen vorgesehen, wenn mehrere Nutzer gleichzeitig mit demselben Gerät interagieren und verschiedene Eingabemethoden oder ‑geräte verwenden, z. B. Android Automotive.
Es wird dringend empfohlen, diese Funktion nicht für normale Geräte zu aktivieren, einschließlich Geräte mit mehreren Bildschirmen oder Geräte, die für desktopähnliche Erlebnisse verwendet werden. Das liegt vor allem an einem Sicherheitsproblem, das dazu führen kann, dass sich Nutzer fragen, welches Fenster den Eingabefokus hat.
Stellen Sie sich vor, der Nutzer gibt sichere Informationen in ein Texteingabefeld ein, meldet sich beispielsweise in einer Banking-App an oder gibt Text ein, der vertrauliche Informationen enthält. Eine schädliche App könnte ein virtuelles Display außerhalb des Bildschirms erstellen, mit dem eine Aktivität ausgeführt wird, auch mit einem Texteingabefeld. Legitime und schädliche Aktivitäten haben den Fokus und zeigen beide eine aktive Eingabeanzeige (blinkender Cursor).
Da die Eingabe über eine Tastatur (Hardware oder Software) jedoch nur in die oberste Aktivität eingegeben wird (die App, die zuletzt gestartet wurde), könnte eine schädliche App durch Erstellen eines verborgenen virtuellen Displays Nutzereingaben abfangen, auch wenn eine Softwaretastatur auf dem primären Display des Geräts verwendet wird.
Verwenden Sie com.android.internal.R.bool.config_perDisplayFocusEnabled, um den Fokus pro Display festzulegen.
Kompatibilität
Problem:Unter Android 9 und niedriger hat jeweils nur ein Fenster im System den Fokus.
Lösung:In dem seltenen Fall, dass zwei Fenster aus demselben Prozess fokussiert werden, gibt das System den Fokus nur an das Fenster, das in der Z-Reihenfolge höher liegt. Diese Einschränkung wird für Apps entfernt, die auf Android 10 ausgerichtet sind. Dann wird erwartet, dass sie die gleichzeitige Fokussierung mehrerer Fenster unterstützen.
Implementierung
WindowManagerService#mPerDisplayFocusEnabled steuert die Verfügbarkeit dieser Funktion. In ActivityManager wird jetzt ActivityDisplay#getFocusedStack() anstelle des globalen Trackings in einer Variablen verwendet. ActivityDisplay#getFocusedStack()
bestimmt den Fokus anhand der Z-Reihenfolge, anstatt den Wert im Cache zu speichern. So muss nur eine Quelle, WindowManager, die Z-Reihenfolge der Aktivitäten verfolgen.
ActivityStackSupervisor#getTopDisplayFocusedStack() verfolgt einen ähnlichen Ansatz für die Fälle, in denen der oberste fokussierte Stack im System identifiziert werden muss. Die Stacks werden von oben nach unten durchlaufen, um den ersten geeigneten Stack zu finden.
InputDispatcher kann jetzt mehrere fokussierte Fenster haben (eines pro Display). Wenn ein Eingabeereignis displayspezifisch ist, wird es an das fokussierte Fenster auf dem entsprechenden Display gesendet. Andernfalls wird es an das fokussierte Fenster auf dem fokussierten Display gesendet, also dem Display, mit dem der Nutzer zuletzt interagiert hat.
Weitere Informationen finden Sie unter InputDispatcher::mFocusedWindowHandlesByDisplay und InputDispatcher::setFocusedDisplay(). Fokussierte Apps werden auch separat in InputManagerService über NativeInputManager::setFocusedApplication() aktualisiert.
In WindowManager werden fokussierte Fenster ebenfalls separat verfolgt.
Weitere Informationen finden Sie unter DisplayContent#mCurrentFocus und DisplayContent#mFocusedApp und den jeweiligen Verwendungen. Verwandte Methoden zum Tracking und Aktualisieren des Fokus wurden von WindowManagerService nach DisplayContent verschoben.