Bu sayfada, hizmetlerin nasıl kaydedileceği ve keşfedileceği, ayrıca .hal
dosyalarındaki arayüzlerde tanımlanan yöntemleri çağırarak bir hizmete nasıl veri gönderileceği açıklanmaktadır.
Hizmetleri kaydet
HIDL arayüz sunucuları (arabirimi uygulayan nesneler), adlandırılmış hizmetler olarak kaydedilebilir. Kayıtlı adın arayüz veya paket adıyla ilgili olması gerekmez. Ad belirtilmezse "varsayılan" adı kullanılır. Bu ad, 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ı için C++ çağrısı şudur:
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 kendisine dahil edilir. Otomatik olarak hizmet kaydıyla ilişkilendirilir ve her HIDL arayüzünde bir yöntem çağrısı (android::hardware::IInterface::getInterfaceVersion()
) aracılığıyla alınabilir. Sunucu nesnelerinin kaydedilmesi gerekmez ve HIDL yöntem parametreleri aracılığıyla sunucuya HIDL yöntem çağrıları yapan başka bir sürece aktarılabilir.
Hizmetleri keşfetme
İstekler, istenen HAL sınıfında getService
çağrılarak belirli bir arayüz için isme ve sürüme göre istemci koduna göre yapı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 sürümü ayrı bir arayüz olarak değerlendirilir. Bu nedenle, IFooService
1.1 sürümü ve IFooService
2.2 sürümü "foo_service" olarak kaydedilebilir ve her iki arayüzdeki getService("foo_service")
, ilgili arayüz için kayıtlı hizmeti alır. Bu nedenle, çoğu durumda kayıt veya keşif için bir ad parametresi sağlamaya gerek yoktur (yani ad "varsayılan"dır).
Tedarikçi firma arayüzü nesnesi, döndürülen arayüzün aktarım yönteminde de rol oynar. android.hardware.foo@1.0
paketindeki IFoo
arayüzü için IFoo::getService
tarafından döndürülen arayüz, giriş varsa her zaman cihaz manifestinde android.hardware.foo
için tanımlanan aktarım yöntemini kullanır. Aktarım yöntemi kullanılamıyorsa nullptr döndürülür.
Bazı durumlarda, hizmeti almadan bile hemen devam etmeniz gerekebilir. Bu durum, örneğin bir istemcinin hizmet bildirimlerini kendisi yönetmek istemesi veya tüm hwservices'i alması ve alması gereken bir teşhis programında (atrace
gibi) ortaya çıkabilir. Bu durumda, C++'ta tryGetService
veya Java'da getService("instance-name", false)
gibi ek API'ler sağlanır. Java'da sağlanan eski APIgetService
de hizmet bildirimleriyle birlikte kullanılmalıdır. Bu API'nin kullanılması, istemcinin bu yeniden deneme yapılmayan API'lerden biriyle istek göndermesinden sonra sunucunun kendisini kaydettiği yarış koşulunu önlemez.
Hizmetin sonlandırılmasıyla ilgili bildirimler
Bir hizmet kullanımdan kaldırıldığında bilgilendirilmek isteyen istemciler, çerçeve tarafından gönderilen kullanımdan kaldırma bildirimlerini alabilir. İstemcinin bildirim alabilmesi için:
- HIDL sınıfı/arabirimi
hidl_death_recipient
için alt sınıf oluşturun (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.- İzlemek istediğiniz hizmette
IDeathRecipient
arayüz nesnesini iletereklinkToDeath()
yöntemini çağırın. Bu yöntemin, ölüm alıcısı veya çağrıldığı proxy'nin sahipliğini almadığını unutmayın.
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 kaydedilebilir.
Veri aktarımı
Veriler, .hal
dosyalarındaki arayüzlerde tanımlanan yöntemler çağrılarak bir hizmete gönderilebilir. İki tür yöntem vardır:
- Engelleme yöntemleri, sunucunun bir sonuç üretmesini bekler.
- Tek yönlü yöntemler verileri yalnızca tek bir yönde gönderir ve engellemez. RPC çağrılarında aktarılan veri miktarı uygulama sınırlarını aşarsa çağrılar engellenebilir veya bir hata göstergesi döndürülebilir (davranış henüz belirlenmemiştir).
Değer döndürmeyen ancak oneway
olarak tanımlanmayan bir yöntem hâlâ engellenmektedir.
HIDL arayüzünde tanımlanan tüm yöntemler, HAL'den veya HAL'e tek bir yönde çağrılır. Arayüz, hangi yönde çağrıldığını belirtmez. Çağrıları HAL'den başlatması gereken mimariler, HAL paketinde iki (veya daha fazla) arayüz sağlamalıdır 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 (ör. HAL bir arayüzün sunucusu ve başka bir arayüzün istemcisi olabilir).
Geri aramalar
Geri çağırma kelimesi, eşzamanlı geri çağırma ve eşzamansız geri çağırma olarak ayrılan iki farklı kavramı ifade eder.
Senkron geri çağırmalar, veri döndüren bazı HIDL yöntemlerinde 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ür ve bu değer ilkel bir türse geri çağırma işlevi kullanılmaz ve değer yöntemden döndürülür. Sunucu HIDL yöntemlerini, istemci ise geri çağırma işlevlerini uygular.
Eşzamansız geri çağırma, HIDL arayüzünün sunucusunun arama başlatmasına olanak tanır. Bu, ikinci arayüzün bir örneğinin ilk arayüzden geçirilmesiyle yapılır. İlk arayüzün istemcisi, ikinci arayüzün sunucusu gibi davranmalıdır. İlk arayüzün sunucusu, ikinci arayüz nesnesinde yöntemleri çağırabilir. Örneğin, bir HAL uygulaması, ilgili işlem tarafından oluşturulan ve sunulan bir arayüz nesnesinde yöntemleri çağırarak bilgileri ayarsız olarak kullanan işleme geri gönderebilir. Asenkron geri çağırma için kullanılan arayüzlerdeki yöntemler engelleme yapıyor olabilir (ve çağırana değer döndürüyor olabilir) veya oneway
olabilir. Örnek için HIDL C++'ta "Asenkron geri çağırmalar" bölümüne bakın.
Bellek sahipliğini basitleştirmek için yöntem çağrıları ve geri çağırma işlevleri yalnızca in
parametreleri alır ve out
veya inout
parametrelerini desteklemez.
İşlem başına sınırlar
HIDL yöntemleri ve geri çağırma işlevlerinde gönderilen veri miktarına işlem başına sınır uygulanmaz. Ancak işlem başına 4 KB'yı aşan çağrılar aşırı olarak kabul edilir. Bu durumla karşılaşırsanız ilgili HIDL arayüzünün yeniden tasarlanması önerilir. Diğer bir sınırlama, HIDL altyapısının birden fazla eşzamanlı işlemi işleyebilmesi için kullanabileceği kaynaklardır. Bir işleme çağrı gönderen birden fazla iş parçacığı veya işlem veya alıcı işlem tarafından hızlı bir şekilde işlenmeyen birden fazla oneway
çağrısı nedeniyle aynı anda birden fazla işlem gönderilebilir. Tüm eşzamanlı işlemler için varsayılan olarak kullanılabilen maksimum toplam alan 1 MB'tır.
İyi tasarlanmış bir arayüzde bu kaynak sınırlarının aşılması söz konusu olmamalıdır. Aksi takdirde, bu sınırları aşan çağrı, kaynaklar kullanılabilir hale gelene kadar engelleyebilir veya aktarım hatası sinyali verebilir. İşlem başına sınırların aşıldığı veya toplu uçuştaki işlemler tarafından HIDL uygulama kaynaklarının taştığı her durum, hata ayıklama işlemini 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 çağırma işlevlerini açıklayan başlık dosyaları oluşturur. HIDL tarafından tanımlanan yöntemlerin ve geri çağırma işlevlerinin prototipi hem istemci hem de sunucu kodu için aynıdır. HIDL sistemi, IPC aktarımı için verileri düzenleyen proxy yöntemlerini arayan tarafında ve verileri yöntemlerin geliştirici uygulamalarında ileten stub kodunu aranan tarafta sağlar.
Bir işlevi çağıran (HIDL yöntemi veya geri çağırma işlevi), işleve iletilen veri yapılarının sahibidir ve çağrıdan sonra da sahipliği korur. Her durumda, çağrılan tarafın depolama alanını boşaltması veya serbest bırakması gerekmez.
- C++'da veriler salt okunur olabilir (verilere yazma girişimleri segmentasyon hatasına neden olabilir) ve çağrı süresi boyunca geçerlidir. İstemci, verileri aramanın ötesine yaymak için derin kopyalayabilir.
- Java'da kod, verilerin yerel bir kopyasını (normal bir Java nesnesi) alır. Bu kopyayı saklayabilir ve değiştirebilir ya da çöp toplanması için izin verebilir.
RPC dışı veri aktarımı
HIDL, RPC çağrısı kullanmadan veri aktarmanın iki yolunu sunar: paylaşılan bellek ve hızlı mesaj kuyruğu (FMQ). Her ikisi de yalnızca C++'ta desteklenir.
- Paylaşılan anı. Yerleşik HIDL türü
memory
, ayrılmış paylaşılan belleği temsil eden bir nesneyi iletmek için kullanılır. Ortak belleği eşlemek için alıcı bir işlemde kullanılabilir. - Hızlı Mesaj Kuyruğu (FMQ). HIDL, beklemesiz mesaj aktarımı uygulayan şablonlu bir mesaj kuyruğu türü sağlar. Geçiş veya bağlayıcı modunda çekirdeği ya da planlayıcıyı kullanmaz (cihazlar arası iletişimde bu özellikler yoktur). HAL genellikle sıranın kendi tarafını kurar ve yerleşik HIDL
MQDescriptorSync
veyaMQDescriptorUnsync
türündeki bir parametre aracılığıyla RPC üzerinden iletilebilecek bir nesne oluşturur. Bu nesne, alıcı süreç tarafından kuyruğun diğer ucunu ayarlamak için kullanılabilir.- Senkronizasyon sıralarının taşmasına izin verilmez ve bu sıralarda yalnızca bir okuyucu bulunabilir.
- Senkronizasyon dışı sıraların taşmasına izin verilir ve bu sıralarda çok sayıda okuyucu bulunabilir. Bu okuyucuların her biri, verileri zamanında okumalı veya kaybeder.
Hızlı Mesaj Kuyruğu (FMQ) hakkında daha fazla bilgi için Hızlı Mesaj Kuyruğu (FMQ) başlıklı makaleyi inceleyin.