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

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

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

В 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), должен обрабатывать следующие случаи:

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

Когда системный пользовательский интерфейс обнаруживает добавление дисплея перед 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. Логика возврата обоев для дополнительных дисплеев

,

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

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

В 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), должен обрабатывать следующие случаи:

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

Когда системный пользовательский интерфейс обнаруживает добавление дисплея перед 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. Логика возврата обоев для дополнительных дисплеев

,

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

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

В 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), должен обрабатывать следующие случаи:

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

Когда системный пользовательский интерфейс обнаруживает добавление дисплея перед 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. Логика возврата обоев для дополнительных дисплеев