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

Обновления, внесенные в эти области, относящиеся к конкретному отображению, представлены на этой странице.

Декорации системы

В 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. Пример запуска приложения на нескольких экранах для платформы/разработки/образцов/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. Для установки обоев используйте класс WallpaperManager .

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

  2. На стороне фреймворка используйте displayId , полученный из объекта Context , и сопоставьте его со статическим идентификатором (например, портом физического дисплея). Используйте статический идентификатор для сохранения выбранных обоев.

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

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

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

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

Выполнение

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

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

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

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

Включить поддержку живых обоев

В Android 10 и выше (API 29) разработчики могут использовать атрибут android:supportsMultipleDisplays , чтобы указать, может ли их обои растягиваться на несколько дисплеев. В оконных средах рабочего стола, где многозадачность является распространенной, отображение живых обоев на внешних дисплеях может значительно увеличить нагрузку на графический процессор и память.

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

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

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

Путь к ресурсу frameworks/base/core/res/res/values/config.xml
Название конфигурации config_isLiveWallpaperSupportedInDesktopExperience

Настройте резервные обои

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

Путь к ресурсу frameworks/base/core/res/res/values/config.xml
Название конфигурации fallback_wallpaper_component

Реализовать поддержку обоев

Для применения этих изменений используйте наложение ресурсов во время сборки в папке, специфичной для вашего устройства, которая обычно находится по device/<vendor>/<product>/overlay/frameworks/base/core/res/res/values/ .