Rozszerzenia WindowManager

Biblioteka Jetpack WindowManager umożliwia deweloperom aplikacji obsługę nowych formatów urządzeń i środowisk wielookiennych.

Rozszerzenia WindowManager (Extensions) to moduł platformy Androida, który wymaga akceptacji użytkownika i umożliwia korzystanie z różnych funkcji Jetpack WindowManager. Moduł jest zaimplementowany w AOSP w regionie frameworks/base/libs/WindowManager/Jetpack i udostępniany na urządzeniach obsługujących funkcje WindowManager.

Rozkład modułów rozszerzeń

Rozszerzenia są kompilowane w bibliotekę .jar i umieszczane w partycji system_ext na urządzeniu, jeśli w pliku Makefile urządzenia są włączone rozszerzenia.

Aby włączyć rozszerzenia na urządzeniu, do pliku DDEX urządzenia dodaj ten fragment:

$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)

Umożliwia to włączenie pakietów androidx.window.extensionsandroidx.window.sidecar na urządzeniu oraz ustawienie właściwości persist.wm.extensions.enabled. Umieszczenie tych pakietów w pliku Makefile spowoduje też umieszczenie deklaracji w etc/permissions/, dzięki czemu będą one dostępne dla procesów aplikacji. Zwykle moduły są ładowane i wykonywane w ramach procesu aplikacji w czasie wykonywania, gdy są używane przez bibliotekę Jetpack WindowManager, co sprawia, że ich działanie jest podobne do działania kodu frameworku po stronie klienta, jak pokazano na poniższym rysunku:

Rysunek 1. Rozszerzenia WindowManager wczytywane do procesu aplikacji podobne do kodu platformy.

Moduł androidx.window.extensions to obecny moduł rozszerzeń, który jest obecnie rozwijany. Moduł androidx.window.sidecar to starszy moduł dostępny w celu zapewnienia zgodności z najwcześniejszymi wersjami Jetpack WindowManager, ale aplikacja pomocnicza nie jest już aktywnie obsługiwana.

Na rysunku poniżej pokazano logikę określania użycia funkcji androidx.window.extensions lub androidx.window.sidecar.

Rysunek 2. Drzewo decyzyjne dotyczące dostępu do androidx.window.extensions lub androidx.window.sidecar.

Moduły rozszerzeń

Rozszerzenia zapewniają funkcje okna na składanych urządzeniach z dużym ekranem oraz na urządzeniach obsługujących okna na zewnętrznych wyświetlaczach. Dostępne obszary:

Rozszerzenia implementowane przez OEM-ów mogą zawierać komponenty null lub komponenty z domyślnymi implementacjami metod lub implementacjami zastępczymi w interfejsie WindowExtensions, jeśli sprzęt urządzenia nie obsługuje odpowiednich funkcji, chyba że funkcja została wyraźnie zażądana w dokumentacji definicji zgodności (CDD) 7.1.1.1.

Interfejsy API rozszerzeń i Jetpacka

Moduł rozszerzeń WindowManager udostępnia własny interfejs API oprócz publicznych interfejsów API platformy. Moduł rozszerzeń jest publicznie rozwijany w bibliotece Jetpacka androidx.window.extensions, która nie jest przeznaczona dla programistów, aby Jetpack WindowManager (androidx.window) mógł się do niej odwoływać w czasie kompilacji. Interfejs Extensions API zwykle udostępnia interfejsy API niskiego poziomu.

Interfejsy API udostępniane przez rozszerzenia są przeznaczone tylko do użytku biblioteki Jetpack WindowManager. Interfejsy API rozszerzeń nie są przeznaczone do bezpośredniego wywoływania przez deweloperów aplikacji. Nie należy dodawać biblioteki rozszerzeń jako zależności aplikacji w pliku kompilacji Gradle, aby zapewnić prawidłowe działanie. Unikaj wstępnego kompilowania biblioteki rozszerzeń bezpośrednio do aplikacji. Zamiast tego polegaj na wczytywaniu środowiska wykonawczego, aby uniknąć wczytywania kombinacji klas rozszerzeń, które są wstępnie skompilowane oraz udostępnione w czasie działania.

