Créer l'interface HAL

Vous devez utiliser HIDL pour décrire tous les indicateurs de compilation utilisés pour les tests la compilation du framework. Les indicateurs de compilation pertinents doivent être regroupés et inclus dans un fichier .hal unique. Utiliser HIDL pour spécifier des éléments de configuration offre les avantages suivants:

  • Avec versions gérées (pour ajouter de nouveaux éléments de configuration, les fournisseurs/OEM doivent étendre explicitement HAL)
  • Bien documenté
  • Contrôle des accès avec SELinux
  • Vérifiez l'intégrité des éléments de configuration via Test fournisseur Suite (vérification des plages, contrôle de l'interdépendance entre les éléments, etc.)
  • API générées automatiquement en C++ et Java

Identifier les indicateurs de compilation utilisés par le framework

Commencez par identifier les configurations de compilation utilisées pour compiler de manière conditionnelle les puis abandonnez les configurations obsolètes pour réduire la taille de l'ensemble. Par exemple : l'ensemble d'indicateurs de compilation suivant est identifié pour surfaceflinger:

  • TARGET_USES_HWC2
  • TARGET_BOARD_PLATFORM
  • TARGET_DISABLE_TRIPLE_BUFFERING
  • TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
  • NUM_FRAMEBUFFER_SURFACE_BUFFERS
  • TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
  • VSYNC_EVENT_PHASE_OFFSET_NS
  • SF_VSYNC_EVENT_PHASE_OFFSET_NS
  • PRESENT_TIME_OFFSET_FROM_VSYNC_NS
  • MAX_VIRTUAL_DISPLAY_DIMENSION

Créer une interface HAL

Les configurations de compilation d'un sous-système sont accessibles via une interface HAL, tandis que les interfaces permettant d'attribuer des valeurs de configuration sont regroupées dans le package HAL android.hardware.configstore (version 1.0 actuellement). Par exemple, pour créer un fichier d'interface HAL pour surfaceflinger, dans hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal:

package android.hardware.configstore@1.0;

interface ISurfaceFlingerConfigs {
    // TO-BE-FILLED-BELOW
};

Après avoir créé le fichier .hal, exécutez la commande suivante : hardware/interfaces/update-makefiles.sh pour ajouter le nouveau .hal à Android.bp et Android.mk fichiers.

Ajouter des fonctions pour les indicateurs de compilation

Pour chaque option de compilation, ajoutez une fonction à l'interface. Par exemple, dans hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal:

interface ISurfaceFlingerConfigs {
    disableTripleBuffering() generates(OptionalBool ret);
    forceHwcForVirtualDisplays() generates(OptionalBool ret);
    enum NumBuffers: uint8_t {
        USE_DEFAULT = 0,
        TWO = 2,
        THREE = 3,
    };
    numFramebufferSurfaceBuffers() generates(NumBuffers ret);
    runWithoutSyncFramework() generates(OptionalBool ret);
    vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret);
    presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret);
    maxVirtualDisplayDimension() generates(OptionalInt32 ret);
};

Lorsque vous ajoutez une fonction:

  • Utilisez un nom concis. Éviter de convertir la variable makefile en noms de fonction et gardez à l'esprit que TARGET_ et Les préfixes BOARD_ ne sont plus nécessaires.
  • Ajoutez des commentaires. aider les développeurs à comprendre l'objectif l'élément de configuration, la façon dont il modifie le comportement du framework, les valeurs valides des informations.

Les types renvoyés par fonction peuvent être Optional[Bool|String|Int32|UInt32|Int64|UInt64] Les types sont définis dans le fichier types.hal du même répertoire et encapsulez les valeurs primitives avec une qui indique si la valeur est spécifiée par le HAL. Si ce n'est pas le cas, est utilisée.

struct OptionalString {
    bool specified;
    string value;
};

Le cas échéant, définissez l'énumération qui représente le mieux le type élément de configuration et utilisez cette énumération comme type renvoyé. Dans l'exemple ci-dessus, l'énumération NumBuffers est définie pour limiter le nombre valeurs. Lorsque vous définissez de tels types de données personnalisées, ajoutez un champ ou une valeur d'énumération (par exemple, USE_DEFAULT) pour indiquer si la valeur est ou n'est pas spécifiée. par le HAL.

Il n'est pas obligatoire qu'un seul indicateur de compilation devienne une fonction unique dans HIDL. Les propriétaires de module peuvent aussi regrouper des options de compilation étroitement liées un struct et d'avoir une fonction qui le renvoie (cela peut réduire nombre d'appels de fonction).

Par exemple, une option permettant d'agréger deux indicateurs de compilation dans un seul struct dans hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal est:

 interface ISurfaceFlingerConfigs {
    // other functions here
    struct SyncConfigs {
        OptionalInt64 vsyncEventPhaseoffsetNs;
        OptionalInt64 presentTimeoffsetFromSyncNs;
    };
    getSyncConfigs() generates (SyncConfigs ret);
    // other functions here
};

Alternatives à une fonction HAL unique

Au lieu d'utiliser une seule fonction HAL pour tous les indicateurs de compilation, propose également des fonctions simples telles que getBoolean(string key) et getInteger(string key). La valeur réelle Les paires key=value sont stockées dans des fichiers distincts et le service HAL fournit des valeurs en lisant/analysant ces fichiers.

Bien que cette approche soit facile à définir, elle n'inclut pas les avantages fournis par HIDL (gestion des versions forcée, facilité de documentation, contrôle des accès) Elle n'est donc pas recommandée.

Interfaces uniques ou multiples

La conception de l'interface HAL pour les éléments de configuration présente deux choix:

  • Une interface unique qui couvre tous les éléments de configuration
  • Plusieurs interfaces, chacune couvrant un ensemble de configurations associées éléments

Une seule interface est plus facile, mais peut devenir difficile à gérer, car de plus éléments de configuration sont ajoutés à ce fichier unique. De plus, le contrôle des accès n'est pas ultraprécis : un processus autorisé à accéder à l'interface peut lire tous les éléments de configuration (l'accès à un ensemble partiel d'éléments de configuration accordé). Sinon, si l'accès n'est pas accordé, les éléments de configuration ne peuvent pas être lire.

En raison de ces problèmes, Android utilise plusieurs interfaces avec un seul HAL. pour accéder à un groupe d'éléments de configuration associés. Par exemple : ISurfaceflingerConfigs pour les contenus surfaceflinger éléments de configuration, et IBluetoothConfigs pour les connexions Bluetooth éléments de configuration.