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

Dystrybucja modułu rozszerzeń

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

Aby włączyć rozszerzenia na urządzeniu, dodaj do pliku makefile urządzenia produktu:

$(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. Uwzględnienie tych pakietów w makefile powoduje też umieszczenie deklaracji w pliku etc/permissions/, dzięki czemu są 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 ładowane do procesu aplikacji w sposób podobny do kodu platformy.

Moduł androidx.window.extensions to obecny moduł rozszerzeń, nad którym obecnie pracujemy. Moduł androidx.window.sidecar to starszy moduł, który jest dołączony ze względu na zgodność z najstarszymi wersjami Jetpack WindowManager, ale nie jest już aktywnie obsługiwany.

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. Obszary funkcji:

Rozszerzenia implementowane przez producentów OEM 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 jest wyraźnie wymagana 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. 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 mieszanki klas z kompilacją wstępną i klas z czasem 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ększenie poziomu interfejsu API rozszerzeń między aktualizacjami interfejsu API platformy Android, co pozwala na szybsze iteracje i daje producentom OEM możliwość dodania oficjalnego dostępu do interfejsu API nowych funkcji w pobliżu premier sprzętowych.

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

Wersja platformy Android Poziom interfejsu API rozszerzeń WindowManager 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 zapewnia 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ść, WindowManager 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ą wersją platformy Android, w której te wersje są finalizowane. Pełną historię interfejsów API rozszerzeń znajdziesz w gałęzi wydania window:extensions:extensions w plikach tekstowych interfejsu API.

Aby zachować zgodność wstecz, nowsze wersje rozszerzeń muszą nadal działać ze starszymi wersjami WindowManagera skompilowanymi w aplikacje. Aby to zapewnić, każda nowa wersja interfejsu API rozszerzeń dodaje tylko nowe interfejsy API i nie usuwa starszych. 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 przechowywany w pamięci podręcznej w systemowych ładowarkach klas poza ścieżką uruchamiania (od Androida 14, czyli z poziomu interfejsu API 34), więc wczytywanie modułu do pamięci podczas uruchamiania aplikacji nie ma wpływu na wydajność. 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 osadzania aktywności umożliwia aplikacjom optymalizację interfejsu użytkownika na urządzeniach z dużym ekranem i na wyświetlaczach zewnętrznych. Umieszczenie aktywności umożliwia prezentowanie obok siebie 2 aktywności w układzie wielopanelowym, co ułatwia tworzenie aplikacji dostosowanych do starszych wersji.

Komponent umożliwiający umieszczanie aktywności musi być dostępny na wszystkich urządzeniach z wbudowanym wyświetlaczem o rozmiary równe lub większe niż sw600dp. Przekazywanie aktywności musi być również 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ą połączone w czasie działania.

Konfiguracja urządzenia

Nie trzeba konfigurować urządzenia w żaden szczególny sposób, poza włączeniem modułu Extensions w sposób opisany w sekcji Distribution of the Extensions module (Rozpowszechnianie modułu Extensions). Warto włączyć rozszerzenia na wszystkich urządzeniach, które obsługują tryb wielookienkowy. W przyszłych wersjach Androida rozszerzenia mogą stać się 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 korzystaniu z tej funkcji znajdziesz w artykule Przygotowanie aplikacji na składanie.

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ą interfejsu WindowLayoutComponent.

Pozycja i granice zawiasów muszą być podawane w stosunku do 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 stan musi być aktualizowany, gdy pozycja zawiasu zmienia się między stabilnymi stanami. Domyślnie w płaskim stanie wyświetlania 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 zwracać wartość 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ądzenia w device_state_configuration.xml, aby były używane przez DeviceStateManagerService. Więcej informacji znajdziesz w sekcji DeviceStateProviderImpl.java.

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

  • Włącz moduł Rozszerzenia zgodnie z opisem w sekcji Rozpowszechnianie modułu Rozszerzenia.

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

    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 układzie współrzędnych wyświetlacza w naturalnej orientacji wyświetlacza. Ciąg konfiguracji może zawierać wiele funkcji wyświetlania rozdzielonych średnikami.

    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 zawiera funkcji złożenia do złożenia. 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 znajdziesz w sekcji DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int).

    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 (zgodność określona przez specyfikację Android CDD pod kątem atrybutów takich jak rozmiar, gęstość i dostępne funkcje nawigacyjne) 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 z kamery 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, podaj odpowiednie identyfikatory stanu w polu com.android.internal.R.array.config_openDeviceStates.

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

  • W przypadku składanych urządzeń, które obsługują stan półskładanego urządzenia (zawias jest częściowo otwarty jak w przypadku laptopa), należy podać 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.
    • Podaj adres fizycznego wyświetlacza tylnego w pliku com.android.internal.R.string.config_rearDisplayPhysicalAddress.
    • W polu com.android.internal.R.integer.config_deviceStateRearDisplay określ identyfikator stanu, którego mają używać rozszerzenia.
    • Dodaj identyfikator stanu w polu 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 adres fizycznego wyświetlacza tylnego w pliku com.android.internal.R.config_deviceStateConcurrentRearDisplay.
    • W interfejsie com.android.internal.R.integer.config_deviceStateConcurrentRearDisplayokreśl identyfikator stanu, który ma być używany przez rozszerzenia, jeśli identyfikator ma być udostępniany aplikacjom.
    • 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 korzystające z Jetpack WindowManager są dostępne dla producentów OEM 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 pod adresem 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 Jetpacka na Androida. Testy znajdują się w bibliotece okien w ramach modułu 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 modułu 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, aby zautomatyzować analizę wyników.