Горячее подключение

Возможности отображения (такие как режимы отображения и поддерживаемые типы HDR) могут динамически изменяться на устройствах с внешними дисплеями (через HDMI или DisplayPort), таких как Android TV-приставки (STB) и OTT-устройства. Это изменение может происходить в результате сигнала горячего подключения HDMI, например, когда пользователь переключается с одного дисплея на другой или загружает устройство без подключенного дисплея. Android 12 и выше включает изменения в фреймворке для обработки горячего подключения и динамических возможностей отображения.

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

Обновить возможности отображения

В этом разделе описывается, как платформа Android обрабатывает изменения в возможностях отображения, инициированные Composer HAL.

Прежде чем Android сможет корректно обрабатывать изменения в возможностях дисплея, производитель оборудования должен реализовать Composer HAL таким образом, чтобы он использовал onHotplug(display, connection=CONNECTED) для уведомления фреймворка о любых изменениях в возможностях дисплея. После реализации этого Android обрабатывает изменения в возможностях дисплея следующим образом:

  1. При обнаружении изменения возможностей отображения платформа получает уведомление onHotplug(display, connection=CONNECTED) .
  2. Получив уведомление, платформа сбрасывает состояние отображения и воссоздает его с новыми возможностями HAL, используя методы getActiveConfig , getDisplayConfigs , getDisplayAttribute , getColorModes , getHdrCapabilities и getDisplayCapabilities .
  3. После того как фреймворк создаст новое состояние дисплея, он отправляет обратный вызов onDisplayChanged приложениям, которые отслеживают подобные события.

В дальнейшем фреймворк перераспределяет буферы кадров при возникновении событий onHotplug(display, connection=CONNECTED) . Дополнительную информацию о том, как правильно управлять памятью буфера кадров, чтобы избежать сбоев при выделении новых буферов кадров, см. в разделе «Управление буферами кадров клиента» .

Обработка распространенных сценариев подключения

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

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

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

Сценарий Умение обращаться
При загрузке не подключен дисплей
  • Отправьте сигнал onHotplug(display, connection=CONNECTED) из Composer HAL в фреймворк.
  • Замените физическое состояние отображения внутри Composer HAL на состояние отображения-заполнитель.
Основной дисплей физически подключен.
  • Отправьте еще одно событие onHotplug(display, connection=CONNECTED) из Composer HAL в фреймворк.

    Это приводит к перезагрузке всех возможностей отображения в рамках системы.

Основной дисплей физически отключен.
  • Отправьте еще одно событие onHotplug(display, connection=CONNECTED) из Composer HAL в фреймворк.
  • Замените физическое состояние дисплея внутри Composer HAL на состояние-заполнитель. У этого состояния-заполнителя должен быть один режим отображения, чтобы фреймворк отправлял обратный вызов onDisplayChanged приложениям (поскольку набор поддерживаемых режимов изменился). Этот единственный режим отображения должен соответствовать последнему активному режиму физического дисплея перед отключением, чтобы приложения не получали события изменения конфигурации .

Вопросы, касающиеся подключения без HDMI.

Android TV поддерживает только следующие разрешения:

  • 720x1280
  • 1080x1920
  • 2160x3840
  • 4320x7680

Когда STB или ТВ-адаптер пытается отобразить неподдерживаемое разрешение, например 480i, через соединение CVBS, пользователю отображается сообщение об ошибке.

Если STB или ТВ-адаптер имеет как HDMI, так и не-HDMI разъемы, то HDMI-разъем является основным дисплеем, а не-HDMI-разъем неактивен. В результате, если HDMI-разъем отключается, а не-HDMI-разъем остается подключенным, в SurfaceFlinger отправляется событие, и возможности не-HDMI-дисплея должны быть отражены через getDisplayAttribute и другие API IComposerClient (например, getHdrCapabilities ).

Используйте последовательные идентификаторы конфигурации, чтобы предотвратить состояния гонки.

Проблемы с состоянием гонки могут возникнуть, если Composer HAL обновляет поддерживаемые конфигурации дисплея одновременно с вызовом фреймворком методов setActiveConfig или setActiveConfigWithConstraints . Решение состоит в том, чтобы реализовать Composer HAL, использующий последовательные идентификаторы, и предотвратить эту проблему.

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

Рассмотрим следующую последовательность событий, когда новым последовательным идентификаторам НЕ присваиваются новые конфигурации дисплея, что приводит к состоянию гонки:

  1. Поддерживаемые идентификаторы конфигурации дисплея:

    • id=1 , 1080x1920 60 Гц
    • id=2 , 1080x1920 50 Гц
  2. Фреймворк вызывает setActiveConfig(display, config=1) .

  3. Одновременно с этим, Composer HAL обрабатывает изменение конфигурации дисплея и обновляет свое внутреннее состояние, используя новый набор конфигураций дисплея, как показано ниже:

    • id=1 , 2160x3840 60 Гц
    • id=2 , 2160x3840 50 Гц
    • id=3 , 1080x1920 60 Гц
    • id=4 , 1080x1920 50 Гц
  4. Composer HAL отправляет событие onHotplug в фреймворк, чтобы уведомить его об изменении набора поддерживаемых режимов.

  5. HAL Composer получает setActiveConfig(display, config=1) (из шага 2).

  6. HAL интерпретирует запрос на изменение конфигурации на 2160x3840 60 Гц , хотя в действительности было выбрано разрешение 1080x1920 60 Гц .

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

Настройте Composer HAL для использования последовательных идентификаторов.

Чтобы избежать подобных состояний гонки, производитель оборудования должен реализовать Composer HAL следующим образом:

  • Когда Composer HAL обновляет поддерживаемые конфигурации дисплея, он присваивает новым конфигурациям дисплея новые последовательные идентификаторы.
  • Когда фреймворк вызывает setActiveConfig или setActiveConfigWithConstraints с недопустимым идентификатором конфигурации, Composer HAL игнорирует этот вызов.

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

Рассмотрим следующую последовательность событий, когда новым конфигурациям дисплея присваиваются новые, последовательные идентификаторы:

  1. Поддерживаемые идентификаторы конфигурации дисплея:

    • id=1 , 1080x1920 60 Гц
    • id=2 , 1080x1920 50 Гц
  2. Фреймворк вызывает setActiveConfig(display, config=1) .

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

    • id=3 , 2160x3840 60 Гц

    • id=4 , 2160x3840 50 Гц

    • id=5 , 1080x1920 60 Гц

    • id=6 , 1080x1920 50 Гц

  4. HAL Composer отправляет событие onHotplug в фреймворк, чтобы уведомить его об изменении набора поддерживаемых режимов.

  5. HAL Composer получает setActiveConfig(display, config=1) (из шага 2).

  6. HAL Composer игнорирует вызов, поскольку идентификатор больше недействителен.

  7. Фреймворк получает и обрабатывает событие onHotplug из шага 4. Он вызывает Composer HAL, используя функции getDisplayConfigs и getDisplayAttribute . С помощью этих функций фреймворк определяет новый ID (5) для выбранного разрешения и частоты обновления 1080x1920 и 60 Гц.

  8. Фреймворк отправляет еще одно событие setActiveConfig с обновленным ID, равным 5.

  9. HAL Composer получает setActiveConfig(display, config=5) из шага 5.

  10. HAL корректно интерпретирует запрос платформы на изменение конфигурации на 1080x1920 60 Гц.

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