Arayüzler

Bir HIDL paketinde tanımlanan her arayüzün otomatik olarak oluşturulmuş kendi C++ sınıfı vardır inceleyebilirsiniz. İstemciler ve sunucular, arayüzlerle farklı şekillerde kullanabilirsiniz:

  • Sunucular arayüzleri uygular.
  • İstemciler, arayüzlerde yöntemleri çağırır.

Arayüzler sunucu tarafından ada göre kaydedilebilir veya ve HIDL'nin tanımladığı yöntemlere uygulanır. Örneğin çerçeve kodu, HAL'den eşzamansız mesajları almak ve bu arayüzü aktarmak için kullanılan arayüz doğrudan HAL'ye gönderebilirsiniz.

Sunucu uygulaması

IFoo arayüzünü uygulayan bir sunucu, Otomatik olarak oluşturulan IFoo başlık dosyası:

#include <android/hardware/samples/1.0/IFoo.h>

Başlık, dosyanın paylaşılan kitaplığı tarafından otomatik olarak dışa aktarılır Bağlantı oluşturulacak IFoo arayüzü. Örnek IFoo.hal:

// IFoo.hal
interface IFoo {
    someMethod() generates (vec<uint32_t>);
    ...
}

IFoo arayüzünün sunucu uygulaması için örnek iskelet:

// From the IFoo.h header
using android::hardware::samples::V1_0::IFoo;

class FooImpl : public IFoo {
    Return<void> someMethod(foo my_foo, someMethod_cb _cb) {
        vec<uint32_t> return_data;
        // Compute return_data
        _cb(return_data);
        return Void();
    }
    ...
};

Sunucu arayüzü uygulamasını bir istemcinin kullanımına sunmak için şunları yapabilir:

  1. Arayüz uygulamasını hwservicemanager (aşağıdaki ayrıntılara bakın),

    VEYA

  2. Arayüz uygulamasını etkileyerek arayüz yöntemi (detaller için, bkz. Eşzamansız geri çağırma).

Arayüz uygulamasını kaydederken, hwservicemanager işlemi, kayıtlı HIDL arayüzlerini takip eder. adı ve sürümüne göre cihazda çalıştırılıyor. Sunucular HIDL arayüzü kaydedebilir ada göre uygulama ve müşteriler ada göre hizmet uygulamaları isteyebilir ve sürümünü seçin. Bu işlem HIDL arayüzüne sunar android.hidl.manager@1.0::IServiceManager

Otomatik olarak oluşturulan her HIDL arayüzü başlık dosyası (IFoo.h gibi) işlevi kaydetmek için kullanılabilecek bir registerAsService() yöntemi vardır hwservicemanager ile arayüzün nasıl uygulandığını öğrenin. Tek gerekli bağımsız değişken, istemciler olarak arayüz uygulamalarının adıdır. hwservicemanager uygulamasından arayüzü almak için bu adı kullanın daha sonra:

::android::sp<IFoo> myFoo = new FooImpl();
::android::sp<IFoo> mySecondFoo = new FooAnotherImpl();
status_t status = myFoo->registerAsService();
status_t anotherStatus = mySecondFoo->registerAsService("another_foo");

hwservicemanager, Etkinleştirmek için [package@version::interface, instance_name] benzersiz farklı arayüzleri (veya aynı arayüzün farklı sürümlerini) aynı örnek adlarına sahip olur ve bunların çakışma olmasını sağlar. Arama yaptığınızda registerAsService() ile tamamen aynı paket sürümünü, arayüzünü ve belirtirse hwservicemanager, yenisini kullanır.

İstemci uygulaması

Sunucunun yaptığı gibi, istemcinin de her arayüzde #include işlemi yapması gerekir şu anlama gelir:

#include <android/hardware/samples/1.0/IFoo.h>

Müşteriler, arayüze iki şekilde ulaşabilir:

  • I<InterfaceName>::getService üzerinden ( hwservicemanager)
  • Bir arayüz yöntemiyle

Otomatik olarak oluşturulan her arayüz başlığı dosyasının statik bir getService öğesi vardır web sitesinden bir hizmet örneği almak için kullanılabilecek bir yöntem hwservicemanager:

// getService returns nullptr if the service can't be found
sp<IFoo> myFoo = IFoo::getService();
sp<IFoo> myAlternateFoo = IFoo::getService("another_foo");

