Платформа Media Conditional Access Systems (Media CAS) предоставляет стандартные API для обеспечения работы сервисов условного доступа (CA) на различных цифровых телевизионных устройствах, включая цифровые кабельные, спутниковые, наземные системы и системы IPTV. Платформа работает с платформами Android TV Input и Android TV Tuner , предоставляя Java API, вызываемые из приложения TV Input Service (TIS).
Основные цели Media CAS заключаются в следующем.
- Предоставить общедоступный Java API и собственную платформу для создания плагинов, которые могут использоваться сторонними разработчиками и OEM-производителями для поддержки CAS для трансляции телепередач в Android.
- Предоставить в Android фреймворк CAS, который позволит производителям Apple TV взаимодействовать с различными поставщиками CAS согласованным образом.
- Поддержка нескольких сторонних поставщиков CAS с использованием собственных плагинов. Плагины CAS могут использовать специфичные для поставщика сетевые протоколы, форматы сообщений управления правами доступа (EMM)/сообщений управления правами доступа (ECM) и дешифраторы.
- Поддержка аппаратной безопасности, например, с помощью ключевых лестниц.
- Поддержка доверенных сред выполнения (TEE), таких как TrustZone.
Поддерживаемые конфигурации
Конфигурация аппаратного тюнера
Если аппаратное обеспечение отвечает за демультиплексирование и дескремблирование транспортного потока MPEG, платформа Tuner предоставляет приложению TIS данные о программно-специфической информации (PSI) с условным доступом для взаимодействия с аппаратными ТВ-тюнерами.
Данные условного доступа PSI включают дескрипторы CA, ECM и EMM. Эти структуры позволяют плагину CAS получать ключи, необходимые для расшифровки потоков контента.

Рисунок 1. Конфигурация аппаратного тюнера.
Конфигурация оборудования может включать слой TEE, например TrustZone, как показано на рисунке 1. Если слоя TEE нет, плагин клиента CAS может взаимодействовать со службами аппаратной лестничной диаграммы ключей, предоставляемыми платформой. Из-за различий в этих интерфейсах, специфичных для каждого производителя, Media CAS не стандартизирует их.
Конфигурация программного обеспечения
До Android 11 фреймворк Media CAS можно было использовать для обработки программного контента, например, IPTV из IP-многоадресной/одноадресной рассылки. Приложение TIS отвечает за создание и корректную настройку Java-объекта Media CAS.
Приложение может использовать MediaExtractor или другие парсеры MPEG2-TS для извлечения данных PSI, связанных с CA, таких как дескрипторы CA, ECM и EMM. Если приложение использует фреймворк MediaExtractor, оно может делегировать управление сессиями CAS, например, открытие сессии и обработку EMM/ECM, фреймворку MediaExtractor. Затем MediaExtractor настраивает сессию CAS, используя непосредственно собственный API.
В противном случае приложение отвечает за извлечение данных PSI, связанных с CA, и настройку сессии CAS с использованием Java API Media CAS (например, когда приложение использует собственный парсер MPEG2-TS).

Рисунок 2. Конфигурация входа IPTV, CAS и дескремблера с использованием фреймворка MediaExtractor.
В сценарии с программным извлечением данных, для каждого зашифрованного трека требуется объект дешифратора на основе программного или аппаратного обеспечения, независимо от того, требуются ли для этого трека защищенные декодеры. Это связано со следующими причинами.
- Если для дорожки не требуется безопасное декодирование, экстрактор дешифрует блок доступа, чтобы очистить буферы, и извлекает сэмплы так же, как если бы они были из чистого потока. Таким образом,
MediaCodecне нужно участвовать в дешифровке. Если для передачи данных требуется безопасное декодирование, экстрактору может потребоваться дескремблер. Это происходит, когда транспортный поток шифруется на уровне транспортного пакета, где шифруется заголовок пакетированного элементарного потока (PES). Экстрактору необходимо получить доступ к заголовку PES для передачи определенной информации (например, метки времени представления).
Дескремблёр не используется экстрактором, если транспортный поток шифруется на уровне пакета PES, где заголовок PES остаётся незашифрованным. Однако подтвердить момент шифрования невозможно до тех пор, пока не прибудет фактически зашифрованный пакет. Для простоты предположим, что дескремблёр используется, если шифр определяется как зашифрованный на основе таблицы сопоставления программ (PMT).
Ограничения конфигурации программного обеспечения
Если для дорожки требуется безопасное декодирование, дескремблер должен проявлять осторожность, разрешая операцию дескремблирования в незашифрованные буферы. Поскольку требуется небезопасное декодирование аудио, если для декодирования видео требуются безопасные декодеры, его следует скремблировать в отдельной сессии, отличной от сессии с аудио. ECM для этой сессии должен сообщить плагину о необходимости использования безопасного декодера.
В качестве альтернативы, плагин должен иметь возможность надежно привязать ключ к своей политике безопасности. В противном случае приложение может легко получить видеокадры с помощью дешифратора звука.
Даже если для сеанса требуется безопасный декодер, его могут попросить вывести небольшой объем данных для очистки буферов экстрактором для обработки заголовка PES. Чтобы предотвратить возврат плагином всего блока доступа со стороны вредоносного приложения, плагину необходимо проанализировать транспортную полезную нагрузку, чтобы убедиться, что она начинается с заголовка PES соответствующего типа потока. В противном случае плагин должен отклонить запрос.
Последовательность настройки CA
При переключении на новый канал модуль TIS регистрируется для получения дескрипторов CA, ECM и EMM от платформы PSI Tuner. Дескриптор CA содержит идентификатор системы CA, который однозначно идентифицирует конкретного поставщика CA, а также другие данные, специфичные для этого поставщика. TIS запрашивает у Media CAS информацию о наличии плагина CAS, способного обрабатывать дескриптор CA.

