Возможности отображения (такие как режимы отображения и поддерживаемые типы HDR) могут динамически изменяться на устройствах с внешним подключением дисплеев (через HDMI или DisplayPort), таких как телевизионные приставки Android TV (STB) и устройства с поддержкой технологии OTT. Это изменение может происходить в результате сигнала горячего подключения HDMI, например, когда пользователь переключается с одного дисплея на другой или загружает устройство без подключенного дисплея. В Android 12 и более поздних версиях внесены изменения в фреймворк для поддержки горячего подключения и динамических возможностей отображения.
На этой странице описывается обработка горячего подключения дисплеев и изменения в возможностях дисплея в реализации Composer HAL. Кроме того, здесь обсуждается управление связанным буфером кадров и предотвращение состояний гонки в таких ситуациях.
Обновление возможностей отображения
В этом разделе описывается, как платформа Android обрабатывает изменения в возможностях отображения, инициированные Composer HAL.
 Прежде чем Android сможет корректно обрабатывать изменения в возможностях отображения, OEM-производитель должен реализовать Composer HAL таким образом, чтобы он использовал onHotplug(display, connection=CONNECTED) для уведомления фреймворка о любых изменениях в возможностях отображения. После этого Android обрабатывает изменения в возможностях отображения следующим образом:
-  При обнаружении изменения в возможностях отображения фреймворк получает уведомление onHotplug(display, connection=CONNECTED).
-  Получив уведомление, фреймворк сбрасывает свое состояние отображения и воссоздает его с новыми возможностями из HAL, используя методы getActiveConfig,getDisplayConfigs,getDisplayAttribute,getColorModes,getHdrCapabilitiesиgetDisplayCapabilities.
-  После того как фреймворк воссоздает новое состояние отображения, он отправляет обратный вызов onDisplayChangedприложениям, которые прослушивают такие события.
 Фреймворк перераспределяет фреймбуферы при последующих событиях onHotplug(display, connection=CONNECTED) . Подробнее о том, как правильно управлять памятью фреймбуфера, чтобы избежать сбоев при выделении новых фреймбуферов, см. в разделе Управление фреймбуфером клиента .
Обработка распространенных сценариев подключения
В этом разделе описывается, как правильно обрабатывать различные сценарии подключения в ваших реализациях, когда основной дисплей подключен и отключен.
Разработанный для мобильных устройств, фреймворк Android не имеет встроенной поддержки отключённого основного дисплея. Вместо этого HAL должен заменять основной дисплей на дисплей-заглушку при взаимодействии с фреймворком в случае физического отключения основного дисплея.
В приставках STB и ТВ-адаптерах с внешними дисплеями, которые можно отключать, могут возникнуть следующие сценарии. Для реализации поддержки этих сценариев используйте информацию из следующей таблицы:
| Сценарий | Умение обращаться | 
|---|---|
| Нет подключенного дисплея во время загрузки | 
 | 
| Основной дисплей физически подключен | 
 | 
| Основной дисплей физически отключен | 
 | 
Рекомендации по подключению без HDMI
Android TV поддерживает только следующие разрешения:
- 720x1280
- 1080x1920
- 2160x3840
- 4320x7680
Когда STB или телевизионный адаптер пытается отобразить неподдерживаемое разрешение, например 480i, по соединению CVBS, пользователю отображается сообщение об ошибке.
 Если у STB или TV-адаптера есть как HDMI-, так и не-HDMI-подключения, HDMI-подключение является основным дисплеем, а не-HDMI-подключение неактивно. В результате, если HDMI-подключение отключается, а не-HDMI-подключение всё ещё подключено, событие отправляется в SurfaceFlinger, и возможности не-HDMI-дисплея должны быть отражены через getDisplayAttribute и другие API IComposerClient (например, getHdrCapabilities ).
Используйте последовательные идентификаторы конфигураций для предотвращения состояний гонки
 Состояние гонки может возникнуть, если Composer HAL обновляет поддерживаемые конфигурации отображения одновременно с вызовом фреймворком setActiveConfig или setActiveConfigWithConstraints . Решение заключается в реализации Composer HAL для использования последовательных идентификаторов и предотвращения этой проблемы.
