Для Android 11 и выше можно использовать фреймворк Android Tuner для доставки аудио- и видеоконтента. Фреймворк использует аппаратный конвейер от производителей, что делает его подходящим как для недорогих, так и для высокопроизводительных SoC. Фреймворк обеспечивает безопасный способ доставки аудио- и видеоконтента, защищенный доверенной средой выполнения (TEE) и защищенным медиа-путем (SMP), что позволяет использовать его в условиях строгой защиты контента.
Стандартизированный интерфейс между тюнером и Android CAS обеспечивает более быструю интеграцию между производителями тюнеров и CAS. Интерфейс тюнера работает с MediaCodec и AudioTrack , создавая универсальное решение для Android TV. Интерфейс тюнера поддерживает как цифровое, так и аналоговое телевидение на основе основных стандартов вещания.
Компоненты
В Android 11 три компонента разработаны специально для телевизионной платформы.
- Tuner HAL: интерфейс между фреймворком и поставщиками.
- API Tuner SDK: интерфейс между фреймворком и приложениями.
- Менеджер ресурсов тюнера (TRM): координирует аппаратные ресурсы тюнера.
В Android 11 были улучшены следующие компоненты.
- CAS V2
-
TvInputServiceили TV Input Service (TIS) -
TvInputManagerServiceили служба управления входами телевизора (TIMS) -
MediaCodecили медиакодек -
AudioTrackили аудиотрек -
MediaResourceManagerили менеджер медиаресурсов (MRM)

Рисунок 1. Взаимодействие компонентов Android TV.
Функции
Фронтенд поддерживает указанные ниже стандарты DTV.
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- Аналоговый
В Android 12 с Tuner HAL 1.1 или выше интерфейс пользователя поддерживает указанный ниже стандарт цифрового телевидения.
- ДТМБ
Демультиплексор поддерживает указанные ниже потоковые протоколы.
- Транспортный поток (ТС)
- Протокол передачи мультимедиа MPEG (MMTP)
- Интернет-протокол (IP)
- Тип значения длины (TLV)
- Протокол канального уровня ATSC (ALP)
Descrambler поддерживает следующие средства защиты контента.
- Защищенный путь передачи медиафайлов
- Очистка пути к медиафайлу
- Надежная локальная запись
- Безопасное локальное воспроизведение
API тюнера поддерживают следующие варианты использования.
- Сканировать
- Жить
- Воспроизведение
- Записывать
Tuner, MediaCodec и AudioTrack поддерживают указанные ниже режимы передачи данных.
- Полезная нагрузка ES с очищенным буфером памяти
- Полезная нагрузка ES с защищенным дескриптором памяти
- Сквозной проход
Общий дизайн
Tuner HAL — это интерфейс, определяющий взаимодействие между фреймворком Android и оборудованием производителя.
- Описывает, чего ожидает платформа от поставщика и как поставщик может это обеспечить.
- Экспортирует функциональные возможности интерфейса, демультиплексора и дескремблера во фреймворк через интерфейсы
IFrontend,IDemux,IDescrambler,IFilter,IDvrиILnb. - Включает в себя функции для интеграции Tuner HAL с другими компонентами фреймворка, такими как
MediaCodecиAudioTrack.
Создаются Java-класс Tuner и нативный класс.
- Java API Tuner позволяет приложениям получать доступ к HAL Tuner через общедоступные API.
- Встроенный класс позволяет контролировать права доступа и обрабатывать большие объемы данных для записи или воспроизведения с помощью Tuner HAL.
- Нативный модуль Tuner представляет собой связующее звено между Java-классом Tuner и HAL-интерфейсом Tuner.
Создан класс TRM.
- Управляет ограниченными ресурсами тюнера, такими как интерфейсная часть, LNB, сессии CAS и входное устройство телевизора, через HAL-интерфейс телевизионного входа.
- Применяет правила для высвобождения недостаточных ресурсов у приложений. Правило по умолчанию — приоритет для приложений переднего плана.
Функции Media CAS и CAS HAL расширены за счет перечисленных ниже возможностей.
- Открывает сессии CAS для различных целей и алгоритмов.
- Поддерживает динамические системы CAS, такие как удаление и установка CICAM.
- Интегрируется с Tuner HAL, предоставляя ключевые токены.
MediaCodec и AudioTrack расширены за счет перечисленных ниже возможностей.
- Принимает в качестве входного контента защищённую аудио- и видеопамять.
- Настроено для аппаратной синхронизации аудио и видео в режиме туннельного воспроизведения.
- Настроена поддержка режима
ES_payloadи режима сквозной передачи.

