- 与驱动通信的类
-
ProcessState : 代表使用Binder的进程。在讲解Binder驱动的时候我们就提到:任何使用Binder机制的进程都必须要对/dev/binder设备进行open以及mmap之后才能使用,这部分逻辑是所有使用Binder机制进程共同的。对于这种共同逻辑的封装便是Framework层的职责之一。libbinder中,ProcessState类封装了这个逻辑,从而负责进程Binder的初始化。
-
IPCThreadState :代表了进程中使用Binder的线程,这个类中封装了与Binder驱动通信的具体实现逻辑。
在客户端接口的实现类中,每个接口在组装好参数之后,都会调用remote()->transact来发送请求,而这里其实就是调用的BpBinder的transact方法,这样请求便通过Binder到达了服务实现方的onTransact中。这个过程如下图所示:
4.2 进程的Binder初始化(ProcessState)
之前讲解Binder驱动的时候讲过,需要使用Binder的进程,需要先通过binder_open打开Binder设备,然后通过binder_mmap进行内存映射。由于这部分逻辑是所有使用Binder的进程共有的,所以libbinder中使用ProcessState类统一封装了这个逻辑,具体代码如下:
/framework/native/libs/binder/ProcessState.cpp/
#define BINDER_VM_SIZE ((110241024) - (4096 *2)) // 1M - 8k
-
ProcessState::ProcessState(const char *driver)
- mDriverName(String8(driver))
, mDriverFD(open_driver(driver))// 1.调用open_driver打开binder驱动设备
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mBinderContextCheckFunc(nullptr)
, mBinderContextUserData(nullptr)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
, mCallRestriction(CallRestriction::NONE)
{
// TODO(b/139016109): enforce in build system
#if defined(ANDROID_APEX)
LOG_ALWAYS_FATAL(“Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.”);
#endif
if (mDriverFD >= 0) {
// 2.mmap执行内存映射动作
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// sigh
ALOGE(“Using %s failed: unable to mmap transaction memory.\n”, mDriverName.c_str());
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
}
这是ProcessState构造函数,Binder的初始化工作都是在这个函数中完成的。在这个函数中,初始化mDriverFD的时候调用了open_driver方法打开binder设备,然后又在函数体中,通过mmap进行内存映射。这里需要注意的是mmap函数的参数中有个BINDER_VM_SIZE,这个就是指定在内核上开辟的内存空间的大小,也是一次Binder通信传递的最大数据量,目前默认定义大小是1016个字节(1M-8K)。这个其实也就解释了我们平常开发过程中遇到的一个问题,就是通过Intent传递过大的对象时会报TransactionTooLargeException异常的原因。open_driver动作具体代码如下:
/framework/native/libs/binder/ProcessState.cpp/
#define DEFAULT_MAX_BINDER_THREADS 15
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);// 1.通过open系统调用打开了dev/binder设备
if (fd >= 0) {
int vers = 0;
// 2.通过ioctl获取Binder实现的版本号,并检查是否匹配
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)! ioctl() return value: %d”,
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
// 3.通过ioctl设置进程支持的最大Binder线程数
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 ‘%s’ failed: %s\n”, driver, strerror(errno));
}
return fd;
}
open_driver函数中除了实现通过open系统调用打开了dev/binder设备外。还会通过ioctl调用的BINDER_SET_MAX_THREADS命令设置进程支持的最大Binder线程数,目前定义的一般进程默认最大Binder线程数是15。这个也解释了我们在开发过程中遇到一类性能问题:就是进程的Binder线程耗尽,此时进程中已经开启了15个Binder线程用于处理binder请求且都处于工作或阻塞状态,此时如果有新的binder请求时就无法继续处理了,从而导致阻塞卡主;
4.3 与Binder驱动的通信(IPCThreadState)
IPCThreadState是一个单例类,进程中的每个Binder线程存在一个实例,负责了与驱动通信的细节处理。这个类中的关键几个方法说明如下:
以其中最主要的是transact方法为例,该方法会完成一次Binder数据传输动作,代码如下:
/framework/native/libs/binder/IPCThreadState.cpp/
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
…
// 1.通过writeTransactionData完成数据组装写入
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
…
// 2.判断是否为TF_ONE_WAY异步单向请求,如果是线程不需要阻塞等待返回值,直接返回即可
if ((flags & TF_ONE_WAY) == 0) {
…
// 3.通过waitForResponse将数据传输到驱动并等待返回结果
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
…
} else {
err = waitForResponse(nullptr, nullptr);
}
return err;
}
从代码可以看出,通过Binder驱动完成一次Binder数据传输的主要流程是:
-
先通过writeTransactionData函数完成传输数据binder_transaction_data的组装填充;
-
通过waitForResponse函数真正完成传输数据写入驱动并等待返回数据,具体实现会调用talkWithDriver函数,通过ioctl命令BINDER_WRITE_READ与Binder驱动通信,完成数据的传输写入,并读取返回数据。
详细代码如下:
/framework/native/libs/binder/IPCThreadState.cpp/
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
// 组装binder_transaction_data
binder_transaction_data tr;
tr.target.ptr = 0; /* Don’t pass uninitialized stack data to a remote process */
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
tr.offsets_size = 0;
tr.data.ptr.offsets = 0;
} else {
return (mLastError = err);
}
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
// 调用talkWithDriver真正完成传输数据写入驱动并等待返回数据
if ((err=talkWithDriver()) < NO_ERROR) break;
}
}
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
…
do {
IF_LOG_COMMANDS() {
alog << "About to read/write, write size = " << mOut.dataSize() << endl;
}
#if defined(ANDROID)
// 通过ioctl命令BINDER_WRITE_READ与Binder驱动通信
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
…
} while (err == -EINTR);
…
}
上面的理论知识可能比较枯燥和抽象,下面以Android系统中的一个系统Binder服务为例,结合上面的理论具体分析一下。 我们以实现系统图像合成显示的核心进程服务SurfaceFlinger为例,来分析C++的Binder服务如何实现。下图是SurfaceFlinger C++ Binder服务实现类图:
ISurfaceComposer定义了SurfaceFlinger对外提供的功能接口,其子类都继承了这些接口。
-
BpSurfaceComposer是提供给客户端调用的远程接口,先通过remote方法获取到指向服务实现方的句柄,然后通过transact方法发送具体请求。
-
BnSurfaceComposer中只有一个onTransact方法,该方法根据请求的code来对接每个请求,并直接调用SurfaceFlinger中对应的方法。
-
SurfaceFlinger是服务接口功能真正的实现。
4.4.1 服务端实现
主要包括BnSurfaceComposer和SurfaceFlinger两个类,SurfaceFlinger是BnSurfaceComposer的子类,因此在BnSurfaceComposer中调用自身的virtual方法其实都是在子类SurfaceFlinger类中实现的。BnSurfaceComposer类要做的就是复写onTransact方法,这个方法的职责是:根据请求的code区分具体调用的是那个接口,然后按顺序从Parcel中读出打包好的参数,接着调用留待子类实现的虚函数。我们看一下BnSurfaceComposer::onTransact中的代码片段:
/framework/native/libs/gui/ISurfaceComposer.cpp/
status_t BnSurfaceComposer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
…
case CREATE_DISPLAY: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
String8 displayName = data.readString8();
bool secure = bool(data.readInt32());
sp display(createDisplay(displayName, secure));
reply->writeStrongBinder(display);
return NO_ERROR;
}
…
}
}
这段代码中我们看到了实现中是如何根据code区分接口,并通过Parcel读出调用参数,然后调用具体服务方的。而SurfaceFlinger这个类中的createDisplay方法才是真正实现创建显示设备的逻辑,详细代码如下:
/framework/native/services/surfaceflinger/SurfaceFlinger.cpp/
sp SurfaceFlinger::createDisplay(const String8& displayName, bool secure) {
class DisplayToken : public BBinder {
sp flinger;
virtual ~DisplayToken() {
// no more references, this display must be terminated
Mutex::Autolock _l(flinger->mStateLock);
flinger->mCurrentState.displays.removeItem(this);
flinger->setTransactionFlags(eDisplayTransactionNeeded);
}
public:
-
explicit DisplayToken(const sp& flinger)
- flinger(flinger) {
}
};
sp token = new DisplayToken(this);
Mutex::Autolock _l(mStateLock);
// Display ID is assigned when virtual display is allocated by HWC.
DisplayDeviceState state;
state.isSecure = secure;
state.displayName = displayName;
mCurrentState.displays.add(token, state);
mInterceptor->saveDisplayCreation(state);
return token;
}
4.4.2 注册服务
服务实现完成之后,并不是立即就能让别人使用的。而是需要先通过Binder驱动向ServiceManager中注册服务,表明可以对外提供服务。下面我们看看SurfaceFlinger服务注册发布的具体代码实现:
/frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp/
int main(int, char**) {
…
// When SF is launched in its own process, limit the number of
// binder threads to 4.
ProcessState::self()->setThreadPoolMaxThreadCount(4);
// 1.启动Binder线程池
// start the thread pool
sp ps(ProcessState::self());
ps->startThreadPool();
// instantiate surfaceflinger
sp flinger = surfaceflinger::createSurfaceFlinger();
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
set_sched_policy(0, SP_FOREGROUND);
// initialize before clients can connect
flinger->init();
// 2.通过IServiceManager::addService在ServiceManager中注册服务,此处服务的名称为“SurfaceFlinger”
// publish surface flinger
sp sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
// run surface flinger in this thread
flinger->run();
return 0;
}
由此可见,发布Binder服务需要先启动Binder线程池,然后通过IServiceManager::addService在ServiceManager中进行服务的注册。
4.4.3 客户端实现
BpSurfaceComposer需要实现ISurfaceComposer中的所有接口。我们以上文提到的createDisplay接口为例,来看看BpSurfaceComposer::createDisplay方法代码是如何实现的:
/frameworks/native/libs/gui/ISurfaceComposer.cpp/
virtual sp createDisplay(const String8& displayName, bool secure)
{
Parcel data, reply;
// 1.填写服务接口的唯一描述信息descriptor
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
// 2.通过Parcel写入发送参数
data.writeString8(displayName);
data.writeInt32(secure ? 1 : 0);
// 3. 调用remote()->transact将请求发送出去
remote()->transact(BnSurfaceComposer::CREATE_DISPLAY, data, &reply);
return reply.readStrongBinder();
}
这段代码很简单,逻辑就是:通过Parcel写入调用参数进行打包,然后调用remote()->transact将请求发送出去。
4.4.4 获取服务
客户端在使用服务端的服务之前,需要先根据服务的名称向ServiceManager中查询获取到访问服务的句柄,才能通过BpSurfaceComposer::remote()函数拿到远端服务的代理后调用transact方法完成一次Binder数据发送。详细代码如下:
/framworks/native/libs/gui/SurfaceComposerClient.cpp/
void ComposerService::connectLocked() {
// 1. 需要查找的远端Binder服务名称为"SurfaceFlinger"
const String16 name(“SurfaceFlinger”);
// 2 .调用IServiceManager::getService封装接口获取远端服务代理并封装到BpSurfaceComposer中
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
…
}
/frameworks/native/include/binder/IServiceManager.h/
template
status_t getService(const String16& name, sp* outService)
{ // 1. 获取到ServiceManager的代理以访问ServiceManager
const sp sm = defaultServiceManager();
if (sm != nullptr) {
// 2. 通过getService获取具体的服务句柄,并使用interface_cast转换获取到BpSurfaceComposer对象
*outService = interface_cast(sm->getService(name));
if ((*outService) != nullptr) return NO_ERROR;
}
return NAME_NOT_FOUND;
}
/frameworks/native/libs/binder/IServiceManager.cpp/
sp defaultServiceManager()
{
sp sm = nullptr;
while (sm == nullptr) {
//ProcessState::getContextObject(nullptr)获取到ServiceManager的访问句柄
sm = interface_cast(ProcessState::self()->getContextObject(nullptr));
…
}
}
});
return gDefaultServiceManager;
}
/frameworks/native/libs/binder/ProcessState.cpp/
sp ProcessState::getContextObject(const sp& /caller/)
{
// 此处的参数“0”代表查找的是ServiceManager服务,这个是个特殊的地址,用于标识ServiceManager
sp context = getStrongProxyForHandle(0);
…
return context;
}
通过interface_cast这个方法来获取服务的接口对象,由这个方法本身根据是否是在同一个进程,来自动确定返回一个本地Binder还是远程Binder。interface_cast是一个模板方法,其源码如下:
/frameworks/native/libs/binder/include/binder/IInterface.h/
template
inline sp interface_cast(const sp& obj)
{
return INTERFACE::asInterface(obj);
}
对于ISurfaceComposer来说,其实就是ISurfaceComposer::asInterface(obj),其定义如下:
/frameworks/native/libs/binder/include/binder/IInterface.h/
::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp<I##INTERFACE> intr; \
if (obj != nullptr) { \
//1.先使用queryLocalInterface尝试获取本地同一进程中的Binder对象
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
//2.失败则创建并返回远端Binder对象,封装成BpSurfaceComposer
if (intr == nullptr) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
}
由于都是模板定义,所以在理解的时候,将“##”替换成SurfaceComposer即可。
5 ServiceManager——Binder服务“大管家”
=============================================================================================
ServerManager(简称SM)的功能可以类比互联网中的DNS服务器,“IP地址”为0。每一个Binder服务都需要有一个唯一的名称,由SM来管理这些服务的注册和查找。另外,和DNS服务器本身也是服务器一样,SM也是一个标准的Binder Server,且Binder驱动中,也会通过特定handle = 0这个位置来访问ServiceManager。因此,分析SM我们可以完整的看到一个上层应用如何通过Binder驱动来构建一个Binder Server的过程。下面我们分析SM模块的的具体实现。
SM作为Binder服务的“大管家”,必须要保证在系统所有Binder服务启动之前就已经启动并处于正常工作状态。所以SM是在开机时由init程序解析init.rc加载时直接启动。如下所示:
/framework/native/cmds/servicemanager/servicemanager.rc/
service servicemanager /system/bin/servicemanager// 1.servicemanager是一个独立可执行文件
class core animation
user system
group system readproc
critical
onrestart restart healthd
onrestart restart zygote// 2.servicemanager重启后会导致zygote重启
onrestart restart audioserver
onrestart restart media
onrestart restart surfaceflinger// 3.servicemanager重启后会导致surfaceflinger重启
onrestart restart inputflinger
onrestart restart drm
onrestart restart cameraserver
onrestart restart keystore
onrestart restart gatekeeperd
onrestart restart thermalservice
writepid /dev/cpuset/system-background/tasks
shutdown critical
由上可见,servicemanager是一个独立可执行文件,由C++编写,是一个独立运行的native进程,在系统开机时有init进程直接拉起。源码路径如下:
/framework/native/cmds/servicemanager/*
其main函数主要逻辑如下:
/framework/native/cmds/servicemanager/main.cpp/
int main(int argc, char** argv) {
if (argc > 2) {
LOG(FATAL) << “usage: " << argv[0] << " [binder driver]”;
}
const char* driver = argc == 2 ? argv[1] : “/dev/binder”;
//1.通过initWithDriver会完成打开/dev/binder下的binder驱动设备和mmap内存映射动作
sp ps = ProcessState::initWithDriver(driver);
ps->setThreadPoolMaxThreadCount(0);
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
//2.创建ServiceManager对象,并通过addService接口将自己注册为名为“manager”的Binder Server
sp manager = new ServiceManager(std::make_unique());
if (!manager->addService(“manager”, manager, false /allowIsolated/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << “Could not self register servicemanager”;
}
IPCThreadState::self()->setTheContextObject(manager);
ps->becomeContextManager(nullptr, nullptr);// 3.通知binder驱动将自己注册为binder服务大管家
sp looper = Looper::prepare(false /allowNonCallbacks/);
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
while(true) {
looper->pollAll(-1);// 4.循环等待其它模块请求服务
}
// should not be reached
return EXIT_FAILURE;
}
主要做了如下四件事情:
-
通过调用ProcessState的initWithDriver静态接口,这其中会创建SM进程的ProcessState对象并完成进程的Binder初始化:先调用open_driver动作打开Binder驱动,然后调用mmap动作通知Binder驱动完成binder_mmap物理内存分配和虚拟内存映射的操作;
-
创建ServiceManager对象,并通过addService接口将SM自身注册为名为“manager”的Binder Server服务,也进一步说明SM自身本质上也是一个C++写的Binder Server服务进程;
-
调用ProcessState的becomeContextManager接口,通过binder_ioctl协议命令BINDER_SET_CONTEXT_MGR通知Binder设备驱动,将SM注册为binder服务“大管家”;
-
进入循环等待Binder Client进程的客户端进程访问请求。
5.2 ServiceManager进程Binder服务接口
我们看看ServiceManager.h接口文件的代码定义:
/framework/native/cmds/servicemanager/ServiceManager.h/
class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
public:
ServiceManager(std::unique_ptr&& access);
~ServiceManager();
…
// getService will try to start any services it cannot find
// 1.根据名称查询Binder Server服务
binder::Status getService(const std::string& name, sp* outBinder) override;
binder::Status checkService(const std::string& name, sp* outBinder) override;
// 2.注册Binder Server服务
binder::Status addService(const std::string& name, const sp& binder,
bool allowIsolated, int32_t d
umpPriority) override;
// 3.遍历列出所有已注册的Binder Server服务
binder::Status listServices(int32_t dumpPriority, std::vectorstd::string* outList) override;
…
};
根据上一节对Binder framework C++层的分析我们可以看到:ServiceManager继承自BnServiceManager,是一个Binder Server服务端实现。对客户端提供getService查询Service服务、addService注册Service服务以及listServices遍历所有已注册服务等核心功能接口。 其内部具体的实现是通过一个全局的名为mNameToService的ServiceMap类型(本质上还是一个map类型的集合)的变量记录维护着服务名称和具体的服务代理之间映射关系;以addService注册服务的实现代码为例:
/framework/native/cmds/servicemanager/ServiceManager.cpp/
Status ServiceManager::addService(const std::string& name, const sp& binder, bool allowIsolated, int32_t dumpPriority) {
…
auto entry = mNameToService.emplace(name, Service {
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.debugPid = ctx.debugPid,
});
…
return Status::ok();
}
5.3 libbinder中对访问ServiceManager接口的封装
源码路径:
frameworks/native/include/binder/IServiceManager.h frameworks/native/libs/binder/IServiceManager.cpp
这块逻辑相当于是Binder framework C++层的libbinder库作为Binder客户端对ServiceManager进程所提供的Binder服务端接口访问的封装。
IServiceManager的C++接口定义如下:
/frameworks/native/include/binder/IServiceManager.h/
class IServiceManager : public IInterface
{
public:
…
// 1.根据名称查询Binder Server服务
/**
-
Retrieve an existing service, blocking for a few seconds
-
if it doesn’t yet exist.
*/
virtual sp getService( const String16& name) const = 0;
/**
- Retrieve an existing service, non-blocking.
*/
virtual sp checkService( const String16& name) const = 0;
// 2.注册Binder Server服务
/**
- Register a service.
*/
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t addService(const String16& name, const sp& service,
bool allowIsolated = false,
int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0;
// 3.遍历列出所有已注册的Binder Server服务
/**
- Return list of all existing services.
*/
// NOLINTNEXTLINE(google-default-arguments)
virtual Vector listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
/**
-
Efficiently wait for a service.
-
Returns nullptr only for permission problem or fatal error.
*/
virtual sp waitForService(const String16& name) = 0;
…
};
普通的Binder服务我们需要通过ServiceManager来获取接口才能调用,那么ServiceManager的接口又该如何获得呢?在libbinder中,提供了一个defaultServiceManager方法来获取ServiceManager的代理,并且这个方法不需要传入参数。原因我们在驱动篇中也已经讲过了:Binder的实现中,为ServiceManager留了一个特殊的位置,不需要像普通服务那样通过标识去查找。defaultServiceManager代码如下:
/frameworks/native/libs/binder/IServiceManager.cpp/
sp defaultServiceManager()
{
sp sm = nullptr;
while (sm == nullptr) {
sm = interface_cast(ProcessState::self()->getContextObject(nullptr));
if (sm == nullptr) {
ALOGE(“Waiting 1s on context object on %s.”, ProcessState::self()->getDriverName().c_str());
sleep(1);
}
}
gDefaultServiceManager = new ServiceManagerShim(sm);
});
return gDefaultServiceManager;
}
======================================================================================
Android应用使用Java语言开发,Binder Framework框架自然也是提供了相关Java接口。前面我们已经分析了Binder Framework C++层的完整实现。因此Java层完全不用重复实现,而是通过虚拟机提供的JNI机制,直接调用而复用C++层的实现。下面借用一张图描述Binder Framework Java层到C++层的调用关系。
JNI全称是Java Native Interface,这个是由Java虚拟机提供的机制。这个机制使得native代码可以和Java代码互相通讯。简单来说就是:我们可以在C/C++端调用Java代码,也可以在Java端调用C/C++代码。实际上,在Android中很多的服务或者机制都是在C/C++层实现的,想要将这些实现复用到Java层,就必须通过JNI进行衔接。其实这里面就是解决两个方向的调用问题:
- Java端的代码是如何调用的libbinder中的C++方法的? 以BinderProxy.java中的transact方法为例,其功能是实现Java层的Binder客户端使用服务端的远端代理完成一次Binder数据发送传输,简化代码实现如下:
/frameworks/base/core/java/android/os/BinderProxy.java/
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
…
try {
return transactNative(code, data, reply, flags);
} finally {
…
}
}
/**
- Native implementation of transact() for proxies
*/
public native boolean transactNative(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
Android精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
r中的C++方法的?** 以BinderProxy.java中的transact方法为例,其功能是实现Java层的Binder客户端使用服务端的远端代理完成一次Binder数据发送传输,简化代码实现如下:
/frameworks/base/core/java/android/os/BinderProxy.java/
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
…
try {
return transactNative(code, data, reply, flags);
} finally {
…
}
}
/**
- Native implementation of transact() for proxies
*/
public native boolean transactNative(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
[外链图片转存中…(img-79WdpU03-1716050852961)]
【算法合集】
[外链图片转存中…(img-RLsk0GAi-1716050852962)]
【延伸Android必备知识点】
[外链图片转存中…(img-wDOhCV45-1716050852962)]
【Android部分高级架构视频学习资源】
Android精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!