Estrutura CAS

A estrutura dos sistemas de acesso condicional de mídia (Media CAS) fornece APIs padrão para permitir serviços de acesso condicional (CA) em uma variedade de hardware de TV digital, incluindo cabo digital, satélite, sistemas terrestres e sistemas de IPTV. A estrutura funciona com a estrutura Android TV Input e a estrutura Android TV Tuner , fornecendo APIs Java invocadas a partir do aplicativo TV Input Service (TIS).

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

  • Fornece uma API Java pública e uma estrutura de plug-in nativa que pode ser usada por desenvolvedores terceirizados e OEMs para oferecer suporte a CAS para transmissão de TV no Android.
  • Forneça uma estrutura CAS no Android que permita que os OEMs de ATV interoperem com vários fornecedores de CAS de maneira consistente.
  • Dê suporte a vários fornecedores de CAS terceirizados usando plug-ins nativos. Os plug-ins 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 decodificadores.
  • Apoie a segurança de hardware, como escadas principais.
  • Dê suporte a ambientes de execução confiáveis ​​(TEEs), como TrustZone.

Configurações suportadas

Configuração do sintonizador de hardware

Se o hardware for responsável pela demultiplexação e decodificação do fluxo de transporte MPEG, a estrutura do Tuner fornece dados PSI (informações específicas do programa) de acesso condicional ao aplicativo TIS para fazer interface com sintonizadores de TV baseados em hardware.

Os dados PSI de acesso condicional incluem descritores de CA, ECMs e EMMs. Essas estruturas permitem que o plugin 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 TrustZone, ilustrada na Figura 1. Se não houver uma camada TEE, um plug-in de cliente CAS pode se comunicar com serviços de lógica ladder de hardware fornecidos pela plataforma. Devido às variações dessas interfaces específicas do fornecedor, o Media CAS não as padroniza.

Configuração de software

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

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

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

Diagrama da configuração do sintonizador.

Figura 2. Configuração de entrada IPTV, CAS e descrambler usando o framework MediaExtractor

No cenário do extrator de software, o extrator requer um objeto descrambler baseado em software ou hardware para cada trilha embaralhada, independentemente de a trilha exigir decodificadores seguros. Isto é devido ao seguinte.

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

    O decodificador não é usado pelo extrator se o fluxo de transporte for embaralhado no nível do pacote PES, onde o cabeçalho PES é deixado em branco. Entretanto, não é possível confirmar quando o embaralhamento acontece até que o pacote embaralhado real chegue. Para simplificar, suponha que um decodificador seja usado se for determinado que a trilha será embaralhada com base na tabela de mapeamento de programa (PMT).

Limitações da configuração do software

Quando a faixa requer decodificação segura, o decodificador precisa ser cauteloso ao permitir uma operação de decodificação em buffers limpos. Como a decodificação de áudio insegura é necessária, se a decodificação de vídeo exigir decodificadores seguros, ela deverá ser embaralhada em uma sessão diferente da de áudio. O ECM da sessão deve sinalizar ao plugin que é necessário um decodificador seguro.

Alternativamente, o plugin deve ser capaz de vincular de forma confiável uma chave à sua política de segurança. Caso contrário, o aplicativo poderá obter facilmente quadros de vídeo com o decodificador de áudio.

Mesmo quando a sessão requer um decodificador seguro, pode ser solicitada a saída de uma pequena quantidade de dados para limpar buffers pelo extrator para processar o cabeçalho PES. Para evitar que um aplicativo malicioso faça o plug-in retornar toda a unidade de acesso, o plug-in precisa analisar a carga de transporte para garantir que a carga comece com um cabeçalho PES do tipo de fluxo apropriado. Caso contrário, o plugin deverá negar a solicitação.

Sequência de ajuste de CA

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

Diagrama de ajuste do conteúdo CAS.

Figura 3. Ajustando o conteúdo CAS

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

Exemplo de fluxo de plug-in CAS

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

Os EMMs podem ser entregues em banda no fluxo de conteúdo ou fora de banda usando uma solicitação de rede iniciada pelo plug-in CA. O TIS usa o método processEMM() para entregar qualquer EMMs em banda ao plugin CA.

Se uma solicitação de rede for necessária para obter um EMM, o plugin CA será responsável por realizar a transação de rede com um servidor de licença.

Diagrama de um exemplo CAS.

Figura 4. Exemplo de plugin CAS para processamento de EMM e ECM

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

API Java CAS de mídia

A API Media CAS Java contém os métodos a seguir.

  • Liste todos os plug-ins de CA disponíveis no dispositivo.

    class MediaCas.PluginDescriptor {
      public String getName();
      public int getSystemId();
    }
    static PluginDescriptor[] enumeratePlugins();
    
  • Construa uma instância do Media CAS para o sistema CA especificado. Isso significa que a estrutura 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 ouvinte de evento e permita que o aplicativo especifique um manipulador cujo looper será 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 privados para o sistema CA. Os dados privados podem vir do descritor CA, da tabela de acesso condicional ou de fontes fora de banda. Isso não está associado a uma sessão específica.

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

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

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

    void provision(String provisionString);
    
  • Acione 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 no guia eletrônico de programação (EPG)), o aplicativo deve ser capaz de informar aos clientes da CA para atualizarem as chaves de autorização.

    void refreshEntitlements(int refreshType);
    
  • Feche o objeto Media CAS.

    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 CA a partir de um descritor de CA no PMT, que pode ser da seção de informações do programa ou da seção de informações ES, para uma sessão CAS.

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

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

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

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