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

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

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

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

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

Чтобы включить расширения на устройстве, добавьте следующее в 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. Расширения 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 Extensions. Библиотека WindowManager автоматически загружает расширения в процесс приложения и оборачивает низкоуровневые API расширений в высокоуровневые абстракции и более сфокусированные интерфейсы. API WindowManager Jetpack соответствуют стандартам современной разработки приложений для Android и предназначены для обеспечения удобной совместимости за счет хорошей интеграции с кодовыми базами, использующими другие библиотеки AndroidX.

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

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

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

версия платформы Android Уровень API расширений WindowManager androidx.window.extensions API version
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

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

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

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

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

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

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

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

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

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

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

Модули

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

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

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

В 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, для устройств, поддерживающих режим двойного (одновременного) отображения:

    • Установите для 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 , чтобы сделать его доступным для приложений.

Проверка

Производители оборудования должны проверять свои реализации, чтобы обеспечить ожидаемое поведение в типичных сценариях. Для проверки реализаций производителям оборудования доступны тесты 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 из командной строки, выполните следующие действия:

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

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

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

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

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