Библиотека Jetpack WindowManager позволяет разработчикам приложений поддерживать новые форм-факторы устройств и многооконные среды.
WindowManager Extensions (Extensions) – это модуль платформы Android, который позволяет использовать различные функции Jetpack WindowManager. Модуль реализован в AOSP в frameworks/base/libs/WindowManager/Jetpack и поставляется на устройствах, поддерживающих функции WindowManager.
Распространение модуля расширений
Расширения компилируются в библиотеку JAR и помещаются в раздел system_ext на устройстве, если они включены в make-файле устройства.
Чтобы включить расширения на устройстве, добавьте в файл makefile следующее:
$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)
Это активирует пакеты androidx.window.extensions и androidx.window.sidecar на устройстве и задает свойство persist.wm.extensions.enabled.
Если включить эти пакеты в makefile, объявления также будут размещены в файле etc/permissions/, что сделает их доступными для процессов приложения. Обычно модули загружаются и выполняются как часть процесса приложения во время выполнения при использовании библиотеки Jetpack WindowManager. Это делает их работу похожей на код клиентской платформы, как показано на рисунке ниже.
Рисунок 1. Расширения, загруженные в процесс приложения.
Модуль androidx.window.extensions – это текущий модуль расширений, который активно разрабатывается. Модуль androidx.window.sidecar – это устаревший модуль, включенный для совместимости с ранними версиями Jetpack WindowManager. В настоящее время он не поддерживается.
На рисунке ниже показана логика определения того, какую функцию использовать: androidx.window.extensions или androidx.window.sidecar.
Рисунок 2. Дерево решений для доступа к androidx.window.extensions или androidx.window.sidecar.
Модули расширений
Расширения предоставляют функции многооконного режима для складных устройств с большим экраном и устройств, поддерживающих многооконный режим на внешних дисплеях. К ним относятся:
В реализациях OEM-производителей расширения могут предоставлять нулевые компоненты или компоненты с реализациями методов по умолчанию или заглушками в интерфейсе WindowExtensions, если оборудование устройства не поддерживает соответствующие функции, за исключением случаев, когда функция специально запрошена в документе Compatibility Definition Document (CDD) 7.1.1.1.
Расширения и API Jetpack
Модуль WindowManager Extensions предоставляет собственный API в дополнение к общедоступным API платформы. Модуль Extensions разрабатывается публично в androidx.window.extensionsбиблиотеке Jetpack, которая не предназначена для разработчиков. Это позволяет Jetpack WindowManager (androidx.window) ссылаться на нее во время компиляции. Extensions API обычно предоставляет API более низкого уровня.
API, предоставляемые Extensions, предназначены для использования только библиотекой Jetpack WindowManager. Разработчики приложений не должны напрямую вызывать API расширений. Чтобы обеспечить правильную работу, не добавляйте библиотеку расширений в качестве зависимости для приложения в файле сборки Gradle. Не компилируйте библиотеку Extensions непосредственно в приложение. Вместо этого используйте загрузку во время выполнения, чтобы избежать загрузки классов Extensions, предоставленных как во время предварительной компиляции, так и во время выполнения.
Jetpack WindowManager (androidx.window) добавляется как зависимость приложения и предоставляет общедоступные API для разработчиков, в том числе для функций WindowManager Extensions. Библиотека WindowManager автоматически загружает расширения в процесс приложения и упаковывает низкоуровневые API расширений в абстракции более высокого уровня и более специализированные интерфейсы. API Jetpack WindowManager соответствуют современным стандартам разработки приложений для Android и обеспечивают удобную совместимость с кодом, в котором используются другие библиотеки AndroidX.
Версии расширений и обновления
Модуль Extensions можно обновлять вместе с ежегодными или ежеквартальными обновлениями платформы Android. Ежеквартальные обновления позволяют повышать уровень Extensions API между обновлениями API платформы Android. Это ускоряет итерацию и дает производителям оригинального оборудования возможность добавлять официальный доступ к API для новых функций ближе к запуску оборудования.
В таблице ниже перечислены версии API androidx.window.extensions для разных выпусков Android.
| Версия платформы Android | Уровень API расширений WindowManager | Версия API androidx.window.extensions |
|---|---|---|
| Android 15 | 6 | 1.5.0 (скоро) |
| Android 14 QPR3 | 5 | 1.4.0 (скоро) |
| 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 |
Уровень Extensions API (центральный столбец) повышается каждый раз, когда в существующий стабильный API (правый столбец) добавляются новые функции.
Обратная и прямая совместимость
Jetpack WindowManager упрощает работу с частыми обновлениями уровней API, быстрой эволюцией API и обратной совместимостью. Когда код библиотеки выполняется в процессе приложения, библиотека проверяет заявленный уровень API расширений и предоставляет доступ к функциям в соответствии с этим уровнем.
Чтобы защитить приложение от сбоев во время выполнения, WindowManager также выполняет проверку доступных API расширений с помощью отражения Java во время выполнения в соответствии с заявленным уровнем API расширений. Если они не совпадают, WindowManager может отключить использование расширений (частично или полностью) и сообщить приложению, что некоторые функции недоступны.
Расширения WindowManager реализованы как модуль system_ext, который использует закрытые API платформы для вызова ядра WindowManager, DeviceStateManager и других системных сервисов при реализации функций расширений.
Совместимость может быть нарушена в предварительных выпусках Extensions до выхода соответствующей квартальной или годовой версии платформы Android, в которой эти версии будут окончательно утверждены. Полную историю API расширений можно найти в ветке выпуска текстовых файлов API window:extensions:extensions.
Более новые версии Extensions должны продолжать работать с более ранними версиями WindowManager, встроенными в приложения, чтобы поддерживать обратную совместимость. Чтобы этого не происходило, в новых версиях Extensions API добавляются только новые API, а старые не удаляются. В результате приложения с более ранними версиями WindowManager могут продолжать использовать старые Extensions API, с которыми они были скомпилированы.
Проверка CTS гарантирует, что для любой заявленной версии API расширений на устройстве присутствуют и работают все API этой и предыдущих версий.
Эффективность
Модуль Extensions по умолчанию кешируется в системных загрузчиках классов, не относящихся к bootclasspath, начиная с Android 14 (уровень API 34), поэтому загрузка модуля в память при запуске приложения не влияет на производительность. Использование отдельных функций модуля может незначительно повлиять на производительность приложений, если между клиентом и сервером выполняются дополнительные вызовы IPC.
Модули
Встраивание объектов activity
Компонент встраивания действий позволяет оптимизировать интерфейс приложений для устройств с большими экранами и внешних дисплеев. Встраивание Activity позволяет показывать два действия рядом в многопанельном макете, что упрощает адаптивную разработку приложений для устаревших версий.
Компонент встраивания действий должен быть доступен на всех устройствах со встроенным экраном размером не менее sw600dp. Встраивание действий также должно быть включено на устройствах, поддерживающих подключение внешних дисплеев, поскольку приложение может отображаться в увеличенном размере, когда внешние дисплеи подключены во время выполнения.
Конфигурация устройства
Никаких специальных конфигураций устройства не требуется, кроме включения модуля расширений, как описано в разделе Распространение модуля расширений. Рекомендуем включить расширения на всех устройствах, поддерживающих многооконный режим. В будущих версиях Android расширения, скорее всего, станут обязательными для распространенных конфигураций портативных устройств и устройств с большим экраном.
Информация о макете окна
Компонент информации о макете окна определяет положение и состояние шарнира на складном устройстве, когда шарнир пересекает окно приложения. Информация о макете окна позволяет приложениям реагировать на изменения и показывать оптимизированные макеты в настольном режиме на складных устройствах. Подробнее о том, как сделать приложение совместимым со складными устройствами…
На складных устройствах Android, в которых используется шарнир для соединения отдельных или непрерывных областей экрана, информация о шарнире должна быть доступна приложениям через WindowLayoutComponent.
Положение и границы шарнира должны быть указаны относительно окна приложения, идентифицированного с помощью Context, переданного в API. Если границы окна приложения не пересекаются с границами шарнира, DisplayFeature не должен сообщаться. Также можно не сообщать о функциях экрана, если их положение может быть определено ненадежно, например когда пользователь может свободно перемещать окно приложения в многооконном режиме или режиме совместимости с черными полосами.
Для функций, связанных со складыванием, состояние должно обновляться, когда шарнир переходит из одного стабильного положения в другое. По умолчанию в плоском состоянии API должен сообщать значение FoldingFeature.State.FLAT.
Если устройство можно оставить в полусложенном состоянии, API должен возвращать значение FoldingFeature.State.HALF_OPENED.
В API нет закрытого состояния, поскольку в этом случае окно приложения либо не будет видно, либо не будет пересекать границы шарнира.
Конфигурация устройства
Чтобы реализовать поддержку складных устройств, производителям оборудования необходимо выполнить следующие действия:
Настройте состояния устройств в
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 внешний экран (в соответствии с определением в CDD для Android, в котором учитываются такие атрибуты, как размер, плотность и доступные возможности навигации), расположенный на той же стороне, что и задние камеры, должны поддерживать режим заднего экрана.
В Android 14 режим двух экранов позволяет приложениям, запущенным на внутреннем экране складного устройства, показывать дополнительный контент на внешнем экране, обращенном к другим пользователям. Например, на внешнем экране может отображаться предварительный просмотр камеры для человека, которого фотографируют или снимают на видео.
Конфигурация устройства
Чтобы реализовать поддержку складных устройств, производителям оборудования необходимо выполнить следующие действия:
Настройте состояния устройств в
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, поддерживающих режим Dual Screen (одновременное использование двух экранов):
- Задайте для параметра
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.
Тесты 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 из командной строки, выполните следующие действия:
- Подключите устройство, на котором включены параметры для разработчиков и отладка по USB.
- Разрешите компьютеру отладку устройства.
- Откройте оболочку в корневом каталоге репозитория androidx.
- Перейдите в каталог
framework/support. - Выполните команду
./gradlew window:window:connectedAndroidTest. - Проанализируйте результаты.
Чтобы запустить тесты из Android Studio, выполните следующие действия:
- Откройте Android Studio.
- Подключите устройство, на котором включены параметры для разработчиков и отладка по USB.
- Разрешите компьютеру отладку устройства.
- Перейдите к тесту в библиотеке окон модуля окон.
- Откройте тестовый класс и запустите его, используя зеленые стрелки в правой части редактора.
Кроме того, в Android Studio можно создать конфигурацию для запуска тестового метода, тестового класса или всех тестов в модуле.
Результаты можно проанализировать вручную, изучив выходные данные оболочки. Некоторые тесты пропускаются, если устройство не соответствует определенным требованиям. Результаты сохраняются в стандартном месте, и аналитики могут написать скрипт для автоматизации анализа результатов.