Расширения оконного менеджера

Библиотека Jetpack WindowManager позволяет разработчикам приложений поддерживать новые форм-факторы устройств и многооконные среды.

Расширения WindowManager (Расширения) — это дополнительный модуль платформы Android, который обеспечивает различные функции Jetpack WindowManager. Модуль реализован в AOSP в frameworks/base/libs/WindowManager/Jetpack и поставляется на устройствах, поддерживающих функции WindowManager.

Распространение модулей расширений

Расширения компилируются в библиотеку .jar и помещаются в раздел system_ext на устройстве, если расширения включены в make-файле устройства.

Чтобы включить расширения на устройстве, добавьте следующее в make-файл устройства продукта:

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

Это активирует пакеты androidx.window.extensions и androidx.window.sidecar на устройстве и установит свойство persist.wm.extensions.enabled . Включение этих пакетов в make-файл также помещает объявления в etc/permissions/ , делая их доступными для процессов приложения. Обычно модули загружаются и выполняются как часть процесса приложения во время выполнения, когда они используются библиотекой Jetpack WindowManager, что делает ее работу похожей на код платформы на стороне клиента, как показано на следующем рисунке:

Рис. 1. Расширения WindowManager, загружаемые в процесс приложения, аналогично коду платформы.

Модуль androidx.window.extensions — это текущий модуль расширений, который находится в активной разработке. Модуль androidx.window.sidecar — это устаревший модуль, включенный для совместимости с самыми ранними версиями Jetpack WindowManager, но этот модуль больше не поддерживается активно.

На следующем рисунке показана логика определения использования androidx.window.extensions или androidx.window.sidecar .

Рисунок 2. Дерево решений для доступа к androidx.window.extensions или androidx.window.sidecar .

Модули расширения

Расширения предоставляют функции оконного управления для складных устройств с большим экраном и устройств, поддерживающих оконное управление на внешних дисплеях. К функциональным областям относятся:

OEM-реализации расширений могут предоставлять нулевые компоненты или компоненты со стандартными или заглушками реализации методов в интерфейсе WindowExtensions , если аппаратное обеспечение устройства не поддерживает соответствующие функции, если только эта функция специально не запрошена в документе определения совместимости (CDD) 7.1.1.1. .

Расширения и API Jetpack

Модуль WindowManager Extensions предоставляет собственную поверхность API в дополнение к API общедоступной платформы. Модуль Extensions разрабатывается публично в библиотеке Jetpack androidx.window.extensions , не предназначенной для разработчиков, так что Jetpack WindowManager ( androidx.window ) может связываться с ним во время компиляции. Поверхность API расширений обычно предоставляет API более низкого уровня.

API-интерфейсы, предоставляемые расширениями, предназначены для использования только библиотекой Jetpack WindowManager. API-интерфейсы расширений не предназначены для прямого вызова разработчиками приложений. Библиотеку расширений нельзя добавлять в качестве зависимости для приложения в файле сборки Gradle, чтобы обеспечить правильную функциональность. Избегайте предварительной компиляции библиотеки расширений напрямую в приложение; вместо этого полагайтесь на загрузку во время выполнения, чтобы предотвратить загрузку одновременно предварительно скомпилированных и предоставленных во время выполнения классов расширений.

Jetpack WindowManager ( androidx.window ) предназначен для добавления в качестве зависимости приложения и предоставляет общедоступные API-интерфейсы для разработчиков, в том числе для функций расширений WindowManager. Библиотека WindowManager автоматически загружает расширения в процесс приложения и превращает API-интерфейсы расширений более низкого уровня в абстракции более высокого уровня и более целенаправленные интерфейсы. API-интерфейсы WindowManager Jetpack соответствуют стандартам разработки современных приложений Android и предназначены для обеспечения удобного взаимодействия за счет хорошей интеграции с базами кода, использующими другие библиотеки AndroidX.

Версии и обновления расширений

Модуль расширений можно обновлять вместе с обновлениями платформы Android ежегодно или ежеквартально. Ежеквартальные обновления позволяют повышать уровень API расширений между обновлениями API платформы Android, что позволяет ускорить итерацию и предоставить OEM-производителям возможность добавить официальный доступ к API к новым функциям, близким к выпуску оборудования.