Рисунок 2. Схема компонентов внутри Tuner HAL.
Общий рабочий процесс
Приведенные ниже диаграммы иллюстрируют последовательность вызовов для воспроизведения прямой трансляции.
Настраивать

Рисунок 3. Последовательность настройки для воспроизведения прямой трансляции.
Обработка аудио- и видеоматериалов

Рисунок 4. Обработка аудио- и видеосигнала для воспроизведения прямой трансляции.
Обработка зашифрованного контента

Рисунок 5. Обработка зашифрованного контента для воспроизведения прямой трансляции.
Обработка аудио-видео данных

Рисунок 6. Обработка аудио/видео для воспроизведения прямой трансляции.
API SDK тюнера
API Tuner SDK обрабатывает взаимодействие с Tuner JNI, Tuner HAL и TunerResourceManager . Приложение TIS использует API Tuner SDK для доступа к ресурсам Tuner и его подкомпонентам, таким как фильтр и дескремблер. Фронтенд и демультиплексор являются внутренними компонентами.

Рисунок 7. Взаимодействие с API Tuner SDK.
Версии
Начиная с Android 12, API Tuner SDK поддерживает новую функцию в Tuner HAL 1.1, которая является обратно совместимым обновлением версии Tuner 1.0.
Для проверки версии HAL используйте следующий API.
-
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
Минимально необходимая версия HAL указана в документации к новым API Android 12.
Пакеты
API Tuner SDK предоставляет четыре пакета, перечисленных ниже.
-
android.media.tv.tuner -
android.media.tv.tuner.frontend -
android.media.tv.tuner.filter -
android.media.tv.tuner.dvr

