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 机制向系统注册其提供的服务

主线:

markdown 复制代码
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
  • 提供 openmmapioctl 系统调用接口。

所有使用 Binder 的进程都必须先 open("/dev/binder")

mmap 映射一块内存用于 Binder 数据传输(减少拷贝)。

驱动已就绪!

init 解析 mediaserver.rc

frameworks/av/media/mediaserver/mediaserver.rc

csharp 复制代码
on property:init.svc.media=*
    setprop init.svc.mediadrm ${init.svc.media}

service media /system/bin/mediaserver
    class main
    user media
    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
    ioprio rt 4
    task_profiles ProcessCapacityHigh HighPerformance

init 进程 在解析 init.rc 时会启动一个名为 mediaserver 的守护进程。

/system/bin/mediaserver 入口

frameworks/av/media/mediaserver/main_mediaserver.cpp

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

执行代码:

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.h
        gProcess = 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)

cpp 复制代码
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 在内核和用户空间之间交换数据。

打开驱动:

cpp 复制代码
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 驱动注册/查询服务。

cpp 复制代码
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 重构为使用 AIDL
        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
    });

    return gDefaultServiceManager;
}

getContextObject(nullptr):

cpp 复制代码
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;
}
cpp 复制代码
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;
}

流程图:

scss 复制代码
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

cpp 复制代码
void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}

因为 defaultServiceManager() 返回的是 sp<IServiceManager> 对象, 所以可以在IServiceManager 中找到下面方法:

cpp 复制代码
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 注册服务:

java 复制代码
    @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,用于统一管理多媒体硬件资源(解码器、音视频硬件编解码能力)

cpp 复制代码
void ResourceManagerService::instantiate() {
    // 创建 ResourceManagerService 实例(使用 NDK AIDL 模式)
    std::shared_ptr<ResourceManagerService> service =
            ::ndk::SharedRefBase::make<ResourceManagerService>();
    // 将服务注册到 servicemanager
    binder_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

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 调用。

关键源码:

cpp 复制代码
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);
}

与驱动进行通信:

cpp 复制代码
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;
        else
            err = -errno;
#else
        err = INVALID_OPERATION;
#endif
        if (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() 发送到内核

cpp 复制代码
sp<BpBinder> b = BpBinder::create(handle);

BpBinder 在 sp ProcessState::getStrongProxyForHandle 中被创建

cpp 复制代码
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:

cpp 复制代码
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 监听返回消息,至此形成闭环。


最后

本人能力有限,关于具体函数的介绍只能停留在表面上,分析不到之处还请不吝赐教,啊,头皮发麻...

相关推荐
咖啡の猫3 小时前
Android开发-工程结构
android
法迪9 小时前
【Android 16】Android W 的冻结机制内核分析
android·功耗
阿华的代码王国10 小时前
【Android】OkHttp发起GET请求 && POST请求
android·java·okhttp·网络连接
WAsbry12 小时前
Android 屏幕适配系列开篇:核心概念、官方机制与主流方案
android·面试
liang_jy16 小时前
抽象工厂模式
android·设计模式·面试
liang_jy16 小时前
工厂方法模式
android·设计模式·面试
future_studio16 小时前
如何用 Kotlin 在 Android 手机开发一个小闹钟、计时器、秒表
android·智能手机·kotlin
zhangguojia717 小时前
android中常见布局及其约束
android
paynnne17 小时前
Android 事件分发机制
android