В следующей таблице перечислены версии API androidx.window.extensions для различных выпусков Android.

Версия платформы Android Уровень API расширений WindowManager Версия API androidx.window.extensions
Андроид 14 3 1.2.0
Андроид 13 КПР3 2 1.1.0
Андроид 13 1 1.0.0
Андроид 12L 1 1.0.0

Уровень API расширений (центральный столбец) повышается каждый раз при добавлении к существующей стабильной поверхности API (правый столбец).

Обратная и прямая совместимость

Jetpack WindowManager справляется со сложностями, связанными с частыми обновлениями уровня API, быстрым развитием API и обратной совместимостью. Когда код библиотеки выполняется в процессе приложения, библиотека проверяет заявленный уровень API расширений и предоставляет доступ к функциям в соответствии с заявленным уровнем.

Чтобы защитить приложение от сбоя во время выполнения, WindowManager также выполняет проверку отражения Java во время выполнения доступных API расширений в соответствии с объявленным уровнем API расширений. В случае несоответствия WindowManager может отключить использование расширений (частично или полностью) и сообщить о том, что соответствующие функции недоступны для приложения.

Расширения WindowManager реализованы как модуль system_ext , который использует API частной платформы для вызова ядра WindowManager, DeviceStateManager и других системных служб при реализации функций расширений.

Совместимость с предварительными версиями расширений может не поддерживаться до соответствующего ежеквартального или ежегодного выпуска платформы Android, с помощью которого версии завершаются. Полную историю API расширений можно найти в текстовых файлах ветки выпуска window:extensions:extensions API .

Новые версии расширений должны продолжать работать со старыми версиями WindowManager, скомпилированными в приложения, для обеспечения прямой совместимости. Чтобы гарантировать это, любая новая версия API расширений добавляет только новые API, а не удаляет старые. В результате приложения с более старыми версиями WindowManager могут продолжать использовать старые API-интерфейсы расширений, для которых приложения были скомпилированы.

Проверка CTS гарантирует, что для любой заявленной версии API расширений на устройстве все API для этой и предыдущих версий присутствуют и работают.

Производительность

Модуль Extensions по умолчанию кэшируется в загрузчиках системных классов без bootclasspath, начиная с Android 14 (уровень API 34), поэтому загрузка модуля в память при запуске приложения не влияет на производительность. Использование отдельных функций модуля может незначительно повлиять на характеристики производительности приложений при выполнении дополнительных вызовов IPC между клиентом и сервером.

Модули

Встраивание активности

Компонент внедрения активности предоставляет набор функций, которые позволяют приложениям организовывать представление окна активности в пределах родительского приложения. Это включает в себя одновременное отображение двух действий рядом в многопанельном макете, что облегчает оптимизацию большого экрана для устаревших приложений.

Компонент внедрения активности должен быть доступен на всех устройствах, имеющих встроенный дисплей размером, равным или превышающим sw600 dp . Внедрение действий также должно быть включено на устройствах, поддерживающих подключение внешних дисплеев, поскольку приложение может отображаться в большем размере при подключении внешних дисплеев во время выполнения.

Конфигурация устройства

Никакой конкретной настройки устройства не требуется, кроме включения модуля расширений, как описано в разделе «Распространение модулей расширений» . Имеет смысл включить расширения на всех устройствах, поддерживающих многооконный режим. В будущих версиях Android, вероятно, потребуются расширения для распространенных конфигураций портативных устройств и устройств с большим экраном.

Информация о расположении окон

Компонент информации о расположении окна идентифицирует положение и состояние шарнира на складном устройстве, когда шарнир пересекает окно приложения. Информация о макете окна позволяет приложениям реагировать и отображать оптимизированные макеты в настольном режиме на складных устройствах. Подробные сведения об использовании см. в разделе «Обеспечение свертывания приложения» .

Складные устройства Android, включающие шарнир, соединяющий отдельные или непрерывные области панели дисплея, должны сделать информацию о шарнире доступной для приложений через WindowLayoutComponent .

