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

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

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

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

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

Чтобы включить расширения на устройстве, добавьте следующее в 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 Extensions обычно предоставляет низкоуровневые API.

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

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

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

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

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

Версия для платформы Android Уровень API расширений WindowManager версия API androidx.window.extensions
Андроид 15 6 1.5.0 (скоро)
Android 14 QPR3 5 1.4.0 (скоро)
Android 14 QPR1 4 1.3.0
Андроид 14 3 1.2.0
Android 13 QPR3 2 1.1.0
Андроид 13 1 1.0.0
Android 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 .

Новые версии Extensions должны продолжать работать со старыми версиями WindowManager, скомпилированными в приложения, для поддержания прямой совместимости. Для этого любая новая версия Extensions API только добавляет новые API и не удаляет старые. В результате приложения со старыми версиями WindowManager могут продолжать использовать старые Extensions API, с которыми они были скомпилированы.

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

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

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

Модули

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

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

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

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

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

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

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

Складные устройства 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 (согласно определению в CDD Android по таким параметрам, как размер, плотность пикселей и доступные навигационные возможности) внешним дисплеем, совмещенным с задними камерами устройства, должны обеспечивать доступ к режиму заднего дисплея.

В 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-производителям необходимо проверять свои реализации, чтобы гарантировать ожидаемое поведение в распространённых сценариях. Для тестирования реализаций 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/src/androidTest/ .

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

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

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

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

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

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