Anciennes HAL

Un HAL définit une interface standard que les fournisseurs de matériel doivent implémenter, ce qui permet à Android d'être indépendant des implémentations de pilotes de niveau inférieur. L'utilisation d'un HAL vous permet d'implémenter des fonctionnalités sans affecter ni modifier le système de niveau supérieur. Cette page décrit l'ancienne architecture, qui n'est plus prise en charge à partir d'Android 8.0. Pour Android 8.0 et versions ultérieures, consultez la présentation du HAL.

Composants HAL

Figure 1 : Composants HAL

Vous devez implémenter le HAL (et le pilote) correspondant au matériel spécifique fourni par votre produit. Les implémentations HAL sont généralement intégrées aux modules de bibliothèque partagée (fichiers .so), mais comme Android n'impose pas d'interaction standard entre une implémentation HAL et les pilotes d'appareil, vous pouvez faire ce qui est le mieux pour votre situation. Toutefois, pour permettre au système Android d'interagir correctement avec votre matériel, vous devez respecter le contrat défini dans chaque interface HAL spécifique au matériel.

Pour garantir que les HAL ont une structure prévisible, chaque interface HAL spécifique au matériel a des propriétés définies dans hardware/libhardware/include/hardware/hardware.h. Cette interface permet au système Android de charger les versions correctes de vos modules HAL de manière cohérente. Une interface HAL se compose de deux composants: des modules et des appareils.

Modules HAL

Un module représente votre implémentation HAL empaquetée, qui est stockée en tant que bibliothèque partagée (.so file). Le fichier d'en-tête hardware/libhardware/include/hardware/hardware.h définit une struct (hw_module_t) qui représente un module et contient des métadonnées telles que la version, le nom et l'auteur du module. Android utilise ces métadonnées pour trouver et charger correctement le module HAL.

De plus, la structure hw_module_t contient un pointeur vers une autre structure, hw_module_methods_t, qui contient un pointeur vers une fonction ouverte pour le module. Cette fonction d'ouverture permet d'établir la communication avec le matériel pour lequel le HAL sert d'abstraction. Chaque HAL spécifique au matériel étend généralement la structure hw_module_t générique avec des informations supplémentaires pour ce matériel spécifique. Par exemple, dans la couche HAL de l'appareil photo, la structure camera_module_t contient une structure hw_module_t ainsi que d'autres pointeurs de fonction spécifiques à l'appareil photo:

typedef struct camera_module {
    hw_module_t common;
    int (*get_number_of_cameras)(void);
    int (*get_camera_info)(int camera_id, struct camera_info *info);
} camera_module_t;

Lorsque vous implémentez un HAL et créez la structure de module, vous devez le nommer HAL_MODULE_INFO_SYM. Exemple de l'HAL audio du Nexus 9:

struct audio_module HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
        .hal_api_version = HARDWARE_HAL_API_VERSION,
        .id = AUDIO_HARDWARE_MODULE_ID,
        .name = "NVIDIA Tegra Audio HAL",
        .author = "The Android Open Source Project",
        .methods = &hal_module_methods,
    },
};

Appareils HAL

Un appareil effectue une abstraction du matériel de votre produit. Par exemple, un module audio peut contenir un périphérique audio principal, un périphérique audio USB ou un périphérique audio Bluetooth A2DP.

Un appareil est représenté par la structure hw_device_t. Comme un module, chaque type d'appareil définit une version détaillée du hw_device_t générique qui contient des pointeurs de fonction pour des fonctionnalités spécifiques du matériel. Par exemple, le type de structure audio_hw_device_t contient des pointeurs de fonction vers les opérations des appareils audio:

struct audio_hw_device {
    struct hw_device_t common;

    /**
     * used by audio flinger to enumerate what devices are supported by
     * each audio_hw_device implementation.
     *
     * Return value is a bitmask of 1 or more values of audio_devices_t
     */
    uint32_t (*get_supported_devices)(const struct audio_hw_device *dev);
  ...
};
typedef struct audio_hw_device audio_hw_device_t;

En plus de ces propriétés standards, chaque interface HAL spécifique au matériel peut définir davantage de ses propres fonctionnalités et exigences. Pour en savoir plus, consultez la documentation de référence sur les HAL, ainsi que les instructions spécifiques à chaque HAL.

Créer des modules HAL

Les implémentations HAL sont intégrées aux fichiers de modules (.so) et sont liées de manière dynamique par Android lorsque cela est approprié. Vous pouvez créer vos modules en créant des fichiers Android.mk pour chacune de vos implémentations HAL et en pointant vers vos fichiers sources. En général, vos bibliothèques partagées doivent être nommées selon un format spécifique afin qu'elles puissent être trouvées et chargées correctement. Le schéma d'attribution de noms varie légèrement d'un module à l'autre, mais suit le modèle général <module_type>.<device_name>.

Ancien HAL

Le terme "ancien HAL" fait référence de manière générale à tous les HAL antérieurs à Android 8.0 (obsolète dans Android 8). La majeure partie des interfaces système Android (appareil photo, audio, capteurs, etc.) sont définies sous "hardware/libhardware/include/hardware". Elles disposent d'une gestion des versions approximative et d'une ABI à peu près stable. Quelques sous-systèmes (y compris le Wi-Fi, la couche d'interface radio et le Bluetooth) disposent d'autres interfaces non standardisées dans "libhardware_legacy" ou dispersées dans le codebase. Les anciens HAL n'offraient jamais de garanties de stabilité strictes.