Поддержка системных украшений

Обновления, внесенные в эти области отображения, представлены ниже:

Системные украшения

В 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 отображает только последние на дисплее по умолчанию и содержит действия со всех дисплеев. При запуске из «Недавних» действие, которое было на дополнительном дисплее, по умолчанию выводится на передний план этого дисплея. У этого подхода есть некоторые известные проблемы, такие как отсутствие немедленного обновления при появлении приложений на других экранах.

Реализация

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

Компонент системного пользовательского интерфейса, поддерживающий Multi-Display (MD), должен обрабатывать следующие случаи:

  • Инициализация нескольких дисплеев при запуске
  • Дисплей добавлен во время выполнения
  • Дисплей удален во время выполнения

Когда системный пользовательский интерфейс обнаруживает добавление дисплея перед WindowManager, он создает состояние гонки. Этого можно избежать путем реализации пользовательского обратного вызова из WindowManager в системный пользовательский интерфейс при добавлении дисплея вместо подписки на события DisplayManager .DisplayListener . Для эталонной реализации см. CommandQueue.Callbacks#onDisplayReady для поддержки панели навигации и WallpaperManagerInternal#onDisplayReady для обоев.

Кроме того, 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 уже поздно. Предлагаемое решение:

  1. Используйте API-интерфейс WallpaperManager для установки обоев.
  2. WallpaperManager получается из объекта Context , и каждый объект Context имеет информацию о соответствующем отображении ( Context#getDisplay()/getDisplayId() ). Поэтому вы можете получить displayId из экземпляра WallpaperManager без добавления новых методов.
  3. На стороне платформы используйте displayId , полученный из объекта Context , и сопоставьте его со статическим идентификатором (например, с портом физического дисплея). Используйте статический идентификатор, чтобы сохранить выбранные обои.

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

Если необходимо установить обои для дисплея, отличного от текущего дисплея, создайте новый объект Context для целевого дисплея ( Context#createDisplayContext ) и получите экземпляр WallpaperManager с этого дисплея.

Ограничения безопасности

Система не будет отображать обои на виртуальных дисплеях, которые ей не принадлежат. Это связано с соображениями безопасности, поскольку вредоносное приложение может создать виртуальный дисплей с включенной поддержкой системных украшений и прочитать конфиденциальную информацию пользователя с поверхности (например, личную фотографию).

Реализация

В Android 10 IWallpaperConnection#attachEngine() и IWallpaperService#attach() принимают параметр displayId для создания соединений для каждого дисплея. WallpaperManagerService.DisplayConnector инкапсулирует механизм обоев для каждого дисплея и соединение. В WindowManager контроллеры обоев создаются для каждого объекта DisplayContent при построении вместо одного контроллера WallpaperController для всех дисплеев.

Некоторые из общедоступных реализаций метода WallpaperManager (например, WallpaperManager#getDesiredMinimumWidth() ) были обновлены для вычисления и предоставления информации для соответствующих дисплеев. Были добавлены WallpaperInfo#supportsMultipleDisplays() и соответствующий атрибут ресурса, чтобы разработчики приложений могли сообщать, какие обои готовы для нескольких экранов.

Если служба обоев, отображаемая на дисплее по умолчанию, не поддерживает несколько дисплеев, система показывает обои по умолчанию на дополнительных дисплеях.

Рис. 3. Логика резервного копирования обоев для дополнительных дисплеев