Rozszerzenia WindowManager

Biblioteka Jetpack WindowManager umożliwia programistom aplikacji obsługę nowych formatów urządzeń i środowisk z wieloma oknami.

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 implementowany w AOSP w frameworks/base/libs/WindowManager/Jetpacki wysyłany na urządzenia, które obsługują funkcje WindowManager.

Rozkład modułów rozszerzeń

Rozszerzenia są kompilowane do biblioteki .jar i przechowywane w partycji system_ext na urządzeniu, jeśli rozszerzenia są włączone w makefile urządzenia.

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. Normalnie moduły są wczytywane do procesu aplikacji i wykonywane w środowisku wykonawczym jako część procesu aplikacji w środowisku wykonawczym, gdy są używane przez bibliotekę Jetpack WindowManager, dzięki czemu operacja jest podobna do kodu platformy po stronie klienta, jak widać na ilustracji:

Rysunek 1. Rozszerzenia WindowManager ładowane do procesu aplikacji w sposób podobny do kodu platformy.

Moduł androidx.window.extensions to obecny moduł rozszerzeń, który jest obecnie rozwijany. Moduł androidx.window.sidecar to starszy moduł, który jest dołączany ze względu na zgodność z najstarszymi wersjami Jetpack WindowManager. Nie jest on jednak już aktywnie aktualizowany.

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 umożliwiają korzystanie z okna na składanych urządzeniach z dużym ekranem i urządzeń obsługujących okna na wyświetlaczach zewnętrznych. Obszary funkcji:

Implementacje rozszerzeń OEM mogą dostarczać komponenty lub komponenty o wartości null z domyślnymi lub skróconymi implementacjami metod w interfejsie WindowExtensions, jeśli sprzęt urządzenia nie obsługuje odpowiednich funkcji, chyba że funkcja ta jest wyraźnie wymagana w Dokumentie 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 dostarczane przez rozszerzenia powinny być używane tylko przez bibliotekę Jetpack WindowManager. Interfejsy API rozszerzeń nie są przeznaczone do bezpośredniego wywoływania przez deweloperów aplikacji. Aby zapewnić prawidłowe działanie, nie dodawaj biblioteki rozszerzeń jako zależności aplikacji w pliku kompilacji Gradle. Unikaj kompilowania biblioteki Extensions bezpośrednio w aplikacji. Zamiast tego ładuj ją w czasie wykonywania, aby uniknąć ładowania mieszaniny klas Extensions kompilowanych wstępnie i klas Extensions udostępnianych w czasie wykonywania.

Jetpack WindowManager (androidx.window) należy dodać jako zależność aplikacji. Zapewnia on publiczne interfejsy API dla programistów, w tym te przeznaczone do funkcji rozszerzeń WindowManager. Biblioteka WindowManager automatycznie wczytuje rozszerzenia do procesu aplikacji i opakowuje interfejsy API rozszerzeń niskiego poziomu w interfejsy abstrakcyjne wyższego poziomu i bardziej skoncentrowane. Interfejsy Jetpack WindowManager są zgodne ze standardami współczesnego rozwoju aplikacji na Androida i mają zapewniać wygodną interoperacyjność dzięki integracji z kodem źródłowym, który korzysta z innych bibliotek AndroidX.

Wersje i aktualizacje rozszerzeń

Moduł rozszerzeń może być aktualizowany wraz z rocznymi lub kwartalnymi aktualizacjami platformy Android. Czterokrotnie szybsze aktualizacje umożliwiają zwiększanie poziomu interfejsu API rozszerzeń między aktualizacjami interfejsu API platformy Android, co pozwala na szybsze iteracje i daje producentom OEM możliwość dodawania oficjalnego dostępu do interfejsu API nowych funkcji w pobliżu premier sprzętowych.

W tabeli poniżej znajdziesz listę wersji interfejsu API androidx.window.extensions na potrzeby różnych wersji Androida.

Wersja platformy Android Poziom interfejsu WindowManager Extensions API 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 Extensions API (kolumna środkowa) jest podwyższany za każdym razem, gdy dodawane są nowe elementy do istniejącej stabilnej wersji interfejsu API (kolumna prawa).

Zgodność wsteczna i wsteczna

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ń. Jeśli wystąpi niezgodność, menedżer okien może wyłączyć korzystanie z rozszerzeń (częściowo lub całkowicie) i oznaczyć odpowiednie funkcje jako niedostępne dla aplikacji.

Rozszerzenia WindowManager są implementowane jako moduł system_ext, który używa interfejsów API prywatnej platformy do wywoływania głównego modułu WindowManager, DeviceStateManager, oraz innych usług systemowych w ramach implementacji funkcji rozszerzeń.

Zgodność z wersjami wstępnymi rozszerzeń może nie być zachowana przed odpowiednią kwartalną lub roczną aktualizacją platformy Android, w ramach której wersje te zostaną sfinalizowane. Całą historię interfejsów API rozszerzeń znajdziesz w gałęzi wydania w window:extensions:extensionsplikach tekstowych interfejsu API.

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. W rezultacie aplikacje ze starszymi wersjami WindowManager mogą nadal używać starszych interfejsów API rozszerzeń, dla których zostały skompilowane.

