Платформа систем условного доступа к мультимедиа (Media CAS) предоставляет стандартные API-интерфейсы для включения услуг условного доступа (CA) на ряде аппаратных средств цифрового телевидения, включая цифровые кабельные, спутниковые, наземные системы и системы IPTV. Платформа работает с платформой Android TV Input и платформой Android TV Tuner , предоставляя API-интерфейсы Java, вызываемые из приложения TV Input Service (TIS).
Основными задачами Media CAS являются следующие.
- Предоставьте общедоступный API Java и собственную платформу плагинов, которые могут использоваться сторонними разработчиками и OEM-производителями для поддержки CAS для телевещания в Android.
- Предоставьте платформу CAS в Android, которая позволит производителям квадроциклов согласованно взаимодействовать с различными поставщиками CAS.
- Поддержка нескольких сторонних поставщиков CAS с использованием собственных плагинов. Плагины CAS могут использовать сетевые протоколы конкретного поставщика, форматы сообщений управления правами (EMM)/сообщений управления правами (ECM) и дескремблеров.
- Поддержка аппаратной безопасности, такой как ключевые лестницы.
- Поддержка доверенных сред выполнения (TEE), таких как TrustZone.
Поддерживаемые конфигурации
Конфигурация аппаратного тюнера
Если за демультиплексирование и дескремблирование транспортного потока MPEG отвечает оборудование, платформа Tuner предоставляет данные условного доступа к информации о программе (PSI) приложению TIS для взаимодействия с аппаратными ТВ-тюнерами.
Данные 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 processEMM()
для доставки любых внутриполосных сообщений EMM подключаемому центру CA.
Если для получения EMM требуется сетевой запрос, плагин CA отвечает за выполнение сетевой транзакции с сервером лицензий.
Рисунок 4. Пример плагина CAS для обработки EMM и ECM.
Когда EMM получено, плагин CA анализирует его, чтобы получить зашифрованный ключ для расшифровки управляющего слова. Зашифрованный ключ EMM и зашифрованное управляющее слово могут быть загружены в цепочку ключей или доверенную среду для выполнения расшифровки управляющего слова и последующего дескремблирования потока контента.
Медиа CAS Java API
Java API Media CAS содержит следующие методы.
Перечислите все доступные плагины 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);
Отправьте событие в систему CA. Формат мероприятия специфичен для схемы и непрозрачен для структуры.
void sendEvent(int event, int arg, @Nullable byte[] data);
Инициировать операцию подготовки указанного типа для системы CA. Когда устройство впервые регистрируется на услугу платного телевидения, ему необходимо сначала подключиться к серверу CAS. Предоставьте набор связанных параметров устройству для подготовки.
void provision(String provisionString);
Запустить обновление прав. Когда пользователь подписывается на новый канал (например, отвечая на рекламу или добавляя канал в электронную программу передач (EPG)), приложение должно иметь возможность сообщать клиентам 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();
Отправьте событие сеанса в систему CA. Формат мероприятия специфичен для схемы и непрозрачен для структуры.
void Session#sendSessionEvent(int event, int arg, @Nullable byte[] data);