Jetpack WindowManager (androidx.window) należy dodać jako zależność aplikacji i udostępniać publiczne interfejsy API dla programistów, w tym dla funkcji rozszerzeń WindowManager. Biblioteka WindowManager automatycznie wczytuje rozszerzenia do procesu aplikacji i opatruje interfejsy API rozszerzeń niższego poziomu w abstrakcje wyższego poziomu i bardziej precyzyjne interfejsy. Interfejsy WindowManager Jetpack API są zgodne ze standardami tworzenia nowoczesnych aplikacji na Androida i mają zapewnić wygodną interoperacyjność dzięki integracji z bazami kodu korzystającymi z innych bibliotek AndroidaX.

Wersje i aktualizacje rozszerzeń

Moduł rozszerzeń może być aktualizowany wraz z rocznymi lub kwartalnymi aktualizacjami platformy Android. Kwartalne aktualizacje umożliwiają zwiększanie poziomu interfejsu Extensions API między aktualizacjami API platformy Androida, co umożliwia szybszą iterację oraz umożliwia producentom OEM możliwość dodawania oficjalnych interfejsów API do nowych funkcji tuż przed premierą sprzętu.

W tabeli poniżej znajdziesz wersje interfejsu androidx.window.extensions API dla różnych wersji Androida.

Wersja platformy Android Poziom interfejsu API WindowManager Extensions Wersja interfejsu API androidx.window.extensions
Android 15 6 1.5.0 (wkrótce)
Android 14 QPR3 5 1.4.0 (wkrótce)
Android 14 QPR1 4 1.3.0
Android 14 3 1.2.0
Android 13 QPR3 2 1.1.0
Android 13 1 1.0.0
Android 12L 1 1.0.0

Poziom interfejsu API rozszerzeń (kolumna środkowa) zwiększa się za każdym razem, gdy pojawia się nowa stabilna powierzchnia interfejsu API (prawa kolumna).

Zgodność wstecz i do przodu

Jetpack WindowManager radzi sobie z zaawansowanymi aktualizacjami interfejsu API, szybkim rozwojem interfejsu API i wsteczną zgodnością. Gdy kod biblioteki jest wykonywany w procesie aplikacji, sprawdza deklarowany poziom interfejsu API rozszerzeń i daje dostęp do funkcji zgodnie z deklarowanym poziomem.

Aby chronić aplikację przed awariami w czasie działania, WindowManager wykonuje też weryfikację interfejsów API rozszerzeń w czasie działania za pomocą mechanizmu Java Reflection zgodnie z deklarowanym poziomem interfejsu API rozszerzeń. W razie wystąpienia niezgodności WindowManager może wyłączyć możliwość korzystania z rozszerzeń (częściowo lub całkowicie) i zgłosić odpowiednie funkcje jako niedostępne dla aplikacji.

Rozszerzenia WindowManager są zaimplementowane jako moduł system_ext, który wykorzystuje interfejsy API platformy prywatnej do wywoływania podstawowych usług systemu WindowManager, DeviceStateManager i innych usług systemowych w ramach implementacji funkcji rozszerzeń.

Nie można zachować zgodności z przedpremierowymi wersjami rozszerzeń przed odpowiednimi kwartalnymi lub rocznymi wydaniami na platformie Androida, na których wersje są finalizowane. Pełną historię interfejsów API rozszerzeń można znaleźć w sekcji Pliki tekstowe interfejsu API window:extensions:extensions.

Aby zachować zgodność wstecz, nowsze wersje rozszerzeń muszą nadal działać ze starszymi wersjami WindowManagera skompilowanych w aplikacje. Aby to zagwarantować, w każdej nowej wersji interfejsu Extensions API są dodawane tylko nowe interfejsy API – starsze nie są usuwane. Oznacza to, że aplikacje ze starszymi wersjami WindowManager mogą nadal korzystać ze starszych interfejsów API rozszerzeń, które zostały skompilowane na podstawie ich utworzenia.

Weryfikacja CTS zapewnia, że w przypadku każdej zadeklarowanej wersji interfejsów API rozszerzeń na urządzeniu wszystkie interfejsy API dla tej i poprzednich wersji są dostępne i działają.

Wydajność

