Implementierung des Dienstes

Zur Vorbereitung der HAL-Implementierung können Sie grundlegenden ConfigStore-Schnittstellencode generieren und ihn dann entsprechend Ihren Anforderungen ändern.

Generieren von Schnittstellencode

Um Boilerplate-Code für die Schnittstelle zu generieren, führen Sie hidl-gen aus. 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

Ändern von Android.mk

Ä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. Beispielsweise können Sie 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 erwägen, Ihren Code in eine neue Datei (d. h. surfaceflinger.mk ) zu verschieben und diese Datei dann aus Android.mk einzubinden.

Funktionen implementieren

Um die Funktionen zur Implementierung des HAL zu füllen, rufen Sie die Funktion _hidl_cb mit unterschiedlichen Werten zurück (abhängig von Build-Flags). Beispielsweise können Sie die Funktionen für surfaceflinger in hardware/interfaces/configstore/1.0/default/SurfaceFlingerConfigs.cpp fü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
}

Stellen Sie sicher, dass die Implementierung keine Funktion mit dem Namen HIDL_FETCH_ interface-name enthält (z. B. HIDL_FETCH_ISurfaceFlingerConfigs ). Diese Funktion wird für den HIDL-Passthrough-Modus benötigt, der von configstore nicht verwendet (und verboten) wird. ConfigStore muss immer im binderisierten Modus ausgeführt werden.

Registrierung als Dienst

Registrieren Sie abschließend alle Schnittstellenimplementierungen beim configstore Dienst. 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();

Gewährleistung eines frühen Zugriffs

Um sicherzustellen, dass ein Framework-Modul frühzeitig auf den HAL-Dienst zugreifen kann, sollte der Konfigurations-HAL-Dienst so früh wie möglich starten, direkt nachdem hwservicemanager bereit ist. Da der Konfigurations-HAL-Dienst keine externen Dateien liest, wird erwartet, dass er nach dem Start schnell bereit ist.