В этом разделе описывается, как могут возникнуть условия гонки, а затем приводятся сведения о том, как реализовать Composer HAL таким образом, чтобы он использовал последовательные идентификаторы для предотвращения таких условий.
Рассмотрим следующую последовательность событий, когда новые последовательные идентификаторы НЕ назначаются новым конфигурациям отображения, что приводит к состоянию гонки:
- Поддерживаемые идентификаторы конфигураций дисплея: - id=1 , 1080x1920 60 Гц
- id=2 , 1080x1920 50 Гц
 
- Фреймворк вызывает - setActiveConfig(display, config=1).
- Одновременно с этим Composer HAL обрабатывает изменение конфигураций дисплея и обновляет свое внутреннее состояние новым набором конфигураций дисплея, как показано ниже: - id=1 , 2160x3840 60 Гц
- id=2 , 2160x3840 50 Гц
- id=3 , 1080x1920 60 Гц
- id=4 , 1080x1920 50 Гц
 
- Composer HAL отправляет событие - onHotplugфреймворку, чтобы уведомить об изменении набора поддерживаемых режимов.
- Composer HAL получает - setActiveConfig(display, config=1)(из шага 2).
- HAL интерпретирует это так, что фреймворк запросил изменение конфигурации на 2160x3840 60 Гц , хотя на самом деле было выбрано 1080x1920 60 Гц . 
Процесс с использованием непоследовательных назначений идентификаторов заканчивается здесь неверной интерпретацией выбранного изменения конфигурации.
Настройте Composer HAL для использования последовательных идентификаторов
Чтобы избежать подобных условий гонки, OEM-производитель должен реализовать Composer HAL следующим образом:
- Когда Composer HAL обновляет поддерживаемые конфигурации отображения, он назначает новые последовательные идентификаторы новым конфигурациям отображения.
-  Когда фреймворк вызывает setActiveConfigилиsetActiveConfigWithConstraintsс недопустимым идентификатором конфигурации, Composer HAL игнорирует вызов.
Эти шаги позволяют предотвратить возникновение состояний гонки, как показано в следующем обсуждении.
Рассмотрим следующую последовательность событий, когда новым конфигурациям отображения присваиваются новые последовательные идентификаторы:
- Поддерживаемые идентификаторы конфигураций дисплея: - id=1 , 1080x1920 60 Гц
- id=2 , 1080x1920 50 Гц
 
- Фреймворк вызывает - setActiveConfig(display, config=1).
- При обработке изменения конфигураций отображения следующий набор идентификаторов конфигураций назначается, начиная со следующего неиспользованного целого числа, как показано ниже: - id=3 , 2160x3840 60 Гц 
- id=4 , 2160x3840 50 Гц 
- id=5 , 1080x1920 60 Гц 
- id=6 , 1080x1920 50 Гц 
 
- Composer HAL отправляет фреймворку событие - onHotplug, чтобы уведомить об изменении набора поддерживаемых режимов.
- Composer HAL получает - setActiveConfig(display, config=1)(из шага 2).
- Composer HAL игнорирует вызов, поскольку идентификатор больше не действителен. 
- Фреймворк получает и обрабатывает событие - onHotplugиз шага 4. Он вызывает Composer HAL, используя функции- getDisplayConfigsи- getDisplayAttribute. С помощью этих функций фреймворк идентифицирует новый идентификатор (5) для выбранного разрешения и частоты обновления 1080x1920 и 60 Гц.
- Фреймворк отправляет еще одно событие - setActiveConfigс обновленным идентификатором 5.
- Composer HAL получает - setActiveConfig(display, config=5)из шага 5.
- HAL правильно интерпретирует, что фреймворк запросил изменение конфигурации на 1080x1920 60 Гц. 
Как показано в предыдущем примере, процесс, использующий последовательное назначение идентификаторов, проверяет, что состояние гонки предотвращено, и обновляется правильное изменение конфигурации дисплея.