Рисунок 8. Пакеты API Tuner SDK
Android.media.tv.tuner
Пакет Tuner является точкой входа для использования фреймворка Tuner. Приложение TIS использует этот пакет для инициализации и получения экземпляров ресурсов, указывая начальные параметры и функцию обратного вызова.
-
tuner(): Инициализирует экземпляр Tuner, указывая параметрыuseCaseиsessionId. -
tune(): Получает ресурс интерфейса и выполняет настройку, указывая параметрFrontendSetting. -
openFilter(): Получает экземпляр фильтра, указывая его тип. -
openDvrRecorder(): Получает экземпляр записи, указывая размер буфера. -
openDvrPlayback(): Получает экземпляр воспроизведения, указывая размер буфера. -
openDescrambler(): Получает экземпляр дескремблера. -
openLnb(): Получает внутренний экземпляр LNB. -
openLnbByName(): Получает внешний экземпляр LNB. -
openTimeFilter(): Получает экземпляр фильтра времени.
Пакет Tuner предоставляет функциональные возможности, которые не входят в пакеты Filter, DVR и Frontend. Эти функциональные возможности перечислены ниже.
-
cancelTuning -
scan/cancelScanning -
getAvSyncHwId -
getAvSyncTime -
connectCiCam1/disconnectCiCam -
shareFrontendFromTuner -
updateResourcePriority -
setOnTuneEventListener -
setResourceLostListener
Android.media.tv.tuner.frontend
Пакет для фронтенда включает в себя наборы настроек, информации, статусов, событий и возможностей, связанных с фронтендом.
Классы
FrontendSettings для различных стандартов цифрового телевидения создается на основе классов, перечисленных ниже.
-
AnalogFrontendSettings -
Atsc3FrontendSettings -
AtscFrontendSettings -
DvbcFrontendSettings -
DvbsFrontendSettings -
DvbtFrontendSettings -
Isdbs3FrontendSettings -
IsdbsFrontendSettings -
IsdbtFrontendSettings
Начиная с Android 12 и Tuner HAL 1.1 или выше, поддерживаются следующие стандарты цифрового телевидения.
-
DtmbFrontendSettings
FrontendCapabilities представленный ниже, наследуется от других классов для различных стандартов цифрового телевидения.
-
AnalogFrontendCapabilities -
Atsc3FrontendCapabilities -
AtscFrontendCapabilities -
DvbcFrontendCapabilities -
DvbsFrontendCapabilities -
DvbtFrontendCapabilities -
Isdbs3FrontendCapabilities -
IsdbsFrontendCapabilities -
IsdbtFrontendCapabilities
Начиная с Android 12 и Tuner HAL 1.1 или выше, поддерживаются следующие стандарты цифрового телевидения.
-
DtmbFrontendCapabilities
FrontendInfo получает информацию о внешнем интерфейсе. FrontendStatus получает текущий статус внешнего интерфейса. OnTuneEventListener прослушивает события на внешнем интерфейсе. Приложение TIS использует ScanCallback для обработки сообщений сканирования с внешнего интерфейса.
сканирование каналов
Для настройки телевизора приложение сканирует возможные частоты и формирует список каналов, к которым пользователи могут получить доступ. TIS может использовать Tuner.tune , Tuner.scan(BLIND_SCAN) или Tuner.scan(AUTO_SCAN) для завершения сканирования каналов.
Если TIS располагает точной информацией о передаче сигнала, такой как частота, стандарт (например, T/T2, S/S2) и дополнительная необходимая информация (например, идентификатор PLD), то Tuner.tune рекомендуется как более быстрый вариант.
Когда пользователь вызывает Tuner.tune , происходят следующие действия:
- TIS заполняет
FrontendSettingsнеобходимой информацией с помощьюTuner.tune. - Если сигнал заблокирован, HAL выдает сообщение "tune
LOCKED. - TIS использует
Frontend.getStatusдля сбора необходимой информации. - TIS переключается на следующую доступную частоту в своем частотном списке.
TIS снова вызывает Tuner.tune до тех пор, пока не будут исчерпаны все частоты.
Во время настройки вы можете вызвать stopTune() или close() чтобы приостановить или завершить вызов Tuner.tune .
Tuner.scan(AUTO_SCAN)
Если у TIS недостаточно информации для использования Tuner.tune , но есть список частот и тип стандарта (например, DVB T/C/S), то рекомендуется использовать Tuner.scan(AUTO_SCAN) .
Когда пользователь вызывает Tuner.scan(AUTO_SCAN) , происходят следующие действия:
TIS использует
Tuner.scan(AUTO_SCAN), в которомFrontendSettingsзаполнены частотой.HAL сообщает о блокировке сигнала (Scan
LOCKED, если сигнал заблокирован. HAL также может сообщать о других сообщениях сканирования, предоставляя дополнительную информацию о сигнале.TIS использует
Frontend.getStatusдля сбора необходимой информации.TIS вызывает
Tuner.scan, чтобы HAL перешел к следующей настройке на той же частоте. Если структураFrontendSettingsпуста, HAL использует следующую доступную настройку. В противном случае HAL используетFrontendSettingsдля однократного сканирования и отправляетEND, указывая на завершение операции сканирования.Система TIS повторяет описанные выше действия до тех пор, пока не будут исчерпаны все настройки частоты.
HAL отправляет
END, указывающий на завершение операции сканирования.TIS переключается на следующую доступную частоту в своем частотном списке.
TIS вызывает Tuner.scan(AUTO_SCAN) снова и снова, пока не будут исчерпаны все частоты.
Во время сканирования вы можете вызвать stopScan() или close() , чтобы приостановить или завершить сканирование.
Tuner.scan(BLIND_SCAN)
Если в TIS отсутствует список частот, а Vendor HAL может выполнить поиск частоты указанного пользователем интерфейса для получения ресурса интерфейса, то рекомендуется использовать Tuner.scan(BLIND_SCAN) .
- TIS использует
Tuner.scan(BLIND_SCAN). ВFrontendSettingsможно указать начальную частоту, но TIS игнорирует другие настройки вFrontendSettings. - Если сигнал заблокирован, HAL выдает сообщение "сканирование
LOCKED. - TIS использует
Frontend.getStatusдля сбора необходимой информации. - TIS снова вызывает
Tuner.scanдля продолжения сканирования. (FrontendSettingsигнорируются.) - TIS повторяет описанные выше действия до тех пор, пока не будут исчерпаны все настройки частоты. HAL увеличивает частоту без каких-либо действий со стороны TIS. HAL сообщает
PROGRESS.
TIS снова вызывает Tuner.scan(AUTO_SCAN) до тех пор, пока не будут исчерпаны все частоты. HAL сообщает END , указывая на завершение операции сканирования.
Во время сканирования вы можете вызвать stopScan() или close() , чтобы приостановить или завершить сканирование.

Рисунок 9. Блок-схема сканирования TIS.
Android.media.tv.tuner.filter
Пакет filter представляет собой набор операций фильтрации, а также конфигурационных файлов, настроек, обратных вызовов и событий. Пакет включает в себя перечисленные ниже операции. Полный список операций см. в исходном коде Android.
-
configure() -
start() -
stop() -
flush() -
read()
Полный список см. в исходном коде Android.
FilterConfiguration является производным от описанных ниже классов. Конфигурации относятся к основному типу фильтра и определяют, какой протокол фильтр использует для извлечения данных.
-
AlpFilterConfiguration -
IpFilterConfiguration -
MmtpFilterConfiguration -
TlvFilterConfiguration -
TsFilterConfiguration
Настройки определяются на основе приведенных ниже классов. Эти настройки относятся к подтипу фильтра и указывают, какие типы данных может исключать фильтр.
-
SectionSettings -
AvSettings -
PesSettings -
RecordSettings -
DownloadSettings
FilterEvent является производным от описанных ниже классов и предназначен для регистрации событий, связанных с различными типами данных.
-
SectionEvent -
MediaEvent -
PesEvent -
TsRecordEvent -
MmtpRecordEvent -
TemiEvent -
DownloadEvent -
IpPayloadEvent
Начиная с Android 12 и версии Tuner HAL 1.1 или выше, поддерживаются следующие события.
-
IpCidChangeEvent -
RestartEvent -
ScramblingStatusEvent
События и формат данных из фильтра
| Тип фильтра | Флаги | События | Операция с данными | Формат данных |
|---|---|---|---|---|
TS.SECTIONMMTP.SECTIONIP.SECTIONTLV.SECTIONALP.SECTION | isRaw: | Обязательный:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWРекомендуется: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | В соответствии с расписанием мероприятия и внутренним графиком, запускFilter.read(buffer, offset, adjustedSize) один или несколько раз.Данные копируются из MQ HAL в буфер клиента. | Один собранный пакет материалов для сессии заполняется в FMQ другим пакетом материалов для сессии. |
isRaw: | Обязательный:DemuxFilterEvent::DemuxFilterSectionEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWНеобязательный: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++Данные копируются из MQ HAL в буфер клиента. | ||
TS.PES | isRaw: | Обязательный:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWРекомендуется: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | В соответствии с расписанием мероприятия и внутренним графиком, запускFilter.read(buffer, offset, adjustedSize) один или несколько раз.Данные копируются из буфера MQ HAL в буфер клиента. | Один собранный пакет из полиэфирсульфона (PES) заполняется методом FMQ другим пакетом из полиэфирсульфона (PES). |
isRaw: | Обязательный:DemuxFilterEvent::DemuxFilterPesEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWНеобязательный: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++Данные копируются из MQ HAL в буфер клиента. | ||
MMTP.PES | isRaw: | Обязательный:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWРекомендуется: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | В соответствии с расписанием мероприятия и внутренним графиком, запускFilter.read(buffer, offset, adjustedSize) один или несколько раз.Данные копируются из буфера MQ HAL в буфер клиента. | Один собранный пакет MFU заполняется методом FMQ другим пакетом MFU. |
isRaw: | Обязательный:DemuxFilterEvent::DemuxFilterPesEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWНеобязательный: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++Данные копируются из буфера MQ HAL в буфер клиента. | ||
TS.TS | Н/Д | Обязательный:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWРекомендуется: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | В соответствии с расписанием мероприятия и внутренним графиком, запускFilter.read(buffer, offset, adjustedSize) один или несколько раз.Данные копируются из буфера MQ HAL в буфер клиента. | Отфильтрованы ts с заголовком tsЗаполняется в формате FMQ. |
TS.AudioTS.VideoMMTP.AudioMMTP.Video | isPassthrough: | Необязательный:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW | Клиент может запустить MediaCodec после получения значения DemuxFilterStatus::DATA_READY .Клиент может вызвать Filter.flush после получения значения DemuxFilterStatus::DATA_OVERFLOW . | Н/Д |
isPassthrough: | Обязательный:DemuxFilterEvent::DemuxFilterMediaEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWНеобязательный: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Для использования MediaCodec :for i=0; i<n; i++Для использования функции Direct Audio в AudioTrack :for i=0; i<n; i++ | Данные ES или частичные данные ES в памяти ION. | |
TS.PCRIP.NTPALP.PTP | Н/Д | Обязательно: Нет данных Необязательно: Нет | Н/Д | Н/Д |
TS.RECORD | Н/Д | Обязательный:DemuxFilterEvent::DemuxFilterTsRecordEvent[n]RecordStatus::DATA_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATERНеобязательный: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Для индексных данных:for i=0; i<n; i++Для записанного контента , в соответствии с RecordStatus::* и внутренним расписанием, выполните одно из следующих действий:
| Для индексных данных: передаются в составе полезной нагрузки события. Для записанного контента: смешанный поток TS, заполненный в формате FMQ. |
TS.TEMI | Н/Д | Обязательный:DemuxFilterEvent::DemuxFilterTemiEvent[n]Необязательный: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ | Н/Д |
MMTP.MMTP | Н/Д | Обязательный:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWРекомендуется: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | В соответствии с расписанием мероприятия и внутренним графиком, запускFilter.read(buffer, offset, adjustedSize) один или несколько раз.Данные копируются из буфера MQ HAL в буфер клиента. | Отфильтрованы протоколы mmtp с заголовком mmtpЗаполняется в формате FMQ. |
MMTP.RECORD | Н/Д | Обязательный:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]RecordStatus::DATA_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATERНеобязательный: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Для индексных данных: for i=0; i<n; i++Для записанного контента , в соответствии с RecordStatus::* и внутренним расписанием, выполните одно из следующих действий:
| Для индексных данных: передаются в составе полезной нагрузки события. Для записанного контента: в поле FMQ заполнен смешанный записанный поток. Если источником фильтра для записи является TLV.TLV в IP.IP с сквозной передачей, то записанный поток будет иметь заголовок TLV и IP. |
MMTP.DOWNLOAD | Н/Д | Обязательный:DemuxFilterEvent::DemuxFilterDownloadEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWНеобязательный: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)Данные копируются из MQ HAL в буфер клиента. | Пакет для загрузки заполняется в FMQ другим пакетом для загрузки с IP-адреса. |
IP.IP_PAYLOAD | Н/Д | Обязательный:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWНеобязательный: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)Данные копируются из MQ HAL в буфер клиента. | Пакет полезной нагрузки IP-протокола заполняется в FMQ другим пакетом полезной нагрузки IP-протокола. |
IP.IPTLV.TLVALP.ALP | isPassthrough: | Необязательный:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW | Отфильтрованный протокольный подпоток поступает на следующий фильтр в цепочке фильтров. | Н/Д |
isPassthrough: | Обязательный:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWРекомендуется: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | В соответствии с расписанием мероприятия и внутренним графиком, запускFilter.read(buffer, offset, adjustedSize) один или несколько раз.Данные копируются из буфера MQ HAL в буфер клиента. | Отфильтрованный подпоток протокола с заголовком протокола заполняется в FMQ. | |
IP.PAYLOAD_THROUGHTLV.PAYLOAD_THROUGHALP.PAYLOAD_THROUGH | Н/Д | Необязательный:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW | Отфильтрованная полезная нагрузка протокола поступает в следующий фильтр в цепочке фильтров. | Н/Д |
Пример алгоритма использования фильтра для построения PSI/SI.

