Framework de CAS

El framework 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, satélite, terrestre y IPTV. El framework funciona con el framework de entrada de Android TV y el framework de sintonizador de Android TV, que proporciona APIs de Java que se invocan desde la app del servicio de entrada de TV (TIS).

Los principales objetivos de Media CAS son los siguientes:

  • Proporciona una API de Java pública y un framework de complementos nativos que los desarrolladores externos y los OEMs puedan usar para admitir CAS para la transmisión de TV en Android.
  • Proporciona un framework de CAS dentro de Android que permita a los OEM de ATV interoperar con una variedad de proveedores de CAS de manera coherente.
  • Admite varios proveedores de CAS de terceros con complementos nativos. Los complementos de CAS pueden usar protocolos de red específicos del proveedor, formatos de mensajes de administración de derechos (EMM) o de control de derechos (ECM), y decodificadores.
  • Admite la seguridad de hardware, como las escaleras de claves.
  • Admite 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 descramble de la transmisión de transporte MPEG, el framework de Tuner proporciona datos de información específica del programa (PSI) de acceso condicional a la app de TIS para interactuar con sintonizadores de TV basados en hardware.

Los datos de PSI de acceso condicional incluyen descriptores de AC, ECM y EMM. Estas estructuras permiten que el complemento de CAS obtenga las claves necesarias para desencriptar los flujos de contenido.

Diagrama de la configuración del sintonizador de hardware.

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 escalera de claves de hardware que proporciona la plataforma. Debido a las variaciones específicas de cada proveedor de estas interfaces, Media CAS no las estandariza.

Configuración de software

Antes de Android 11, el framework de Media CAS aún se podía usar para procesar contenido basado en software, como IPTV desde multicast/unicast de IP. La app de TIS es responsable de crear instancias del objeto Java de Media CAS y aprovisionarlo correctamente.

La app puede usar MediaExtractor o algún otro analizador MPEG2-TS para extraer datos de PSI relacionados con la AC, como descriptores de AC, ECM y EMM. Si la app usa el framework MediaExtractor, puede delegar la administración de la sesión de CAS, como abrir una sesión y procesar EMM/ECM, al 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 AC y configurar la sesión de CAS con las APIs de Java de Media CAS (por ejemplo, cuando la app usa su propio analizador MPEG2-TS).

Diagrama de la configuración del sintonizador.

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 descodificador basado en software o hardware para cada pista desordenada, independientemente de si la pista requiere decodificadores seguros. Esto se debe a lo siguiente:

  • Si la pista no requiere decodificación segura, el extractor desencripta la unidad de acceso para borrar los búferes y extraer muestras como si fueran de una transmisión clara. De esta manera, MediaCodec no necesita participar en el desempaquetado.
  • Si la pista requiere una decodificación segura, es posible que el extractor aún necesite un descodificador. Esto sucede cuando la transmisión de transporte se codifica a nivel del paquete de transporte, donde se codifica el encabezado de la transmisión elemental empaquetada (PES). El extractor debe acceder al encabezado de PES para transferir cierta información (por ejemplo, la marca de tiempo de presentación).

    El extractor no usa el descodificador si la transmisión de transporte está desordenada a nivel del paquete PES, donde el encabezado PES queda claro. Sin embargo, no es posible confirmar cuándo se produce la codificación hasta que llega el paquete codificado. Para simplificar, supongamos que se usa un descodificador si se determina que la pista está codificada según la tabla de asignación de programas (PMT).

Limitaciones de la configuración de software

Cuando la pista requiere una decodificación segura, el descodificador debe ser cauto cuando permite que una operación de desencriptación se realice en búferes claros. Debido a 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 a la del 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 descodificador de audio.

Incluso cuando la sesión requiere un decodificador seguro, es posible que el extractor le solicite que genere una pequeña cantidad de datos para borrar los búferes y procesar el encabezado PES. Para evitar que una app maliciosa haga que el complemento muestre toda la unidad de acceso, el complemento debe analizar la carga útil de transporte para garantizar que comience con un encabezado PES del tipo de transmisión adecuado. De lo contrario, el complemento debe rechazar la solicitud.

Secuencia de ajuste de CA

Cuando se sintoniza un canal nuevo, el módulo 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 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 Media para determinar si existe un complemento de CAS que pueda controlar el descriptor de AC.

Diagrama de ajuste del contenido de CAS.

Figura 3: Cómo ajustar el contenido de CAS

Si se admite el ID del sistema de la AC, se crea una instancia del CAS de Media y se proporcionan al complemento los datos privados del proveedor del descriptor de la AC. Luego, se abren sesiones nuevas en Media CAS para controlar las transmisiones de audio y video. Las sesiones recién abiertas reciben ECM y EMM para el complemento.

Ejemplo de flujo del complemento de CAS

TIS entrega ECM al complemento de CAS con las APIs de Media CAS. Un ECM contiene la palabra de control encriptada, que se debe desencriptar con información de un EMM. El complemento CAS determina cómo adquirir un EMM para el recurso según la información específica del proveedor en el descriptor de AC, que proporciona el método setPrivateData().

Los EMM se pueden entregar en banda en el flujo de contenido o fuera de banda mediante una solicitud de red que inicia el complemento de AC. TIS usa el método processEMM() para entregar cualquier EMM en banda al complemento de la AC.

Si se requiere una solicitud de red para obtener un EMM, el complemento de AC es responsable de realizar la transacción de red con un servidor de licencias.

Diagrama de un CAS de ejemplo

Figura 4: Ejemplo de complemento de CAS para el procesamiento de EMM y ECM

Cuando se recibe el EMM, el complemento de AC lo analiza para obtener la clave encriptada y desencriptar la palabra de control. La clave EMM encriptada y la palabra de control encriptada se pueden cargar en una escalera de claves o un entorno de confianza para realizar la desencriptación de la palabra de control y, luego, el desentrelazamiento de la transmisión de contenido.

API de Java de Media CAS

La API de Java de Media CAS contiene los siguientes métodos.

  • Muestra una lista de todos los complementos de AC disponibles en el dispositivo.

    class MediaCas.PluginDescriptor {
      public String getName();
      public int getSystemId();
    }
    static PluginDescriptor[] enumeratePlugins();
    
  • Crea una instancia de Media CAS para el sistema de AC 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 del sistema de la AC. Los datos privados pueden provenir del descriptor de AC, la tabla de acceso condicional o fuentes fuera de banda. No está asociado con 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 AC. El formato del evento es específico para el 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 AC. Cuando un dispositivo se registra en un servicio de TV paga 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 derechos. Cuando un usuario se suscribe a un canal nuevo (por ejemplo, respondiendo a un anuncio o agregando un canal en la guía de programas electrónicos [EPG]), la app debería poder indicarles a los clientes de la AC 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);
    
  • Cerrar una sesión abierta anteriormente

    void Session#close();
    
  • Proporciona los datos privados de la AC desde un descriptor de AC en el PMT, que puede ser de la información del programa o de la sección de información de ES, a una sesión de CAS.

    void Session#setPrivateData(@NonNull byte[] sessionId, @NonNull byte[] data);
    
  • Procesa un paquete ECM para una sesión.

    void Session#processEcm(@NonNull byte[] data, int offset, int length);
    
  • Obtén el ID de la sesión.

    byte[] Session#getSessionId();
    
  • Envía un evento de sesión a un sistema de AC. 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);