Mise en œuvre du service

Pour préparer l'implémentation de HAL, vous pouvez générer le code de l'interface ConfigStore de base, puis le modifier pour répondre à vos besoins.

Génération du code d'interface

Pour générer du code passe-partout pour l'interface, exécutez hidl-gen . Par exemple, pour générer du code pour surfaceflinger :

hidl-gen -o hardware/interfaces/configstore/1.0/default \
    -Lc++-impl \
    -randroid.hardware:hardware/interfaces \
    -randroid.hidl:system/libhidl/transport \
    android.hardware.config@1.0::ISurfaceFlingerConfigs

Modification d'Android.mk

Ensuite, modifiez le fichier Android.mk pour ajouter le fichier d'implémentation ( <modulename>Configs.cpp ) à LOCAL_SRC_FILES et pour mapper les indicateurs de build dans les définitions de macro. Par exemple, vous pouvez modifier surfaceflinger dans hardware/interface/configstore/1.0/default/Android.mk :

LOCAL_SRC_FILES += SurfaceFlingerConfigs.cpp
ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
    LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
endif

ifeq ($(TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK),true)
    LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK
endif

Si Android.mk inclut plusieurs blocs ifeq-endif , envisagez de déplacer votre code dans un nouveau fichier (c'est-à-dire surfaceflinger.mk ), puis incluez ce fichier depuis Android.mk .

Fonctions de mise en œuvre

Pour remplir les fonctions pour implémenter le HAL, rappelez la fonction _hidl_cb avec des valeurs différentes (conditionnées aux drapeaux de build). Par exemple, vous pouvez remplir les fonctions de surfaceflinger dans hardware/interfaces/configstore/1.0/default/SurfaceFlingerConfigs.cpp :

Return<void> SurfaceFlingerConfigs::numFramebufferSurfaceBuffers(
        numFramebufferSurfaceBuffers_cb _hidl_cb) {
    #if NUM_FRAMEBUFFER_SURFACE_BUFFERS 2
    _hidl_cb(NumBuffers.TWO);
    #else if NUM_FRAMEBUFFER_SURFACE_BUFFERS 3
    _hidl_cb(NumBuffers.THREE);
    #else
    _hidl_cb(NumBuffers.USE_DEFAULT);
    #endif
}

Return<void> SurfaceFlingerConfigs::runWithoutSyncFramework(
        runWithoutSyncFramework_cb _hidl_cb) {
    #ifdef RUNNING_WITHOUT_SYNC_FRAMEWORK
    _hidl_cb({true /* specified */, true /* value */});
    #else
    // when macro not defined, we can give any value to the second argument.
    // It will simply be ignored in the framework side.
    _hidl_cb({false /* specified */, false /* value */});
    #endif
}

Assurez-vous que l'implémentation ne contient pas de fonction nommée HIDL_FETCH_ interface-name (par exemple, HIDL_FETCH_ISurfaceFlingerConfigs ). Cette fonction est nécessaire pour le mode passthrough HIDL, qui n'est pas utilisé (et interdit) par configstore . ConfigStore doit toujours s'exécuter en mode binderisé.

S'inscrire en tant que service

Enfin, enregistrez toutes les implémentations d'interface auprès du service configstore . Par exemple, vous pouvez enregistrer les implémentations surfaceflinger dans hardware/interfaces/configstore/1.0/default/service.cpp :

configureRpcThreadpool(maxThreads, true);
sp<ISurfaceFlingerConfigs> surfaceFlingerConfigs = new SurfaceFlingerConfigs;
status_t status = surfaceFlingerConfigs->registerAsService();

sp<IBluetoothConfigs> bluetoothConfigs = new BluetoothConfigs;
status = bluetoothConfigs->registerAsService();

// register more interfaces here
joinRpcThreadpool();

Assurer un accès anticipé

Pour garantir qu'un module de structure puisse accéder rapidement au service HAL, le service de configuration HAL doit démarrer le plus tôt possible, juste après que hwservicemanager soit prêt. Comme le service de configuration HAL ne lit pas les fichiers externes, il devrait être prêt rapidement après son lancement.