Framework CAS

O framework de sistemas de acesso condicional de mídia (Media CAS) fornece APIs padrão para ativar serviços de acesso condicional (CA, na sigla em inglês) em uma variedade de hardware de TV digital, incluindo sistemas digitais a cabo, por satélite, terrestres e IPTV. O framework funciona com o framework de entrada do Android TV e o framework do sintonizador do Android TV, fornecendo APIs Java invocadas pelo app de entrada de TV (TIS).

Os principais objetivos do Media CAS são os seguintes.

  • Fornecer uma API Java pública e um framework de plug-in nativo que podem ser usados por desenvolvedores terceirizados e OEMs para oferecer suporte ao CAS para TV de transmissão no Android.
  • Fornecer um framework de CAS no Android que permita a interoperabilidade de OEMs de ATV com vários fornecedores de CAS de maneira consistente.
  • Oferece suporte a vários fornecedores de CAS de terceiros usando plug-ins nativos. Os plug-ins do CAS podem usar protocolos de rede específicos do fornecedor, formatos de mensagem de gerenciamento de direitos (EMM)/mensagem de controle de direitos (ECM) e descriptografadores.
  • Oferecer suporte à segurança de hardware, como escadas de chaves.
  • Ofereça suporte a ambientes de execução confiáveis (TEEs), como o TrustZone.

Configurações compatíveis

Configuração do sintonizador de hardware

Se o hardware for responsável pela desmultiplexação e da decodificação de stream de transporte MPEG, o framework Tuner fornece dados de informações específicas do programa de acesso condicional (PSI, na sigla em inglês) ao app TIS para interagir com sintonizadores de TV baseados em hardware.

Os dados de PSI de acesso condicional incluem descrições de CA, ECMs e EMMs. Essas estruturas permitem que o plug-in do CAS obtenha as chaves necessárias para descriptografar os fluxos de conteúdo.

Diagrama da configuração do sintonizador de hardware.

Figura 1. Configuração do sintonizador de hardware

A configuração de hardware pode ter uma camada TEE, como o TrustZone, ilustrado na Figura 1. Se não houver uma camada TEE, um plug-in de cliente CAS poderá se comunicar com os serviços de escada de chaves de hardware fornecidos pela plataforma. Devido a variações específicas do fornecedor dessas interfaces, o Media CAS não as padroniza.

Configuração de software

Antes do Android 11, o framework Media CAS ainda podia ser usado para processar conteúdo baseado em software, como IPTV de IP multicast/unicast. O app TIS é responsável por instanciar e provisionar corretamente o objeto Java do Media CAS.

O app pode usar o MediaExtractor ou outros analisadores MPEG2-TS para extrair dados de PSI relacionados à CA, como descritores de CA, ECMs e EMMs. Se o app usar o framework MediaExtractor, ele poderá delegar o gerenciamento de sessão do CAS, como abrir uma sessão e processar EMM/ECM, ao framework MediaExtractor. O MediaExtractor configura a sessão do CAS diretamente usando a API nativa.

Caso contrário, o app será responsável por extrair os dados PSI relacionados à CA e configurar a sessão do CAS usando as APIs Java do Media CAS (por exemplo, quando o app usa o próprio analisador MPEG2-TS).

Diagrama da configuração do sintonizador.

Figura 2. Entrada de IPTV, CAS e configuração do decodificador usando o framework MediaExtractor

No cenário do extrator de software, o extrator requer um objeto de decodificador baseado em software ou hardware para cada faixa embaralhada, independente de a faixa exigir decodificadores seguros. Isso ocorre devido ao seguinte:

  • Se a faixa não exigir uma decodificação segura, o extrator descriptografa a unidade de acesso para limpar os buffers e extrai amostras como se fossem de um stream claro. Dessa forma, MediaCodec não precisa estar envolvido na decodificação.
  • Se a faixa exigir uma decodificação segura, o extrator ainda precisará de um decodificador. Isso acontece quando o fluxo de transporte é embaralhado no nível do pacote de transporte, em que o cabeçalho do fluxo elementar em pacotes (PES, na sigla em inglês) é embaralhado. O extrator precisa acessar o cabeçalho PES para downstream de determinadas informações (por exemplo, o carimbo de data/hora da apresentação).

    O desembaralhador não será usado pelo extrator se o fluxo de transporte for embaralhado no nível do pacote PES, em que o cabeçalho PES está livre. No entanto, não é possível confirmar quando a embaralhamento acontece até que o pacote embaralhado real chegue. Para simplificar, suponha que um desembaralhador seja usado se a faixa for determinada como embaralhada com base na tabela de mapeamento do programa (PMT, na sigla em inglês).

Limitações da configuração de software

Quando a faixa exige uma decodificação segura, o desembaralhador precisa ter cuidado ao permitir que uma operação de decodificação em buffers claros seja feito. Como a decodificação de áudio não segura é necessária, se a decodificação de vídeo exigir decodificadores seguros, ela precisará ser codificada em uma sessão diferente do áudio. O ECM da sessão precisa sinalizar ao plug-in que um decodificador seguro é necessário.

Como alternativa, o plug-in precisa vincular de forma confiável uma chave à política de segurança. Caso contrário, o app pode conseguir frames de vídeo facilmente com o descrambador de áudio.

