El marco de trabajo de sistemas de acceso condicional multimedia (Media CAS) proporciona APIs estándar para habilitar servicios de acceso condicional (CA) en una variedad de hardware de TV digital, incluidos sistemas de cable digital, satelitales, terrestres y de IPTV. El framework funciona con el framework de entrada de Android TV y el framework de sintonizador de Android TV, y proporciona APIs de Java que se invocan desde la app de TV Input Service (TIS).
Los principales objetivos de Media CAS son los siguientes:
- Proporcionar una API pública de Java y un marco de trabajo de complementos nativos que los desarrolladores externos y los OEM puedan usar para admitir CAS para la TV por transmisión en Android
- Proporcionar un marco de trabajo de CAS en Android que permita a los OEM de ATV interoperar con una variedad de proveedores de CAS de manera coherente
- Admite varios proveedores de CAS externos con complementos nativos. Es posible que los complementos de CAS usen protocolos de red específicos del proveedor, formatos de mensajes de administración de derechos (EMM) o de mensajes de control de derechos (ECM), y descodificadores.
- Admitir la seguridad del hardware, como las cadenas de claves
- Admitir entornos de ejecución confiables (TEE), como TrustZone
Configuraciones admitidas
Configuración del sintonizador de hardware
Si el hardware es responsable de la demultiplexación y el descifrado del flujo de transporte MPEG, el framework de Tuner proporciona datos de la información específica del programa (PSI) de acceso condicional a la app de TIS para interactuar con los sintonizadores de TV basados en hardware.
Los datos del PSI de acceso condicional incluyen descriptores de CA, ECM y EMM. Estas estructuras permiten que el complemento del CAS obtenga las claves necesarias para desencriptar los flujos de contenido.
Figura 1: Configuración del sintonizador de hardware
La configuración de hardware puede tener una capa de TEE, como TrustZone, que se ilustra en la Figura 1. Si no hay una capa de TEE, un complemento de cliente de CAS puede comunicarse con los servicios de la cadena de claves de hardware que proporciona la plataforma. Debido a las variaciones específicas del proveedor de estas interfaces, Media CAS no las estandariza.
Configuración del software
Antes de Android 11, el framework de Media CAS aún se podía usar para procesar contenido basado en software, como IPTV de multidifusión o unidifusión IP. La app de TIS es responsable de crear instancias y aprovisionar correctamente el objeto Java de Media CAS.
Es posible que la app use MediaExtractor o algún otro analizador de MPEG2-TS para extraer datos de PSI relacionados con la CA, como descriptores de CA, ECM y EMM. Si la app usa el framework MediaExtractor, puede delegar la administración de la sesión de CAS, como la apertura de una sesión y el procesamiento de EMM/ECM, en el framework MediaExtractor. Luego, MediaExtractor configura la sesión de CAS directamente con la API nativa.
De lo contrario, la app es responsable de extraer los datos de PSI relacionados con la CA y configurar la sesión del CAS con las APIs de Java de Media CAS (por ejemplo, cuando la app usa su propio analizador de MPEG2-TS).
Figura 2: Configuración de entrada de IPTV, CAS y decodificador con el framework MediaExtractor
En el caso del extractor de software, este requiere un objeto de decodificador basado en software o hardware para cada pista codificada, independientemente de si la pista requiere decodificadores seguros. Esto se debe a lo siguiente:
- Si el segmento no requiere decodificación segura, el extractor descifra la unidad de acceso para borrar los búferes y extrae muestras como si se tratara de una transmisión clara. De esta manera,
MediaCodec
no necesita participar en el proceso de descifrado. Si el segmento requiere decodificación segura, es posible que el extractor aún necesite un decodificador. Esto sucede cuando el flujo de transporte se codifica a nivel del paquete de transporte, en el que se codifica el encabezado del flujo elemental empaquetado (PES). El extractor necesita acceder al encabezado del PES para transmitir cierta información a los sistemas posteriores (por ejemplo, la marca de tiempo de presentación).
El extractor no usa el decodificador si el flujo de transporte está codificado a nivel del paquete PES, en el que el encabezado PES se deja sin codificar. Sin embargo, no es posible confirmar cuándo se produce la codificación hasta que llega el paquete codificado real. Para simplificar, supón que se usa un decodificador si se determina que la pista está codificada según la tabla de asignación de programas (PMT).
Limitaciones de la configuración del software
Cuando el segmento requiere una decodificación segura, el decodificador debe tener cuidado al permitir que una operación de decodificación ingrese a los búferes claros. Dado que se requiere una decodificación de audio no segura, si la decodificación de video requiere decodificadores seguros, se debe codificar en una sesión diferente de la de audio. El ECM de la sesión debe indicarle al complemento que se requiere un decodificador seguro.
Como alternativa, el complemento debe poder vincular de forma confiable una clave a su política de seguridad. De lo contrario, la app puede obtener fácilmente fotogramas de video con el decodificador de audio.
Incluso cuando la sesión requiere un decodificador seguro, es posible que se le solicite que genere una pequeña cantidad de datos para borrar los búferes del extractor y procesar el encabezado PES. Para evitar que una app maliciosa haga que el complemento devuelva toda la unidad de acceso, el complemento debe analizar la carga útil de transporte para garantizar que esta comience con un encabezado PES del tipo de transmisión adecuado. De lo contrario, el complemento debe rechazar la solicitud.
Secuencia de ajuste de la CA
Cuando se sintoniza un canal nuevo, el módulo de TIS se registra para recibir descriptores de CA, ECM y EMM del framework de PSI Tuner. Un descriptor de AC contiene el ID del sistema de la AC, que identifica de forma única a un proveedor de AC específico y otros datos específicos del proveedor. TIS consulta el CAS de medios para determinar si existe un complemento de CAS que pueda controlar el descriptor de la CA.
Figura 3: Ajusta el contenido del CAS
Si se admite el ID del sistema de la CA, se crea una instancia de Media CAS y se proporcionan al complemento los datos privados del proveedor del descriptor de la CA. Luego, se abren sesiones nuevas en Media CAS para controlar los flujos de audio y video. Las sesiones recién abiertas reciben ECM y EMM para el complemento.
Flujo de ejemplo del complemento de CAS
El TIS entrega ECM al complemento de CAS a través de las APIs de Media CAS. Un ECM contiene la palabra de control encriptada, que debe desencriptarse con la información de un EMM. El complemento de CAS determina cómo adquirir un EMM para el activo según la información específica del proveedor en el descriptor de CA, que proporciona el método setPrivateData()
.
Los EMM se pueden entregar en banda en el flujo de contenido o fuera de banda a través de una solicitud de red iniciada por el complemento de la CA. El TIS usa el método processEMM()
para entregar cualquier EMM dentro de la banda al complemento de CA.
Si se requiere una solicitud de red para obtener un EMM, el complemento de la CA es responsable de realizar la transacción de red con un servidor de licencias.
Figura 4: Ejemplo de un complemento de CAS para el procesamiento de EMM y ECM
Cuando se recibe el EMM, el complemento de la CA lo analiza para obtener la clave encriptada y desencriptar la palabra de control. La clave de EMM encriptada y la palabra de control encriptada se pueden cargar en una jerarquía de claves o en un entorno de confianza para realizar la desencriptación de la palabra de control y la posterior decodificación de la transmisión de contenido.
API de Java de Media CAS
La API de Media CAS de Java contiene los siguientes métodos.
Enumera todos los complementos de CA disponibles en el dispositivo.
class MediaCas.PluginDescriptor { public String getName(); public int getSystemId(); } static PluginDescriptor[] enumeratePlugins();
Construye una instancia de Media CAS para el sistema de CA especificado. Esto significa que el framework de Media CAS puede controlar varios sistemas de CAS de forma simultánea.
MediaCas(int CA_system_id); MediaCas(@NonNull Context context, int casSystemId, @Nullable String tvInputServiceSessionId, @PriorityHintUseCaseType int priorityHint);
Registra un objeto de escucha de eventos y permite que la app especifique un controlador cuyo bucle se use.
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);
Envía los datos privados para el sistema de la CA. Los datos privados pueden provenir del descriptor de la CA, la tabla de acceso condicional o fuentes fuera de banda. No está asociado a una sesión en particular.
void setPrivateData(@NonNull byte[] data);
Procesa un paquete de EMM.
void processEmm(@NonNull byte[] data, int offset, int length);
Envía un evento a un sistema de CA. El formato del evento es específico del esquema y opaco para el framework.
void sendEvent(int event, int arg, @Nullable byte[] data);
Inicia una operación de aprovisionamiento del tipo especificado para un sistema de CA. Cuando un dispositivo se registra en un servicio de TV de pago por primera vez, primero debe aprovisionarse en el servidor de CAS. Proporciona un conjunto de parámetros relacionados al dispositivo para el aprovisionamiento.
void provision(String provisionString);
Activa una actualización de los derechos. Cuando un usuario se suscribe a un canal nuevo (por ejemplo, cuando responde a un anuncio o agrega un canal en la guía electrónica de programas [EPG]), la app debe poder indicarles a los clientes de la CA que actualicen las claves de derechos.
void refreshEntitlements(int refreshType);
Cierra el objeto Media CAS.
void close();
Abre una sesión.
Session openSession(); Session openSession(@SessionUsage int sessionUsage, @ScramblingMode int scramblingMode);
Cierra una sesión abierta anteriormente.
void Session#close();
Proporciona los datos privados de la CA desde un descriptor de CA en la PMT, que puede provenir de la sección de información del programa o de información del ES, a una sesión de CAS.
void Session#setPrivateData(@NonNull byte[] sessionId, @NonNull byte[] data);
Procesa un paquete de ECM para una sesión.
void Session#processEcm(@NonNull byte[] data, int offset, int length);
Obtén el ID de sesión.
byte[] Session#getSessionId();
Envía un evento de sesión a un sistema de CA. El formato del evento es específico del esquema y es opaco para el framework.
void Session#sendSessionEvent(int event, int arg, @Nullable byte[] data);