Bir HIDL paketinde tanımlanan her arabirim, paketin ad alanında kendi otomatik olarak oluşturulmuş C++ sınıfına sahiptir. İstemciler ve sunucular arayüzlerle farklı şekillerde ilgilenir:
- Sunucular arayüzleri uygular.
- İstemciler arayüzlerdeki yöntemleri çağırır.
Arayüzler sunucu tarafından isme göre kaydedilebilir veya HIDL tanımlı yöntemlere parametre olarak aktarılabilir. Örneğin, çerçeve kodu, HAL'den eşzamansız mesajları almak ve bu arayüzü kaydetmeden doğrudan HAL'ye geçirmek için bir arayüz görevi görebilir.
Sunucu uygulaması
IFoo
arayüzünü uygulayan bir sunucu, otomatik olarak oluşturulan IFoo
başlık dosyasını içermelidir:
#include <android/hardware/samples/1.0/IFoo.h>
Başlık, bağlantı kurulacak IFoo
arayüzünün paylaşılan kitaplığı tarafından otomatik olarak dışa aktarılır. Ö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(); } ... };
Bir sunucu arayüzünün uygulanmasını istemcinin kullanımına sunmak için şunları yapabilirsiniz:
- Arayüz uygulamasını
hwservicemanager
kaydedin (aşağıdaki ayrıntılara bakın),
VEYA - Arayüz uygulamasını bir arayüz yönteminin argümanı olarak iletin (ayrıntılar için bkz. Eşzamansız geri aramalar ).
Arayüz uygulamasını kaydederken hwservicemanager
işlemi, cihazda çalışan kayıtlı HIDL arayüzlerini ad ve sürüme göre takip eder. Sunucular bir HIDL arayüz uygulamasını ada göre kaydedebilir ve istemciler, hizmet uygulamalarını ada ve sürüme göre talep edebilir. Bu işlem android.hidl.manager@1.0::IServiceManager
HIDL arayüzüne hizmet eder.
Otomatik olarak oluşturulan her HIDL arabirim başlık dosyası ( IFoo.h
gibi), arabirim uygulamasını hwservicemanager
kaydetmek için kullanılabilecek bir registerAsService()
yöntemine sahiptir. İstemciler daha sonra hwservicemanager
arayüzü almak için bu adı kullanacaklarından gerekli olan tek argüman arayüz uygulamalarının adıdır:
::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
farklı arayüzlerin (veya aynı arayüzün farklı sürümlerinin) çakışma olmadan aynı örnek adlarıyla kaydedilmesini sağlamak için [package@version::interface, instance_name]
kombinasyonunu benzersiz olarak ele alır. registerAsService()
ı tam olarak aynı paket sürümü, arayüz ve örnek adı ile çağırırsanız, hwservicemanager
referansını önceden kayıtlı hizmete bırakır ve yenisini kullanır.
İstemci uygulaması
Tıpkı sunucunun yaptığı gibi, istemcinin de başvurduğu her arayüzü #include
etmesi gerekir:
#include <android/hardware/samples/1.0/IFoo.h>
Bir istemci bir arayüzü iki şekilde elde edebilir:
-
I<InterfaceName>::getService
aracılığıyla (hwservicemanager
aracılığıyla) - Bir arayüz yöntemi aracılığıyla
Otomatik oluşturulan her arayüz başlık dosyası, hwservicemanager
bir hizmet örneğini almak için kullanılabilecek statik bir getService
yöntemine sahiptir:
// getService will return nullptr if the service can't be found sp<IFoo> myFoo = IFoo::getService(); sp<IFoo> myAlternateFoo = IFoo::getService("another_foo");
Artık istemcinin bir IFoo
arayüzü var ve sanki yerel bir sınıf uygulamasıymış gibi ona yöntemleri çağırabiliyor. Gerçekte uygulama aynı süreçte, farklı bir süreçte veya hatta başka bir cihazda (HAL uzaktan kumandayla) çalışabilir. İstemci, paketin 1.0
sürümünde yer alan bir IFoo
nesnesinde getService
adını verdiğinden, hwservicemanager
, yalnızca bu uygulamanın 1.0
istemcilerle uyumlu olması durumunda bir sunucu uygulamasını döndürür. Pratikte bu, yalnızca 1.n
sürümüne (bir arayüzün x.(y+1)
sürümü) sahip sunucu uygulamalarının xy
genişletmesi (ve devralması) gerektiği anlamına gelir.
Ek olarak, farklı arayüzler arasında geçiş yapmak için castFrom
yöntemi sağlanmıştır. Bu yöntem, temel türün istenen türle aynı olduğundan emin olmak için uzak arabirime bir IPC çağrısı yaparak çalışır. İstenilen tür mevcut değilse nullptr
döndürülür.
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 aramalar
Mevcut HAL uygulamalarının çoğu eşzamansız donanımla konuşur; bu da, istemcileri meydana gelen yeni olaylar hakkında bilgilendirmek için eşzamansız bir yola ihtiyaç duydukları anlamına gelir. HIDL arabirimi işlevleri, HIDL arabirimi nesnelerini parametre olarak alabildiğinden, HIDL arabirimi eşzamansız geri çağırma olarak kullanılabilir.
Ö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
IFooCallback
parametresini alan örnek yeni yöntem:
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 sunucusudur ; IFooCallback
bir uygulamasını sağlar:
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 IFoo
arayüzünün mevcut bir örneğinin üzerinden de aktarabilir:
sp<IFooCallback> myFooCallback = new FooCallback(); myFoo.registerCallback(myFooCallback);
IFoo
uygulayan sunucu bunu bir sp<IFooCallback>
nesnesi olarak alır. Geri aramayı saklayabilir ve bu arayüzü kullanmak istediğinde istemciye geri arama yapabilir.
Ölüm alıcıları
Hizmet uygulamaları farklı bir süreçte çalışabildiğinden, istemci hayatta kalırken arayüzü uygulayan sürecin ölmesi mümkündür. Ölen bir süreçte barındırılan bir arayüz nesnesine yapılan tüm çağrılar, bir aktarım hatasıyla başarısız olur ( isOK()
işlevi false değerini döndürür). Böyle bir hatadan kurtulmanın tek yolu I<InterfaceName>::getService()
öğesini çağırarak hizmetin yeni bir örneğini istemektir. Bu, yalnızca çöken işlem yeniden başlatıldığında ve hizmetlerini servicemanager
yeniden kaydettirdiğinde işe yarar (bu genellikle HAL uygulamaları için geçerlidir).
Bununla reaktif olarak uğraşmak yerine, bir arayüzün istemcileri, bir hizmet sona erdiğinde bildirim almak için bir ölüm alıcısını da kaydedebilir. Alınan bir IFoo
arayüzünde bu tür bildirimlere kaydolmak için istemci aşağıdakileri yapabilir:
foo->linkToDeath(recipient, 1481 /* cookie */);
recipient
parametresi, HIDL tarafından sağlanan android::hardware::hidl_death_recipient
arayüzünün bir uygulaması olmalıdır; bu arayüz, arayüzü barındıran işlem öldüğünde RPC iş parçacığı havuzundaki bir iş parçacığından çağrılacak tek bir serviceDied()
yöntemini içerir:
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()
ile iletilen çerezi içerirken who
parametresi istemcideki hizmeti temsil eden nesneye yönelik zayıf bir işaretçi içerir. Yukarıda verilen örnek çağrı ile cookie
1481'e, who
ise foo
eşittir.
Ölüm alıcısını kaydettikten sonra kaydını silmek de mümkündür:
foo->unlinkToDeath(recipient);