Android Binder 驱动 - Media 服务启动流程
到现在为止我对Binder 的了解只是知道它很难和它是 Android 系统中最核心的跨进程通信机制,仅此而已,所以接下来几篇文章都是学习的Android Binder 驱动的。
以安卓 12 源码为基础分析
相关文件:
frameworks/av/media/mediaserver/mediaserver.rc
frameworks/av/media/mediaserver/main_mediaserver.cpp
frameworks/native/libs/binder/ProcessState.cpp
frameworks/native/libs/binder/IServiceManager.cpp
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
frameworks/native/libs/binder/BpBinder.cpp
frameworks/native/libs/binder/ndk/service_manager.cpp
frameworks/native/libs/binder/IPCThreadState.cpp
我们关注的是:一个系统级 Native 服务(mediaserver)如何被创建,并通过 Binder 机制向系统注册其提供的服务
主线:
1. 内核启动 → 加载 Binder 驱动↓
2. init 进程启动 → 解析 .rc 文件↓
3. 启动 mediaserver 进程(fork + exec)↓
4. mediaserver 初始化 ProcessState 和 IPCThreadState↓
5. 实例化并注册媒体服务(如 MediaPlayerService)↓
6. 服务通过 Binder 被 servicemanager 管理↓
7. 其他进程可通过 Binder 获取服务代理
在开始之前我们要先简单了解下什么是Binder,首先我们都知道它可以用来跨进程通信,那么对跨进程该怎么理解呢:
每个 Android 应用通常运行在自己独立的进程中,拥有自己独立的内存空间。一个进程不能直接访问另一个进程的内存。当应用需要与其他应用或系统服务交互时,就必须通过 IPC 机制。
这个很简单,但是Binder 是如何实现跨进程通信的呢?
Binder 的架构基于客户端-服务器(Client-Server)模型。它的核心思想是:虽然不能直接访问对方的内存,但可以通过内核空间(一个所有进程都能共享的区域)来间接地完成数据交换和方法调用。
这个也很好理解,Binder 就相当于做了各个进程之间的中转工作,和路由器的原理有点像,对客户端来说,你只需要调用一个简单的方法,Binder 就可以帮你完成跨进程的通信任务,我们对Binder 的理解先到这,先不去深究其实现。
另外 Binder 只需要一次数据拷贝(从用户空间到内核空间),相较于其他 IPC 机制性能更高,这也是安卓选它跨进程通信的原因之一!
Binder 驱动初始化(内核层)
- 内核启动时加载
binder
模块。 - 创建设备节点
/dev/binder
。 - 提供
open
、mmap
、ioctl
系统调用接口。
所有使用 Binder 的进程都必须先 open("/dev/binder")
。
mmap
映射一块内存用于 Binder 数据传输(减少拷贝)。
驱动已就绪!
init
解析 mediaserver.rc
frameworks/av/media/mediaserver/mediaserver.rc
on property:init.svc.media=*setprop init.svc.mediadrm ${init.svc.media}service media /system/bin/mediaserverclass mainuser mediagroup audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrmioprio rt 4task_profiles ProcessCapacityHigh HighPerformance
init 进程在解析 init.rc
时会启动一个名为 mediaserver
的守护进程。
/system/bin/mediaserver
入口
frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char **argv __unused)
{signal(SIGPIPE, SIG_IGN);// 获取 ProcessState 单例(打开 /dev/binder,mmap)sp<ProcessState> proc(ProcessState::self());// 获取 ServiceManager 代理sp<IServiceManager> sm(defaultServiceManager());ALOGI("ServiceManager: %p", sm.get());// 实例化核心媒体服务MediaPlayerService::instantiate();// 媒体资源管理ResourceManagerService::instantiate();// 注册可选的媒体扩展服务(厂商定制或第三方插件)registerExtensions();::android::hardware::configureRpcThreadpool(16, false);// 启动 Binder 线程池ProcessState::self()->startThreadPool();// 当前线程加入线程池,等待 Binder 请求IPCThreadState::self()->joinThreadPool();::android::hardware::joinRpcThreadpool();
}
sp<...>
是 Android 的强引用智能指针(StrongPointer
),用于自动管理 Binder 对象生命周期。
sp<ProcessState> proc(ProcessState::self());
执行 sp<ProcessState> proc(ProcessState::self());
来到ProcessState.cpp 中:
frameworks/native/libs/binder/ProcessState.cpp
执行代码:
sp<ProcessState> ProcessState::self() {return init(kDefaultDriver, false /*requireDefault*/);
}sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault) {static sp<ProcessState> gProcess;static std::mutex gProcessMutex;static std::once_flag gProcessOnce;if (driver == nullptr) {std::lock_guard<std::mutex> l(gProcessMutex);return gProcess;}std::call_once(gProcessOnce, [&](){if (access(driver, R_OK) == -1) {ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);// 如果传入的 driver 设备文件不可访问,则退回 /dev/binder。driver = "/dev/binder";}std::lock_guard<std::mutex> l(gProcessMutex);// make 就是执行构造函数,等价于:new ProcessState("/dev/binder");// make 属于sp 作用域,具体可以看 system/core/libutils/include/utils/StrongPointer.hgProcess = sp<ProcessState>::make(driver);});if (requireDefault) {LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver,"ProcessState was already initialized with %s, can't initialize with %s.",gProcess->getDriverName().c_str(), driver);}return gProcess;
}
构造函数 ProcessState::ProcessState(const char* driver)
ProcessState::ProcessState(const char *driver): mDriverName(String8(driver)) // 保存驱动路径到 mDriverName, mDriverFD(open_driver(driver)) // 打开驱动 → 调用 open_driver(driver) 返回 mDriverFD, mVMStart(MAP_FAILED), mMaxThreads(DEFAULT_MAX_BINDER_THREADS), mThreadPoolStarted(false), mThreadPoolSeq(1), mCallRestriction(CallRestriction::NONE)
{if (mDriverFD >= 0) {// 内存映射 (mmap) → 分配一块虚拟内存空间给 Binder 事务缓冲区mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ,MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);if (mVMStart == MAP_FAILED) {ALOGE("Using %s failed: unable to mmap transaction memory.\n",mDriverName.c_str());// 没有足够空间分配给 /dev/binder, 则关闭驱动close(mDriverFD);mDriverFD = -1;mDriverName.clear();}}LOG_ALWAYS_FATAL_IF(mDriverFD < 0,"Binder driver '%s' could not be opened. Terminating.", driver);
}
mmap:
- 作用:给 Binder 驱动分配一块进程虚拟内存,专门用来存放事务数据(Parcel 数据 buffer)。
- Binder 驱动通过 copy_from_user/copy_to_user 在内核和用户空间之间交换数据。
打开驱动:
static int open_driver(const char *driver)
{// 打开驱动,得到一个文件描述符 → Binder 驱动的通信入口int fd = open(driver, 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)! ioctl() return value: %d",vers, BINDER_CURRENT_PROTOCOL_VERSION, result);close(fd);fd = -1;}size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;// 告诉内核这个进程最多可以有多少个 Binder 线程(默认 15)result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);if (result == -1) {ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));}uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;// 开启单向调用滥用检测(性能保护)result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);if (result == -1) {ALOGD("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));}} else {ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));}return fd;
}
open 是打开驱动、mmap 是映射驱动、ioctl 是操作驱动、close 是关闭驱动,分别对应以下函数:
binder_open()
:打开 Binder 设备(每个进程调用一次)binder_mmap()
:映射内核缓冲区到用户空间(用于高效数据传输)binder_ioctl()
:处理 Binder 通信命令(如 BC_TRANSACTION)binder_colse
:关闭驱动
sp<IServiceManager> sm(defaultServiceManager())
获取系统的 ServiceManager(服务的大管家),用来向 Binder 驱动注册/查询服务。
sp<IServiceManager> defaultServiceManager()
{// call_once:确保里面的 lambda 函数 只执行一次,即使多线程调用 defaultServiceManager()// 这是 C++ 中实现单例的经典模式std::call_once(gSmOnce, []() {sp<AidlServiceManager> sm = nullptr;while (sm == nullptr) {// 获取 Binder 驱动为每个进程自动提供的 “上下文管理者”(context manager) 的 Binder 引用。// 这个“上下文管理者”其实就是 /dev/vndbinder 或 /dev/binder 上的 servicemanager 进程 的代理。// 将原始的 IBinder 接口(BpBinder(0))转换为 AidlServiceManager 接口sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));if (sm == nullptr) {ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());// 因为 servicemanager 进程可能 还没有启动完成,等待一秒sleep(1);}}// 兼容层(Shim Layer)// 在 Android 10 及之前:servicemanager 使用 HIDL 定义// Android 11+ 开始:Google 将 servicemanager 重构为使用 AIDLgDefaultServiceManager = sp<ServiceManagerShim>::make(sm);});return gDefaultServiceManager;
}
getContextObject(nullptr):
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{// 传入 handle = 0,这是整个 Binder 架构中唯一硬编码的句柄// handle=0 固定代表 ServiceManager// 所有进程都知道:要找 ServiceManager,就去拿 handle=0 的代理。sp<IBinder> context = getStrongProxyForHandle(0);if (context) {// The root object is special since we get it directly from the driver, it is never// written by Parcell::writeStrongBinder.internal::Stability::markCompilationUnit(context.get());} else {ALOGW("Not able to get context object on %s.", mDriverName.c_str());}return context;
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{sp<IBinder> result;// mLock 是 ProcessState 的互斥锁AutoMutex _l(mLock);// struct handle_entry {// IBinder* binder; // 对应的代理对象(BpBinder)// weakref_type* refs; // 弱引用计数器// };//lookupHandleLocked 维护一个数组:mHandleToObject(Vector<handle_entry>)// 所有 handle 的映射都集中管理,避免重复创建代理。handle_entry* e = lookupHandleLocked(handle);if (e != nullptr) {IBinder* b = e->binder;if (b == nullptr || !e->refs->attemptIncWeak(this)) {// 代理不存在 或 弱引用已失效 → 需要重建if (handle == 0) {IPCThreadState* ipc = IPCThreadState::self();CallRestriction originalCallRestriction = ipc->getCallRestriction();ipc->setCallRestriction(CallRestriction::NONE);Parcel data;// 即使 handle=0 存在,也不能保证 servicemanager 进程还活着// 发送一个 PING_TRANSACTION 事务,如果返回 DEAD_OBJECT:说明 servicemanager 死了,不能返回代理status_t status = ipc->transact(0, IBinder::PING_TRANSACTION, data, nullptr, 0);ipc->setCallRestriction(originalCallRestriction);if (status == DEAD_OBJECT)return nullptr;}// 创建一个 BpBinder 对象,封装 handle// BpBinder 是 Binder 代理的基类// 所有跨进程调用最终都通过 BpBinder::transact() 发送到内核sp<BpBinder> b = BpBinder::create(handle);e->binder = b.get();if (b) e->refs = b->getWeakRefs();result = b;} else {// 代理存在且有效 → 直接返回强引用result.force_set(b);e->refs->decWeak(this);}}return result;
}
流程图:
getStrongProxyForHandle(handle)↓
加锁 mLock↓
lookupHandleLocked(handle) → 获取 handle_entry↓
是否有有效代理?├─ 是 → attemptIncWeak → 成功? → 返回强引用└─ 否 → handle == 0? → 是 → 发送 PING_TRANSACTION 检查存活→ 失败? → 返回 nullptr创建 BpBinder(handle)保存到 handle_entry返回 sp<BpBinder>
这样就拿到了 ServiceManager 的 Binder 代理对象。
MediaPlayerService::instantiate();
启动并向 ServiceManager 注册 MediaPlayerService
。
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
void MediaPlayerService::instantiate() {defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());
}
因为 defaultServiceManager()
返回的是sp<IServiceManager>
对象, 所以可以在IServiceManager 中找到下面方法:
using AidlServiceManager = android::os::IServiceManager;
//...
class ServiceManagerShim : public IServiceManager//...status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,bool allowIsolated, int dumpsysPriority)
{Status status = mTheRealServiceManager->addService(String8(name).c_str(), service, allowIsolated, dumpsysPriority);return status.exceptionCode();
}
mTheRealServiceManager
是一个 AIDL 接口的客户端代理,指向真正的 AIDL 版 servicemanager
服务。
此处的 addService 就对应了 frameworks/base/core/java/android/os/ServiceManager.java 中的 addService 方法,代表着 Java 和 Native 都可以独立地向 servicemanager
注册服务:
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)public static void addService(String name, IBinder service, boolean allowIsolated,int dumpPriority) {try {getIServiceManager().addService(name, service, allowIsolated, dumpPriority);} catch (RemoteException e) {Log.e(TAG, "error in addService", e);}}
ResourceManagerService::instantiate();
启动并注册 ResourceManagerService
,用于统一管理多媒体硬件资源(解码器、音视频硬件编解码能力)
void ResourceManagerService::instantiate() {// 创建 ResourceManagerService 实例(使用 NDK AIDL 模式)std::shared_ptr<ResourceManagerService> service =::ndk::SharedRefBase::make<ResourceManagerService>();// 将服务注册到 servicemanagerbinder_status_t status =AServiceManager_addService(service->asBinder().get(), getServiceName());// 如果失败就直接返回,不继续初始化if (status != STATUS_OK) {return;}// 创建并设置观察者服务std::shared_ptr<ResourceObserverService> observerService =ResourceObserverService::instantiate();// 使用观察者模式解耦资源管理和状态通知。if (observerService != nullptr) {service->setObserverService(observerService);}// TODO: mediaserver main() is already starting the thread pool,// move this to mediaserver main() when other services in mediaserver// are converted to ndk-platform aidl.//ABinderProcess_startThreadPool();
}
这段代码的作用是: 使用现代 NDK AIDL 架构,创建并注册 ResourceManagerService
服务到 servicemanager
,同时设置其依赖的观察者服务,为 mediaserver
提供资源管理能力。
其中AServiceManager_addService 代码实现在 service_manager.cpp :
frameworks/native/libs/binder/ndk/service_manager.cpp
binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance) {if (binder == nullptr || instance == nullptr) {return EX_ILLEGAL_ARGUMENT;}sp<IServiceManager> sm = defaultServiceManager();status_t exception = sm->addService(String16(instance), binder->getBinder());return PruneException(exception);
}
IPCThreadState::self()->joinThreadPool();
将当前线程变成一个可处理传入和传出 Binder 请求的“Binder 线程”,并进入一个无限循环,等待并执行来自其他进程的 Binder 调用。
关键源码:
void IPCThreadState::joinThreadPool(bool isMain)
{status_t result;mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);do {processPendingDerefs();// 等待并处理来自 Binder 驱动的消息result = getAndExecuteCommand();} while (result != -ECONNREFUSED && result != -EBADF);mOut.writeInt32(BC_EXIT_LOOPER);talkWithDriver(false);
}
与驱动进行通信:
status_t IPCThreadState::talkWithDriver(bool doReceive)
{if (mProcess->mDriverFD < 0) {return -EBADF;}binder_write_read bwr;const bool needRead = mIn.dataPosition() >= mIn.dataSize();const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;bwr.write_size = outAvail;bwr.write_buffer = (uintptr_t)mOut.data();// This is what we'll read.if (doReceive && needRead) {// 接收数据缓冲区信息的填充。如果以后收到数据,就直接填在mIn中了。bwr.read_size = mIn.dataCapacity();bwr.read_buffer = (uintptr_t)mIn.data();} else {bwr.read_size = 0;bwr.read_buffer = 0;}IF_LOG_COMMANDS() {TextOutput::Bundle _b(alog);if (outAvail != 0) {alog << "Sending commands to driver: " << indent;const void* cmds = (const void*)bwr.write_buffer;const void* end = ((const uint8_t*)cmds)+bwr.write_size;alog << HexDump(cmds, bwr.write_size) << endl;while (cmds < end) cmds = printCommand(alog, cmds);alog << dedent;}alog << "Size of receive buffer: " << bwr.read_size<< ", needRead: " << needRead << ", doReceive: " << doReceive << endl;}// Return immediately if there is nothing to do.if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;bwr.write_consumed = 0;bwr.read_consumed = 0;status_t err;do {IF_LOG_COMMANDS() {alog << "About to read/write, write size = " << mOut.dataSize() << endl;}
#if defined(__ANDROID__)// 通过ioctl不停的读写操作,跟Binder Driver进行通信if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)err = NO_ERROR;elseerr = -errno;
#elseerr = INVALID_OPERATION;
#endifif (mProcess->mDriverFD < 0) {err = -EBADF;}IF_LOG_COMMANDS() {alog << "Finished read/write, write size = " << mOut.dataSize() << endl;}} while (err == -EINTR);//...return err;
}
这里提一下 binder_write_read 可以把它理解为一个 双向信封:
- 一边装着 我要告诉驱动什么(write)
- 一边留着 驱动要告诉我什么(read)
write_size/buffer | 用户 → 内核 | 发送命令(BC_TRANSACTION 等) |
---|---|---|
read_size/buffer | 内核 → 用户 | 接收事件(BR_TRANSACTION 等) |
write/read_consumed | 内核 → 用户 | 告知处理进度 |
上面我们说过 所有跨进程调用最终都通过 BpBinder::transact() 发送到内核
sp<BpBinder> b = BpBinder::create(handle);
BpBinder 在 sp ProcessState::getStrongProxyForHandle 中被创建
status_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{LOG_ALWAYS_FATAL_IF(data.isForRpc(), "Parcel constructed for RPC, but being used with binder.");status_t err;// ...waitForResponse(nullptr, nullptr);//...return err;
}
waitForResponse:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{uint32_t cmd;int32_t err;while (1) {// 调用 talkWithDriver if ((err=talkWithDriver()) < NO_ERROR) break;err = mIn.errorCheck();if (err < NO_ERROR) break;if (mIn.dataAvail() == 0) continue;cmd = (uint32_t)mIn.readInt32();IF_LOG_COMMANDS() {alog << "Processing waitForResponse Command: "<< getReturnString(cmd) << endl;}switch (cmd) {case BR_ONEWAY_SPAM_SUSPECT://..case BR_TRANSACTION_COMPLETE://..case BR_DEAD_REPLY://..case BR_FAILED_REPLY:err = FAILED_TRANSACTION;goto finish;case BR_FROZEN_REPLY:err = FAILED_TRANSACTION;goto finish;case BR_ACQUIRE_RESULT://..case BR_REPLY://..default:err = executeCommand(cmd);if (err != NO_ERROR) goto finish;break;}}finish:if (err != NO_ERROR) {if (acquireResult) *acquireResult = err;if (reply) reply->setError(err);mLastError = err;}return err;
}
客户端通过 transact 发送消息, 调用 talkWithDriver 监听返回消息,至此形成闭环。
最后
本人能力有限,关于具体函数的介绍只能停留在表面上,分析不到之处还请不吝赐教,啊,头皮发麻…