Рисунок 10. Поток для построения PSI/SI
Откройте фильтр.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );Настройте и запустите фильтр.
Settings settings = SectionSettingsWithTableInfo .builder(Filter.TYPE_TS) .setTableId(2) .setVersion(1) .setCrcEnabled(true) .setRaw(false) .setRepeat(false) .build(); FilterConfiguration config = TsFilterConfiguration .builder() .setTpid(10) .setSettings(settings) .build(); filter.configure(config); filter.start();Process
SectionEvent.FilterCallback filterCallback = new FilterCallback() { @Override public void onFilterEvent(Filter filter, FilterEvent[] events) { for (FilterEvent event : events) { if (event instanceof SectionEvent) { SectionEvent sectionEvent = (SectionEvent) event; int tableId = sectionEvent.getTableId(); int version = sectionEvent.getVersion(); int dataLength = sectionEvent.getDataLength(); int sectionNumber = sectionEvent.getSectionNumber(); filter.read(buffer, 0, dataLength); } } } };
Пример схемы использования MediaEvent из фильтра.

Рисунок 11. Схема использования MediaEvent из фильтра.
- Откройте, настройте и запустите аудио- и видеофильтры.
- Обработка
MediaEvent. - Получить
MediaEvent. - Поставьте линейный блок в очередь на
codec. - Отпустите дескриптор аудио/видео, когда данные будут израсходованы.
Android.media.tv.tuner.dvr
DvrRecorder предоставляет следующие методы для записи.
-
configure -
attachFilter -
detachFilter -
start -
flush -
stop -
setFileDescriptor -
write
DvrPlayback предоставляет следующие методы для воспроизведения.
-
configure -
start -
flush -
stop -
setFileDescriptor -
read
DvrSettings используется для настройки DvrRecorder и DvrPlayback . OnPlaybackStatusChangedListener и OnRecordStatusChangedListener используются для сообщения о состоянии экземпляра DVR.
Пример последовательности действий для начала записи.

