Obsługa dekoracji systemu

Aktualizacje wprowadzone w tych obszarach specyficznych dla wyświetlacza są przedstawione poniżej:

Dekoracje systemowe

W systemie Android 10 dodano obsługę konfigurowania dodatkowych wyświetlaczy w celu wyświetlania niektórych dekoracji systemu, takich jak tapeta, pasek nawigacyjny i program uruchamiający. Domyślnie główny wyświetlacz pokazuje wszystkie dekoracje systemu, a wyświetlacze dodatkowe pokazują te opcjonalnie włączone. Obsługa edytora Input Method Editor (IME) może być ustawiona oddzielnie od innych dekoracji systemu.

Użyj DisplayWindowSettings#setShouldShowSystemDecorsLocked() , aby dodać obsługę dekoracji systemowych na określonym ekranie lub podać wartość domyślną w /data/system/display_settings.xml . Aby zapoznać się z przykładami, zobacz Ustawienia okna wyświetlania .

Realizacja

DisplayWindowSettings#setShouldShowSystemDecorsLocked() jest również dostępny w WindowManager#setShouldShowSystemDecors() do testowania. Wyzwolenie tej metody z zamiarem włączenia dekorów systemowych nie powoduje dodania okien dekorów, których wcześniej brakowało, ani usunięcia ich, jeśli były wcześniej obecne. W większości przypadków zmiana obsługi dekoracji systemu zaczyna obowiązywać dopiero po ponownym uruchomieniu urządzenia.

Kontrole obsługi dekoracji systemowych w bazie kodu WindowManagera zwykle przechodzą przez DisplayContent#supportsSystemDecorations() , podczas gdy sprawdzanie usług zewnętrznych (takich jak interfejs systemu w celu sprawdzenia, czy powinien być wyświetlany pasek nawigacji) używa WindowManager#shouldShowSystemDecors() . Aby zrozumieć, co jest kontrolowane przez to ustawienie, zapoznaj się z punktami wywołania tych metod.

Okna z dekoracją interfejsu systemu

Android 10 dodaje obsługę okna wystroju systemu tylko dla paska nawigacyjnego, ponieważ pasek nawigacyjny jest niezbędny do poruszania się między działaniami i aplikacjami. Domyślnie pasek nawigacyjny pokazuje afordancje Wstecz i Dom. Jest to uwzględniane tylko wtedy, gdy ekran docelowy obsługuje dekoracje systemowe (zobacz DisplayWindowSettings ).

Pasek stanu jest bardziej skomplikowanym oknem systemowym, ponieważ zawiera również cień powiadomień, szybkie ustawienia i ekran blokady. W systemie Android 10 pasek stanu nie jest obsługiwany na dodatkowych wyświetlaczach. Dlatego powiadomienia, ustawienia i pełna ochrona klawiatury są dostępne tylko na głównym wyświetlaczu.

Okno systemowe Przegląd/Ostatnie nie jest obsługiwane na ekranach dodatkowych. W systemie Android 10 AOSP wyświetla tylko ostatnie na domyślnym ekranie i zawiera działania ze wszystkich ekranów. Po uruchomieniu z Ostatnich aktywność, która była na dodatkowym ekranie, jest domyślnie przenoszona na pierwszy ekran tego ekranu. To podejście ma kilka znanych problemów, takich jak brak aktualizacji natychmiast, gdy aplikacje pojawiają się na innych ekranach.

Realizacja

Aby zaimplementować dodatkowe funkcje interfejsu użytkownika systemu, producenci urządzeń powinni używać pojedynczego składnika interfejsu systemu, który nasłuchuje dodawania/usuwania ekranów i przedstawia odpowiednią zawartość.

Komponent System UI obsługujący Multi-Display (MD) powinien obsługiwać następujące przypadki:

  • Inicjalizacja wielu wyświetlaczy podczas uruchamiania
  • Wyświetlacz dodany w czasie wykonywania
  • Wyświetlacz został usunięty w czasie wykonywania

