HwServiceManager 学习

HwServiceManager介绍

和FW的ServiceManager类似,HwServiceManager是用来管理硬件HAL的service的,下面图的③④的通信方式都需要最终走hwservicemanager(HW Service Process)请求对应的服务,之后通过获得的代理对象来调用(Java or Native)HAL的接口。

image

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

path system/hwservicemanager

.
├── AccessControl.cpp
├── AccessControl.h
├── Android.bp
├── HidlService.cpp
├── HidlService.h
├── hwservicemanager.rc
├── MODULE_LICENSE_APACHE2
├── NOTICE
├── OWNERS
├── service.cpp
├── ServiceManager.cpp
├── ServiceManager.h
├── TokenManager.cpp
├── TokenManager.h
├── Vintf.cpp
└── Vintf.h

从hwservicemanager.rc中可以看到此service作为系统服务开机启动

1
2
3
4
5
6
7
8
9
10
11
service hwservicemanager /system/bin/hwservicemanager
user system
disabled
group system readproc
critical
onrestart setprop hwservicemanager.ready false
onrestart class_restart hal
onrestart class_restart early_hal
writepid /dev/cpuset/system-background/tasks
class animation
shutdown critical

之后我们分析一下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
code path service.cpp


int main() {
// 配置kernel binder线程池线程数
configureRpcThreadpool(1, true /* callerWillJoin */);

// ServiceManager.cpp中定义的对象,管理类,hal service需要获取这个对象来
// 注册自己到hw service
ServiceManager *manager = new ServiceManager();

// 把自己做为第一个服务添加进manager,注意这里的名字"default”,
// 这个名字很重要,在之后的添加服务中,要先获取这个叫default的service
// 通过这个service向servicemanager中添加服务,类似servicemanager的0号service
if (!manager->add(serviceName, manager)) {
ALOGE("Failed to register hwservicemanager with itself.");
}

// tokenmanager有待分析,从名字看是通信相关的
TokenManager *tokenManager = new TokenManager();

// 同样添加到service 中
if (!manager->add(serviceName, tokenManager)) {
ALOGE("Failed to register ITokenManager with hwservicemanager.");
}

// Tell IPCThreadState we're the service manager
// 将ServiceManager套了一层类,BnHwServiceManager,既然是Bn开头,
// 应该是服务端的,为了加通信层接口transact,可以理解为添加通信层
sp<BnHwServiceManager> service = new BnHwServiceManager(manager);

// 之后把这个BnHwServiceManager设置到IPCThreadState中,作为ContextObject
// IPCThreadState不是原来的FW中libbinder中的,而是libhwbinder中的,
// 包括ProcessState,他们操作的设备节点不同
IPCThreadState::self()->setTheContextObject(service);

// Then tell the kernel
// 告诉kernel这个context是manager
ProcessState::self()->becomeContextManager(nullptr, nullptr);

// 设置ready属性为true
int rc = property_set("hwservicemanager.ready", "true");
if (rc) {
ALOGE("Failed to set \"hwservicemanager.ready\" (error %d). "\
"HAL services will not start!\n", rc);
}

// 将当前进程添加到线程池,和binder通信的套路都一样,最终调用的是
// IPCThreadState::self()->joinThreadPool(); 之后我们分析
joinRpcThreadpool();

return 0;
}

其中关键的三个类IPCThreadState、ProcessState、BnHwServiceManager这个三个类需要分别看一下。

IPCThreadState

路径和目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
code path system/libhwbinder

.
├── Android.bp
├── Binder.cpp
├── BpHwBinder.cpp
├── BufferedTextOutput.cpp
├── Debug.cpp
├── IInterface.cpp
├── include
│   └── hwbinder
│   ├── Binder.h
│   ├── binder_kernel.h
│   ├── BpHwBinder.h
│   ├── BufferedTextOutput.h
│   ├── Debug.h
│   ├── IBinder.h
│   ├── IInterface.h
│   ├── IPCThreadState.h
│   ├── Parcel.h
│   ├── ProcessState.h
│   ├── Static.h
│   └── TextOutput.h
├── IPCThreadState.cpp
├── MODULE_LICENSE_APACHE2
├── NOTICE
├── OWNERS
├── Parcel.cpp
├── PREUPLOAD.cfg
├── ProcessState.cpp
├── Static.cpp
├── TextOutput.cpp
└── vts
├── OWNERS
└── performance
├── Android.bp
├── Benchmark_binder.cpp
├── Benchmark.cpp
├── Benchmark_throughput.cpp
├── Latency.cpp
├── PerfTest.cpp
└── PerfTest.h

