Il framework dei sistemi di accesso condizionale ai contenuti multimediali (Media CAS) fornisce API standard per abilitare i servizi di accesso condizionale (CA) su una serie di hardware TV digitale, inclusi sistemi via cavo digitale, satellitari, terrestri e IPTV. Il framework funziona con il framework di input TV Android e framework di sintonizzatore TV Android, fornendo API Java richiamate dall'app TV Input Service (TIS).
Di seguito sono riportati i principali obiettivi di Media CAS.
- Fornire un'API Java pubblica e un framework di plug-in nativo che possono essere utilizzati da sviluppatori di terze parti e OEM per supportare CAS per la TV via etere su Android.
- Fornire un framework CAS all'interno di Android che consenta agli OEM ATV di interagire con una varietà di fornitori CAS in modo coerente.
- Supportare più fornitori CAS di terze parti utilizzando plug-in nativi. I plug-in CAS potrebbero utilizzare protocolli di rete specifici del fornitore, formati di messaggi di gestione dei diritti (EMM)/messaggi di controllo dei diritti (ECM) e decodificatori.
- Supportare la sicurezza hardware, ad esempio le scale di chiavi.
- Supportare gli ambienti di esecuzione affidabili (TEE), come TrustZone.
Configurazioni supportate
Configurazione del sintonizzatore hardware
Se l'hardware è responsabile della demultiplexing dello stream di trasporto MPEG e della decodifica, il framework del sintonizzatore fornisce i dati delle informazioni specifiche del programma (PSI) di accesso condizionale all' app TIS per interfacciarsi con i sintonizzatori TV basati su hardware.
I dati PSI di accesso condizionale includono descrittori CA, ECM ed EMM. Queste strutture consentono al plug-in CAS di ottenere le chiavi necessarie per decriptare gli stream di contenuti.
Figura 1. Configurazione del sintonizzatore hardware
La configurazione hardware potrebbe avere un livello TEE, come TrustZone, illustrato nella Figura 1. Se non è presente un livello TEE, un plug-in client CAS può comunicare con i servizi di scale di chiavi hardware forniti dalla piattaforma. A causa delle variazioni specifiche del fornitore di queste interfacce, Media CAS non le standardizza.
Configurazione software
Prima di Android 11, il framework Media CAS poteva comunque essere utilizzato per elaborare contenuti basati su software, come IPTV da multicast/unicast IP. L'app TIS è responsabile dell'istanza e del provisioning corretto dell'oggetto Java Media CAS.
L'app potrebbe utilizzare MediaExtractor o altri parser MPEG2-TS per estrarre i dati PSI relativi a CA, come descrittori CA, ECM ed EMM. Se l'app utilizza il framework MediaExtractor, può delegare la gestione delle sessioni CAS, ad esempio l'apertura di una sessione e l'elaborazione di EMM/ECM, al framework MediaExtractor. MediaExtractor configura quindi la sessione CAS utilizzando direttamente l'API nativa.
In caso contrario, l'app è responsabile dell'estrazione dei dati PSI relativi a CA e della configurazione della sessione CAS utilizzando le API Java Media CAS (ad esempio, quando l'app utilizza il proprio parser MPEG2-TS).
Figura 2. Configurazione di input IPTV, CAS e decodificatore utilizzando il framework MediaExtractor
Nello scenario dell'estrattore software, l'estrattore richiede un oggetto decodificatore basato su software o hardware per ogni traccia codificata, indipendentemente dal fatto che la traccia richieda decodificatori sicuri. Questo è dovuto a quanto segue.
- Se la traccia non richiede la decodifica sicura, l'estrattore decodifica l'unità di accesso per cancellare i buffer ed estrae i campioni come se provenissero da uno stream chiaro. In questo modo,
MediaCodecnon deve essere coinvolto nella decodifica. Se la traccia richiede la decodifica sicura, l'estrattore potrebbe comunque aver bisogno di un decodificatore. Ciò si verifica quando lo stream di trasporto viene codificato a livello di pacchetto di trasporto, dove l'intestazione dello stream elementare in pacchetti (PES) è codificata. L'estrattore deve accedere all'intestazione PES per trasmettere alcune informazioni (ad esempio, il timestamp di presentazione).
Il decodificatore non viene utilizzato dall'estrattore se lo stream di trasporto è codificato a livello di pacchetto PES, dove l'intestazione PES viene lasciata chiara. Tuttavia, non è possibile confermare quando si verifica la codifica fino all'arrivo del pacchetto codificato effettivo. Per semplicità, supponi che venga utilizzato un decodificatore se la traccia viene determinata come codificata in base alla tabella di mappatura del programma (PMT).
Limitazioni della configurazione software
Quando la traccia richiede la decodifica sicura, il decodificatore deve prestare attenzione quando consente a un'operazione di decodifica di accedere ai buffer chiari. Poiché è richiesta la decodifica audio non sicura, se la decodifica video richiede decodificatori sicuri, deve essere codificata in una sessione diversa dall'audio. L'ECM per la sessione deve segnalare al plug-in che è necessario un decodificatore sicuro.
In alternativa, il plug-in deve essere in grado di collegare in modo affidabile una chiave alla sua policy di sicurezza. In caso contrario, l'app può ottenere facilmente i frame video con il decodificatore audio.
Anche quando la sessione richiede un decodificatore sicuro, potrebbe essere richiesto di generare una piccola quantità di dati per cancellare i buffer dall'estrattore per elaborare l'intestazione PES. Per impedire a un'app dannosa di far sì che il plug-in restituisca l'intera unità di accesso, il plug-in deve analizzare il payload di trasporto per assicurarsi che il payload inizi con un'intestazione PES del tipo di stream appropriato. In caso contrario, il plug-in deve rifiutare la richiesta.
Sequenza di sintonizzazione CA
Quando si sintonizza un nuovo canale, il modulo TIS si registra per ricevere descrittori CA, ECM ed EMM dal framework PSI Tuner. Un descrittore CA contiene l'ID sistema CA, che identifica in modo univoco un fornitore CA specifico e altri dati specifici del fornitore. TIS esegue una query su Media CAS per determinare se esiste un plug-in CAS in grado di gestire il descrittore CA.
Figura 3. Sintonizzazione dei contenuti CAS
Se l'ID sistema CA è supportato, viene creata un'istanza di Media CAS e i dati privati del fornitore del descrittore CA vengono forniti al plug-in. Vengono quindi aperte nuove sessioni in Media CAS per gestire gli stream audio e video. Le sessioni appena aperte ricevono ECM ed EMM per il plug-in.
Flusso di esempio del plug-in CAS
TIS fornisce ECM al plug-in CAS utilizzando le API Media CAS. Un ECM contiene la parola di controllo codificata, che deve essere decriptata utilizzando le informazioni di un EMM. Il plug-in CAS determina come acquisire un EMM per l'asset in base alle informazioni specifiche del fornitore nel descrittore CA, fornite dal metodo setPrivateData().
Gli EMM possono essere forniti in banda nello stream di contenuti o fuori banda utilizzando una richiesta di rete avviata dal plug-in CA. TIS utilizza il metodo processEMM() per fornire tutti gli EMM in banda al plug-in CA.
Se è necessaria una richiesta di rete per ottenere un EMM, il plug-in CA è responsabile dell'esecuzione della transazione di rete con un server di licenze.
Figura 4. Esempio di plug-in CAS per l'elaborazione di EMM ed ECM
Quando viene ricevuto l'EMM, il plug-in CA lo analizza per ottenere la chiave codificata per decriptare la parola di controllo. La chiave EMM codificata e la parola di controllo codificata potrebbero essere caricate in una scala di chiavi o in un ambiente affidabile per eseguire la decriptazione della parola di controllo e la successiva decodifica dello stream di contenuti.
API Java Media CAS
L'API Java Media CAS contiene i seguenti metodi.
Elenca tutti i plug-in CA disponibili sul dispositivo.
class MediaCas.PluginDescriptor { public String getName(); public int getSystemId(); } static PluginDescriptor[] enumeratePlugins();Costruisci un'istanza Media CAS per il sistema CA specificato. Ciò significa che il framework Media CAS può gestire più sistemi CAS contemporaneamente.
MediaCas(int CA_system_id); MediaCas(@NonNull Context context, int casSystemId, @Nullable String tvInputServiceSessionId, @PriorityHintUseCaseType int priorityHint);Registra un listener di eventi e consenti all'app di specificare un gestore il cui looper viene utilizzato.
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);Invia i dati privati per il sistema CA. I dati privati possono provenire dal descrittore CA, dalla tabella di accesso condizionale o da fonti fuori banda. Non è associato a una sessione specifica.
void setPrivateData(@NonNull byte[] data);Elabora un pacchetto EMM.
void processEmm(@NonNull byte[] data, int offset, int length);Invia un evento a un sistema CA. Il formato dell'evento è specifico per lo schema e opaco per il framework.
void sendEvent(int event, int arg, @Nullable byte[] data);Avvia un'operazione di provisioning del tipo specificato per un sistema CA. Quando un dispositivo si registra per la prima volta a un servizio di pay TV, deve prima essere sottoposto a provisioning sul server CAS. Fornisci al dispositivo un insieme di parametri correlati per il provisioning.
void provision(String provisionString);Attiva un aggiornamento dei diritti. Quando un utente si abbona a un nuovo canale (ad esempio, rispondendo a una pubblicità o aggiungendo un canale alla guida ai programmi elettronica (EPG)), l'app deve essere in grado di indicare ai client CA di aggiornare le chiavi dei diritti.
void refreshEntitlements(int refreshType);Chiudi l'oggetto Media CAS.
void close();Apri una sessione.
Session openSession(); Session openSession(@SessionUsage int sessionUsage, @ScramblingMode int scramblingMode);Chiudi una sessione aperta in precedenza.
void Session#close();Fornisci i dati privati CA da un descrittore CA nel PMT, che può provenire dalla sezione delle informazioni sul programma o delle informazioni ES, a una sessione CAS.
void Session#setPrivateData(@NonNull byte[] sessionId, @NonNull byte[] data);Elabora un pacchetto ECM per una sessione.
void Session#processEcm(@NonNull byte[] data, int offset, int length);Recupera l'ID sessione.
byte[] Session#getSessionId();Invia un evento di sessione a un sistema CA. Il formato dell'evento è specifico per lo schema ed è opaco per il framework.
void Session#sendSessionEvent(int event, int arg, @Nullable byte[] data);