Mesmo quando a sessão exige um decodificador seguro, ela pode ser solicitada a gerar uma pequena quantidade de dados para limpar buffers pelo extrator para processar o cabeçalho PES. Para evitar que um app malicioso faça o plug-in retornar toda a unidade de acesso, o plug-in precisa analisar o payload de transporte para garantir que o payload comece com um cabeçalho PES do tipo de stream adequado. Caso contrário, o plug-in vai negar a solicitação.

Sequência de ajuste de CA

Ao sintonizar um novo canal, o módulo TIS se registra para receber descritores de CA, ECMs e EMMs do framework do PSI Tuner. Um descritor de AC contém o ID do sistema de AC, que identifica exclusivamente um fornecedor de AC específico e outros dados específicos do fornecedor. O TIS consulta o CAS de mídia para determinar se existe um plug-in de CAS que possa processar o descritor de AC.

Diagrama de como ajustar o conteúdo do CAS.

Figura 3. Como ajustar o conteúdo do CAS

Se o ID do sistema de AC for aceito, uma instância do Media CAS será criada e os dados privados do fornecedor do descritor de AC serão fornecidos ao plug-in. Em seguida, novas sessões são abertas no Media CAS para gerenciar os streams de áudio e vídeo. As sessões recém-abertas recebem ECMs e EMMs para o plug-in.

Exemplo de fluxo do plug-in do CAS

O TIS envia ECMs para o plug-in CAS usando as APIs Media CAS. Um ECM contém a palavra de controle criptografada, que precisa ser descriptografada usando informações de um EMM. O plug-in CAS determina como adquirir um EMM para o recurso com base nas informações específicas do fornecedor no descritor da CA, que é fornecido pelo método setPrivateData().

Os EMMs podem ser enviados na banda no stream de conteúdo ou fora da banda usando uma solicitação de rede iniciada pelo plug-in de CA. O TIS usa o método processEMM() para enviar EMMs na banda ao plug-in da CA.

Se uma solicitação de rede for necessária para receber um EMM, o plug-in da CA será responsável por executar a transação de rede com um servidor de licença.

Diagrama de um exemplo de CAS.

Figura 4. Exemplo de plug-in CAS para processamento de EMM e ECM

Quando o EMM é recebido, o plug-in da CA o analisa para conseguir a chave criptografada e descriptografar a palavra de controle. A chave de EMM criptografada e a palavra de controle criptografada podem ser carregadas em uma escada de chaves ou em um ambiente confiável para executar a descriptografia da palavra de controle e a decodificação subsequente do stream de conteúdo.

API Java Media CAS

A API Media CAS Java contém os seguintes métodos.

  • Lista todos os plug-ins de assinaturas digitais disponíveis no dispositivo.

    class MediaCas.PluginDescriptor {
      public String getName();
      public int getSystemId();
    }
    static PluginDescriptor[] enumeratePlugins();
    
  • Crie uma instância do Media CAS para o sistema de AC especificado. Isso significa que o framework do Media CAS pode lidar com vários sistemas CAS simultaneamente.

    MediaCas(int CA_system_id);
    MediaCas(@NonNull Context context, int casSystemId,
             @Nullable String tvInputServiceSessionId,
             @PriorityHintUseCaseType int priorityHint);
    
  • Registre um listener de eventos e permita que o app especifique um gerenciador cujo looper seja usado.

    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);
    
  • Envie os dados particulares para o sistema de AC. Os dados particulares podem vir do descritor de AC, da tabela de acesso condicional ou de fontes fora da banda. Isso não está associado a uma sessão específica.

    void setPrivateData(@NonNull byte[] data);
    
  • Processar um pacote EMM.

    void processEmm(@NonNull byte[] data, int offset, int length);
    
  • Enviar um evento para um sistema de CA. O formato do evento é específico do esquema e opaco para o framework.

    void sendEvent(int event, int arg, @Nullable byte[] data);
    
  • Inicia uma operação de provisionamento do tipo especificado para um sistema de AC. Quando um dispositivo se inscreve em um serviço de TV paga pela primeira vez, ele precisa ser provisionado para o servidor de CAS. Forneça um conjunto de parâmetros relacionados ao dispositivo para provisionamento.

    void provision(String provisionString);
    
  • Acionar uma atualização de direitos. Quando um usuário se inscreve em um novo canal (por exemplo, respondendo a um anúncio ou adicionando um canal ao guia de programação eletrônica (EPG, na sigla em inglês), na sigla em inglês), o app precisa solicitar que os clientes da CA atualizem as chaves de direitos.

    void refreshEntitlements(int refreshType);
    
  • Feche o objeto CAS de mídia.

    void close();
    
  • Abra uma sessão.

    Session openSession();
    Session openSession(@SessionUsage int sessionUsage, @ScramblingMode int scramblingMode);
    
  • Feche uma sessão aberta anteriormente.

    void Session#close();
    
  • Forneça os dados privados da AC de um descritor de AC no PMT, que pode ser da seção de informações do programa ou da ES, para uma sessão de CAS.

    void Session#setPrivateData(@NonNull byte[] sessionId, @NonNull byte[] data);
    
  • processar um pacote de ECM para uma sessão;

    void Session#processEcm(@NonNull byte[] data, int offset, int length);
    
  • Receba o ID da sessão.

    byte[] Session#getSessionId();
    
  • Enviar um evento de sessão para um sistema de CA. O formato do evento é específico para o esquema e é opaco para o framework.

    void Session#sendSessionEvent(int event, int arg, @Nullable byte[] data);