HIDL C++

Android O, cihazdan bağımsız Android platformu ile cihaza ve satıcıya özel kod arasında net arayüzler tanımlamak için Android işletim sistemini yeniden tasarlar. Android, bu tür birçok arabirimi, hardware/libhardware C başlıkları olarak tanımlanan HAL arabirimleri biçiminde zaten tanımlar. HIDL, bu HAL arabirimlerini, C++ (aşağıda açıklanmıştır) veya Java'da istemci ve sunucu tarafı HIDL arabirimleri olabilen kararlı, sürümlü arabirimlerle değiştirir.

Bu bölümdeki sayfalar, hidl-gen derleyicisi tarafından HIDL .hal dosyalarından otomatik olarak oluşturulan dosyalar, bu dosyaların nasıl paketlendiği ve bu dosyaların C++ koduyla nasıl entegre edileceği hakkında ayrıntılar dahil olmak üzere HIDL arabirimlerinin C++ uygulamalarını açıklar. onları kullanır.

İstemci ve sunucu uygulamaları

HIDL arayüzleri, istemci ve sunucu uygulamalarına sahiptir:

  • Bir HIDL arabiriminin istemcisi , arabirim üzerindeki yöntemleri çağırarak arabirimi kullanan koddur.
  • Sunucu , istemcilerden gelen çağrıları alan ve (gerekirse) sonuçları döndüren bir HIDL arabiriminin bir uygulamasıdır.

libhardware HAL'lerinden HIDL HAL'lere geçişte, HAL uygulaması sunucu olur ve HAL'ı çağıran süreç istemci olur. Varsayılan uygulamalar hem doğrudan geçiş hem de ciltlenmiş HAL'ler sunabilir ve zamanla değişebilir:

Şekil 1. Eski HAL'ler için geliştirme ilerlemesi.

HAL istemcisini oluşturma

HAL kitaplıklarını makefile'e ekleyerek başlayın:

  • Yapın: LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
  • Soong: shared_libs: [ …, android.hardware.nfc@1.0 ]

Ardından, HAL başlık dosyalarını ekleyin:

#include <android/hardware/nfc/1.0/IFoo.h>
…
// in code:
sp<IFoo> client = IFoo::getService();
client->doThing();

HAL sunucusunu oluşturma

HAL uygulamasını oluşturmak için, HAL'inizi temsil eden .hal dosyalarına sahip olmanız ve hidl-gen üzerinde -Lmakefile veya -Landroidbp kullanarak -Lmakefile için makefile'ler oluşturmuş olmanız gerekir ( ./hardware/interfaces/update-makefiles.sh bunu aşağıdakiler için yapar: dahili HAL dosyalarıdır ve iyi bir referanstır). libhardware kullanarak bu işlerin çoğunu kolayca yapabilirsiniz.

HAL'inizi uygulamak için gerekli dosyaları oluşturmak için:

PACKAGE=android.hardware.nfc@1.0
LOC=hardware/interfaces/nfc/1.0/default/
m -j hidl-gen
hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \
    -randroid.hidl:system/libhidl/transport $PACKAGE
hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \
    -randroid.hidl:system/libhidl/transport $PACKAGE

HAL'in geçiş modunda çalışması için, /(system|vendor|...)/lib(64)?/hw/android.hardware.package@3.0-impl( OPTIONAL_IDENTIFIER ).so bulunan HIDL_FETCH_IModuleName işlevine sahip olmanız gerekir. burada OPTIONAL_IDENTIFIER , geçiş uygulamasını tanımlayan bir dizedir. Geçiş modu gereksinimleri, android.hardware.nfc@1.0-impl hedefini de oluşturan yukarıdaki komutlar tarafından otomatik olarak karşılanır, ancak herhangi bir uzantı kullanılabilir. Örneğin android.hardware.nfc@1.0-impl-foo , kendisini farklılaştırmak için -foo kullanır.

Bir HAL, başka bir HAL'ın alt sürümü veya uzantısıysa, bu ikili dosyayı adlandırmak için temel HAL kullanılmalıdır. Örneğin, android.hardware.graphics.mapper@2.1 uygulamaları hala android.hardware.graphics.mapper@2.0-impl( OPTIONAL_IDENTIFIER ) adlı bir ikili dosyada olmalıdır. Genellikle, buradaki OPTIONAL_IDENTIFIER , gerçek HAL sürümünü içerir. İkiliyi bu şekilde adlandırarak, 2.0 istemciler onu doğrudan alabilir ve 2.1 istemciler uygulamayı yükseltebilir.

Ardından, taslakları işlevsellikle doldurun ve bir arka plan programı kurun. Örnek arka plan programı kodu (geçiş desteği):

#include <hidl/LegacySupport.h>

int main(int /* argc */, char* /* argv */ []) {
    return defaultPassthroughServiceImplementation<INfc>("nfc");
}

defaultPassthroughServiceImplementation , sağlanan -impl kitaplığını dlopen() yapacak ve onu bir ciltlenmiş hizmet olarak sağlayacaktır. Örnek arka plan programı kodu (saf ciltleştirilmiş hizmet için):

int main(int /* argc */, char* /* argv */ []) {
    // This function must be called before you join to ensure the proper
    // number of threads are created. The threadpool will never exceed
    // size one because of this call.
    ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/);

    sp<INfc> nfc = new Nfc();
    const status_t status = nfc->registerAsService();
    if (status != ::android::OK) {
        return 1; // or handle error
    }

    // Adds this thread to the threadpool, resulting in one total
    // thread in the threadpool. We could also do other things, but
    // would have to specify 'false' to willJoin in configureRpcThreadpool.
    ::android::hardware::joinRpcThreadpool();
    return 1; // joinRpcThreadpool should never return
}

Bu arka plan programı genellikle $PACKAGE + "-service-suffix" (örneğin, android.hardware.nfc@1.0-service ) içinde yaşar, ancak herhangi bir yerde olabilir. Belirli bir HAL sınıfı için sepolicy , hal_<module> özniteliğidir (örneğin, hal_nfc) . Bu öznitelik, belirli bir HAL'ı çalıştıran arka plan programına uygulanmalıdır (aynı işlem birden çok HAL'e hizmet ediyorsa, ona birden çok öznitelik uygulanabilir).