Gdy systemowy interfejs użytkownika wykryje dodanie ekranu przed WindowManagerem, tworzy sytuację wyścigu. Można tego uniknąć, implementując niestandardowe wywołanie zwrotne z WindowManager do interfejsu użytkownika systemu, gdy ekran jest dodawany zamiast subskrybowania zdarzeń DisplayManager .DisplayListener . Aby zapoznać się z implementacją referencyjną, zobacz CommandQueue.Callbacks#onDisplayReady dla obsługi paska nawigacyjnego i WallpaperManagerInternal#onDisplayReady dla tapet.

Ponadto Android 10 zapewnia następujące aktualizacje:

  • Klasa NavigationBarController kontroluje wszystkie funkcje specyficzne dla pasków nawigacyjnych.
  • Aby wyświetlić dostosowany pasek nawigacji, zobacz CarStatusBar .
  • TYPE_NAVIGATION_BAR nie jest już ograniczony do pojedynczego wystąpienia i może być używany na każdym ekranie.
  • IWindowManager#hasNavigationBar() został zaktualizowany tak, aby zawierał parametr displayId tylko dla interfejsu systemu.

Wyrzutnia

W systemie Android 10 każdy wyświetlacz skonfigurowany do obsługi dekoracji systemowych ma domyślnie dedykowany stos domowy dla działań programu uruchamiającego o typie WindowConfiguration#ACTIVITY_TYPE_HOME . Każdy wyświetlacz wykorzystuje osobną instancję aktywności programu uruchamiającego.

Rysunek 1. Przykładowy program uruchamiający na wielu ekranach dla platform/development/samples/MultiDisplay

Większość istniejących programów uruchamiających nie obsługuje wielu wystąpień i nie jest zoptymalizowana pod kątem dużych rozmiarów ekranu. Ponadto często oczekuje się innego rodzaju wrażeń na wyświetlaczach drugorzędnych/zewnętrznych. Aby zapewnić dedykowaną aktywność dla ekranów dodatkowych, Android 10 wprowadza kategorię SECONDARY_HOME w filtrach intencji. Wystąpienia tej czynności są wykorzystywane na wszystkich wyświetlaczach obsługujących dekoracje systemowe, po jednym na wyświetlacz.

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

Działanie musi mieć tryb uruchamiania, który nie zapobiega wielu instancjom i powinien dostosowywać się do różnych rozmiarów ekranu. Tryb uruchamiania nie może być singleInstance ani singleTask .

Realizacja

W systemie Android 10 RootActivityContainer#startHomeOnDisplay() automatycznie wybiera żądany składnik i intencję w zależności od wyświetlacza, na którym uruchamiany jest ekran główny. RootActivityContainer#resolveSecondaryHomeActivity() zawiera logikę wyszukiwania komponentu aktywności programu uruchamiającego w zależności od aktualnie wybranego programu uruchamiającego i może w razie potrzeby używać domyślnych ustawień systemowych (zobacz ActivityTaskManagerService#getSecondaryHomeIntent() ).

Ograniczenia bezpieczeństwa

Oprócz ograniczeń, które dotyczą działań na wyświetlaczach pomocniczych, aby uniknąć możliwości, że złośliwa aplikacja stworzy wirtualny wyświetlacz z włączonymi dekoracjami systemu i odczyta z powierzchni informacje wrażliwe dla użytkownika, launcher pojawia się tylko na wirtualnych wyświetlaczach należących do systemu. Program uruchamiający nie wyświetla treści na niesystemowych ekranach wirtualnych.

Tapety

W systemie Android 10 (i nowszym) tapety są obsługiwane na dodatkowych wyświetlaczach:

Rysunek 2. Animowana tapeta na wyświetlaczach wewnętrznych (powyżej) i zewnętrznych (poniżej)

Deweloperzy mogą zadeklarować obsługę funkcji tapety, podając android:supportsMultipleDisplays="true" w definicji WallpaperInfo XML. Oczekuje się również, że twórcy tapet będą ładować zasoby przy użyciu kontekstu wyświetlania w WallpaperService.Engine#getDisplayContext() .

