Pour Android 11 ou version ultérieure, vous pouvez utiliser le framework Android Tuner pour diffuser des contenus audio et vidéo. Le framework utilise le pipeline matériel des fournisseurs, ce qui le rend adapté aux SoC bas et haut de gamme. Il fournit un moyen sécurisé de diffuser du contenu A/V protégé par un environnement d'exécution sécurisé (TEE) et un chemin média sécurisé (SMP), ce qui lui permet d'être utilisé dans un environnement de protection de contenu très restreint.
L'interface standardisée entre le tuner et le CAS Android permet une intégration plus rapide entre les fournisseurs de tuner et les fournisseurs de CAS. L'interface Tuner fonctionne avec MediaCodec et AudioTrack pour créer une solution unique pour Android TV.
L'interface Tuner est compatible avec la télévision numérique et analogique, en fonction des principales normes de diffusion.
Composants
Pour Android 11, trois composants sont spécifiquement conçus pour la plate-forme TV.
- Tuner HAL : interface entre le framework et les fournisseurs
- API Tuner SDK : interface entre le framework et les applications
- Gestionnaire de ressources du tuner (TRM) : coordonne les ressources matérielles du tuner.
Pour Android 11, les composants suivants ont été améliorés.
- CAS V2
- TvInputServiceou service d'entrée TV (TIS, TV Input Service)
- TvInputManagerServiceou TV Input Manager Service (TIMS)
- MediaCodecou codec multimédia
- AudioTrackou une piste audio
- MediaResourceManagerou gestionnaire de ressources multimédias (MRM)
 
 
Figure 1 : Interactions entre les composants Android TV
Fonctionnalités
L'interface est compatible avec les normes DTV ci-dessous.
- ATSC
- ATSC3
- DVB-C/S/T
- ISDB S/S3/T
- Analogique
Le frontend d'Android 12 avec Tuner HAL 1.1 ou version ultérieure est compatible avec la norme DTV ci-dessous.
- DTMB
Demux est compatible avec les protocoles de flux ci-dessous.
- Flux de transport (TS)
- Protocole de transport de contenu multimédia MPEG (MMTP)
- Protocole Internet (IP)
- Type, longueur et valeur (TLV)
- Protocole de couche liaison ATSC (ALP)
Le désembrouilleur est compatible avec les protections de contenu ci-dessous.
- Chemin d'accès sécurisé aux contenus multimédias
- Effacer le chemin multimédia
- Enregistrement local sécurisé
- Lecture locale sécurisée
Les API Tuner sont compatibles avec les cas d'utilisation ci-dessous.
- Analyser
- Live
- Lecture
- Enregistrer
Tuner, MediaCodec et AudioTrack sont compatibles avec les modes de flux de données ci-dessous.
- Charge utile ES avec mémoire tampon claire
- Charge utile ES avec un handle de mémoire sécurisé
- Passthrough
Aspect général
Le HAL du tuner est défini entre le framework Android et le matériel du fournisseur.
- Décrit ce que le framework attend du fournisseur et comment il peut le faire.
- Exporte les fonctionnalités du frontend, du démultiplexeur et du désembrouilleur vers le framework via les interfaces IFrontend,IDemux,IDescrambler,IFilter,IDvretILnb.
- Inclut les fonctions permettant d'intégrer le Tuner HAL à d'autres composants du framework, tels que MediaCodecetAudioTrack.
Une classe Java Tuner et une classe native sont créées.
- L'API Java Tuner permet aux applications d'accéder à la couche HAL Tuner via des API publiques.
- La classe native permet de contrôler les autorisations et de gérer de grandes quantités de données d'enregistrement ou de lecture avec le HAL du tuner.
- Le module Native Tuner sert de passerelle entre la classe Tuner Java et le HAL Tuner.
Une classe TRM est créée.
- Gère les ressources limitées du tuner, telles que le frontend, le LNB, les sessions CAS et un périphérique d'entrée TV à partir du HAL d'entrée TV.
- Applique des règles pour récupérer les ressources insuffisantes des applications. La règle par défaut est la victoire au premier plan.
Le CAS média et le CAS HAL sont améliorés avec les fonctionnalités ci-dessous.
- Ouvre des sessions CAS pour différents usages et algorithmes.
- Compatible avec les systèmes CAS dynamiques, tels que l'insertion et la suppression de CICAM.
- S'intègre à Tuner HAL en fournissant des jetons clés.
MediaCodec et AudioTrack sont améliorés grâce aux fonctionnalités ci-dessous.
- Utilise la mémoire A/V sécurisée comme entrée de contenu.
- Configuré pour effectuer la synchronisation matérielle audio/vidéo lors de la lecture en tunnel.
- Prise en charge configurée pour ES_payloadet le mode Passthrough.
 
 
Figure 2. Schéma des composants du HAL du tuner
Workflow global
Les schémas ci-dessous illustrent les séquences d'appels pour la lecture de diffusions en direct.
Configuration
 
 
Figure 3. Séquence de configuration pour la lecture d'une diffusion en direct
Gestion de l'audio et de la vidéo
 
 
Figure 4. Gestion de l'audio et de la vidéo pour la lecture des diffusions en direct
Gérer les contenus brouillés
 
 
Figure 5. Gérer le contenu brouillé pour la lecture de diffusions en direct
Traitement des données audio et vidéo
 
 
Figure 6. Traitement de l'audio et de la vidéo pour la lecture d'une diffusion en direct
API du SDK Tuner
L'API Tuner SDK gère les interactions avec Tuner JNI, Tuner HAL et TunerResourceManager. L'application TIS utilise l'API Tuner SDK pour accéder aux ressources et sous-composants Tuner, tels que le filtre et le désembrouilleur. Les composants frontend et demux sont internes.
 
 
Figure 7. Interactions avec l'API Tuner SDK
Versions
À partir d'Android 12, l'API Tuner SDK est compatible avec la nouvelle fonctionnalité de Tuner HAL 1.1, qui est une mise à niveau rétrocompatible de Tuner 1.0.
Utilisez l'API suivante pour vérifier la version HAL en cours d'exécution.
- android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
La version HAL minimale requise est indiquée dans la documentation des nouvelles API Android 12.
Packages
L'API Tuner SDK fournit les quatre packages ci-dessous.
- android.media.tv.tuner
- android.media.tv.tuner.frontend
- android.media.tv.tuner.filter
- android.media.tv.tuner.dvr
 
 
Figure 8. Packages de l'API Tuner SDK
Android.media.tv.tuner
Le package Tuner est un point d'entrée pour utiliser le framework Tuner. L'application TIS utilise le package pour initialiser et acquérir des instances de ressources en spécifiant le paramètre initial et le rappel.
- tuner(): initialise une instance Tuner en spécifiant les paramètres- useCaseet- sessionId.
- tune(): acquiert une ressource frontend et l'ajuste en spécifiant le paramètre- FrontendSetting.
- openFilter(): acquiert une instance de filtre en spécifiant le type de filtre.
- openDvrRecorder(): acquiert une instance d'enregistrement en spécifiant la taille du tampon.
- openDvrPlayback(): acquiert une instance de lecture en spécifiant la taille du tampon.
- openDescrambler(): acquiert une instance de désembrouilleur.
- openLnb(): acquiert une instance LNB interne.
- openLnbByName(): acquiert une instance LNB externe.
- openTimeFilter(): acquiert une instance de filtre temporel.
Le package Tuner fournit des fonctionnalités qui ne sont pas couvertes par les packages de filtre, d'enregistreur vidéo numérique et d'interface. Les fonctionnalités sont listées ci-dessous.
- cancelTuning
- scan/- cancelScanning
- getAvSyncHwId
- getAvSyncTime
- connectCiCam1/- disconnectCiCam
- shareFrontendFromTuner
- updateResourcePriority
- setOnTuneEventListener
- setResourceLostListener
Android.media.tv.tuner.frontend
Le package frontend inclut des ensembles de paramètres, d'informations, d'états, d'événements et de fonctionnalités liés au frontend.
Classes
FrontendSettings est dérivé pour différentes normes DTV par les classes ci-dessous.
- AnalogFrontendSettings
- Atsc3FrontendSettings
- AtscFrontendSettings
- DvbcFrontendSettings
- DvbsFrontendSettings
- DvbtFrontendSettings
- Isdbs3FrontendSettings
- IsdbsFrontendSettings
- IsdbtFrontendSettings
À partir d'Android 12 avec Tuner HAL 1.1 ou version ultérieure, la norme DTV suivante est prise en charge.
- DtmbFrontendSettings
FrontendCapabilities est dérivé pour différentes normes de TVN par les classes ci-dessous.
- AnalogFrontendCapabilities
- Atsc3FrontendCapabilities
- AtscFrontendCapabilities
- DvbcFrontendCapabilities
- DvbsFrontendCapabilities
- DvbtFrontendCapabilities
- Isdbs3FrontendCapabilities
- IsdbsFrontendCapabilities
- IsdbtFrontendCapabilities
À partir d'Android 12 avec Tuner HAL 1.1 ou version ultérieure, la norme DTV suivante est prise en charge.
- DtmbFrontendCapabilities
FrontendInfo récupère les informations de l'interface.
FrontendStatus récupère l'état actuel de l'interface utilisateur.
OnTuneEventListener écoute les événements sur le frontend.
L'application TIS utilise ScanCallback pour traiter les messages d'analyse provenant de l'interface utilisateur.
Recherche de chaînes
Pour configurer un téléviseur, l'application recherche les fréquences disponibles et crée une liste de chaînes auxquelles les utilisateurs peuvent accéder. TIS peut utiliser Tuner.tune, Tuner.scan(BLIND_SCAN) ou Tuner.scan(AUTO_SCAN) pour effectuer l'analyse des chaînes.
Si le TIS dispose d'informations de diffusion précises pour le signal, telles que la fréquence, la norme (par exemple, T/T2, S/S2) et d'autres informations nécessaires (par exemple, l'ID PLD), Tuner.tune est recommandé, car il s'agit de l'option la plus rapide.
Lorsque l'utilisateur appelle Tuner.tune, les actions suivantes se produisent :
- TIS remplit FrontendSettingsavec les informations requises à l'aide deTuner.tune.
- Le HAL signale les messages de réglage LOCKEDsi le signal est verrouillé.
- TIS utilise Frontend.getStatuspour collecter les informations nécessaires.
- Le TIS passe à la fréquence disponible suivante dans sa liste de fréquences.
TIS appelle Tuner.tune à nouveau jusqu'à ce que toutes les fréquences soient épuisées.
Pendant le réglage, vous pouvez appeler stopTune() ou close() pour mettre en pause ou mettre fin à l'appel Tuner.tune.
Tuner.scan(AUTO_SCAN)
Si TIS ne dispose pas de suffisamment d'informations pour utiliser Tuner.tune, mais qu'il possède une liste de fréquences et un type standard (par exemple, DVB T/C/S), Tuner.scan(AUTO_SCAN) est recommandé.
Lorsque l'utilisateur appelle Tuner.scan(AUTO_SCAN), les actions suivantes se produisent :
- TIS utilise - Tuner.scan(AUTO_SCAN)avec- FrontendSettingsrempli de fréquence.
- L'analyse HAL signale les messages - LOCKEDsi le signal est verrouillé. Le HAL peut également signaler d'autres messages d'analyse pour fournir des informations supplémentaires sur le signal.
- TIS utilise - Frontend.getStatuspour collecter les informations nécessaires.
- TIS appelle - Tuner.scanpour que HAL passe au paramètre suivant sur la même fréquence. Si la structure- FrontendSettingsest vide, la HAL utilise le prochain paramètre disponible. Sinon, HAL utilise- FrontendSettingspour une analyse unique et envoie- ENDpour indiquer que l'opération d'analyse est terminée.
- TIS répète les actions ci-dessus jusqu'à ce que tous les paramètres de la fréquence soient épuisés. 
- Le HAL envoie - ENDpour indiquer que l'opération d'analyse est terminée.
- Le TIS passe à la fréquence disponible suivante dans sa liste de fréquences. 
TIS appelle Tuner.scan(AUTO_SCAN) à nouveau jusqu'à ce que toutes les fréquences soient épuisées.
Pendant l'analyse, vous pouvez appeler stopScan() ou close() pour la mettre en pause ou l'arrêter.
Tuner.scan(BLIND_SCAN)
Si TIS ne dispose pas d'une liste de fréquences et que le HAL du fournisseur peut rechercher la fréquence du frontend spécifié par l'utilisateur pour obtenir la ressource de frontend, Tuner.scan(BLIND_SCAN) est recommandé.
- TIS utilise Tuner.scan(BLIND_SCAN). Une fréquence peut être spécifiée dansFrontendSettingspour la fréquence de démarrage, mais TIS ignore les autres paramètres deFrontendSettings.
- Le HAL signale un message d'analyse LOCKEDsi le signal est verrouillé.
- TIS utilise Frontend.getStatuspour collecter les informations nécessaires.
- TIS appelle Tuner.scanà nouveau pour poursuivre l'analyse. (FrontendSettingsest ignoré.)
- TIS répète les actions ci-dessus jusqu'à ce que tous les paramètres de la fréquence soient épuisés. La fréquence HAL augmente sans qu'aucune action ne soit requise de la part de TIS.
Le HAL indique PROGRESS.
TIS appelle Tuner.scan(AUTO_SCAN) à nouveau jusqu'à ce que toutes les fréquences soient épuisées.
Le HAL signale END pour indiquer que l'opération d'analyse est terminée.
Pendant l'analyse, vous pouvez appeler stopScan() ou close() pour la mettre en pause ou l'arrêter.
 
 
Figure 9. Schéma du flux d'une analyse TIS
Android.media.tv.tuner.filter
Le package de filtres est une collection d'opérations de filtrage avec la configuration, les paramètres, les rappels et les événements. Le package inclut les opérations ci-dessous. Pour obtenir la liste complète des opérations, consultez le code source Android.
- configure()
- start()
- stop()
- flush()
- read()
Pour obtenir la liste complète, consultez le code source Android.
FilterConfiguration est dérivé des classes ci-dessous. Les configurations concernent le type de filtre principal et spécifient le protocole utilisé par le filtre pour extraire les données.
- AlpFilterConfiguration
- IpFilterConfiguration
- MmtpFilterConfiguration
- TlvFilterConfiguration
- TsFilterConfiguration
Les paramètres sont dérivés des classes ci-dessous. Les paramètres concernent le sous-type de filtre et spécifient les types de données que le filtre peut exclure.
- SectionSettings
- AvSettings
- PesSettings
- RecordSettings
- DownloadSettings
FilterEvent est dérivé des classes ci-dessous pour signaler les événements pour différents types de données.
- SectionEvent
- MediaEvent
- PesEvent
- TsRecordEvent
- MmtpRecordEvent
- TemiEvent
- DownloadEvent
- IpPayloadEvent
À partir d'Android 12 avec Tuner HAL 1.1 ou version ultérieure, les événements suivants sont acceptés.
- IpCidChangeEvent
- RestartEvent
- ScramblingStatusEvent
Événements et format de données du filtre
| Type de filtre | Drapeaux | Événements | Opération de données | Format des données | 
|---|---|---|---|---|
| TS.SECTIONMMTP.SECTIONIP.SECTIONTLV.SECTIONALP.SECTION | isRaw: | Obligatoire : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWRecommandé : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Selon l'événement et le calendrier interne, exécutez Filter.read(buffer, offset, adjustedSize)une ou plusieurs
        fois.Les données sont copiées du MQ de HAL dans le tampon client. | Un package de session assemblé est complété dans FMQ par un autre package de session. | 
| isRaw: | Obligatoire : DemuxFilterEvent::DemuxFilterSectionEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWFacultatif : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++Les données sont copiées du MQ de HAL dans le tampon client. | ||
| TS.PES | isRaw: | Obligatoire : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWRecommandé : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Selon l'événement et le calendrier interne, exécutez Filter.read(buffer, offset, adjustedSize)une ou plusieurs
        fois.Les données sont copiées du MQ du HAL dans le tampon client. | Un package PES assemblé est rempli dans FMQ par un autre package PES. | 
| isRaw: | Obligatoire : DemuxFilterEvent::DemuxFilterPesEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWFacultatif : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++Les données sont copiées du MQ de HAL dans le tampon client. | ||
| MMTP.PES | isRaw: | Obligatoire : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWRecommandé : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Selon l'événement et le calendrier interne, exécutez Filter.read(buffer, offset, adjustedSize)une ou plusieurs
        fois.Les données sont copiées du MQ du HAL dans le tampon client. | Un package MFU assemblé est rempli dans FMQ par un autre package MFU. | 
| isRaw: | Obligatoire : DemuxFilterEvent::DemuxFilterPesEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWFacultatif : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++Les données sont copiées du MQ du HAL dans le tampon client. | ||
| TS.TS | N/A | Obligatoire : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWRecommandé : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Selon l'événement et le calendrier interne, exécutez Filter.read(buffer, offset, adjustedSize)une ou plusieurs
        fois.Les données sont copiées du MQ du HAL dans le tampon client. | tsfiltré avec l'en-têtetsest renseigné dans FMQ. | 
| TS.AudioTS.VideoMMTP.AudioMMTP.Video | isPassthrough: | Facultatif : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW | Le client peut commencer MediaCodecaprès avoir reçuDemuxFilterStatus::DATA_READY.Le client peut appeler Filter.flushaprès avoir reçuDemuxFilterStatus::DATA_OVERFLOW. | N/A | 
| isPassthrough: | Obligatoire : DemuxFilterEvent::DemuxFilterMediaEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWFacultatif : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Pour utiliser MediaCodec:for i=0; i<n; i++Pour utiliser l'audio direct de AudioTrack:for i=0; i<n; i++ | Données ES ou ES partielles dans la mémoire ION. | |
| TS.PCRIP.NTPALP.PTP | N/A | Obligatoire : N/A Facultatif : N/A | N/A | N/A | 
| TS.RECORD | N/A | Obligatoire :  DemuxFilterEvent::DemuxFilterTsRecordEvent[n]RecordStatus::DATA_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATERFacultatif : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Pour les données d'index : for i=0; i<n; i++Pour le contenu enregistré, selon RecordStatus::*et le calendrier interne, effectuez l'une des opérations suivantes :
 | Pour les données d'index : elles sont incluses dans la charge utile de l'événement. Pour les contenus enregistrés : flux TS multiplexé renseigné dans FMQ. | 
| TS.TEMI | N/A | Obligatoire : DemuxFilterEvent::DemuxFilterTemiEvent[n]Facultatif : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++ | N/A | 
| MMTP.MMTP | N/A | Obligatoire : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWRecommandé : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Selon l'événement et le calendrier interne, exécutez Filter.read(buffer, offset, adjustedSize)une ou plusieurs
        fois.Les données sont copiées du MQ du HAL dans le tampon client. | mmtpfiltré avec l'en-têtemmtpest renseigné dans FMQ. | 
| MMTP.RECORD | N/A | Obligatoire : DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]RecordStatus::DATA_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATERFacultatif : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Pour les données d'index :  for i=0; i<n; i++Pour le contenu enregistré, selon RecordStatus::*et le calendrier interne, procédez comme suit :
 | Pour les données d'index : elles sont incluses dans la charge utile de l'événement. Pour les contenus enregistrés : flux enregistré multiplexé renseigné dans la FMQ. Si la source de filtre pour l'enregistrement est définie sur TLV.TLVàIP.IPavec transmission directe, le flux enregistré comporte un en-tête TLV et IP. | 