Moduł rozszerzeń jest domyślnie zapisany w pamięci podręcznej w programach wczytujących klas systemu innych niż bootclasspath, począwszy od Androida 14 (poziom interfejsu API 34), dlatego nie ma wpływu na wydajność, ponieważ wczytuje się on do pamięci podczas uruchamiania aplikacji. Korzystanie z funkcji poszczególnych modułów może mieć niewielki wpływ na charakterystykę wydajności aplikacji, gdy między klientem a serwerem są wykonywane dodatkowe wywołania IPC.

Moduły

Umieszczanie aktywności

Komponent osadzania aktywności udostępnia zestaw funkcji, które umożliwiają aplikacjom organizowanie prezentacji okna aktywności w ramach aplikacji nadrzędnej. Obejmuje to wyświetlanie 2 czynności obok siebie w układzie z wieloma panelami, co ułatwia optymalizację dużych ekranów w przypadku starszych aplikacji.

Komponent umożliwiający umieszczanie aktywności musi być dostępny na wszystkich urządzeniach z wbudowanym wyświetlaczem o rozmiarze równym lub większym niż sw600 dp. Umieszczenie w ramce musi być też włączone na urządzeniach, które obsługują połączenia z wyświetlaczami zewnętrznymi, ponieważ aplikacja może być wyświetlana w większym rozmiarze, gdy wyświetlacze zewnętrzne są podłączone w czasie działania.

Konfiguracja urządzenia

Nie jest wymagana żadna konkretna konfiguracja urządzenia poza włączeniem modułu rozszerzeń zgodnie z opisem w sekcji Rozkład modułów rozszerzeń. Warto włączyć rozszerzenia na wszystkich urządzeniach, które obsługują tryb wielookienkowy. W przyszłych wersjach Androida rozszerzenia będą prawdopodobnie wymagane w przypadku typowych konfiguracji urządzeń przenośnych i z dużym ekranem.

Informacje o układzie okna

Komponent informacji o układzie okna określa położenie i stan zawiasu na urządzeniu składanym, gdy zawias przecina okno aplikacji. Informacje o układzie okna umożliwiają aplikacjom reagowanie na optymalne układy i wyświetlanie ich w trybie stołu na urządzeniach składanych. Szczegółowe informacje o wykorzystaniu znajdziesz w artykule Informacje o umieszczeniu aplikacji na ekranie.

Składane urządzenia z Androidem, które mają zawias łączący oddzielne lub ciągłe obszary panelu wyświetlacza, muszą udostępniać informacje o tym zawiasie aplikacjom za pomocą WindowLayoutComponent.

Położenie zawiasu i granice zawiasu muszą być zgłaszane w odniesieniu do okna aplikacji wskazywanego przez parametr Context przekazywany do interfejsu API. Jeśli granice okna aplikacji nie pokrywają się z granicami zawiasów, zawiasy DisplayFeaturenie muszą być zgłaszane. Nie musisz też raportować funkcji wyświetlania, jeśli ich pozycja nie może być wiarygodnie raportowana, na przykład gdy użytkownik może swobodnie przenosić okno aplikacji w trybie wielookiennym lub trybie Letterbox.

W przypadku funkcji składania stany muszą być aktualizowane, gdy pozycja zawiasu zmienia się między stabilnymi stanami. Domyślnie w stanie wyświetlania w płaskim formacie interfejs API musi zwracać wartość FoldingFeature.State.FLAT. Jeśli sprzęt urządzenia może znajdować się w trybie złożonym do połowy w stabilnym stanie, interfejs API musi zgłosić FoldingFeature.State.HALF_OPENED. W interfejsie API nie ma stanu zamkniętego, ponieważ w takim przypadku okno aplikacji albo nie byłoby widoczne, albo nie przekraczałoby granic zawiasów.

Konfiguracja urządzenia