Struktura tworzy jedną instancję WallpaperService.Engine na ekran, więc każdy silnik ma własną powierzchnię i kontekst wyświetlania. Deweloper musi upewnić się, że każdy silnik może rysować niezależnie, z różnymi szybkościami klatek, z poszanowaniem VSYNC.

Wybór tapet dla poszczególnych ekranów

Android 10 nie zapewnia bezpośredniej obsługi platform do wybierania tapet dla poszczególnych ekranów. Aby to osiągnąć, potrzebny jest stabilny identyfikator wyświetlacza, aby zachować ustawienia tapety na ekranie. Display#getDisplayId() jest funkcją dynamiczną, więc nie ma gwarancji, że fizyczny wyświetlacz będzie miał ten sam identyfikator po ponownym uruchomieniu.

Jednak Android 10 dodał DisplayInfo.mAddress , który zawiera stabilne identyfikatory dla fizycznych wyświetlaczy i może być używany do pełnej implementacji w przyszłości. Niestety na zaimplementowanie logiki dla Androida 10 jest już za późno. Sugerowane rozwiązanie:

  1. Użyj interfejsu API WallpaperManager , aby ustawić tapety.
  2. WallpaperManager jest uzyskiwany z obiektu Context , a każdy obiekt Context zawiera informacje o odpowiednim wyświetlaniu ( Context#getDisplay()/getDisplayId() ). Dlatego możesz uzyskać displayId z instancji WallpaperManager bez dodawania nowych metod.
  3. Po stronie frameworku użyj displayId uzyskanego z obiektu Context i przypisz go do statycznego identyfikatora (takiego jak port fizycznego wyświetlacza). Użyj statycznego identyfikatora, aby zachować wybraną tapetę.

To obejście wykorzystuje istniejące implementacje dla selektorów tapet. Jeśli został otwarty na konkretnym wyświetlaczu i korzysta z odpowiedniego kontekstu, to przy wywołaniu ustawienia tapety system może automatycznie zidentyfikować wyświetlacz.

Jeśli istnieje potrzeba ustawienia tapety dla wyświetlacza innego niż bieżący wyświetlacz, utwórz nowy obiekt Context dla wyświetlacza docelowego ( Context#createDisplayContext ) i uzyskaj instancję WallpaperManager z tego wyświetlacza.

Ograniczenia bezpieczeństwa

System nie wyświetla tapet na wirtualnych wyświetlaczach, których nie posiada. Wynika to z obawy o bezpieczeństwo, że złośliwa aplikacja może utworzyć wirtualny wyświetlacz z włączoną obsługą dekoracji systemu i odczytać z powierzchni informacje wrażliwe dla użytkownika (takie jak osobiste zdjęcie).

Realizacja

W systemie Android 10 IWallpaperConnection#attachEngine() i IWallpaperService#attach() akceptują parametr displayId w celu tworzenia połączeń na ekran. WallpaperManagerService.DisplayConnector zawiera w sobie mechanizm tapet dla każdego ekranu i połączenie. W WindowManager kontrolery tapet są tworzone dla każdego obiektu DisplayContent podczas budowy zamiast pojedynczego WallpaperController dla wszystkich wyświetlaczy.

Niektóre z publicznych implementacji metody WallpaperManager (takie jak WallpaperManager#getDesiredMinimumWidth() ) zostały zaktualizowane w celu obliczenia i dostarczenia informacji dla odpowiednich ekranów. Dodano WallpaperInfo#supportsMultipleDisplays() i odpowiedni atrybut zasobów, aby twórcy aplikacji mogli zgłaszać, które tapety są gotowe na wiele ekranów.

Jeśli usługa tapet wyświetlana na domyślnym wyświetlaczu nie obsługuje wielu wyświetlaczy, system wyświetla domyślną tapetę na wyświetlaczach dodatkowych.

Rysunek 3. Logika awaryjna tapety na wyświetlaczach dodatkowych