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. Beispiel: So generieren Sie Code für 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

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. Beispiel: Sie können 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 verschieben (z. B. surfaceflinger.mk) und diese Datei dann in Android.mk einfügen.

Funktionen implementieren

Um die Funktionen zur Implementierung der HAL auszufüllen, rufen Sie die Funktion _hidl_cb mit verschiedenen Werten auf (abhängig von den Build-Flags). Beispiel: Sie können die Funktionen für surfaceflinger in hardware/interfaces/configstore/1.0/default/SurfaceFlingerConfigs.cpp ausfüllen:

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
}

Die Implementierung darf keine Funktion mit dem Namen HIDL_FETCH_interface-name enthalten (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 Binder-Modus ausgeführt werden.

Als Dienst registrieren

Registrieren Sie schließlich alle Schnittstellenimplementierungen für den Dienst configstore. Beispiel: Sie können 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 vorab 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, ist er voraussichtlich schnell nach dem Start bereit.