Обновления, внесенные в области отображения, представлены на этой странице.
Системные украшения
В Android 10 добавлена поддержка настройки дополнительных дисплеев для отображения определенных системных украшений, таких как обои, панель навигации и лаунчер. По умолчанию основной дисплей отображает все системные украшения, а дополнительные дисплеи отображают те, которые включены по желанию. Вы можете настроить поддержку редактора метода ввода (IME) отдельно от других системных украшений.
Используйте DisplayWindowSettings#setShouldShowSystemDecorsLocked()
для добавления поддержки системных декораций на определенном дисплее или предоставления значения по умолчанию в /data/system/display_settings.xml
. Примеры см. в разделе Настройки окна дисплея .
Выполнение
DisplayWindowSettings#setShouldShowSystemDecorsLocked()
также представлен в WindowManager#setShouldShowSystemDecors()
для тестирования. Запуск этого метода с намерением включить системные декоры не добавляет окна декоров, которые ранее отсутствовали, или не удаляет их, если они ранее присутствовали. В большинстве случаев изменение поддержки системных декораций вступает в силу полностью только после перезагрузки устройства.
Проверки поддержки системных декораций в кодовой базе WindowManager обычно проходят через DisplayContent#supportsSystemDecorations()
тогда как проверки внешних служб (например, System UI для проверки того, должна ли отображаться панель навигации) используют WindowManager#shouldShowSystemDecors()
. Чтобы понять, что контролируется этим параметром, изучите точки вызова этих методов.
Окна оформления пользовательского интерфейса системы
Android 10 добавляет поддержку системного декора окна только для панели навигации, поскольку панель навигации необходима для навигации между действиями и приложениями. По умолчанию панель навигации показывает возможности Назад и Домой. Это включается только в том случае, если целевой дисплей поддерживает системные декорации (см. DisplayWindowSettings
).
Строка состояния — это более сложное системное окно, поскольку оно также содержит Notification Shade, Quick Settings и Lock Screen. В Android 10 строка состояния не поддерживается на дополнительных дисплеях. Поэтому уведомления, настройки и полная блокировка клавиатуры доступны только на основном дисплее.
Системное окно Overview/Recents не поддерживается на дополнительных экранах. В Android 10 AOSP отображает только Recents на дисплее по умолчанию и содержит действия со всех дисплеев. При запуске из Recents действие, которое было на дополнительном дисплее, по умолчанию выводится на передний план на этом дисплее. Этот подход имеет некоторые известные проблемы, такие как не немедленное обновление, когда приложения появляются на других экранах.
Выполнение
Для реализации дополнительных функций системного пользовательского интерфейса производители устройств должны использовать единый компонент системного пользовательского интерфейса, который отслеживает добавление или удаление дисплеев и представляет соответствующий контент.
Компонент пользовательского интерфейса системы, поддерживающий многодисплейный режим (MD), должен обрабатывать следующие случаи:
- Инициализация нескольких дисплеев при запуске
- Дисплей добавлен во время выполнения
- Дисплей удален во время выполнения
Когда System UI обнаруживает добавление дисплея до WindowManager, он создает состояние гонки. Вы можете избежать этого, реализовав пользовательский обратный вызов из WindowManager в System UI при добавлении дисплея вместо подписки на события DisplayManager.DisplayListener
. Для справочной реализации см. CommandQueue.Callbacks#onDisplayAddSystemDecorations
для поддержки панели навигации и WallpaperManagerInternal#onDisplayAddSystemDecorations
для обоев.
Кроме того, Android 10 предоставляет следующие обновления:
- Класс
NavigationBarController
управляет всеми функциями, специфичными для панелей навигации. - Чтобы просмотреть настроенную панель навигации, см.
CarStatusBar
. -
TYPE_NAVIGATION_BAR
больше не ограничивается одним экземпляром и может использоваться для каждого дисплея. -
IWindowManager#hasNavigationBar()
обновлен и включает параметрdisplayId
только для системного пользовательского интерфейса.
Пусковая установка
В Android 10 каждый дисплей, настроенный на поддержку системных декораций, имеет выделенный домашний стек для действий запуска с типом WindowConfiguration#ACTIVITY_TYPE_HOME
по умолчанию. Каждый дисплей использует отдельный экземпляр действия запуска:
Рисунок 1. Пример многодисплейного лаунчера для platform/development/samples/MultiDisplay.
Большинство существующих лаунчеров не поддерживают несколько экземпляров и не оптимизированы для больших размеров экрана. Кроме того, на дополнительных/внешних дисплеях часто ожидается другой тип опыта. Чтобы предоставить выделенную активность для дополнительных экранов, Android 10 представил категорию SECONDARY_HOME
в фильтрах намерений. Экземпляры этой активности используются на всех дисплеях, которые поддерживают системные украшения, по одному на дисплей.
<activity> ... <intent-filter> <category android:name="android.intent.category.SECONDARY_HOME" /> ... </intent-filter> </activity>
Активность должна иметь режим запуска, который не препятствует множественным экземплярам и, как ожидается, адаптируется к разным размерам экрана. Режим запуска не может быть singleInstance
или singleTask
.
Выполнение
В Android 10 RootActivityContainer#startHomeOnDisplay()
автоматически выбирает нужный компонент и намерение в зависимости от дисплея, на котором запущен домашний экран. RootActivityContainer#resolveSecondaryHomeActivity()
содержит логику для поиска компонента активности лаунчера в зависимости от выбранного в данный момент лаунчера и может использовать системное значение по умолчанию, если это необходимо (см. ActivityTaskManagerService#getSecondaryHomeIntent()
).
Ограничения по соображениям безопасности
В дополнение к ограничениям, которые применяются к действиям на вторичных дисплеях, чтобы избежать возможности создания вредоносным приложением виртуального дисплея с включенными системными декорациями и считывания конфиденциальной информации пользователя с поверхности, лаунчер отображается только на виртуальных дисплеях, принадлежащих системе. Лаунчер не отображает контент на несистемных виртуальных дисплеях.
Обои
В Android 10 и выше обои поддерживаются на дополнительных дисплеях:
Рисунок 2. Живые обои на внутреннем (вверху) и внешнем дисплеях (внизу).
Разработчики могут объявить о поддержке функции обоев, указав android:supportsMultipleDisplays="true"
в определении XML WallpaperInfo
. Разработчики обоев также должны загружать активы с помощью контекста отображения в WallpaperService.Engine#getDisplayContext()
.
Фреймворк создает один экземпляр WallpaperService.Engine
на дисплей, поэтому каждый движок имеет собственную поверхность и контекст дисплея. Разработчику необходимо убедиться, что каждый движок может рисовать независимо, с разной частотой кадров, соблюдая VSync.
Выберите обои для отдельных экранов
Android 10 не обеспечивает прямую поддержку платформы для выбора обоев для отдельных экранов. Для этого необходим стабильный идентификатор дисплея, чтобы сохранить настройки обоев для каждого дисплея. Display#getDisplayId()
является динамическим, поэтому нет гарантии, что физический дисплей будет иметь тот же идентификатор после перезагрузки.
Однако в Android 10 добавлен DisplayInfo.mAddress
, который содержит стабильные идентификаторы для физических дисплеев и может быть использован для полной реализации в будущем. К сожалению, уже слишком поздно реализовывать логику для Android 10. Предлагаемое решение:
- Для установки обоев используйте класс
WallpaperManager
.WallpaperManager
получается из объектаContext
, а каждый объектContext
имеет информацию о соответствующем дисплее (Context#getDisplay()/getDisplayId()
). Таким образом, вы можете получитьdisplayId
из экземпляраWallpaperManager
без добавления новых методов. - На стороне фреймворка используйте
displayId
, полученный из объектаContext
, и сопоставьте его со статическим идентификатором (например, портом физического дисплея). Используйте статический идентификатор для сохранения выбранных обоев.
Этот обходной путь использует существующие реализации для выбора обоев. Если он был открыт на определенном дисплее и использует правильный контекст, то при вызове установки обоев система может автоматически идентифицировать дисплей.
Если необходимо установить обои для дисплея, отличного от текущего, создайте новый объект Context
для целевого дисплея ( Context#createDisplayContext
) и получите экземпляр WallpaperManager
из этого дисплея.
Ограничения по соображениям безопасности
Система не будет показывать обои на виртуальных дисплеях, которые ей не принадлежат. Это связано с проблемами безопасности, так как вредоносное приложение может создать виртуальный дисплей с включенной поддержкой системных украшений и считать конфиденциальную информацию пользователя с поверхности (например, личную фотографию).
Выполнение
В Android 10 интерфейсы IWallpaperConnection#attachEngine()
и IWallpaperService#attach()
принимают параметр displayId
для создания подключений по каждому дисплею. WallpaperManagerService.DisplayConnector
инкапсулирует движок обоев и подключение по каждому дисплею. В WindowManager контроллеры обоев создаются для каждого объекта DisplayContent
при построении вместо одного WallpaperController
для всех дисплеев.
Некоторые из реализаций общедоступных методов WallpaperManager
(таких как WallpaperManager#getDesiredMinimumWidth()
) были обновлены для вычисления и предоставления информации для соответствующих дисплеев. WallpaperInfo#supportsMultipleDisplays()
и соответствующий атрибут ресурса были добавлены, чтобы разработчики приложений могли сообщать, какие обои готовы для нескольких экранов.
Если служба обоев, отображаемая на дисплее по умолчанию, не поддерживает несколько дисплеев, то система отображает обои по умолчанию на дополнительных дисплеях:
Рисунок 3. Логика возврата обоев для дополнительных дисплеев.