Dienst implementieren

Zur Vorbereitung auf die HAL-Implementierung können Sie einfachen 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. So generieren Sie beispielsweise 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 modifizieren

Ändern Sie als Nächstes die Datei Android.mk, um die Implementierungsdatei (<modulename>Configs.cpp) zu LOCAL_SRC_FILES hinzuzufügen und Build-Flags den 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, können Sie den Code in eine neue Datei (d. h. surfaceflinger.mk) verschieben und dann diese Datei aus 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 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 wird für den HIDL-Passthrough-Modus benötigt, der von configstore nicht verwendet (und verboten) ist. ConfigStore muss immer im Binder-Modus ausgeführt werden.

Als Dienst registrieren

Registrieren Sie abschließend alle Schnittstellenimplementierungen beim Dienst configstore. Beispielsweise können Sie 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 sichern

Damit ein Framework-Modul Vorabzugriff auf den HAL-Dienst erhalten kann, sollte der HAL-Konfigurationsdienst so früh wie möglich gestartet werden, kurz nachdem hwservicemanager bereit ist. Da der Konfigurations-HAL-Dienst keine externen Dateien liest, wird erwartet, dass er schnell nach dem Start einsatzbereit ist.