前言
这一系列文章基本都以英文原版的形式表现出来。
会补充一些自己在学习的过程中遇到的不懂的地方加上自己的一些见解。
官方文档(要梯子):https://source.android.com/devices/architecture/hidl
Android HIDL基础篇(一)
This section describes how to register and discover services and how to send data to a service by calling methods defined in interfaces in .halfiles.
HIDL interface servers (objects implementing the interface) can be registered as named services. The registered name need not be related to the interface or package name. If no name is specified, the name “default” is used; this should be used for HALs that do not need to register two implementations of the same interface. For example, the C++ call for service registration defined in each interface is:
registerAsService(); registerAsService("another_foo_service"); // if neededThe version of a HIDL interface is included in the interface itself. It is automatically associated with service registration and can be retrieved via a method call (android::hardware::IInterface::getInterfaceVersion()) on every HIDL interface. Server objects need not be registered and can be passed via HIDL method parameters to another process that will make HIDL method calls into the server.
作为服务端接口,可以被注册为自定义名称,否则是default。
在HIDL接口包含在自身接口的版本中,它能自动关联到注册的服务上而且能够通过方法调用被检索。并且服务端对象不需要注册也能通过HIDL方法将参数转递给另一个进程。
Requests by client code are made for a given interface by name and by version, calling getService on the desired HAL class:
sp<V1_1::IFooService> service = V1_1::IFooService::getService(); sp<V1_1::IFooService> alternateService = 1_1::IFooService::getService("another_foo_service");Each version of a HIDL interface is treated as a separate interface. Thus, IFooService version 1.1 and IFooService version 2.2 can both be registered as “foo_service” and getService(“foo_service”) on either interface gets the registered service for that interface. This is why, in most cases, no name parameter needs to be supplied for registration or discovery (meaning name “default”).The Vendor Interface Object also plays a part in the transport method of the returned interface. For an interface IFoo in package android.hardware.foo@1.0, the returned interface by IFoo::getService always use the transport method declared for android.hardware.foo in the device manifest if the entry exists; and if the transport method is not available, nullptr is returned.
客户端请求的代码是由给定的接口版本名称调用HAL类中的getService方法构成的。
每个版本中的HIDL接口被视为一个单独的接口。
供应商接口对象在返回接口以及传送方法起了一定的作用。
Clients who want to be notified when a service dies can receive death notifications delivered by the framework. To receive notifications, the client must:
eg.
Subclass the HIDL class/interface hidl_death_recipient (in C++ code, not in HIDL).Override its serviceDied() method.Instantiate an object of the hidl_death_recipient subclass.Call the linkToDeath() method on the service to monitor, passing in the IDeathRecipient’s interface object. 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);The same death recipient may be registered on multiple different services.
当客户端一个服务死亡的时候将会收到来自framework的死亡通知。
一个死亡接受者会被多个不同的服务注册。
Data may be sent to a service by calling methods defined in interfaces in .hal files. There are two kinds of methods:
Blocking methods wait until the server has produced a result.Oneway methods send data in only one direction and do not block. If the amount of data in-flight in RPC calls exceeds implementation limits, the calls may either block or return an error indication (behavior is not yet determined).A method that does not return a value but is not declared as oneway is still blocking.
All methods declared in a HIDL interface are called in a single direction, either from the HAL or into the HAL. The interface does not specify which direction it will be called in. Architectures that need calls to originate from the HAL should provide two (or more) interfaces in the HAL package and serve the appropriate interface from each process. The words client and server are used with respect to the calling direction of the interface (i.e. the HAL can be a server of one interface and a client of another interface).
通过调用定义在.hal文件中的接口可以实现数据传送给服务端。有两种方式,有值返回则是Blocking,否则是Oneway。
在HIDL接口上声明的方法都是单向调用的,所以对每个进程都需要选择合适的接口。
The word callback refers to two different concepts, distinguished by synchronous callback and asynchronous callback.
Synchronous callbacks are used in some HIDL methods that return data. A HIDL method that returns more than one value (or returns one value of non-primitive type) returns its results via a callback function. If only one value is returned and it is a primitive type, a callback is not used and the value is returned from the method. The server implements the HIDL methods and the client implements the callbacks.
Asynchronous callbacks allow the server of a HIDL interface to originate calls. This is done by passing an instance of a second interface through the first interface. The client of the first interface must act as the server of the second. The server of the first interface can call methods on the second interface object. For example, a HAL implementation may send information asynchronously back to the process that is using it by calling methods on an interface object created and served by that process. Methods in interfaces used for asynchronous callback may be blocking (and may return values to the caller) or oneway. For an example, see “Asynchronous callbacks” in HIDL C++.
To simplify memory ownership, method calls and callbacks take only in parameters and do not support out or inout parameters .
同步回调是用来调用HIDL方法实现返回多个值或者一个非基本类的值。
异步回调是指两个接口,第一个接口的客户端作为第二个接口的服务端,从而使得第一个接口的服务端能够直接调用第二个接口对象的方法。
为了简化内存所有权,在调用方法和回调的时候尽量都使用in。
Per-transaction limits may be imposed on the amount of data sent in HIDL methods and callbacks. The limits are yet to be determined but may be as small as 4K. Calls exceeding these limits return failure immediately. Another limitation is the resources available to the HIDL infrastructure to handle multiple simultaneous transactions. Multiple transactions can be in-flight simultaneously due to multiple threads or processes sending calls to a process or multiple oneway calls that are not handled quickly by the receiving process.In a well-designed interface, exceeding these resource limitations should not happen; if it does, the call which exceeded them may either block until resources become available or signal a transport error. Each occurrence of exceeding per-transaction limits or overflowing HIDL implementation resources by aggregate in-flight transactions is logged to facilitate debugging.
每次传输的限制条件包括:HIDL 方法或回调中所传输的数据量;处理多个同时事务时的 HIDL 基础结构的可用资源量;
HIDL generates header files declaring the necessary types, methods, and callbacks in the target language (C++ or Java). The prototype of HIDL-defined methods and callbacks is the same for both client and server code. The HIDL system provides proxy implementations of the methods on the caller side that organize the data for IPC transport, and stub code on the callee side that passes the data into developer implementations of the methods.
The caller of a function (HIDL method or callback) has ownership of the data structures passed into the function, and retains ownership after the call; in all cases the callee does not need to free or release the storage.
In C++, the data may be read-only (attempts to write to it may cause a segmentation fault) and are valid for the duration of the call. The client can deep-copy the data to propagate it beyond the call.In Java, the code receives a local copy of the data (a normal Java object), which it may keep and modify or allow to be garbage-collected.HIDL头文件包含了必须的方法,类型和回调。HIDL定义的方法和回调的原型在客户端和服务端必须一致。
在调用端 利用proxy组织IPC传输数据,被调用端 利用stub将数据传递给开发人员。
调用端在调用函数的时候就会有数据接口的所有权,并且将一直拥有,这也就表示所有被调用端不需要释放存储。
HIDL has two ways to transfer data without using an RPC call: shared memory and a Fast Message Queue (FMQ), both supported only in C++.
Shared memory. The built-in HIDL type memory is used to pass an object representing shared memory that has been allocated. Can be used in a receiving process to map the shared memory.Fast Message Queue (FMQ). HIDL provides a templated message queue type that implements no-wait message-passing. It does not use the kernel or scheduler in passthrough or binderized mode (inter-device communication will not have these properties). Typically, the HAL sets up its end of the queue, creating an object that can be passed through RPC via a parameter of built-in HIDL type MQDescriptorSync or MQDescriptorUnsync. This object can be used by the receiving process to set up the other end of the queue. Sync queues are not allowed to overflow, and can only have one reader.Unsync queues are allowed to overflow, and can have many readers, each of which must read data in time or lose it.Neither type is allowed to underflow (read from an empty queue will fail), and each type can only have one writer.非远程过程调用,HIDL还可以通过共享内存和快速消息队列进行传输数据。