| MMTP.DOWNLOAD | N/A | Obligatoire : DemuxFilterEvent::DemuxFilterDownloadEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWFacultatif : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++
        Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)Les données sont copiées du MQ de HAL dans le tampon client. | Le package de téléchargement est renseigné dans FMQ par un autre package de téléchargement d'adresse IP. | 
| IP.IP_PAYLOAD | N/A | Obligatoire : DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWFacultatif : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | for i=0; i<n; i++
        Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)Les données sont copiées du MQ de HAL dans le tampon client. | Le package de charge utile IP est rempli dans FMQ par un autre package de charge utile IP. | 
| IP.IPTLV.TLVALP.ALP | isPassthrough: | Facultatif : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW | Le flux de sous-flux de protocole filtré alimente le filtre suivant dans la chaîne de filtres. | N/A | 
| isPassthrough: | Obligatoire : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWRecommandé : DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER | Selon l'événement et le calendrier interne, exécutez Filter.read(buffer, offset, adjustedSize)une ou plusieurs
        fois.Les données sont copiées du MQ du HAL dans le tampon client. | Le sous-flux de protocole filtré avec l'en-tête de protocole est rempli dans la FMQ. | |
| IP.PAYLOAD_THROUGHTLV.PAYLOAD_THROUGHALP.PAYLOAD_THROUGH | N/A | Facultatif : DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW | La charge utile du protocole filtrée alimente le filtre suivant dans la chaîne de filtres. | N/A | 
Exemple de flux pour utiliser un filtre afin de créer des PSI/SI
 
 
Figure 10. Flux de création de PSI/SI
- Ouvrez un filtre. - Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );
- Configurez et démarrez le filtre. - Settings settings = SectionSettingsWithTableInfo .builder(Filter.TYPE_TS) .setTableId(2) .setVersion(1) .setCrcEnabled(true) .setRaw(false) .setRepeat(false) .build(); FilterConfiguration config = TsFilterConfiguration .builder() .setTpid(10) .setSettings(settings) .build(); filter.configure(config); filter.start();
- Traitement de - SectionEvent.- FilterCallback filterCallback = new FilterCallback() { @Override public void onFilterEvent(Filter filter, FilterEvent[] events) { for (FilterEvent event : events) { if (event instanceof SectionEvent) { SectionEvent sectionEvent = (SectionEvent) event; int tableId = sectionEvent.getTableId(); int version = sectionEvent.getVersion(); int dataLength = sectionEvent.getDataLength(); int sectionNumber = sectionEvent.getSectionNumber(); filter.read(buffer, 0, dataLength); } } } };
Exemple de flux pour utiliser MediaEvent à partir d'un filtre
 
 
Figure 11 : Flux permettant d'utiliser MediaEvent à partir du filtre
- Ouvrez, configurez et démarrez les filtres audio et vidéo.
- Traitement de MediaEvent.
- Recevez MediaEvent.
- Mettez le bloc linéaire en file d'attente sur codec.
- Libérez le handle A/V lorsque les données ont été consommées.
Android.media.tv.tuner.dvr
DvrRecorder fournit ces méthodes d'enregistrement.
- configure
- attachFilter
- detachFilter
- start
- flush
- stop
- setFileDescriptor
- write
DvrPlayback fournit ces méthodes pour la lecture.
- configure
- start
- flush
- stop
- setFileDescriptor
- read
DvrSettings permet de configurer DvrRecorder et DvrPlayback.
OnPlaybackStatusChangedListener et OnRecordStatusChangedListener sont utilisés pour signaler l'état d'une instance DVR.
Exemple de flux pour démarrer un enregistrement
 
 
Figure 12. Flux pour démarrer un enregistrement
- Ouvrez, configurez et démarrez - DvrRecorder.- DvrRecorder recorder = openDvrRecorder(/* bufferSize */ 1000, executor, listener); DvrSettings dvrSettings = DvrSettings .builder() .setDataFormat(DvrSettings.DATA_FORMAT_TS) .setLowThreshold(100) .setHighThreshold(900) .setPacketSize(188) .build(); recorder.configure(dvrSettings); recorder.attachFilter(filter); recorder.setFileDescriptor(fd); recorder.start();
- Recevez - RecordEventet récupérez les informations sur l'index.- FilterCallback filterCallback = new FilterCallback() { @Override public void onFilterEvent(Filter filter, FilterEvent[] events) { for (FilterEvent event : events) { if (event instanceof TsRecordEvent) { TsRecordEvent recordEvent = (TsRecordEvent) event; int tsMask = recordEvent.getTsIndexMask(); int scMask = recordEvent.getScIndexMask(); int packetId = recordEvent.getPacketId(); long dataLength = recordEvent.getDataLength(); // handle the masks etc. } } } };
- Initialisez - OnRecordStatusChangedListeneret stockez les données d'enregistrement.- OnRecordStatusChangedListener listener = new OnRecordStatusChangedListener() { @Override public void onRecordStatusChanged(int status) { // a customized way to consume data efficiently by using status as a hint. if (status == Filter.STATUS_DATA_READY) { recorder.write(size); } } };
Tuner HAL
Le HAL du tuner suit HIDL et définit l'interface entre le framework et le matériel du fournisseur. Les fournisseurs utilisent l'interface pour implémenter la HAL du tuner, et le framework l'utilise pour communiquer avec l'implémentation de la HAL du tuner.
Modules
Tuner HAL 1.0
| Modules | Commandes de base | Contrôles spécifiques aux modules | Fichiers HAL | 
|---|---|---|---|
| ITuner | N/A | frontend(open, getIds, getInfo),openDemux,openDescrambler,openLnb,getDemuxCaps | ITuner.hal | 
| IFrontend | setCallback,getStatus,close | tune,stopTune,scan,stopScan,setLnb | IFrontend.halIFrontendCallback.hal | 
| IDemux | close | setFrontendDataSource,openFilter,openDvr,getAvSyncHwId,getAvSyncTime,connect/disconnectCiCam | IDemux.hal | 
| IDvr | close,start,stop,configure | attach/detachFilters,flush,getQueueDesc | IDvr.halIDvrCallback.hal | 
| IFilter | close,start,stop,configure,getId | flush,getQueueDesc,releaseAvHandle,setDataSource | IFilter.halIFilterCallback.hal | 
| ILnb | close,setCallback | setVoltage,setTone,setSatellitePosition,sendDiseqcMessage | ILnb.halILnbCallback.hal | 
| IDescrambler | close | setDemuxSource,setKeyToken,addPid,removePid | IDescrambler.hal | 
Tuner HAL 1.1 (dérivé de Tuner HAL 1.0)
| Modules | Commandes de base | Contrôles spécifiques aux modules | Fichiers HAL | 
|---|---|---|---|
| ITuner | N/A | getFrontendDtmbCapabilities | @1.1::ITuner.hal | 
| IFrontend | tune_1_1,scan_1_1,getStatusExt1_1 | link/unlinkCiCam | @1.1::IFrontend.hal@1.1::IFrontendCallback.hal | 
| IFilter | getStatusExt1_1 | configureIpCid,configureAvStreamType,getAvSharedHandle,configureMonitorEvent | @1.1::IFilter.hal@1.1::IFilterCallback.hal | 
 
 
Figure 13. Diagramme des interactions entre les modules Tuner HAL
Association de filtres
Le HAL du tuner prend en charge la liaison de filtres de sorte que les filtres puissent être liés à d'autres filtres pour plusieurs couches. Les filtres suivent les règles ci-dessous.
- Les filtres sont associés sous forme d'arborescence. Les chemins fermés ne sont pas autorisés.
- Le nœud racine est "demux".
- Les filtres fonctionnent indépendamment.
- Tous les filtres commencent à obtenir des données.
- La liaison de filtre est vidée sur le dernier filtre.
Le bloc de code ci-dessous et la figure 14 illustrent un exemple de filtrage de plusieurs calques.
demuxCaps = ITuner.getDemuxCap;
If (demuxCaps[IP][MMTP] == true) {
        ipFilter = ITuner.openFilter(<IP, ..>)
        mmtpFilter1 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter2 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter1.setDataSource(<ipFilter>)
        mmtpFilter2.setDataSource(<ipFilter>)
}
 
 
Figure 14. Diagramme de flux d'une liaison de filtre pour plusieurs couches
Tuner Resource Manager
Avant le gestionnaire de ressources Tuner (TRM), le passage d'une application à une autre nécessitait le même matériel Tuner. Le framework TV Input (TIF) utilisait un mécanisme de "premier arrivé, premier servi", ce qui signifie que l'application qui obtient la ressource en premier la conserve. Toutefois, ce mécanisme peut ne pas être idéal pour certains cas d'utilisation complexes.
TRM s'exécute en tant que service système pour gérer les ressources matérielles du tuner, de TVInput et du CAS pour les applications. TRM utilise un mécanisme de "gain au premier plan", qui calcule la priorité de l'application en fonction de son état (au premier plan ou en arrière-plan) et du type de cas d'utilisation. Le TRM accorde ou révoque la ressource en fonction de la priorité. TRM centralise la gestion des ressources ATV pour la diffusion, l'OTT et le DVR.
Interface TRM
TRM expose les interfaces AIDL dans ITunerResourceManager.aidl pour le framework Tuner, MediaCas et TvInputHardwareManager afin d'enregistrer, de demander ou de libérer des ressources.
Les interfaces de gestion des clients sont listées ci-dessous.
- registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
- unregisterClientProfile(in int clientId)
Les interfaces permettant de demander et de libérer des ressources sont listées ci-dessous.
- requestFrontend(TunerFrontendRequest request, int[] frontendHandle)/- releaseFrontend
- requestDemux(TunerDemuxRequest request, int[] demuxHandle)/- releaseDemux
- requestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle)/- releaseDescrambler
- requestCasSession(CasSessionRequest request, int[] casSessionHandle)/- releaseCasSession
- requestLnb(TunerLnbRequest request, int[] lnbHandle)/- releaseLnb
Les classes de client et de requête sont listées ci-dessous.
- ResourceClientProfile
- ResourcesReclaimListener
- TunerFrontendRequest
- TunerDemuxRequest
- TunerDescramblerRequest
- CasSessionRequest
- TunerLnbRequest
Priorité du client
TRM calcule la priorité du client à l'aide des paramètres du profil du client et de la valeur de priorité du fichier de configuration. La priorité peut également être mise à jour par une valeur de priorité arbitraire du client.
Paramètres du profil du client
TRM récupère l'ID de processus à partir de mTvInputSessionId pour déterminer si une application est une application de premier plan ou d'arrière-plan. Pour créer mTvInputSessionId, TvInputService.onCreateSession ou TvInputService.onCreateRecordingSession, une session TIS est initialisée.
mUseCase indique le cas d'utilisation de la session. Les cas d'utilisation prédéfinis sont listés ci-dessous.
TvInputService.PriorityHintUseCaseType  {
  PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK
  PRIORITY_HINT_USE_CASE_TYPE_LIVE
  PRIORITY_HINT_USE_CASE_TYPE_RECORD,
  PRIORITY_HINT_USE_CASE_TYPE_SCAN,
  PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND
}
Fichier de configuration
Fichier de configuration par défaut
Le fichier de configuration par défaut ci-dessous fournit des valeurs de priorité pour les cas d'utilisation prédéfinis. Les utilisateurs peuvent modifier les valeurs à l'aide d'un fichier de configuration personnalisé.
| Cas d'utilisation | Premier plan | Arrière-plan | 
|---|---|---|
| LIVE | 490 | 400 | 
| PLAYBACK | 480 | 300 | 
| RECORD | 600 | 500 | 
| SCAN | 450 | 200 | 
| BACKGROUND | 180 | 100 | 
Fichier de configuration personnalisé
Les fournisseurs peuvent personnaliser le fichier de configuration /vendor/etc/tunerResourceManagerUseCaseConfig.xml. Ce fichier permet d'ajouter, de supprimer ou de modifier les types de cas d'utilisation et les valeurs de priorité des cas d'utilisation.
Le fichier personnalisé peut utiliser platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml comme modèle.
Par exemple, un nouveau cas d'utilisation du fournisseur est VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000].
Le format doit être platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd.
Valeur de priorité arbitraire et valeur nice
Le TRM fournit updateClientPriority au client pour qu'il puisse mettre à jour la valeur de priorité arbitraire et la valeur nice.
La valeur de priorité arbitraire remplace celle calculée à partir du type de cas d'utilisation et de l'ID de session.
La valeur "nice" indique la tolérance du comportement du client lorsqu'il est en conflit avec un autre client. La valeur nice diminue la valeur de priorité du client avant que celle-ci ne soit comparée à celle du client difficile.
Mécanisme de récupération
Le schéma ci-dessous montre comment les ressources sont récupérées et attribuées en cas de conflit de ressources.
 
 
Figure 15. Schéma du mécanisme de récupération en cas de conflit entre les ressources du tuner