Böylece istemcinin bir IFoo arayüzü vardır ve müşterinin bunu sanki yerel bir sınıf uygulamasıymış gibi ele alacağız. Gerçekte ise uygulama, Aynı işlemde, farklı bir işlemde, hatta başka bir cihazda çalışabilir (HAL uzaktan erişimli). Çünkü müşteri getService adlı kullanıcıyı Paketin 1.0 sürümünden IFoo nesne dahil edildi, hwservicemanager, yalnızca uygulama 1.0 istemcileriyle uyumludur. Pratikte bu yalnızca 1.n sürümüne (sürüm 1.n) sahip sunucu uygulamaları anlamına gelir Bir arayüzün x.(y+1) kadarı genişletilmelidir (devralınacak kaynak) x.y).

Ayrıca, uygulamalar arasında yayın yapmak için castFrom yöntemi sağlanır. farklı arayüzler. Bu yöntem, uzaktan kumandaya bir IPC çağrısı yapılarak çalışır kullanılan türle aynı olduğundan emin olmak için yeni arayüze istendi. İstenen tür kullanılamıyorsa nullptr geri döndü.

sp<V1_0::IFoo> foo1_0 = V1_0::IFoo::getService();
sp<V1_1::IFoo> foo1_1 = V1_1::IFoo::castFrom(foo1_0);

Eşzamansız geri çağırma işlevleri

Mevcut HAL uygulamalarının çoğunda eşzamansız donanımlar kullanılıyor. etkinlikleri hakkında müşterileri bilgilendirmek için eşzamansız bir yönteme meydana geldi. HIDL, eşzamansız geri çağırma olarak HIDL arayüzü kullanılabilir. arayüz işlevleri, HIDL arayüz nesnelerini parametre olarak alabilir.

Örnek arayüz dosyası IFooCallback.hal:

package android.hardware.samples@1.0;
interface IFooCallback {
    sendEvent(uint32_t event_id);
    sendData(vec<uint8_t> data);
}

IFoo ürününde IFooCallback parametresi:

package android.hardware.samples@1.0;
interface IFoo {
    struct Foo {
       int64_t someValue;
       handle myHandle;
    };

    someMethod(Foo foo) generates (int32_t ret);
    anotherMethod() generates (vec<uint32_t>);
    registerCallback(IFooCallback callback);
};

IFoo arayüzünü kullanan istemci, IFooCallback arayüzünün sunucusu; sağladığı IFooCallback uygulaması:

class FooCallback : public IFooCallback {
    Return<void> sendEvent(uint32_t event_id) {
        // process the event from the HAL
    }
    Return<void> sendData(const hidl_vec<uint8_t>& data) {
        // process data from the HAL
    }
};

Ayrıca bunu, istemcinin mevcut bir örneği üzerinden de IFoo arayüzü:

sp<IFooCallback> myFooCallback = new FooCallback();
myFoo.registerCallback(myFooCallback);

IFoo öğesini uygulayan sunucu bunu sp<IFooCallback> nesne algılandı. Geri çağırmayı depolayabilir ve bu arayüzü kullanmak istediğinde istemciye geri bildirim gönderir.

Vefat edenler

Hizmet uygulamaları farklı bir süreçte çalışabileceğinden, kullanıcı hayatta kaldığında, arayüzü uygulama işleminin kapanacağını hatırlatır. Ölen bir işlemde barındırılan arayüz nesnesine yapılan tüm çağrılar başarısız oluyor (isOK(), false değerini döndürür). Projenizi yönetmenin bir hatadan kurtulmak için, hizmetin yeni bir örneğini I<InterfaceName>::getService() aranıyor. Bu yalnızca aşağıdaki durumlarda çalışır: kilitlenen işlem yeniden başlatılmış ve hizmetleri servicemanager (HAL uygulamaları için genellikle geçerlidir).

Bir arayüzün müşterileri bununla reaktif şekilde uğraşmak yerine, Bir hizmet öldüğünde bildirim almak için ölüm alıcısı kaydedin. Alınan IFoo arayüzünde bu tür bildirimlere kaydolmak için şunları yapabilir:

foo->linkToDeath(recipient, 1481 /* cookie */);

recipient parametresi, HIDL tarafından sağlanan android::hardware::hidl_death_recipient arayüzü, Bu yöntem, adı verilen tek bir serviceDied() yöntemini içerir. arayüzü barındıran işlem öldüğünde, RPC iş parçacığındaki bir iş parçacığından:

class MyDeathRecipient : public android::hardware::hidl_death_recipient {
    virtual void serviceDied(uint64_t cookie, const android::wp<::android::hidl::base::V1_0::IBase>& who) {
       // Deal with the fact that the service died
    }
}

cookie parametresi, linkToDeath() ise who parametresi bir istemcide hizmeti temsil eden nesneye yönelik zayıf işaretçi. Şununla yukarıda verilen örnek çağrı, cookie eşittir 1481 ve who foo değerine eşit.

Ayrıca, ölen bir alıcıyı kaydettirdikten sonra kaydı iptal edebilirsiniz:

foo->unlinkToDeath(recipient);