Aby umożliwić implementację funkcji składania, producenci OEM muszą:

  • Skonfiguruj stany urządzeń w usłudze device_state_configuration.xml, których ma używać DeviceStateManagerService. Więcej informacji znajdziesz w DeviceStateProviderImpl.java.

    Jeśli domyślne implementacje funkcji DeviceStateProvider lub DeviceStatePolicy nie są odpowiednie na danym urządzeniu, możesz użyć implementacji niestandardowej.

  • Włącz moduł Rozszerzenia w sposób opisany w sekcji Dystrybucja modułu Rozszerzenia.

  • Określ lokalizację funkcji wyświetlania w zasobach napisów com.android.internal.R.string.config_display_features (zwykle w frameworks/base/core/res/res/values/config.xml w nakładce na urządzeniu).

    Oczekiwany format ciągu znaków:

    <type>-[<left>,<top>,<right>,<bottom>]

    Wartość type może być równa fold lub hinge. Wartości left, top, rightbottom to całkowite współrzędne pikseli w przestrzeni współrzędnych wyświetlacza w naturalnym ułożeniu wyświetlacza. Ciąg konfiguracji może zawierać wiele funkcji wyświetlania rozdzielonych średnikami.

    Na przykład:

    <!-- Jetpack WindowManager display features -->
    <string name="config_display_features" translatable="false">fold-[1000,0,1000,2000]</string>
    
  • Określ mapowanie między wewnętrznymi identyfikatorami stanu urządzenia używanymi w DeviceStateManager a konstantami stanu publicznego wysyłanymi do deweloperów w com.android.internal.R.array.config_device_state_postures.

    Oczekiwany format każdego wpisu:

    <device_specific_state_identifier>:<Jetpack WindowManager state identifier>

    Obsługiwane identyfikatory stanów:

    • COMMON_STATE_NO_FOLDING_FEATURES = 1: stan nie ma funkcji składania, które można by zgłosić. Może to być na przykład zamknięty stan typowego urządzenia z ekranem głównym po wewnętrznej stronie.
    • COMMON_STATE_HALF_OPENED = 2: funkcja zwijania jest otwarta w połowie.
    • COMMON_STATE_FLAT = 3: funkcja składania jest płaska. Może to być na przykład stan otwarty w typowym składanym urządzeniu, którego ekran główny jest od strony wewnętrznej.
    • COMMON_STATE_USE_BASE_STATE = 1000: w Androidzie 14 wartość, której można używać w emulowanych stanach, w których stan zawiasu jest określany na podstawie stanu podstawowego, jak określono w CommonFoldingFeature.java.

    Więcej informacji: DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int).

    Na przykład:

    <!-- Map of System DeviceState supplied by DeviceStateManager to WindowManager posture.-->
    <string-array name="config_device_state_postures" translatable="false">
        <item>0:1</item>    <!-- CLOSED       : COMMON_STATE_NO_FOLDING_FEATURES -->
        <item>1:2</item>    <!-- HALF_OPENED  : COMMON_STATE_HALF_OPENED -->
        <item>2:3</item>    <!-- OPENED       : COMMON_STATE_FLAT -->
        <item>3:1</item>    <!-- REAR_DISPLAY : COMMON_STATE_NO_FOLDING_FEATURES -->
        <item>4:1000</item> <!-- CONCURRENT   : COMMON_STATE_USE_BASE_STATE -->
    </string-array>
    

Obszar okna

Komponent obszaru okna udostępnia zestaw funkcji, które umożliwiają aplikacjom dostęp do dodatkowych wyświetlaczy i obszarów wyświetlacza na niektórych składanych urządzeniach oraz urządzeniach z wielorakiem wyświetlaczem.

Tryb wyświetlacza tylnego umożliwia aplikacji wyświetlanie interfejsu podglądu aparatu na wyświetlaczu zewnętrznym składanego urządzenia, aby umożliwić korzystanie z głównego aparatu urządzenia do robienia selfie i filmów. Urządzenia z urządzeniami zgodnymi z Androidem (zgodnie z definicjami atrybutów takich jak rozmiar, gęstość i dostępne funkcje nawigacji) muszą zapewniać dostęp do trybu tylnego wyświetlacza.

W Androidzie 14 tryb podwójnego ekranu umożliwia aplikacjom, które działają na wewnętrznym wyświetlaczu urządzenia składanego, wyświetlanie dodatkowych treści na wyświetlaczu na okładce skierowanym do innych użytkowników. Na przykład na wyświetlaczu na okładce może być widoczny podgląd z aparatu osobie, która jest fotografowana lub nagrywana.

Konfiguracja urządzenia