Рисунок 3. Настройка содержания CAS.
Если идентификатор системы CA поддерживается, создается экземпляр Media CAS, и плагину передаются частные данные поставщика из дескриптора CA. Затем в Media CAS открываются новые сессии для обработки аудио- и видеопотоков. Вновь открытые сессии получают ECM и EMM для плагина.
Пример работы плагина CAS
TIS передает ECM-файлы плагину CAS, используя API Media CAS. ECM-файл содержит зашифрованное управляющее слово, которое необходимо расшифровать, используя информацию из EMM-файла. Плагин CAS определяет, как получить EMM-файл для актива, на основе информации, специфичной для поставщика, содержащейся в дескрипторе CA, который предоставляется методом setPrivateData() .
EMM-сообщения могут передаваться внутри полосы пропускания в потоке контента или вне полосы пропускания с помощью сетевого запроса, инициированного плагином CA. TIS использует метод processEMM() для передачи любых внутриполосных EMM-сообщений плагину CA.
Если для получения EMM требуется сетевой запрос, плагин CA отвечает за выполнение сетевой транзакции с сервером лицензий.

Рисунок 4. Пример плагина CAS для обработки EMM и ECM.
После получения EMM-сообщения плагин CA анализирует его для получения зашифрованного ключа, необходимого для расшифровки управляющего слова. Зашифрованный ключ EMM и зашифрованное управляющее слово могут быть загружены в ключевую лестницу или доверенную среду для выполнения расшифровки управляющего слова и последующего дешифрования потока содержимого.
Media CAS Java API
API Media CAS для Java содержит следующие методы.
Перечислите все доступные плагины CA на устройстве.
class MediaCas.PluginDescriptor { public String getName(); public int getSystemId(); } static PluginDescriptor[] enumeratePlugins();Создайте экземпляр Media CAS для указанной системы CA. Это означает, что платформа Media CAS может одновременно обрабатывать несколько систем CAS.
MediaCas(int CA_system_id); MediaCas(@NonNull Context context, int casSystemId, @Nullable String tvInputServiceSessionId, @PriorityHintUseCaseType int priorityHint);Зарегистрируйте обработчик событий и разрешите приложению указать обработчик, для которого будет использоваться цикл обработки событий.
interface MediaCas.EventListener { void onEvent(MediaCas, int event, int arg, byte[] data); void onSessionEvent(@NonNull MediaCas mediaCas, @NonNull Session session, int event, int arg, @Nullable byte[] data); void onPluginStatusUpdate(@NonNull MediaCas mediaCas, @PluginStatus int status, int arg); void onResourceLost(@NonNull MediaCas mediaCas); } void setEventListener(MediaCas.EventListener listener, Handler handler);Отправьте закрытые данные для системы CA. Закрытые данные могут поступать из дескриптора CA, таблицы условного доступа или из внеполосных источников. Они не связаны с конкретной сессией.
void setPrivateData(@NonNull byte[] data);Обработайте пакет EMM.
void processEmm(@NonNull byte[] data, int offset, int length);Отправьте событие в систему центра сертификации. Формат события зависит от конкретной схемы и непрозрачен для используемой платформы.
void sendEvent(int event, int arg, @Nullable byte[] data);Инициируйте операцию инициализации указанного типа для системы CA. Когда устройство впервые подключается к платной телевизионной услуге, ему сначала необходимо пройти инициализацию на сервере CAS. Предоставьте устройству набор соответствующих параметров для инициализации.
void provision(String provisionString);Необходимо инициировать обновление прав доступа. Когда пользователь подписывается на новый канал (например, отвечая на рекламу или добавляя канал в электронную программу передач), приложение должно иметь возможность сообщить клиентам CA о необходимости обновления ключей доступа.
void refreshEntitlements(int refreshType);Закройте объект Media CAS.
void close();Откройте сессию.
Session openSession(); Session openSession(@SessionUsage int sessionUsage, @ScramblingMode int scramblingMode);Закрыть ранее открытую сессию.
void Session#close();Передайте в сессию CAS частные данные центра сертификации (CA) из дескриптора CA в PMT (который может быть взят из раздела информации о программе или информации о ES).
void Session#setPrivateData(@NonNull byte[] sessionId, @NonNull byte[] data);Обработайте пакет ECM для сессии.
void Session#processEcm(@NonNull byte[] data, int offset, int length);Получите идентификатор сессии.
byte[] Session#getSessionId();Отправьте событие сессии в систему центра сертификации. Формат события зависит от конкретной схемы и непрозрачен для используемой платформы.
void Session#sendSessionEvent(int event, int arg, @Nullable byte[] data);