以以往FW的libbinder(frameworks/native/libs/binder)中的IPCThreadState中可以知道,IPCThreadState是通过Process打开的binder节点和底层kernel通信的,而且是单例模式的类。这里关注三个方法 self() 、setTheContextObject() 、joinThreadPool()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
IPCThreadState* IPCThreadState::self()
{
if (gHaveTLS) {
restart:
const pthread_key_t k = gTLS;
IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
if (st) return st;
return new IPCThreadState;
}

if (gShutdown) {
ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
return NULL;
}

pthread_mutex_lock(&gTLSMutex);
if (!gHaveTLS) {
int key_create_value = pthread_key_create(&gTLS, threadDestructor);
if (key_create_value != 0) {
pthread_mutex_unlock(&gTLSMutex);
ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
strerror(key_create_value));
return NULL;
}
gHaveTLS = true;
}
pthread_mutex_unlock(&gTLSMutex);
goto restart;
}

self方法基本和libbinder中的一样,单例模式用来获取当前进程中唯一一个IPCThreadState对象的方法。

1
2
3
4
void IPCThreadState::setTheContextObject(sp<BHwBinder> obj)
{
mContextObject = obj;
}

这样就要看一下mContextObject的使用的地方,看看我们设置了这个变量(BnHwServiceManager)后,这个变量用来起什么作用,只有一处。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
IPCThreadState::executeCommand方法中


case BR_TRANSACTION:
{

......

if (tr.target.ptr) {
// We only have a weak reference on the target object, so we must first try to
// safely acquire a strong reference before doing anything else with it.
if (reinterpret_cast<RefBase::weakref_type*>(
tr.target.ptr)->attemptIncStrong(this)) {
// 调用到这里其实是hw service从kernel binder读取上来的数据
error = reinterpret_cast<BHwBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags, reply_callback);
reinterpret_cast<BHwBinder*>(tr.cookie)->decStrong(this);
} else {
error = UNKNOWN_TRANSACTION;
}

} else {
// 调用了transact,传递数据
error = mContextObject->transact(tr.code, buffer, &reply, tr.flags, reply_callback);
}

if ((tr.flags & TF_ONE_WAY) == 0) {
if (!reply_sent) {
// Should have been a reply but there wasn't, so there
// must have been an error instead.
reply.setError(error);
sendReply(reply, 0);
} else {
if (error != NO_ERROR) {
ALOGE("transact() returned error after sending reply.");
} else {
// Ok, reply sent and transact didn't return an error.
}
}
} else {
// One-way transaction, don't care about return value or reply.
}

//ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
// mCallingPid, origPid, origUid);

......

}
break;

只有上面的一条语句,这样可以看出,将ServiceManager嵌套成BnHwServiceManager是为了通信,因为BnHwServiceManager是有binder通信能力的类。读取binder传递到kernel层的数据,通过这个BnHwServiceManager查询到注册到hwservicemanager的service对象,之后执行对应服务提供的方法。

ProcessState

和IPCThreadState在同一个目录下,IPCThreadState中被使用,在IPCThreadState构造时被创建,保存到IPCThreadState的mProcess变量中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
IPCThreadState::IPCThreadState()
: mProcess(ProcessState::self()),
mMyThreadId(gettid()),
mStrictModePolicy(0),
mLastTransactionBinderFlags(0),
mIsLooper(false),
mIsPollingThread(false) {
pthread_setspecific(gTLS, this);
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);

// TODO(b/67742352): remove this variable from the class
(void)mMyThreadId;
}

同样是单例的类,看看ProcessState的构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ProcessState::ProcessState(size_t mmap_size)
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mSpawnThreadOnStart(true)
, mThreadPoolSeq(1)
, mMmapSize(mmap_size)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using /dev/hwbinder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
}
}
else {
ALOGE("Binder driver could not be opened. Terminating.");
}
}

这里的mDriverFD是通过方法open_driver()返回值,而open_driver()返回的binder驱动的节点描述符,和libbinder的区别是,libbinder打开的是/dev/binder,而这里打开的是/dev/hwbinder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static int open_driver()
{
int fd = open("/dev/hwbinder", O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)!", vers, BINDER_CURRENT_PROTOCOL_VERSION);
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '/dev/hwbinder' failed: %s\n", strerror(errno));
}
return fd;
}

对于binder节点的使用方法,google有说明

1
https://source.android.com/devices/architecture/hidl/binder-ipc
IPC 域 说明
/dev/binder 框架/应用进程之间的 IPC,使用 AIDL 接口
/dev/hwbinder 框架/供应商进程之间的 IPC,使用 HIDL 接口/供应商进程之间的 IPC,使用 HIDL 接口
/dev/vndbinder 供应商/供应商进程之间的 IPC,使用 AIDL 接口

BnHwServiceManager

1
2
3
4
5
6
7
8
9
10
11
12
13
code path system/libhidl/transport/manager

.
├── 1.0
│   ├── Android.bp
│   ├── IServiceManager.hal
│   └── IServiceNotification.hal
├── 1.1
│   ├── Android.bp
│   └── IServiceManager.hal
└── 1.2
├── Android.bp
└── IServiceManager.hal

有三个版本的接口定义。
hal文件只是对接口的定义,代码是由hidl-gen工具生成的

