本頁說明如何註冊及探索服務,以及如何傳送
呼叫 .hal
中介面中定義的方法,將資料傳送至服務
檔案。
註冊服務
可註冊 HIDL 介面伺服器 (實作此介面的物件) 標示為已命名的服務註冊的名稱與介面無關,或 套件名稱。如果沒有指定名稱,名稱為「default」這應該 HAL 適用不需要為同一個容器註冊 存取 API舉例來說, 介面如下:
status_t status = myFoo->registerAsService(); status_t anotherStatus = anotherFoo->registerAsService("another_foo_service"); // if needed
介面本身會包含 HIDL 介面的版本。是
會自動連結服務註冊,並可透過
方法呼叫 (android::hardware::IInterface::getInterfaceVersion()
)
在每個 HIDL 介面上運作伺服器物件不需要註冊,且可以傳遞
經由 HIDL 方法參數傳送至另一個進行 HIDL 方法的處理程序
複製到伺服器中
探索服務
用戶端程式碼發出的要求會以名稱和下列順序,向特定介面發出:
對所需的 HAL 類別呼叫 getService
:
// 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 介面版本都會視為獨立介面。因此,
IFooService
1.1 版和 IFooService
2.2 版
皆可註冊為「foo_service」和
任一介面上的 getService("foo_service")
都會取得
該介面的 Service因此在大多數情況下,您不需要提供名稱參數
提供註冊或探索服務 (即名稱「預設」)。
供應商介面物件也會在
傳回的介面。適用於套件中的介面 IFoo
android.hardware.foo@1.0
,由
IFoo::getService
一律會使用宣告的傳輸方法
android.hardware.foo
(如有)。
如果沒有可用的傳輸方法,則會傳回 nullptr。
在某些情況下,可能必須立即繼續執行,即使沒有
取得服務舉例來說,如果用戶端想要
管理服務通知本身或在診斷程式中 (例如
atrace
),需要取得並擷取所有 hwservices。於
在這個例子中,在 C++ 或tryGetService
Java 中的 getService("instance-name", false)
。舊版 API
以 Java 提供的 getService
也必須與服務搭配使用
通知。使用這個 API 無法避免伺服器發生競爭狀況
在用戶端使用其中一個非重試 API 要求之後,便會自行註冊。
服務死亡通知
想在服務故障時收到通知的客戶 由架構傳送的通知為了接收通知,用戶端 必須:
- 將 HIDL 類別/介面
hidl_death_recipient
設為子類別 (在 C++ 中) 而非 HIDL)。 - 覆寫其
serviceDied()
方法。 - 將
hidl_death_recipient
子類別的物件例項化。 - 在服務上呼叫
linkToDeath()
方法進行監控, 傳入IDeathRecipient
的介面物件。請注意,此 方法沒有取得死亡者或其 Proxy 的擁有權 方法。
虛擬程式碼示例 (C++ 和 Java 類似):
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);
同一名死亡者可以登錄在多項不同服務中。
資料移轉
您可以呼叫在以下介面中定義的方法,將資料傳送至服務:
.hal
個檔案。方法有兩種:
- 封鎖方法,會等到伺服器產生 結果。
- 單向方法只會以單一方向傳送資料, 封鎖。如果 RPC 呼叫的傳輸資料量超過實作項目 這些呼叫可能會封鎖或傳回錯誤指標 (行為 尚未確定)。
未宣告為未傳回值的方法
「oneway
」仍在封鎖中。
HIDL 介面上宣告的所有方法都會以單一方向呼叫。 從 HAL 轉換為 HAL介面會未指定 開始傾印需要發出呼叫的架構 HAL 應在 HAL 套件中提供兩個 (或更多) 介面, 並根據每個程序產生的適當介面「client」和 server 用於表示介面的呼叫方向 (也就是 HAL 可以是不同介面的伺服器和另一個介面的用戶端) 介面)。
回呼
「回呼」一詞是指兩種不同的概念, 同步回呼和非同步回呼。
同步回呼會用於某些會傳回 HIDL 方法的 HIDL 方法。 資料。會傳回多個值 (或 非原始型別) 會透過回呼函式傳回結果。如果只有一個 值也會傳回,而且這是原始型別,則未使用回呼,且 值。伺服器會實作 HIDL 方法, 用戶端會實作回呼。
「非同步回呼」可讓 HIDL 介面的伺服器執行以下作業:
發出呼叫。方法是傳送第二個介面的執行個體
第一個介面第一個介面的用戶端必須做為
伺服器第一個介面的伺服器可以在
第二個介面物件舉例來說,HAL 實作項目可以傳送
非同步傳回使用這個方法的處理程序,方法是呼叫
由該程序建立及提供的介面物件。使用介面中的方法
非同步回呼可能處於封鎖狀態 (而且可能會將值傳回呼叫端)
或 oneway
。如需範例,請參閱「非同步回呼」英吋
HIDL C++。
為了簡化記憶體擁有權,方法呼叫和回呼僅需要
in
參數,不支援 out
或
inout
參數。
單筆交易限額
每次交易上限不適用於 HIDL 傳送的資料量
方法和回呼。不過,每筆交易的呼叫超過 4 KB
視為過度處理如果看見此情況,請重新建構指定的 HIDL 介面
建議。另一個限制是 HIDL 可用的資源
適用於同時處理多筆交易的基礎架構。多個
交易可能會因為多個執行緒或
處理將呼叫傳送至處理程序或多個 oneway
呼叫
無法透過收件程序迅速處理最大總空間
所有並行交易都可以使用預設值 1MB。
在設計精良的介面中,超過這些資源限制不應 發生;在這種情況下,超出範圍的呼叫可封鎖,直到 或指出傳輸錯誤每當 超過個別交易上限或溢位 HIDL 實作資源。 系統會記錄所有傳輸期間的匯總交易,以便偵錯。
方法實作
HIDL 會產生標頭檔案來宣告必要的類型、方法和 以目標語言 (C++ 或 Java) 為基礎的回呼。HIDL 定義的原型 用戶端與伺服器程式碼的方法和回呼相同。HIDL 系統提供 Proxy 實作方法,在 呼叫端 (整理 IPC 傳輸資料) 的呼叫端,以及 stub 呼叫端程式碼,將資料傳到開發人員實作 方法。
函式的呼叫者 (HIDL 方法或回呼) 具備資料擁有權 傳遞至函式,並在呼叫後保留擁有權;英吋 任何情況下,受話方不需要釋出儲存空間或釋出儲存空間。
- 在 C++ 中,資料可能是唯讀 (如果您嘗試寫入資料,可能會導致 片段錯誤),且在呼叫期間都有效。客戶可以 然後深複製資料,在呼叫以外的地方傳播
- 在 Java 中,程式碼會接收本機的資料副本 (一般 Java 物件), 可能會保留並修改,或者允許進行垃圾收集。
非遠端程序呼叫 (RPC) 資料移轉
HIDL 在不使用 RPC 呼叫的情況下轉移資料的方式有兩種:已分享 和快速訊息佇列 (FMQ) 均僅支援 C++。
- 共用記憶體:內建的 HIDL 類型:
memory
用於傳遞物件,代表已分配的共用記憶體。 可在接收程序中使用,對應共用記憶體。 - 快速訊息佇列 (FMQ)。HIDL 是按照範本分類的訊息
佇列類型,實作無等待訊息傳遞。不會使用核心
採用直通式或 Binder 模式的排程器 (裝置間通訊沒有
擁有這些屬性)。HAL 通常會設定佇列的末端
建立一個可透過內建參數通過 RPC 的物件
HIDL 類型:
MQDescriptorSync
或MQDescriptorUnsync
。這個 物件,可由接收程序用來設定佇列的另一端。- 同步佇列不能溢位,只能有一個 讀取器。
- 取消同步處理佇列會溢位,且可以有多個讀取器。 而且每個容器都必須及時讀取或遺失資料
如要進一步瞭解 FMQ,請參閱 快速訊息佇列 (FMQ)。