Cette page explique comment implémenter la radio aux niveaux matériel et logiciel.
- Les composants du système illustrent et décrivent la pile technologique radio.
- La couche d'abstraction matérielle (HAL) de diffusion radio fournit des structures de données et des interfaces permettant aux OEM de mettre en œuvre la radio de diffusion telle que la radio AM/FM et la radio de diffusion audio numérique (DAB) au niveau matériel.
- La mise en œuvre du contrôle radio est basée sur
MediaSession
etMediaBrowse
, qui permettent aux applications multimédias et d'assistant vocal de contrôler la radio. En plus du contenu fourni ci-dessous, consultez Créer des applications multimédias pour les voitures .
Composants du système
La pile radio de diffusion comprend les composants suivants.
Application de référence radio
Pour plus de détails sur la façon d'implémenter le contrôle radio, voir Implémentation du contrôle radio .
Un exemple d'application radio Java ( packages/apps/Car/Radio
) sert d'implémentation de référence. Lorsque le service d'application démarre, il demande à Radio Manager d'ouvrir un tuner radio. Ensuite, l'application peut envoyer des demandes au tuner radio, telles que la syntonisation d'une station de radio, d'une fréquence spécifique ou la recherche de la prochaine station de radio disponible. L'application reçoit des mises à jour du Radio Manager et du Tuner Radio dans Radio, telles que les informations sur le programme actuel, les listes de programmes radio, les configurations et les paramètres définis par le fournisseur. L'application Radio de référence prend uniquement en charge la radio AM et FM. Les constructeurs OEM peuvent modifier ou remplacer l'application Radio à leur guise.
Responsable radio
Lorsque l'application demande à Radio Manager d'ouvrir un tuner, Radio Manager ( frameworks/base/core/java/android/hardware/radio/RadioManager.java
) demande au service Broadcast Radio d'ouvrir une session Tuner, puis enveloppe la session dans un Radio Tuner ( frameworks/base/core/java/android/hardware/radio/RadioTuner.java
), qui est renvoyé à l'application. Le tuner radio définit des API (telles que le réglage, le pas et l'annulation) qui peuvent être appelées à partir d'applications radio et envoyer des requêtes au service de radio de diffusion. Les méthodes de rappel ( RadioTuner.Callback
) définies dans Radio Tuner envoient des mises à jour sur la radio diffusée HAL, telles que les informations sur le programme actuel, les listes de programmes et les paramètres définis par le fournisseur, du service de radio de diffusion aux applications.
Service de radiodiffusion
Le service Broadcast Radio ( frameworks/base/services/core/java/com/android/server/broadcastradio
) est le service client de Broadcast Radio HAL. Le service de radio de diffusion coordonne plusieurs gestionnaires de radio avec les HAL de radio de diffusion. Le service de diffusion radio prend en charge les HAL de diffusion radio en langage HAL (HIDL) et en langage de définition d'interface Android (AIDL) . Le service de diffusion radio est lié au AIDL HAL lorsqu'un service AIDL HAL existe ; sinon, le service est lié au HIDL HAL. Le service de diffusion radio crée un module radio pour chaque instance HAL disponible (telle que AM, FM et DAB).
Chaque Manager Radio peut demander au Service Broadcast Radio de créer une session tuner sur le Module Radio correspondant, en fonction du type de radio. Chaque session de tuner peut appeler des méthodes, telles que tune, step et Cancel (définies dans les interfaces HAL) pour effectuer des opérations sur l'instance HAL de radio de diffusion correspondante. Lorsqu'une session de tuner reçoit un rappel de l'instance HAL sur une mise à jour HAL, telle que les informations sur le programme actuel, la liste des programmes, les indicateurs de configuration et les paramètres du fournisseur, les rappels concernant la mise à jour sont envoyés à tous les tuners radio liés au même module radio.
Diffusion radio HAL
Pour en savoir plus sur les interfaces HIDL et AIDL de la radio de diffusion et les différences entre les deux, consultez Interface HAL de radio de diffusion .
Couche d'abstraction du matériel radio de diffusion
Les sections suivantes décrivent comment utiliser la couche d'abstraction matérielle (HAL) pour implémenter la diffusion radio.
Interface de diffusion radio HAL
Le Broadcast radio HAL fournit des structures de données et des interfaces au niveau matériel pour mettre en œuvre la radio de diffusion, telle que la radio AM/FM et DAB.
Interfaces HIDL 2.0 et AIDL
La radio de diffusion HAL utilise les interfaces décrites dans les sections suivantes.
- Écouteur d'annonce
- Fermer la poignée
- Interface de rappel
- Interface HAL de radio de diffusion principale
Écouteur d'annonce
IAnnouncementListener
est l'interface de rappel pour l'auditeur d'annonces, qui peut être enregistrée sur la radio diffusée HAL pour recevoir des annonces. L'interface dispose des méthodes suivantes :
IAnnonceÉcouteur | ||
---|---|---|
Description : Appelé chaque fois que la liste des annonces a changé. | ||
HIDL2.0 | oneway onListUpdated(vec<Announcement> announcements) | |
AIDL | oneway void onListUpdated(in Announcement[] announcements) |
Fermer la poignée
ICloseHandle
est le handle de fermeture générique permettant de supprimer un rappel qui n'a pas besoin d'une interface active.
ICloseHandle | ||
---|---|---|
Description : Fermez la poignée. | ||
HIDL2.0 | close() | |
AIDL | void close() |
Interface de rappel
ITunerCallback
est l'interface de rappel appelée par la radio de diffusion HAL pour envoyer des mises à jour au service client HAL.
ITunerCallback | ||
---|---|---|
Description : appelé par HAL lorsqu'une opération de réglage (réglage, recherche (en AIDL) ou analyse (en HIDL) et étape réussit) échoue de manière asynchrone. | ||
HIDL2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Description : Appelé lorsque le réglage, la recherche (en AIDL) ou l'analyse (en HIDL) ou l'étape réussissent. | ||
HIDL2.0 | oneway onTuneFailed(Result result, ProgramSelector selector) | |
AIDL | void onTuneFailed(in Result result, in ProgramSelector selector) | |
Description : Appelé lorsque le réglage, la recherche (en AIDL) ou l'analyse (en HIDL) ou l'étape réussissent. | ||
HIDL2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Description : Appelé lorsque la liste des programmes est mise à jour ; la taille de chaque morceau doit être limitée à 500 Ko. | ||
HIDL2.0 | oneway onProgramListUpdated(ProgramListChunk chunk) | |
AIDL | oneway onProgramListUpdated(ProgramListChunk chunk) | |
Description : Appelé lorsque l'antenne est connectée ou déconnectée. | ||
HIDL2.0 | oneway onAntennaStateChange(bool connected) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Description : appelé lorsque les valeurs des paramètres spécifiques au fournisseur sont mises à jour en interne dans HAL (ne doit pas être invoqué après l'appel de setParameters par le client HAL). | ||
HIDL2.0 | oneway onParametersUpdated(vec<VendorKeyValue> parameters) | |
AIDL | void onParametersUpdated(in VendorKeyValue[] parameters) | |
Description : Nouveau dans AIDL. Appelé lorsque l'indicateur de configuration est mis à jour en interne dans HAL (ne doit pas être invoqué après l'appel setConfigFlag par le client HAL). | ||
HIDL2.0 | N'est pas applicable. | |
AIDL | void onConfigFlagUpdated(in ConfigFlag flag, in boolean value) |
Interface HAL de radio de diffusion principale
IBroadcastRadio
est l'interface principale pour la diffusion radio HAL. Dans le HAL HIDL 2.0, utilisez l'interface ITunerSession
avec le tuner pour appeler des opérations. Cependant, au plus un tuner est actif à la fois (à condition que chaque instance HAL de radio diffusée ne dispose que d'une seule puce de tuner). ITunerSession
a été supprimé des interfaces AIDL et ses interfaces ont été déplacées vers IBroadcastRadio
.
IBroadcastRadio | ||
---|---|---|
Description : Obtenez la description d’un module et de ses capacités. | ||
HIDL2.0 | getProperties() generates (Properties properties) | |
AIDL | Properties getProperties() | |
Description : Récupère la configuration actuelle ou possible de la région AM/FM. | ||
HIDL2.0 | getAmFmRegionConfig(bool full) generates (Result result, AmFmRegionConfig config) | |
AIDL | AmFmRegionConfig getAmFmRegionConfig(bool full) | |
Description : récupère la configuration actuelle de la région DAB. | ||
HIDL2.0 | getDabRegionConfig() generates (Result result, vec<DabTableEntry> config) | |
AIDL | DabTableEntry[] getDabRegionConfig() | |
Description : obtient une image du cache du module radio. Dans AIDL, la taille de l'image doit être inférieure à 1 Mo en raison d'une limite stricte sur le tampon de transaction du classeur. | ||
HIDL2.0 | getImage(uint32_t id) generates (vec<uint8_t> image) | |
AIDL | byte[] getImage(in int id) | |
Description : Enregistre l'écouteur d'annonce. | ||
HIDL2.0 | registerAnnouncementListener(vec<AnnouncementType> enabled,IAnnouncementListener listener) generates (Result result, ICloseHandle closeHandle) | |
AIDL | ICloseHandle registerAnnouncementListener(in IAnnouncementListener listener, in AnnouncementType[] enabled) | |
Description:
| ||
HIDL2.0 | openSession(ITunerCallback callback) génère (Result result, ITunerSession session) | |
AIDL | void setTunerCallback(in ITunerCallback callback) | |
Description:
| ||
HIDL2.0 | close() | |
AIDL | unsetTunerCallback() | |
Description : Permet de syntoniser un programme spécifié. | ||
HIDL2.0 | tune(ProgramSelector program) generates (Result result) | |
AIDL | void tune(in ProgramSelector program) | |
Description : Recherche le prochain programme valide à l' antenne . Pour éviter toute confusion dans AIDL, scan est renommé seek . | ||
HIDL2.0 | scan(bool directionUp, bool skipSubChannel) generates (Result result) | |
AIDL | void seek(in boolean directionUp, in boolean skipSubChannel) | |
Description : Étapes vers le canal adjacent, qui ne peut être occupé par aucun programme. | ||
HIDL2.0 | step(bool directionUp) generates (Result result) | |
AIDL | void step(in boolean directionUp) | |
Description : Annule les opérations de réglage, de balayage (en HIDL) ou de recherche (en AIDL) ou de pas à pas en attente. | ||
HIDL2.0 | cancel() | |
AIDL | void cancel() | |
Description : applique un filtre à la liste des programmes et commence à envoyer des mises à jour de la liste des programmes via le rappel onProgramListUpdated . | ||
HIDL2.0 | startProgramListUpdates(ProgramFilter filter) generates (Result result) | |
AIDL | void startProgramListUpdates(in ProgramFilter filter) | |
Description : Arrête d'envoyer les mises à jour de la liste des programmes. | ||
HIDL2.0 | stopProgramListUpdates() | |
AIDL | void stopProgramListUpdates() | |
Description : récupère le paramètre actuel d'un indicateur de configuration donné. | ||
HIDL2.0 | isConfigFlagSet(ConfigFlag flag) generates (Result result, bool value) | |
AIDL | boolean isConfigFlagSet(in ConfigFlag flag) | |
Description : définit l'indicateur de configuration donné. | ||
HIDL2.0 | setConfigFlag(ConfigFlag flag, bool value) generates (Result result) | |
AIDL | void setConfigFlag(in ConfigFlag flag, boolean value) | |
Description : définit les valeurs des paramètres spécifiques au fournisseur. | ||
HIDL2.0 | setParameters(vec<VendorKeyValue> parameters) génère , (vec<VendorKeyValue> results) | |
AIDL | VendorKeyValue[] setParameters(in VendorKeyValue[] parameters) | |
Description : récupère les valeurs de paramètres spécifiques au fournisseur. | ||
HIDL2.0 | getParameters(vec<string> keys) generates (vec<VendorKeyValue> parameters) | |
AIDL | VendorKeyValue[] getParameters(in String[] keys) |
Clarifications de l'interface
Comportement asynchrone
Étant donné que chaque opération de réglage (par exemple, réglage, analyse (en HIDL) ou recherche (en AIDL) et étape) peut prendre du temps et que le thread ne doit pas être bloqué pendant une longue période, l'opération doit planifier des opérations qui prennent beaucoup de temps. pour se produire plus tard et renvoyer rapidement un statut ou un résultat. Dans le détail, chaque opération doit :
- Annulez toutes les opérations de réglage en attente.
- Vérifiez si l'opération peut être traitée en fonction des entrées de la méthode et de l'état du tuner.
- Planifiez la tâche de réglage, puis renvoyez immédiatement le
Result
(en HIDL) oustatus
(en AIDL). Si leResult
oustatus
estOK
, le rappel du tunertuneFailed
oucurrentProgramInfoChanged
doit être appelé lorsque la tâche de réglage a échoué (par exemple, en raison d'un délai d'attente) ou est terminée.
De même, startProgramListUpdates
planifie également la tâche fastidieuse de mise à jour de la liste des programmes pour qu'elle ait lieu plus tard et pour renvoyer rapidement un statut ou un résultat. La méthode annule d'abord les demandes de mise à jour en attente, puis planifie la tâche de mise à jour et renvoie rapidement le résultat.
Condition de course
En raison du comportement asynchrone des opérations de réglage (par exemple, réglage, balayage (en HIDL) ou recherche (en AIDL) et étape), il existe une condition de concurrence entre l'annulation de l'opération et les opérations de réglage. Si cancel
est appelée après que HAL a terminé une opération de réglage et avant la fin du rappel, l'annulation peut être ignorée et le rappel doit se terminer et être reçu par le client HAL.
De même, si stopProgramListUpdates
est appelé après que HAL ait terminé une mise à jour de la liste de programmes et avant la fin du rappel onCurrentProgramInfoChanged
, stopProgramListUpdates
peut être ignoré et le rappel doit se terminer.
Limite de taille des données
Puisqu'il existe une limite stricte sur le tampon de transaction du classeur, la limite de données pour certaines méthodes d'interface transmettant des données d'une taille potentiellement importante est clarifiée dans le HAL AIDL.
-
getImage
nécessite que l'image renvoyée fasse moins de 1 Mo. -
onProgramListUpdate
nécessite que chaquechunk
fasse moins de 500 Ko. Les listes de programmes plus grandes doivent être divisées par l'implémentation de HAL en plusieurs morceaux et envoyées via plusieurs rappels.
Modifications des structures de données AIDL HAL
En plus des changements dans les interfaces, ces changements ont été appliqués aux structures de données définies dans la diffusion radio AIDL HAL, qui profite de l'AIDL.
- L'énumération
Constant
est supprimée dans AIDL et définie comme const int dansIBroadcastRadio
. Pendant ce temps,ANTENNA_DISCONNECTED_TIMEOUT_MS
est renomméANTENNA_STATE_CHANGE_TIMEOUT_MS
. Un nouveau const intTUNER_TIMEOUT_MS
est ajouté. Toutes les opérations de réglage, de recherche et de pas doivent être terminées dans ce délai. - Enum
RDS
etDeemphasis
sont supprimés dans AIDL et définis comme const int dansAmFmRegionConfig
. En conséquence,fmDeemphasis
etfmRds
dansProgramInfo
sont déclarés comme int, un résultat de calcul binaire des indicateurs respectifs. Pendant ce temps,D50
etD75
sont renommés respectivementDEEMPHASIS_D50
etDEEMPHASIS_D75
. - Les Enum
ProgramInfoFlags
sont supprimés dans AIDL et définis comme const int dansProgramInfo
avec un préfixeFLAG_
ajouté. En conséquence,infoFlags
dansProgramInfo
est déclaré comme int, un résultat de calcul binaire des indicateurs.TUNED
est également renomméFLAG_TUNABLE
, pour mieux décrire sa définition sur laquelle la station peut être syntonisée. - Dans
AmFmBandRange
,scanSpacing
est renomméseekSpacing
, puisquescan
est renomméseek
dans AIDL. - Depuis que le concept d' union est introduit dans AIDL,
MetadataKey
etMetadata
définies dans HIDL HAL ne sont plus utilisées. UneMetadata
d'union AIDL est définie dans AIDL HAL. Chaque valeur d'énumération précédemment dansMetadataKey
est désormais un champ dansMetadata
avec le type de chaîne ou int, selon leurs définitions.
Implémentation de la radiocommande
La mise en œuvre du contrôle radio est basée sur MediaSession
et MediaBrowse
, qui permettent aux applications multimédias et d'assistant vocal de contrôler la radio. Pour plus d'informations, consultez Créer des applications multimédias pour les voitures sur Developer.android.com.
Une implémentation de l'arborescence de navigation multimédia est fournie dans la bibliothèque car-broadcastradio-support dans packages/apps/Car/libs
. Cette bibliothèque contient également des extensions de ProgramSelector pour convertir vers et depuis l'URI. Il est recommandé aux implémentations radio d'utiliser cette bibliothèque pour créer l'arborescence de navigation associée.
Sélecteur de source multimédia
Pour assurer une transition transparente entre la radio et les autres applications affichées dans les médias, la bibliothèque car-media-common contient des classes qui doivent être intégrées dans l'application radio. MediaAppSelectorWidget
peut être inclus dans le XML de l'application radio (l'icône et la liste déroulante utilisées dans les applications multimédia et radio de référence) :
<com.android.car.media.common.MediaAppSelectorWidget android:id="@+id/app_switch_container" android:layout_width="@dimen/app_switch_widget_width" android:layout_height="wrap_content" android:background="@drawable/app_item_background" android:gravity="center" />
Ce widget lance AppSelectionFragment
, qui affiche une liste de sources multimédias vers lesquelles il est possible de basculer. Si une interface utilisateur autre que celle fournie est souhaitée, vous pouvez créer un widget personnalisé pour lancer AppSelectionFragment
lorsque le sélecteur doit être affiché.
AppSelectionFragment newFragment = AppSelectionFragment.create(widget, packageName, fullScreen); newFragment.show(mActivity.getSupportFragmentManager(), null);
Un exemple d’implémentation est fourni dans l’implémentation de l’application radio de référence, située dans packages/apps/Car/Radio
.
Spécifications de contrôle détaillées
L'interface MediaSession
(via MediaSession.Callback
) fournit des mécanismes de contrôle pour le programme radio en cours de lecture :
-
onPlay
,onStop
. (Dé)couper la lecture de la radio. -
onPause
. Pause décalée dans le temps (si prise en charge). -
onPlayFromMediaId
. Lisez n'importe quel contenu à partir d'un dossier de niveau supérieur. Par exemple, « Play FM » ou « Play Radio ». -
onPlayFromUri
. Jouez une fréquence spécifique. Par exemple, « Jouer sur 88,5 FM ». -
onSkipToNext
,onSkipToPrevious
. Syntonisez une station suivante ou précédente. -
onSetRating
. Ajouter ou supprimer des favoris.
Le MediaBrowser expose un MediaItem réglable sur trois types de répertoires de niveau supérieur :
- ( Facultatif ) Programmes (stations). Ce mode est généralement utilisé par les radios à double tuner pour indiquer toutes les stations de radio réglables disponibles à l'emplacement de l'utilisateur.
- Favoris. Programmes radio ajoutés à la liste des Favoris, certains peuvent être indisponibles (hors de portée de réception).
- Canaux de bande. Tous les canaux physiquement possibles dans la région actuelle (87.9, 88.1, 88.3, 88.5, 88.7, 88.9, 89.1 et ainsi de suite). Chaque groupe possède un répertoire de niveau supérieur distinct.
Chaque élément de chacun de ces dossiers (AM/FM/Programmes) est un MediaItem avec un URI qui peut être utilisé avec MediaSession pour effectuer le réglage. Chaque dossier de niveau supérieur (AM/FM/Programmes) est un MediaItem avec un mediaId qui peut être utilisé avec MediaSession pour déclencher la lecture et est à la discrétion de l'OEM. Par exemple, « Play FM », « Play AM » et « Play Radio » sont toutes des requêtes radio non spécifiques qui utilisent un mediaId à envoyer à l'application radio OEM. C'est à l'application radio de déterminer ce qu'il faut jouer à partir de la requête générique et du mediaId.
Session Média
Étant donné qu'il n'existe aucun concept de pause d'un flux de diffusion, les actions Lecture, Pause et Arrêt ne s'appliquent pas toujours à la radio. Avec la radio, l'action Stop est associée à la mise en sourdine du flux tandis que Play est associée à la suppression de la sourdine.
Certains tuners radio (ou applications) offrent la possibilité de simuler une pause de diffusion en mettant en cache le contenu, puis en le lisant plus tard. Dans de tels cas, utilisez onPause
.
La lecture à partir des actions mediaId et URI est destinée à syntoniser une station récupérée depuis l'interface MediaBrowser. Le mediaId est une chaîne arbitraire fournie par l'application radio pour imposer une valeur unique (donc un identifiant donné pointe vers un seul élément) et stable (donc un élément donné a le même identifiant pendant toute la session) avec laquelle identifier une station donnée. . L'URI sera d'un schéma bien défini. En bref, une forme URI de ProgramSelector. Bien que cela préserve l'attribut d'unicité, il n'est pas nécessaire qu'il soit stable, bien qu'il puisse changer lorsque la station passe à une fréquence différente.
De par sa conception, onPlayFromSearch
n’est pas utilisé. Il incombe au client (application compagnon) de sélectionner un résultat de recherche dans l’arborescence MediaBrowser. Transférer cette responsabilité à l'application radio augmenterait la complexité, nécessiterait des contrats formels sur la manière dont les requêtes de chaîne devraient apparaître et entraînerait une expérience utilisateur inégale sur différentes plates-formes matérielles.
Remarque : L'application radio ne contient pas d'informations supplémentaires qui seraient utiles pour rechercher un nom de station non exposé au client via l'interface MediaBrowser.
Le passage à la station suivante ou précédente dépend du contexte actuel :
- Lorsqu'une application est syntonisée sur une station de la liste des Favoris, l'application peut passer à la station suivante de la liste des Favoris.
- L'écoute d'une station de la liste des programmes peut entraîner la syntonisation de la prochaine station disponible, triée selon le numéro de chaîne.
- L'écoute d'une chaîne arbitraire peut entraîner la syntonisation sur la chaîne physique suivante, même en l'absence de signal de diffusion.
L'application radio gère ces actions.
La gestion des erreurs
Les actions TransportControls
(Play, Stop et Next) ne fournissent pas d'informations indiquant si l'action réussit ou non. La seule façon d'indiquer une erreur est de définir l'état MediaSession sur STATE_ERROR
avec un message d'erreur.
L'application radio doit gérer ces actions et soit les exécuter, soit définir un état d'erreur. Si l'exécution de la commande Play n'est pas immédiate, l'état de lecture doit être modifié en STATE_CONNECTING
(en cas de réglage direct) ou STATE_SKIPPING_TO_PREVIOUS
ou NEXT
pendant l'exécution de la commande.
Le client doit surveiller le PlaybackState
et vérifier que la session a modifié le programme actuel par rapport à ce qui a été demandé ou est entré dans l'état d'erreur. STATE_CONNECTING
ne doit pas dépasser 30 s. Cependant, une syntonisation directe sur une fréquence AM/FM donnée devrait être beaucoup plus rapide.
Ajouter et supprimer des favoris
MediaSession prend en charge la notation, qui peut être utilisée pour contrôler les favoris. onSetRating
appelé avec une note de type RATING_HEART
ajoute ou supprime la station actuellement écoutée vers ou de la liste des favoris.
Contrairement aux préréglages existants, ce modèle suppose une liste de favoris non ordonnée et illimitée, lorsque chaque favori enregistré a été attribué à un emplacement numérique (généralement 1 à 6). En conséquence, les systèmes basés sur des préréglages seraient incompatibles avec le fonctionnement onSetRating
.
La limitation de l'API MediaSession est que seule la station actuellement écoutée peut être ajoutée ou supprimée. Par exemple, les éléments doivent d'abord être sélectionnés avant de pouvoir être supprimés. Il ne s'agit que d'une limitation du client MediaBrowser, telle qu'une application compagnon. L'application radio n'est pas soumise à des restrictions similaires. Cette partie est facultative lorsqu'une application ne prend pas en charge les favoris.
Navigateur multimédia
Pour exprimer quelles fréquences ou noms de canaux physiques (lorsque le réglage sur un canal arbitraire convient à une technologie radio donnée) sont valides pour une région donnée, tous les canaux valides (fréquences) sont répertoriés pour chaque bande. Aux États-Unis, cela équivaut à 101 canaux FM dans la plage de 87,8 à 108,0 MHz (en utilisant un espacement de 0,2 MHz) et 117 canaux AM dans la plage de 530 à 1 700 kHz (en utilisant un espacement de 10 kHz). La radio HD utilisant le même espace de canaux, elle n’est pas présentée séparément.
La liste des programmes de radio actuellement disponibles est plate dans la mesure où elle ne permet pas de schémas d'affichage tels que le regroupement par ensemble de diffusion audio directe (DAB).
Les entrées de la liste des favoris peuvent ne pas être réglables. Par exemple si un programme donné est hors de portée. L'application radio peut détecter ou non si l'entrée peut être réglée au préalable. Si c'est le cas, il se peut que l'entrée ne soit pas marquée comme jouable.
Pour identifier les dossiers de niveau supérieur, le même mécanisme que celui utilisé par Bluetooth est appliqué. Autrement dit, un bundle Extras de l'objet MediaDescription
contient un champ spécifique au tuner, tout comme Bluetooth le fait avec EXTRA_BT_FOLDER_TYPE
. Dans le cas de la diffusion radio, cela conduit à définir les nouveaux champs suivants dans l'API publique :
-
EXTRA_BCRADIO_FOLDER_TYPE = "android.media.extra.EXTRA_BCRADIO_FOLDER_TYPE"
. Une des valeurs suivantes :-
BCRADIO_FOLDER_TYPE_PROGRAMS = 1
. Programmes actuellement disponibles. -
BCRADIO_FOLDER_TYPE_FAVORITES = 2
. Favoris. -
BCRADIO_FOLDER_TYPE_BAND = 3
. Tous les canaux physiques pour une bande donnée.
Il n'est pas nécessaire de définir des champs de métadonnées personnalisés spécifiques à la radio, car toutes les données pertinentes s'intègrent dans le schéma
MediaBrowser.MediaItem
existant :- Nom du programme (RDS PS, nom du service DAB).
MediaDescription.getTitle
. - Fréquence FM. URI (voir ProgramSelector ) ou
MediaDescription.getTitle
(si une entrée se trouve dans le dossierBROADCASTRADIO_FOLDER_TYPE_BAND
). - Identifiants spécifiques à la radio (RDS PI, DAB SId).
MediaDescription.getMediaUri
analysé dans ProgramSelector.
En règle générale, il n'est pas nécessaire de récupérer la fréquence FM pour une entrée du programme en cours ou de la liste des favoris (car le client doit opérer sur les identifiants de média). Cependant, si un tel besoin devait se présenter (par exemple, à des fins d'affichage), il est présent dans l'URI et peut être analysé dans
ProgramSelector
. Cela dit, il n'est pas recommandé d'utiliser l'URI pour sélectionner des éléments dans la session en cours. Pour plus de détails, consultezProgramSelector
.Pour éviter les problèmes de performances ou liés au classeur, le service MediaBrowser doit prendre en charge la pagination :
-
EXTRA_PAGE
-
EXTRA_PAGE_SIZE
- Paramètres supplémentaires pour
subscribe()
Remarque : Par défaut, la pagination est implémentée par défaut dans la variante
onLoadChildren()
sans gestion des options.Les entrées associées de tous les types de listes (chaînes brutes, programmes trouvés et favoris) peuvent avoir des identifiants de média différents (cela dépend de l'application radio ; la bibliothèque de support les aura différents). Les URI (sous forme ProgramSelector) diffèrent entre les chaînes brutes et les programmes trouvés dans la plupart des cas (sauf pour la FM sans RDS), mais sont pour la plupart les mêmes entre les programmes trouvés et les favoris (sauf, par exemple, lorsque AF a été mis à jour).
Avoir différents mediaIds pour les entrées de différents types de listes permet d'effectuer différentes actions sur celles-ci. Vous pouvez parcourir la liste des Favoris ou la liste Tous les programmes sur
onSkipToNext
, en fonction du dossier duMediaItem
récemment sélectionné (voir MediaSession ).Actions de réglage spéciales
La liste des programmes permet aux utilisateurs de syntoniser une station spécifique, mais ne permet pas aux utilisateurs de faire des demandes générales telles que « Régler sur FM », ce qui pourrait entraîner la syntonisation d'une station récemment écoutée sur la bande FM.
Pour prendre en charge de telles actions, certains répertoires de niveau supérieur ont l'indicateur
FLAG_PLAYABLE
(avecFLAG_BROWSABLE
pour les dossiers).Action S'accorde sur Comment émettre Jouer la radio N'importe quelle chaîne radio startService(ACTION_PLAY_BROADCASTRADIO)
ou
playFromMediaId(MediaBrowser. getRoot() )
Jouer sur FM N'importe quelle chaîne FM Lecture à partir du mediaId
de la bande FM.La détermination du programme à écouter dépend de l'application. Il s'agit généralement de la chaîne la plus récemment écoutée dans la liste donnée. Pour plus de détails sur
ACTION_PLAY_BROADCASTRADIO
, consultez Intentions de lecture générales .Découverte et connexion au service
PackageManager
peut trouver directement l'arborescence radio de diffusion MediaBrowserService. Pour ce faire, appelezresolveService
avec l'intentionACTION_PLAY_BROADCASTRADIO
(voir Intentions de lecture générales ) et l'indicateurMATCH_SYSTEM_ONLY
. Pour rechercher tous les services qui diffusent la radio (il peut y en avoir plusieurs ; par exemple, AM/FM et satellite séparés), utilisezqueryIntentServices
.Le service résolu gère également l'intention de liaison
android.media.browse.MediaBrowserService
. Ceci est vérifié avec GTS.Pour vous connecter au MediaBrowserService sélectionné, créez une instance
MediaBrowser
pour un composant de service donné etconnect
. Après avoir établi la connexion, un handle vers MediaSession peut être obtenu viagetSessionToken
.L'application Radio peut restreindre les packages clients autorisés à se connecter dans une implémentation
onGetRoot
de leur service. L'application doit permettre aux applications système de se connecter sans liste blanche. Pour plus d’informations sur la liste blanche, consultez Accepter le package et la signature de l’application Assistant .Si l'application spécifique à la source (par exemple, une application radio) est installée sur un appareil sans une telle prise en charge de la source, elle se présentera toujours comme gérant l'intention
ACTION_PLAY_BROADCASTRADIO
, mais son arborescence MediaBrowser ne contiendra pas de balises spécifiques à la radio. Ainsi, un client souhaitant vérifier si une source donnée est disponible sur un appareil doit :- Découvrez le service radio (appelez
resolveService
pourACTION_PLAY_BROADCASTRADIO
). - Créez
MediaBrowser
, puis connectez-vous-y. - Déterminez la présence de
MediaItem
avecEXTRA_BCRADIO_FOLDER_TYPE
supplémentaire.
Remarque : Dans la plupart des cas, le client doit analyser toutes les arborescences MediaBrowser disponibles pour détecter toutes les sources disponibles pour un périphérique donné.
Noms des groupes
La liste de bandes est représentée par un ensemble de répertoires de niveau supérieur avec une balise de type de dossier définie sur
BCRADIO_FOLDER_TYPE_BAND
. Les titres de leursMediaItem
sont des chaînes localisées représentant les noms des groupes. Dans la plupart des cas, ce sera la même chose qu'une traduction en anglais, mais le client ne peut pas se fier à cette hypothèse.Pour fournir un mécanisme stable de recherche de certaines bandes, une balise supplémentaire est ajoutée pour les dossiers de bandes,
EXTRA_BCRADIO_BAND_NAME_EN
. Il s'agit d'un nom non localisé du groupe et ne peut prendre qu'une de ces valeurs prédéfinies :-
AM
-
FM
-
DAB
Si le groupe ne figure pas sur cette liste, l'étiquette du nom du groupe ne doit pas être définie. Cependant, si le groupe figure sur la liste, il doit avoir un jeu de balises. La radio HD n'énumère pas de bandes distinctes car elle utilise le même support sous-jacent que l'AM/FM.
Intentions générales de jeu
Chaque application dédiée à la lecture d'une source donnée (comme la radio ou le CD) doit gérer une intention de lecture générale pour commencer à lire certains contenus éventuellement à partir d'un état inactif (par exemple, après le démarrage). C'est à l'application de décider comment sélectionner le contenu à lire, mais il s'agit généralement du programme de radio ou de la piste de CD récemment diffusé. Une intention distincte est définie pour chaque source audio :
-
android.car.intent.action.PLAY_BROADCASTRADIO
-
android.car.intent.action.PLAY_AUDIOCD
: CD-DA ou CD-Texte -
android.car.intent.action.PLAY_DATADISC
: disque de données optique comme un CD/DVD, mais pas un CD-DA (peut être un CD en mode mixte) -
android.car.intent.action.PLAY_AUX
: Sans préciser quel port AUX -
android.car.intent.action.PLAY_BLUETOOTH
-
android.car.intent.action.PLAY_USB
: Sans préciser quel périphérique USB -
android.car.intent.action.PLAY_LOCAL
: stockage multimédia local (flash intégré)
Les intentions ont été choisies pour être utilisées pour la commande de lecture générale, car elles résolvent deux problèmes à la fois : la commande de lecture générale elle-même et la découverte de services. L'avantage supplémentaire d'avoir une telle intention serait la possibilité d'exécuter une action aussi simple sans ouvrir la session MediaBrowser.
La découverte de services est en fait le problème le plus important résolu avec ces intentions. La procédure de découverte de service est ainsi simple et sans équivoque (voir Découverte et connexion au service ).
Pour faciliter certaines implémentations client, il existe une autre façon d'émettre une telle commande Play (qui doit également être implémentée par l'application radio) : émettre
playFromMediaId
avec le rootId du nœud racine (utilisé comme mediaId). Bien que le nœud racine ne soit pas censé être jouable, son rootId est une chaîne arbitraire qui peut être rendue consommable en tant que mediaId. Cependant, les clients ne sont pas tenus de comprendre cette nuance.Sélecteur de programme
Bien que
mediaId
soit suffisant pour sélectionner un canal dansMediaBrowserService
, il devient lié à une session et n'est plus cohérent entre les fournisseurs. Dans certains cas, le client peut avoir besoin d'un pointeur absolu (comme une fréquence absolue) pour la maintenir entre les sessions et les appareils.À l’ère des émissions de radio numériques, une simple fréquence ne suffit pas pour syntoniser une station spécifique. Par conséquent, utilisez
ProgramSelector
pour syntoniser une chaîne analogique ou numérique.ProgramSelector
se compose de deux parties :- Identifiant principal. Un identifiant unique et stable pour une station de radio donnée qui ne change pas mais peut ne pas suffire pour syntoniser cette station. Par exemple, le code RDS PI, qui peut être traduit en indicatif d'appel aux États-Unis.
- Identifiants secondaires. Identifiants supplémentaires utiles pour syntoniser cette station (par exemple, fréquence), incluant éventuellement des identifiants provenant d'autres technologies radio. Par exemple, une station DAB peut disposer d’une solution de secours en matière de diffusion analogique.
Pour permettre
ProgramSelector
de s'intégrer à la solution baséeMediaBrowser
ouMediaSession
, définissez un schéma URI pour le sérialiser. Le schéma est défini comme suit :broadcastradio://program/<primary ID type>/<primary ID>? <secondary ID type>=<secondary ID>&<secondary ID type>=<secondary ID>
Dans cet exemple, la partie secondaire Identifiers (après le point d'interrogation (
?
)) est facultative et peut être supprimée pour fournir un identifiant stable à utiliser commemediaId
. Par exemple:-
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=88500&AMFM_FREQUENCY=103300
-
broadcastradio://program/AMFM_FREQUENCY/102100
-
broadcastradio://program/DAB_SID_EXT/14895264?RDS_PI=1234
La partie autorité (hôte AKA) du
program
offre une certaine marge d'extension du programme à l'avenir. Les chaînes de type d'identifiant sont spécifiées précisément comme leurs noms dans la définition HAL 2.x deIdentifierType
et le format de la valeur est un nombre décimal ou hexadécimal (avec le préfixe0x
).Tous les identifiants spécifiques au fournisseur sont représentés par le préfixe
VENDOR_
. Par exemple,VENDOR_0
pourVENDOR_START
etVENDOR_1
pourVENDOR_START
plus 1. Ces URI sont spécifiques au matériel radio sur lequel ils ont été générés et ne peuvent pas être transférés entre des appareils fabriqués par différents OEM.Ces URI doivent être attribués à chaque MediaItem sous les dossiers radio de niveau supérieur. De plus, MediaSession doit prendre en charge à la fois
playFromMediaId
etplayFromUri
. Cependant, l'URI est principalement destiné à l'extraction de métadonnées radio (telles que la fréquence FM) et au stockage persistant. Il n'y a aucune garantie que l'URI sera disponible pour tous les éléments multimédias (par exemple, lorsque le type d'ID principal n'est pas encore pris en charge par le framework). D’un autre côté, Media ID fonctionne toujours. Il n'est pas recommandé aux clients d'utiliser l'URI pour sélectionner des éléments de la session MediaBrowser en cours. Utilisez plutôtplayFromMediaId
. Cela dit, ce n’est pas facultatif pour l’application de desserte et les URI manquants sont réservés à des cas bien justifiés.La conception initiale utilisait un seul deux-points au lieu de la séquence
://
après la partie schéma. Cependant, le premier n'est pas pris en charge parandroid.net.Uri
pour les références URI hiérarchiques absolues.Autres types de sources
D'autres sources audio peuvent être gérées de la même manière. Par exemple, l'entrée auxiliaire et le lecteur CD audio.
Une seule application peut servir plusieurs types de sources. Dans de tels cas, il est recommandé de créer un MediaBrowserService distinct pour chaque type de source. Même dans une configuration avec plusieurs sources/MediaBrowserServices servis, il est fortement recommandé d’avoir une seule MediaSession au sein d’une seule application.
CD audio
Semblable au CD audio dans la mesure où l'application qui sert de tels disques exposerait MediaBrowser avec une seule entrée consultable (ou plus, si le système dispose d'un changeur de CD), qui à son tour contiendrait toutes les pistes d'un CD donné. Si le système ne connaît pas les pistes de chaque CD (par exemple, lorsque tous les disques sont insérés dans une cartouche en même temps et qu'il ne les lit pas tous), alors MediaItem pour l'ensemble du disque serait simplement
PLAYABLE
, et nonBROWSABLE
etPLAYABLE
. S'il n'y a pas de disque dans un emplacement donné, l'élément ne sera niPLAYABLE
niBROWSABLE
(mais chaque emplacement doit toujours être présent dans l'arborescence).Ces entrées seraient marquées de la même manière que les dossiers de diffusion radio ; ils contiendraient des champs supplémentaires supplémentaires définis dans l'API MediaDescription :
-
EXTRA_CD_TRACK
: pour chaqueMediaItem
sur CD audio, numéro de piste basé sur 1. -
EXTRA_CD_DISK
: numéro de disque basé sur 1.
Pour les systèmes compatibles CD-Text et les disques compatibles, le MediaItem de niveau supérieur aurait le titre du disque. De même, les MediaItems pour les pistes auraient un titre de piste.
Entrée auxiliaire
L'application qui sert d'entrée auxiliaire expose une arborescence MediaBrowser avec une seule entrée (ou plus, lorsque plusieurs ports existent) représentant le port d'entrée AUX. La MediaSession respective prend son mediaId et passe à cette source après avoir reçu la requête
playFromMediaId
.Chaque entrée AUX MediaItem aurait un champ supplémentaire
EXTRA_AUX_PORT_NAME
défini sur le nom non localisé du port sans la phrase « AUX ». Par exemple, "AUX 1" aurait été défini sur "1", "AUX front" sur "front" et "AUX" sur une chaîne vide. Dans les langues autres que l'anglais, la balise de nom restera la même chaîne anglaise. Peu probable, comme pourEXTRA_BCRADIO_BAND_NAME_EN
, les valeurs sont définies par l'OEM et ne sont pas contraintes à une liste prédéfinie.Si le matériel peut détecter les périphériques connectés au port AUX, le matériel doit marquer le Mediatem comme
PLAYABLE
, uniquement si l'entrée est connectée. Le matériel doit toujours être énuméré (mais pasPLAYABLE
) si rien n'était connecté à ce port. Si le matériel n'a pas une telle capacité, le Mediitem doit toujours être défini surPLAYABLE
.Champs supplémentaires
Définissez les champs suivants:
-
EXTRA_CD_TRACK = "android.media.extra.CD_TRACK"
-
EXTRA_CD_DISK = "android.media.extra.CD_DISK"
-
EXTRA_AUX_PORT_NAME = "android.media.extra.AUX_PORT_NAME"
Le client doit examiner les Mediitems de niveau supérieur pour les éléments ayant le jeu de champ
EXTRA_CD_DISK
ouEXTRA_AUX_PORT_NAME
.Exemples détaillés
Les exemples suivants abordent la structure de l'arborescence MediaBrowser pour les types de source qui font partie de cette conception.
Diffusé radio mediaBrowsService (gère
ACTION_PLAY_BROADCASTRADIO
):- Stations (navigateur)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_PROGRAMS
- BBC One (jouable) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=90500
- ABC 88.1 (Playable) URI:
broadcastradio://program/RDS_PI/5678?AMFM_FREQUENCY=88100
- ABC 88.1 HD1 (Playable) URI:
broadcastradio://program/HD_STATION_ID_EXT/158241DEADBEEF?AMFM_FREQUENCY=88100&RDS_PI=5678
- ABC 88.1 HD2 (Playable) Uri:
broadcastradio://program/HD_STATION_ID_EXT/158242DEADBEFE
- 90.5 FM (jouable) - FM sans Rdsuri:
broadcastradio://program/AMFM_FREQUENCY/90500
- 620 AM (jouable) URI:
broadcastradio://program/AMFM_FREQUENCY/620
- BBC ONE (jouable) URI:
broadcastradio://program/DAB_SID_EXT/1E24102?RDS_PI=1234
- BBC One (jouable) URI:
- Favoris (navigateur, jouable)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_FAVORITES
- BBC One (jouable) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=101300
- BBC Two (Not Playable) URI:
broadcastradio://program/RDS_PI/1300?AMFM_FREQUENCY=102100
- BBC One (jouable) URI:
- Am (Browsable, jouable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="AM"
- 530 AM (jouable) URI:
broadcastradio://program/AMFM_FREQUENCY/530
- 540 AM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/540
- 550 AM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/550
- 530 AM (jouable) URI:
- FM (Browsable, Playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="FM"
- 87.7 FM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/87700
- 87.9 FM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/87900
- 88.1 FM (Playable) URI:
broadcastradio://program/AMFM_FREQUENCY/88100
- 87.7 FM (Playable) URI:
- Dab (playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="DAB"
Audio CD MediaBrowsserService (gère
ACTION_PLAY_AUDIOCD
):- Disque 1 (playable)
EXTRA_CD_DISK=1
- Disque 2 (navigateur, jouable)
EXTRA_CD_DISK=2
- Piste 1 (jouable)
EXTRA_CD_TRACK=1
- Piste 2 (jouable)
EXTRA_CD_TRACK=2
- Piste 1 (jouable)
- Mon CD de musique (navigable, jouable)
EXTRA_CD_DISK=3
- Tout par moi-même (jouable)
EXTRA_CD_TRACK=1
- Reise, reise (playable)
EXTRA_CD_TRACK=2
- Tout par moi-même (jouable)
- Emplacement vide 4 (non jouable)
EXTRA_CD_DISK=4
AUX MediaBrowSerService (gère
ACTION_PLAY_AUX
):- AUX Front (playable)
EXTRA_AUX_PORT_NAME="front"
- Aux arrière (jouable)
EXTRA_AUX_PORT_NAME="rear"
-