Bu bölümde hizmetlerin nasıl kaydedilip keşfedileceği ve .hal
dosyalarındaki arabirimlerde tanımlanan yöntemlerin çağrılması yoluyla bir hizmete nasıl veri gönderileceği açıklanmaktadır.
Hizmetlerin kaydedilmesi
HIDL arayüz sunucuları (arayüz uygulayan nesneler), adlandırılmış hizmetler olarak kaydedilebilir. Kayıtlı adın arayüz veya paket adıyla ilişkili olması gerekmez. Herhangi bir ad belirtilmezse "varsayılan" adı kullanılır; bu, aynı arayüzün iki uygulamasını kaydetmesi gerekmeyen HAL'ler için kullanılmalıdır. Örneğin, her arayüzde tanımlanan hizmet kaydına yönelik C++ çağrısı şöyledir:
status_t status = myFoo->registerAsService(); status_t anotherStatus = anotherFoo->registerAsService("another_foo_service"); // if needed
HIDL arayüzünün sürümü arayüzün kendisinde bulunur. Otomatik olarak hizmet kaydıyla ilişkilendirilir ve her HIDL arabiriminde bir yöntem çağrısı ( android::hardware::IInterface::getInterfaceVersion()
) aracılığıyla alınabilir. Sunucu nesnelerinin kaydedilmesine gerek yoktur ve HIDL yöntemi parametreleri aracılığıyla, sunucuya HIDL yöntemi çağrıları yapacak başka bir işleme aktarılabilir.
Hizmetleri keşfetme
İstemci koduna göre istekler, belirli bir arayüz için ada ve sürüme göre yapılır ve istenen HAL sınıfında getService
çağrılır:
// C++ sp<V1_1::IFooService> service = V1_1::IFooService::getService(); sp<V1_1::IFooService> alternateService = V1_1::IFooService::getService("another_foo_service"); // Java V1_1.IFooService service = V1_1.IFooService.getService(true /* retry */); V1_1.IFooService alternateService = V1_1.IFooService.getService("another", true /* retry */);
HIDL arayüzünün her versiyonu ayrı bir arayüz olarak ele alınır. Böylece, IFooService
sürüm 1.1 ve IFooService
sürüm 2.2'nin her ikisi de "foo_service" olarak kaydedilebilir ve her iki arayüzde de getService("foo_service")
o arayüz için kayıtlı hizmeti alır. Bu nedenle çoğu durumda kayıt veya keşif için hiçbir ad parametresinin sağlanmasına gerek yoktur ("varsayılan ad" anlamına gelir).
Satıcı Arayüzü Nesnesi aynı zamanda iade edilen arayüzün taşıma yönteminde de rol oynar. android.hardware.foo@1.0
paketindeki bir IFoo
arayüzü için, IFoo::getService
tarafından döndürülen arayüz, giriş mevcutsa her zaman cihaz bildiriminde android.hardware.foo
için bildirilen taşıma yöntemini kullanır; ve taşıma yöntemi mevcut değilse nullptr döndürülür.
Bazı durumlarda hizmet almadan dahi hemen devam etmek gerekebilmektedir. Bu, (örneğin) bir müşteri hizmet bildirimlerini kendisi yönetmek istediğinde veya tüm hwservices'i alması ve alması gereken bir teşhis programında ( atrace
gibi) meydana gelebilir. Bu durumda, C++'da tryGetService
veya Java'da getService("instance-name", false)
gibi ek API'ler sağlanır. Java'da sağlanan eski API getService
de hizmet bildirimleriyle birlikte kullanılması gerekir. Bu API'nin kullanılması, istemcinin bu yeniden denemesiz API'lerden biriyle talep etmesinden sonra sunucunun kendisini kaydettirdiği yarış durumunu engellemez.
Hizmet ölümü bildirimleri
Bir hizmet sona erdiğinde bilgilendirilmek isteyen müşteriler, çerçeve tarafından gönderilen ölüm bildirimlerini alabilirler. Bildirim almak için müşterinin şunları yapması gerekir:
- HIDL sınıfını/arayüzünü
hidl_death_recipient
alt sınıfına alın (HIDL'de değil, C++ kodunda). -
serviceDied()
yöntemini geçersiz kılın. -
hidl_death_recipient
alt sınıfının bir nesnesini oluşturun. -
IDeathRecipient
'ın arayüz nesnesini ileterek izlemek için hizmettekilinkToDeath()
yöntemini çağırın. Bu yöntemin, ölüm alıcısının veya çağrıldığı proxy'nin sahipliğini almadığını unutmayın.
Bir sözde kod örneği (C++ ve Java benzerdir):
class IMyDeathReceiver : hidl_death_recipient { virtual void serviceDied(uint64_t cookie, wp<IBase>& service) override { log("RIP service %d!", cookie); // Cookie should be 42 } }; .... IMyDeathReceiver deathReceiver = new IMyDeathReceiver(); m_importantService->linkToDeath(deathReceiver, 42);
Aynı ölüm alıcısı birden fazla farklı hizmete kayıtlı olabilir.
Veri aktarımı
Veriler, .hal
dosyalarındaki arayüzlerde tanımlanan yöntemlerin çağrılması yoluyla bir servise gönderilebilir. İki tür yöntem vardır:
- Engelleme yöntemleri, sunucu bir sonuç üretene kadar bekler.
- Tek yönlü yöntemler verileri yalnızca tek yönde gönderir ve engellemez. RPC çağrılarında hareket halindeki veri miktarı uygulama sınırlarını aşarsa, çağrılar ya engellenebilir ya da bir hata göstergesi döndürebilir (davranış henüz belirlenmemiştir).
Değer döndürmeyen ancak oneway
olarak bildirilmeyen bir yöntem hâlâ engelliyor demektir.
HIDL arayüzünde bildirilen tüm yöntemler, HAL'den veya HAL'e tek bir yönde çağrılır. Arayüz hangi yönde çağrılacağını belirtmez. Çağrıların HAL'den kaynaklanması gereken mimariler, HAL paketinde iki (veya daha fazla) arayüz sağlamalı ve her işlemden uygun arayüzü sunmalıdır. İstemci ve sunucu kelimeleri, arayüzün çağrı yönüne göre kullanılır (yani HAL, bir arayüzün sunucusu ve başka bir arayüzün istemcisi olabilir).
Geri aramalar
Geri arama sözcüğü, senkronize geri arama ve senkronize olmayan geri arama ile ayırt edilen iki farklı kavramı ifade eder.
Veri döndüren bazı HIDL yöntemlerinde eşzamanlı geri aramalar kullanılır. Birden fazla değer döndüren (veya ilkel olmayan türde bir değer döndüren) bir HIDL yöntemi, sonuçlarını bir geri çağırma işlevi aracılığıyla döndürür. Yalnızca bir değer döndürülürse ve bu ilkel bir türse, geri çağırma kullanılmaz ve yöntemden değer döndürülür. Sunucu HIDL yöntemlerini uygular ve istemci geri aramaları uygular.
Eşzamansız geri aramalar, HIDL arayüzünün sunucusunun aramaları başlatmasına olanak tanır. Bu, ikinci bir arayüzün bir örneğinin birinci arayüzden geçirilmesiyle yapılır. İlk arayüzün istemcisi, ikinci arayüzün sunucusu olarak hareket etmelidir. Birinci arayüzün sunucusu ikinci arayüz nesnesindeki yöntemleri çağırabilir. Örneğin, bir HAL uygulaması, kendisini kullanan sürece, o süreç tarafından oluşturulan ve sunulan bir arayüz nesnesindeki yöntemleri çağırarak bilgileri eşzamansız olarak geri gönderebilir. Eşzamansız geri çağırma için kullanılan arayüzlerdeki yöntemler engelliyor olabilir (ve arayan kişiye değerleri döndürebilir) veya oneway
olabilir. Örnek için, HIDL C++' daki "Eşzamansız geri aramalar" konusuna bakın.
Bellek sahipliğini basitleştirmek için yöntem çağrıları ve geri aramalar yalnızca in
alır ve out
veya inout
parametrelerini desteklemez.
İşlem başına limitler
HIDL yöntemlerinde ve geri aramalarda gönderilen veri miktarına işlem başına sınırlama getirilmez. Ancak işlem başına 4 KB'yi aşan çağrılar aşırı kabul edilir. Eğer bu görülüyorsa, verilen HIDL arayüzünün yeniden mimarisinin oluşturulması tavsiye edilir. Diğer bir sınırlama ise birden fazla eş zamanlı işlemi gerçekleştirmek için HIDL altyapısının kullanabileceği kaynaklardır. Bir işleme çağrı gönderen birden çok iş parçacığı veya işlem veya alma işlemi tarafından hızlı bir şekilde ele alınmayan birden çok oneway
çağrı nedeniyle birden çok işlem aynı anda hareket halinde olabilir. Tüm eşzamanlı işlemler için kullanılabilen maksimum toplam alan varsayılan olarak 1 MB'tır.
İyi tasarlanmış bir arayüzde bu kaynak sınırlamalarının aşılmaması gerekir; eğer öyleyse, bunları aşan çağrı ya kaynaklar kullanılabilir hale gelene kadar bloke edebilir ya da bir aktarım hatası sinyali verebilir. İşlem başına limitlerin aşıldığı veya toplu hareket halindeki işlemler nedeniyle HIDL uygulama kaynaklarının taştığı her olay, hata ayıklamayı kolaylaştırmak için günlüğe kaydedilir.
Yöntem uygulamaları
HIDL, hedef dilde (C++ veya Java) gerekli türleri, yöntemleri ve geri aramaları bildiren başlık dosyaları oluşturur. HIDL tanımlı yöntemlerin ve geri aramaların prototipi, hem istemci hem de sunucu kodu için aynıdır. HIDL sistemi, arayan tarafta IPC aktarımı için verileri düzenleyen yöntemlerin proxy uygulamalarını ve aranan tarafta verileri yöntemlerin geliştirici uygulamalarına aktaran saplama kodunu sağlar.
Bir işlevi çağıran kişi (HIDL yöntemi veya geri çağırma), işleve aktarılan veri yapılarının sahipliğine sahiptir ve çağrıdan sonra da sahipliği korur; her durumda aranan kişinin depolamayı serbest bırakmasına veya serbest bırakmasına gerek yoktur.
- C++'da veriler salt okunur olabilir (buna yazma girişimleri segmentasyon hatasına neden olabilir) ve çağrı süresince geçerlidir. İstemci, çağrının ötesine yaymak için verileri derin kopyalayabilir.
- Java'da kod, verilerin yerel bir kopyasını (normal bir Java nesnesi) alır ve bu kopyayı saklayabilir, değiştirebilir veya çöp toplama işlemine izin verebilir.
RPC olmayan veri aktarımı
HIDL'nin RPC çağrısı kullanmadan veri aktarmanın iki yolu vardır: paylaşılan bellek ve Hızlı Mesaj Kuyruğu (FMQ), her ikisi de yalnızca C++'da desteklenir.
- Paylaşılan hafıza Yerleşik HIDL tipi
memory
tahsis edilen paylaşılan belleği temsil eden bir nesneyi iletmek için kullanılır. Paylaşılan hafızayı haritalamak için bir alma işleminde kullanılabilir. - Hızlı Mesaj Kuyruğu (FMQ) . HIDL, beklemesiz mesaj iletimini uygulayan şablonlu bir mesaj kuyruğu türü sağlar. Geçişli veya bağlayıcı modda çekirdeği veya zamanlayıcıyı kullanmaz (cihazlar arası iletişim bu özelliklere sahip olmayacaktır). Tipik olarak HAL, yerleşik HIDL tipi
MQDescriptorSync
veyaMQDescriptorUnsync
parametresi aracılığıyla RPC'den geçirilebilecek bir nesne oluşturarak kuyruğun sonunu ayarlar. Bu nesne, alma işlemi tarafından kuyruğun diğer ucunu ayarlamak için kullanılabilir.- Senkronizasyon kuyruklarının taşmasına izin verilmez ve yalnızca bir okuyucu bulunabilir.
- Senkronize olmayan kuyrukların taşmasına izin verilir ve çok sayıda okuyucuya sahip olabilir; bunların her birinin verileri zamanında okuması veya kaybetmesi gerekir.
FMQ hakkında daha fazla ayrıntı için bkz. Hızlı Mesaj Kuyruğu (FMQ) .