Dienst implementieren

Zur Vorbereitung auf die HAL-Implementierung können Sie grundlegenden ConfigStore-Schnittstellencode generieren und ihn dann an Ihre Anforderungen anpassen.

Schnittstellencode generieren

Führen Sie hidl-gen aus, um Boilerplate-Code für die Schnittstelle zu generieren. Wenn Sie beispielsweise Code für surfaceflinger generieren möchten, gehen Sie so vor:

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

Android.mk ändern

Ändern Sie als Nächstes die Datei Android.mk, um die Implementierungsdatei (<modulename>Configs.cpp) zu LOCAL_SRC_FILES hinzuzufügen und Build-Flags Makrodefinitionen zuzuordnen. Sie können beispielsweise surfaceflinger in hardware/interface/configstore/1.0/default/Android.mk ändern:

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

Wenn Android.mk mehrere ifeq-endif-Blöcke enthält, sollten Sie den Code in eine neue Datei (surfaceflinger.mk) verschieben und diese Datei dann in Android.mk einfügen.

Funktionen implementieren

Um die Funktionen zum Implementieren des HAL zu füllen, rufen Sie die Funktion _hidl_cb mit verschiedenen Werten zurück (abhängig von Build-Flags). Sie können beispielsweise die Funktionen für surfaceflinger in hardware/interfaces/configstore/1.0/default/SurfaceFlingerConfigs.cpp einfügen:

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
}

Achten Sie darauf, dass die Implementierung keine Funktion mit dem Namen HIDL_FETCH_interface-name enthält (z. B. HIDL_FETCH_ISurfaceFlingerConfigs). Diese Funktion ist für den HIDL-Passthrough-Modus erforderlich, der von configstore nicht verwendet wird (und verboten ist). ConfigStore muss immer im Binderized-Modus ausgeführt werden.

Als Dienst registrieren

Registrieren Sie schließlich alle Schnittstellenimplementierungen beim configstore-Dienst. Sie können beispielsweise surfaceflinger-Implementierungen in hardware/interfaces/configstore/1.0/default/service.cpp registrieren:

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();

Vorabzugriff sicherstellen

Damit ein Framework-Modul frühzeitig auf den HAL-Dienst zugreifen kann, sollte der Config-HAL-Dienst so früh wie möglich gestartet werden, direkt nachdem hwservicemanager bereit ist. Da der Config-HAL-Dienst keine externen Dateien liest, sollte er schnell nach dem Start bereit sein.