Рисунок 12. Схема начала записи.
Откройте, настройте и запустите
DvrRecorder.DvrRecorder recorder = openDvrRecorder(/* bufferSize */ 1000, executor, listener); DvrSettings dvrSettings = DvrSettings .builder() .setDataFormat(DvrSettings.DATA_FORMAT_TS) .setLowThreshold(100) .setHighThreshold(900) .setPacketSize(188) .build(); recorder.configure(dvrSettings); recorder.attachFilter(filter); recorder.setFileDescriptor(fd); recorder.start();Получите
RecordEventи извлеките информацию об индексе.FilterCallback filterCallback = new FilterCallback() { @Override public void onFilterEvent(Filter filter, FilterEvent[] events) { for (FilterEvent event : events) { if (event instanceof TsRecordEvent) { TsRecordEvent recordEvent = (TsRecordEvent) event; int tsMask = recordEvent.getTsIndexMask(); int scMask = recordEvent.getScIndexMask(); int packetId = recordEvent.getPacketId(); long dataLength = recordEvent.getDataLength(); // handle the masks etc. } } } };Инициализируйте обработчик
OnRecordStatusChangedListenerи сохраните данные записи.OnRecordStatusChangedListener listener = new OnRecordStatusChangedListener() { @Override public void onRecordStatusChanged(int status) { // a customized way to consume data efficiently by using status as a hint. if (status == Filter.STATUS_DATA_READY) { recorder.write(size); } } };
Тюнер HAL
Tuner HAL следует протоколу HIDL и определяет интерфейс между фреймворком и оборудованием поставщика. Поставщики используют этот интерфейс для реализации Tuner HAL, а фреймворк использует его для связи с реализацией Tuner HAL.
Модули
Тюнер HAL 1.0
| Модули | Основные элементы управления | Элементы управления, специфичные для модуля | Файлы HAL |
|---|---|---|---|
ITuner | Н/Д | frontend(open, getIds, getInfo) , openDemux , openDescrambler , openLnb , getDemuxCaps | ITuner.hal |
IFrontend | setCallback , getStatus , close | tune , stopTune , scan , stopScan , setLnb | IFrontend.halIFrontendCallback.hal |
IDemux | close | setFrontendDataSource , openFilter , openDvr , getAvSyncHwId , getAvSyncTime , connect / disconnectCiCam | IDemux.hal |
IDvr | close , start , stop , configure | attach/detachFilters , flush , getQueueDesc | IDvr.halIDvrCallback.hal |
IFilter | close , start , stop , configure , getId | flush , getQueueDesc , releaseAvHandle , setDataSource | IFilter.halIFilterCallback.hal |
ILnb | close , setCallback | setVoltage , setTone , setSatellitePosition , sendDiseqcMessage | ILnb.halILnbCallback.hal |
IDescrambler | close | setDemuxSource , setKeyToken , addPid , removePid | IDescrambler.hal |
Tuner HAL 1.1 (на основе Tuner HAL 1.0)
| Модули | Основные элементы управления | Элементы управления, специфичные для модуля | Файлы HAL |
|---|---|---|---|
ITuner | Н/Д | getFrontendDtmbCapabilities | @1.1::ITuner.hal |
IFrontend | tune_1_1 , scan_1_1 , getStatusExt1_1 | link/unlinkCiCam | @1.1::IFrontend.hal@1.1::IFrontendCallback.hal |
IFilter | getStatusExt1_1 | configureIpCid , configureAvStreamType , getAvSharedHandle , configureMonitorEvent | @1.1::IFilter.hal@1.1::IFilterCallback.hal |

Рисунок 13. Схема взаимодействия между модулями Tuner HAL.
Фильтр связи
Tuner HAL поддерживает связь фильтров, что позволяет связывать фильтры с другими фильтрами для нескольких слоев. Фильтры подчиняются приведенным ниже правилам.
- Фильтры связаны между собой в виде дерева, замыкание путей не допускается.
- Корневой узел — это демультиплексор.
- Фильтры работают независимо друг от друга.
- Все фильтры начинают получать данные.
- Механизм промывки фильтра срабатывает при использовании последнего фильтра.
Приведённый ниже фрагмент кода и рисунок 14 иллюстрируют пример фильтрации нескольких слоёв.
demuxCaps = ITuner.getDemuxCap;
If (demuxCaps[IP][MMTP] == true) {
ipFilter = ITuner.openFilter(<IP, ..>)
mmtpFilter1 = ITuner.openFilter(<MMTP ..>)
mmtpFilter2 = ITuner.openFilter(<MMTP ..>)
mmtpFilter1.setDataSource(<ipFilter>)
mmtpFilter2.setDataSource(<ipFilter>)
}

Рисунок 14. Блок-схема механизма фильтрации для нескольких слоев.
Менеджер ресурсов тюнера
До появления Tuner Resource Manager (TRM) для переключения между двумя приложениями требовалось одно и то же аппаратное обеспечение тюнера. TV Input Framework (TIF) использовал механизм «кто первый получит ресурс, тот и сохранит его». Однако этот механизм может быть не идеальным для некоторых сложных сценариев использования.
TRM работает как системная служба и управляет аппаратными ресурсами тюнера, TVInput и CAS для приложений. TRM использует механизм «победы в фоновом режиме», который вычисляет приоритет приложения на основе его состояния (в фоновом или переднем плане) и типа использования. TRM предоставляет или отзывает ресурс в зависимости от приоритета. TRM централизует управление ресурсами ATV для вещания, OTT и DVR.
интерфейс TRM
TRM предоставляет интерфейсы AIDL в файле ITunerResourceManager.aidl для фреймворка Tuner, MediaCas и TvInputHardwareManager для регистрации, запроса или освобождения ресурсов.
Ниже перечислены интерфейсы для управления клиентами.
-
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId) -
unregisterClientProfile(in int clientId)
Ниже перечислены интерфейсы для запроса и выделения ресурсов.
-
requestFrontend(TunerFrontendRequest request, int[] frontendHandle)/releaseFrontend -
requestDemux(TunerDemuxRequest request, int[] demuxHandle)/releaseDemux -
requestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle)/releaseDescrambler -
requestCasSession(CasSessionRequest request, int[] casSessionHandle)/releaseCasSession -
requestLnb(TunerLnbRequest request, int[] lnbHandle)/releaseLnb
Ниже перечислены классы клиента и запроса.
-
ResourceClientProfile -
ResourcesReclaimListener -
TunerFrontendRequest -
TunerDemuxRequest -
TunerDescramblerRequest -
CasSessionRequest -
TunerLnbRequest
Приоритет клиента
TRM вычисляет приоритет клиента, используя параметры из профиля клиента и значение приоритета из файла конфигурации. Приоритет также может быть обновлен произвольным значением приоритета, предоставленным клиентом.
Параметры в профиле клиента
TRM получает идентификатор процесса из mTvInputSessionId , чтобы определить, является ли приложение активным или фоновым. Для создания mTvInputSessionId TvInputService.onCreateSession или TvInputService.onCreateRecordingSession , которые инициализируют сессию TIS.
mUseCase указывает сценарий использования сессии. Предопределенные сценарии использования перечислены ниже.
TvInputService.PriorityHintUseCaseType {
PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK
PRIORITY_HINT_USE_CASE_TYPE_LIVE
PRIORITY_HINT_USE_CASE_TYPE_RECORD,
PRIORITY_HINT_USE_CASE_TYPE_SCAN,
PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND
}
Файл конфигурации
Файл конфигурации по умолчанию
Приведенный ниже файл конфигурации по умолчанию содержит значения приоритета для предопределенных сценариев использования. Пользователи могут изменить эти значения с помощью настраиваемого файла конфигурации .
| Вариант использования | Передний план | Фон |
|---|---|---|
LIVE | 490 | 400 |
PLAYBACK | 480 | 300 |
RECORD | 600 | 500 |
SCAN | 450 | 200 |
BACKGROUND | 180 | 100 |
Пользовательский файл конфигурации
Производители могут настраивать конфигурационный файл /vendor/etc/tunerResourceManagerUseCaseConfig.xml . Этот файл используется для добавления, удаления или обновления типов вариантов использования и значений приоритета вариантов использования. В качестве шаблона для настраиваемого файла можно использовать platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml .
Например, новый вариант использования поставщика обозначается как VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000] . Формат должен соответствовать файлу platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd .
Произвольное значение приоритета и хорошее значение
TRM предоставляет updateClientPriority позволяющий клиенту обновлять произвольное значение приоритета и значение nice. Произвольное значение приоритета перезаписывает значение приоритета, вычисленное на основе типа варианта использования и идентификатора сессии.
Значение показателя «доброжелательность» указывает на то, насколько снисходительно клиент ведет себя в конфликтных ситуациях с другим клиентом. Значение «доброжелательность» снижает приоритет клиента перед сравнением его приоритета с приоритетом клиента, создающего конфликт.
Механизм восстановления
На приведенной ниже диаграмме показано, как происходит высвобождение и распределение ресурсов при возникновении ресурсного конфликта.

Рисунок 15. Схема механизма восстановления при конфликте между ресурсами тюнера.