Положение шарнира и границы должны сообщаться относительно окна приложения, определенного Context , передаваемым в API. Если границы окна приложения не пересекаются с границами шарнира, о шарнире DisplayFeature сообщать нельзя. Также допустимо не сообщать о функциях дисплея, если их положение не может быть сообщено надежно, например, когда окно приложения может свободно перемещаться пользователем в многооконном режиме или режиме почтового ящика совместимости.

Для складных элементов обновления состояния должны сообщаться при изменении положения шарнира между стабильными состояниями. По умолчанию в состоянии плоского отображения API должен сообщать FoldingFeature.State.FLAT . Если аппаратное обеспечение устройства можно оставить в полусложенном режиме в стабильном состоянии, API должен сообщить FoldingFeature.State.HALF_OPENED . В API нет закрытого состояния, так как в таком случае окно приложения либо не будет видно, либо не будет пересекать границы шарнира.

Конфигурация устройства

Чтобы поддержать реализацию функции складывания, OEM-производители должны сделать следующее:

  • Настройте состояния устройства в device_state_configuration.xml , которые будут использоваться DeviceStateManagerService . Для справки см. DeviceStateProviderImpl.java .

    Если реализации DeviceStateProvider или DeviceStatePolicy по умолчанию не подходят для устройства, можно использовать пользовательскую реализацию.

  • Включите модуль «Расширения», как описано в разделе «Распространение модуля «Расширения» .

  • Укажите расположение функций отображения в строковом ресурсе com.android.internal.R.string.config_display_features (обычно в frameworks/base/core/res/res/values/config.xml в наложении устройств).

    Ожидаемый формат строки:

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

    type может быть fold или hinge . Значения left , top , right и bottom представляют собой целочисленные координаты пикселей в пространстве координат дисплея в естественной ориентации дисплея. Строка конфигурации может содержать несколько функций отображения, разделенных точкой с запятой.

    Например:

    <!-- Jetpack WindowManager display features -->
    <string name="config_display_features" translatable="false">fold-[1000,0,1000,2000]</string>
    
  • Определите сопоставление между внутренними идентификаторами состояния устройства, используемыми в DeviceStateManager , и общедоступными константами состояния, отправляемыми разработчикам в com.android.internal.R.array.config_device_state_postures .

    Ожидаемый формат каждой записи:

    <device_specific_state_identifier>:<Jetpack WindowManager state identifier>

    Поддерживаемые идентификаторы состояний:

    • COMMON_STATE_NO_FOLDING_FEATURES = 1 : в штате нет функций сгиба, о которых можно сообщить. Например, это может быть закрытое состояние типичного складного устройства с основным экраном на внутренней стороне.
    • COMMON_STATE_HALF_OPENED = 2 : функция складывания наполовину открыта.
    • COMMON_STATE_FLAT = 3 : элемент складывания плоский. Например, это может быть открытое состояние типичного складного устройства с основным экраном на внутренней стороне.
    • COMMON_STATE_USE_BASE_STATE = 1000 : в Android 14 значение, которое можно использовать для эмулируемых состояний, в которых состояние шарнира получается с использованием базового состояния, как определено в CommonFoldingFeature.java .

    Дополнительную информацию см. в DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int) .

    Например:

    <!-- 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>
    

Площадь окна

Компонент области окна предоставляет набор функций, которые предоставляют приложениям доступ к дополнительным дисплеям и областям отображения на некоторых складных и многоэкранных устройствах.

Режим заднего дисплея позволяет приложению отображать пользовательский интерфейс предварительного просмотра камеры на крышке складного устройства, что позволяет использовать основную камеру устройства для селфи и видео. Устройства, имеющие Android-совместимый (согласно определению Android CDD с точки зрения таких атрибутов, как размер, плотность и доступные возможности навигации) закрывающий дисплей, который совмещен с камерами заднего устройства, должны обеспечивать доступ к режиму заднего дисплея.

В Android 14 режим двойного дисплея позволяет приложениям, работающим на внутреннем дисплее складного устройства, отображать дополнительный контент на обложке, обращенной к другим пользователям; например, на обложке может отображаться предварительный просмотр камеры для человека, которого фотографируют или записывают.

Конфигурация устройства