Aby umożliwić implementację funkcji składania, producenci OEM muszą:

  • Skonfiguruj stany urządzeń w usłudze device_state_configuration.xml, których ma używać DeviceStateManagerService. Więcej informacji znajdziesz w sekcji DeviceStateProviderImpl.java.

    Jeśli domyślna implementacja DeviceStateProvider lub DeviceStatePolicy nie jest odpowiednia dla danego urządzenia, można użyć implementacji niestandardowej.

  • W przypadku urządzeń składanych, które obsługują tryb otwarty lub płaski, w polu com.android.internal.R.array.config_openDeviceStates podaj odpowiednie identyfikatory stanów.

  • W przypadku urządzeń składanych, które obsługują stan złożenia, wymień odpowiednie identyfikatory stanów w pliku com.android.internal.R.array.config_foldedDeviceStates.

  • W przypadku urządzeń składanych, które umożliwiają złożenie do połowy (zawias jest otwarty w połowie jak w laptopie), wymień odpowiednie stany w polu com.android.internal.R.array.config_halfFoldedDeviceStates.

  • W przypadku urządzeń obsługujących tryb wyświetlacza tylnego:

    • Wyświetl odpowiednie stany w polu com.android.internal.R.array.config_rearDisplayDeviceStates dla: DeviceStateManager.
    • W pliku com.android.internal.R.string.config_rearDisplayPhysicalAddress określ adres fizycznego wyświetlacza tylnego.
    • W elementach com.android.internal.R.integer.config_deviceStateRearDisplay określ identyfikator stanu, który ma być używany przez rozszerzenia.
    • Dodaj identyfikator stanu w com.android.internal.R.array.config_deviceStatesAvailableForAppRequests, aby udostępnić go aplikacjom.
  • Na Androidzie 14 na urządzeniach obsługujących tryb podwójnego (jednoczesnego) wyświetlania:

    • Ustaw com.android.internal.R.bool.config_supportsConcurrentInternalDisplays na true.
    • Podaj fizyczny wyświetlany adres tylnego wyświetlacza w polu com.android.internal.R.config_deviceStateConcurrentRearDisplay.
    • Określ identyfikator stanu w zasadzie com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay, który ma być używany przez rozszerzenia, jeśli ma być on dostępny dla aplikacji.
    • Dodaj identyfikator stanu w polu com.android.internal.R.array.config_deviceStatesAvailableForAppRequests, aby udostępnić go aplikacjom.

Weryfikacja

Producenci OEM muszą sprawdzić swoje implementacje, aby zapewnić oczekiwane działanie w typowych scenariuszach. Testy CTS i testy za pomocą Jetpack WindowManager są dostępne dla OEM-ów do testowania implementacji.

Testy CTS

Aby przeprowadzić testy CTS, zobacz Przeprowadzanie testów CTS. Testy CTS dotyczące Jetpack WindowManager są dostępne w sekcji cts/tests/framework/base/windowmanager/jetpack/. Nazwa modułu testowego to CtsWindowManagerJetpackTestCases.

Testy WindowManager

Aby pobrać testy Jetpack WindowManager, postępuj zgodnie z instrukcjami dotyczącymi Androida Jetpacka. Testy znajdują się w bibliotece okien w module window:window: window/window/src/androidTest/.

Aby uruchomić testy urządzenia dla modułu window:window w wierszu poleceń, wykonaj te czynności:

  1. Podłącz urządzenie z włączonymi opcjami programisty i debugowaniem USB.
  2. Zezwól komputerowi na debugowanie urządzenia.
  3. Otwórz powłokę w katalogu głównym repozytorium androidx.
  4. Zmień katalog na framework/support.
  5. Uruchom to polecenie: ./gradlew window:window:connectedAndroidTest.
  6. Przeanalizuj wyniki.

Aby uruchomić testy w Android Studio, wykonaj te czynności:

  1. Otwórz Android Studio.
  2. Podłącz urządzenie z włączonymi opcjami programisty i debugowaniem USB.
  3. Zezwól komputerowi na debugowanie urządzenia.
  4. Przejdź do testu w bibliotece okien modułu okna.
  5. Otwórz klasę testową i uruchom ją za pomocą zielonych strzałek po prawej stronie edytora.

Możesz też utworzyć w Android Studio konfigurację, aby uruchomić metodę testową, klasę testową lub wszystkie testy w module.

Wyniki można analizować ręcznie, sprawdzając dane wyjściowe powłoki. Niektóre testy są pomijane, jeśli urządzenie nie spełnia określonych założeń. Wyniki są zapisywane w standardowej lokalizacji, a analitycy mogą napisać skrypt, który zautomatyzuje analizę wyników.