Обновления, внесенные в области отображения, представлены на этой странице.
Системные украшения
В Android 10 добавлена поддержка настройки дополнительных дисплеев для отображения определённых системных элементов оформления, таких как обои, панель навигации и панель запуска. По умолчанию на основном дисплее отображаются все системные элементы оформления, а на дополнительных дисплеях — те, которые включены опционально. Вы можете настроить поддержку редактора методов ввода (IME) отдельно от других системных элементов оформления.
Используйте DisplayWindowSettings#setShouldShowSystemDecorsLocked()
чтобы добавить поддержку системных декораций на определённом дисплее или задать значение по умолчанию в /data/system/display_settings.xml
. Примеры см. в разделе Параметры окна дисплея .
Выполнение
DisplayWindowSettings#setShouldShowSystemDecorsLocked()
также доступен в WindowManager#setShouldShowSystemDecors()
для тестирования. Запуск этого метода с намерением включить системные декоры не добавляет ранее отсутствовавшие окна декоров и не удаляет их, если они ранее присутствовали. В большинстве случаев изменение поддержки системных декораций вступает в силу только после перезагрузки устройства.
Проверки поддержки системных декораций в кодовой базе WindowManager обычно выполняются с помощью DisplayContent#supportsSystemDecorations()
а проверки внешних служб (например, системного пользовательского интерфейса для проверки необходимости отображения панели навигации) — с помощью WindowManager#shouldShowSystemDecors()
. Чтобы понять, что контролирует этот параметр, изучите точки вызова этих методов.
Окна оформления пользовательского интерфейса системы
В Android 10 добавлена поддержка системных декораций только для панели навигации, поскольку она необходима для навигации между приложениями и задачами. По умолчанию на панели навигации отображаются кнопки «Назад» и «Домой». Это возможно только в том случае, если целевой дисплей поддерживает системные декорации (см. DisplayWindowSettings
).
Строка состояния — более сложное системное окно, поскольку оно также содержит панель уведомлений, быстрые настройки и экран блокировки. В Android 10 строка состояния не поддерживается на дополнительных дисплеях. Поэтому уведомления, настройки и полноценная блокировка клавиатуры доступны только на основном дисплее.
Системное окно «Обзор/Недавние» не поддерживается на дополнительных экранах. В Android 10 AOSP отображает только «Недавние» на дисплее по умолчанию и содержит действия со всех дисплеев. При запуске из окна «Недавние» действие, отображавшееся на дополнительном дисплее, по умолчанию выводится на передний план. Этот подход имеет ряд известных проблем, таких как несвоевременное обновление приложений при появлении на других экранах.
Выполнение
Для реализации дополнительных функций системного пользовательского интерфейса производители устройств должны использовать единый компонент системного пользовательского интерфейса, который отслеживает добавление или удаление дисплеев и представляет соответствующий контент.
Компонент пользовательского интерфейса системы, поддерживающий многодисплейный режим (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. Логика возврата обоев для дополнительных дисплеев.