Чтобы поддержать реализацию функции складывания, OEM-производители должны сделать следующее:

  • Настройте состояния устройства в device_state_configuration.xml , которые будут использоваться DeviceStateManagerService . Дополнительную информацию см. в DeviceStateProviderImpl.java .

    Если реализация DeviceStateProvider или DeviceStatePolicy по умолчанию не подходит для устройства, можно использовать пользовательскую реализацию.

  • Для складных устройств, поддерживающих открытый или плоский режим, укажите соответствующие идентификаторы состояния в com.android.internal.R.array.config_openDeviceStates .

  • Для складывающихся устройств, поддерживающих сложенные состояния, перечислите соответствующие идентификаторы состояний в com.android.internal.R.array.config_foldedDeviceStates .

  • Для складных устройств, поддерживающих полусложенное состояние (шарнир наполовину открыт, как у ноутбука), перечислите соответствующие состояния в com.android.internal.R.array.config_halfFoldedDeviceStates .

  • Для устройств, поддерживающих режим заднего дисплея:

    • Перечислите соответствующие состояния в com.android.internal.R.array.config_rearDisplayDeviceStates для DeviceStateManager .
    • Укажите физический адрес заднего дисплея в com.android.internal.R.string.config_rearDisplayPhysicalAddress .
    • Укажите идентификатор состояния в com.android.internal.R.integer.config_deviceStateRearDisplay , который будет использоваться расширениями.
    • Добавьте идентификатор состояния в com.android.internal.R.array.config_deviceStatesAvailableForAppRequests , чтобы сделать его доступным для приложений.
  • В Android 14 для устройств, поддерживающих режим двойного (одновременного) отображения:

    • Установите для com.android.internal.R.bool.config_supportsConcurrentInternalDisplays true .
    • Укажите физический адрес заднего дисплея в com.android.internal.R.config_deviceStateConcurrentRearDisplay .
    • Укажите идентификатор состояния в com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay , который будет использоваться расширениями, если идентификатор предназначен для использования приложениями.
    • Добавьте идентификатор состояния в com.android.internal.R.array.config_deviceStatesAvailableForAppRequests , чтобы сделать его доступным для приложений.

Проверка

OEM-производители должны проверять свои реализации, чтобы гарантировать ожидаемое поведение в распространенных сценариях. Тесты CTS и тесты с использованием Jetpack WindowManager доступны OEM-производителям для тестирования реализаций.

CTS-тесты

Чтобы запустить тесты CTS, см. раздел «Выполнение тестов CTS» . Тесты CTS, связанные с Jetpack WindowManager, находятся в cts/tests/framework/base/windowmanager/jetpack/ . Имя тестового модуля — CtsWindowManagerJetpackTestCases .

Тесты WindowManager

Чтобы загрузить тесты Jetpack WindowManager, следуйте инструкциям Android Jetpack . Тесты расположены в библиотеке окон в модуле window:window window: window/window/src/androidTest/ .

Чтобы запустить тесты устройства для модуля window:window из командной строки, выполните следующие действия:

  1. Подключите устройство с опциями разработчика и включенной отладкой по USB.
  2. Разрешите компьютеру выполнить отладку устройства.
  3. Откройте оболочку в корневом каталоге репозитория androidx.
  4. Измените каталог на framework/support .
  5. Выполните следующую команду: ./gradlew window:window:connectedAndroidTest .
  6. Проанализируйте результаты.

Чтобы запустить тесты из Android Studio, выполните следующие действия:

  1. Откройте Android-студию.
  2. Подключите устройство с опциями разработчика и включенной отладкой по USB.
  3. Разрешите компьютеру выполнить отладку устройства.
  4. Перейдите к тесту в библиотеке окон оконного модуля.
  5. Откройте тестовый класс и запустите его, используя зеленые стрелки в правой части редактора.

Альтернативно вы можете создать конфигурацию в Android Studio для запуска тестового метода, тестового класса или всех тестов в модуле.

Результаты можно анализировать вручную, просматривая выходные данные оболочки. Некоторые тесты пропускаются, если устройство не соответствует определенным предположениям. Результаты сохраняются в стандартном месте, и аналитики могут написать сценарий для автоматизации анализа результатов.