Pour préparer l'implémentation de la HAL, vous pouvez générer un code d'interface ConfigStore de base, puis le modifier en fonction de vos besoins.
Générer le code d'interface
Pour générer un code récurrent 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
Modifier 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 compilation 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 (par exemple, surfaceflinger.mk), puis d'inclure ce fichier à partir de Android.mk.
Implémenter des fonctions
Pour remplir les fonctions afin d'implémenter la HAL, rappelez la fonction _hidl_cb avec différentes valeurs (conditionnées par les indicateurs de compilation). 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 de transfert
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 dans le 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();
Garantir un accès anticipé
Pour s'assurer qu'un module de framework peut bénéficier d'un accès anticipé au service HAL, le service HAL de configuration doit démarrer le plus tôt possible, juste après que hwservicemanager est prêt. Comme le service HAL de configuration ne lit pas les fichiers externes, il devrait être prêt rapidement après son lancement.