Weryfikacja CTS zapewnia, że w przypadku każdej zadeklarowanej wersji interfejsów API rozszerzeń na urządzeniu wszystkie interfejsy API tej i poprzednich wersji są obecne 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 wydajność aplikacji, gdy między klientem a serwerem wykonywane są dodatkowe wywołania IPC.

Moduły

Umieszczenie aktywności

Komponent Umieszczanie aktywności udostępnia zestaw funkcji, które umożliwiają aplikacjom porządkowanie prezentacji okna aktywności w granicach aplikacji nadrzędnej. Obejmuje to wyświetlanie 2 aktywności jednocześnie obok siebie w układzie z wieloma panelami, co ułatwia optymalizację dużego ekranu w starszych aplikacjach.

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 trzeba konfigurować urządzenia w żaden szczególny sposób, poza włączeniem modułu Rozszerzenia zgodnie z opisem w sekcji Rozpowszechnianie modułu Rozszerzenia. 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 popularnych urządzeń mobilnych i urządzeń 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 okien pozwalają aplikacjom reagować i wyświetlać zoptymalizowane układy 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 wyposażone w zawias łączący osobne lub ciągłe obszary panelu wyświetlacza muszą udostępniać informacje o zawiasie aplikacjom przez WindowLayoutComponent.

Pozycja i granice zawiasu muszą być raportowane względem okna aplikacji zidentyfikowanego przez Context przekazany 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 aktualizacje stanu muszą być zgłaszane w przypadku zmiany pozycji zawiasu między stanami stabilnymi. 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 być w stabilnym stanie w trybie półskładanym, interfejs API musi zwrócić wartość FoldingFeature.State.HALF_OPENED. Interfejs API nie ma stanu zamkniętego, ponieważ w takim przypadku okno aplikacji nie jest widoczne lub 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 na stronie DeviceStateProviderImpl.java.

    Jeśli domyślne implementacje DeviceStateProvider lub DeviceStatePolicy nie pasują do urządzenia, możesz użyć implementacji niestandardowej.

  • Włącz moduł rozszerzeń w sposób opisany w sekcji Dystrybucja modułów rozszerzeń.

  • 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, right i bottom to całkowite współrzędne w pikselach w przestrzeni współrzędnych wyświetlania w naturalnej orientacji 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 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 składania jest w połowie otwarta.
    • COMMON_STATE_FLAT = 3: funkcja składania jest płaska. Może to być na przykład otwarty stan typowego urządzenia z ekranem głównym po wewnętrznej stronie.
    • COMMON_STATE_USE_BASE_STATE = 1000: w Androidzie 14 wartość, która może być używana do emulowanych stanów, w których stan zawiasu jest określany na podstawie stanu podstawowego zgodnie z definicją 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 ekranem zgodnym z Androidem (zgodnie z definicją w specyfikacji Android CDD pod kątem atrybutów takich jak rozmiar, gęstość i dostępne funkcje nawigacji) pokrywającym wyświetlacz tylnych kamer muszą zapewniać dostęp do trybu wyświetlacza tylnego.

W Androidzie 14 tryb podwójnego wyświetlacza umożliwia aplikacjom działającym na wewnętrznym wyświetlaczu składanego urządzenia wyświetlanie dodatkowych treści na wyświetlaczu przednim, który jest skierowany w kierunku innych użytkowników. Na przykład wyświetlacz przedni może wyświetlać podgląd aparatu osobie, która jest fotografowana lub nagrywana.

Konfiguracja urządzenia

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

  • Skonfiguruj stany urządzenia w sekcji device_state_configuration.xml, aby były używane przez DeviceStateManagerService. Więcej informacji znajdziesz w sekcji DeviceStateProviderImpl.java.

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

  • W przypadku składanych urządzeń, które obsługują tryb otwarty lub złożony, określ odpowiednie identyfikatory stanu w pliku com.android.internal.R.array.config_openDeviceStates.

  • W przypadku urządzeń z ekranem składanym, które obsługują stany złożonego urządzenia, podaj odpowiednie identyfikatory stanów w polu 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:

    • Wymień odpowiednie stany w polu com.android.internal.R.array.config_rearDisplayDeviceStates w przypadku 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 polu com.android.internal.R.array.config_deviceStatesAvailableForAppRequests, aby udostępnić go aplikacjom.
  • W przypadku urządzeń z Androidem 14, które obsługują tryb podwójnego (równoczesnego) wyświetlania:

    • Ustaw com.android.internal.R.bool.config_supportsConcurrentInternalDisplays na true.
    • W pliku com.android.internal.R.config_deviceStateConcurrentRearDisplay określ adres fizycznego wyświetlacza tylnego.
    • W wartości com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay określ stan identyfikatora, którego mają używać rozszerzenia, jeśli identyfikator ma być udostępniany aplikacjom.
    • Dodaj identyfikator stanu w 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, zapoznaj się z artykułem 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, wykonaj instrukcje dotyczące Jetpacka na Androida. 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. przeanalizować wyniki;

Aby uruchomić testy w Android Studio:

  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 w module okien.
  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ę, która uruchamia test metody, testową klasę lub wszystkie testy w module.

Wyniki można analizować ręcznie, korzystając z wyjścia 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.