代码是中间产物,所以是隐藏的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
code path out/soong/.intermediates/system/libhidl/transport/manager

.
├── 1.0
│   ├── android.hidl.manager@1.0-adapter
│   ├── android.hidl.manager@1.0-adapter_genc++
│   ├── android.hidl.manager@1.0-adapter-helper
│   ├── android.hidl.manager@1.0-adapter-helper_genc++
│   ├── android.hidl.manager@1.0-adapter-helper_genc++_headers
│   ├── android.hidl.manager@1.0_genc++
│   ├── android.hidl.manager@1.0_genc++_headers
│   ├── android.hidl.manager-V1.0-java
│   └── android.hidl.manager-V1.0-java_gen_java
├── 1.1
│   ├── android.hidl.manager@1.1-adapter
│   ├── android.hidl.manager@1.1-adapter_genc++
│   ├── android.hidl.manager@1.1-adapter-helper
│   ├── android.hidl.manager@1.1-adapter-helper_genc++
│   ├── android.hidl.manager@1.1-adapter-helper_genc++_headers
│   ├── android.hidl.manager@1.1_genc++
│   ├── android.hidl.manager@1.1_genc++_headers
│   ├── android.hidl.manager-V1.1-java
│   └── android.hidl.manager-V1.1-java_gen_java
└── 1.2
├── android.hidl.manager@1.2-adapter
├── android.hidl.manager@1.2-adapter_genc++
├── android.hidl.manager@1.2-adapter-helper
├── android.hidl.manager@1.2-adapter-helper_genc++
├── android.hidl.manager@1.2-adapter-helper_genc++_headers
├── android.hidl.manager@1.2_genc++
├── android.hidl.manager@1.2_genc++_headers
├── android.hidl.manager-V1.2-java
└── android.hidl.manager-V1.2-java_gen_java

中间产物很多,其中头文件和实现部分,最终这些文件会打包成动态库和静态库,java会打包成jar来提供给java代码调用。

1
code path out/soong/.intermediates/system/libhidl/transport/manager/1.1/android.hidl.manager@1.1_genc++_headers/gen/android/hidl/manager/1.1

1
2
3
4
5
6
7
.
├── BnHwServiceManager.h
├── BpHwServiceManager.h
├── BsServiceManager.h
├── IHwServiceManager.h
├── IServiceManager.h
└── IServiceManager.h.d

hidl-gen工具会将hal文件自动生成Bn、Bp和Bs(直通模式)的头文件,自动生成是有规律的,BnXXX.h、BpXXX.h、BsXXX.h、IHwXXX.h、XXX.h

1
out/soong/.intermediates/system/libhidl/transport/manager/1.1/android.hidl.manager@1.1_genc++/gen/android/hidl/manager/1.1
1
2
3
.
├── ServiceManagerAll.cpp
└── ServiceManagerAll.cpp.d

ServiceManagerAll.cpp是实现部分,这样的实现方式很类似AIDL的使用,通过.aidl生成.java文件,而且里面的代码形式也很相像。这里可以看到一下关键的方法的实现。

1
2
3
::android::sp<IServiceManager> IServiceManager::getService(const std::string &serviceName, const bool getStub) {
return ::android::hardware::details::getServiceInternal<BpHwServiceManager>(serviceName, true, getStub);
}

getService()在hwservicemanager在注册时调用的方法,可以发现里面的实现在libhidl中,HidlTransportSupport.h中,方法的调用流程很像FW的binder中的getService,最终获取到的其实是BpHwBinder。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
code path /home/yoon/code/system/libhidl/transport

ServiceManagement.cpp

sp<IServiceManager1_2> defaultServiceManager1_2() {
using android::hidl::manager::V1_2::BnHwServiceManager;
using android::hidl::manager::V1_2::BpHwServiceManager;

static std::mutex gDefaultServiceManagerLock;
static sp<IServiceManager1_2> gDefaultServiceManager;

{
// 同步处理,防止多次创建
std::lock_guard<std::mutex> _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager != nullptr) {
return gDefaultServiceManager;
}

if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
// HwBinder not available on this device or not accessible to
// this process.
return nullptr;
}

waitForHwServiceManager();

// 这里使用了while循环,1毫秒重试一次
while (gDefaultServiceManager == nullptr) {
gDefaultServiceManager =
fromBinder<IServiceManager1_2, BpHwServiceManager, BnHwServiceManager>(
ProcessState::self()->getContextObject(nullptr));
if (gDefaultServiceManager == nullptr) {
LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
sleep(1);
}
}
}

return gDefaultServiceManager;
}

我们跟踪一下ProcessState::self()->getContextObject(nullptr)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
ProcessState.cpp

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}



sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;

AutoMutex _l(mLock);

handle_entry* e = lookupHandleLocked(handle);

if (e != NULL) {
// We need to create a new BpHwBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
b = new BpHwBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}

return result;
}

最终创建了一个BpHwBinder,并且BpHwBinder中的mHandle是0,代表这个是ServiceManager。