Android Native服务注册流程概述

关于Android Native服务的实现
Views: 388
1 0
Read Time:9 Minute, 22 Second

在Android系统中,Java Framework层的诸多服务都通过Binder与Native层的服务进行通信;基于此再对外提供接口给各个Java应用。在这种通信模式下,两端遵守的是C-S架构。一般而言Native服务会作为Server端而存在。

Native服务作为Server端,是需要注册到serviceManager成为服务之后才能被系统中的各个Client进行获取、连接与使用的。本篇博客将以Android12的源码为基础,简单分析一下Android Native服务的注册流程。

这里我们先以CameraService为例做一个分析讲解。

CameraService在Native层主要分为两个部分:一个是以binary形式而存在的cameraserver;另外一个则是以共享库形式而存在的libcameraservice。前者作为CamearService的程序入口,而后者则是具体的逻辑主体实现,且后者是前者的依赖项之一,由前者负责调用。其服务注册的主体部分,位于cameraserver内,总体涉及的到源码路径如下:

//cameraserver
frameworks/av/camera/cameraserver

//libcameraservice
frameworks/av/services/camera/libcameraservice

我们找到cameraserver启动的源码文件:main_cameraserver.cpp,其源码内容非常精简,具体内容如下所示:

#define LOG_TAG "cameraserver"
//#define LOG_NDEBUG 0

#include "CameraService.h"
#include <hidl/HidlTransportSupport.h>

using namespace android;

int main(int argc __unused, char** argv __unused)
{
    signal(SIGPIPE, SIG_IGN);

    // Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls in
    // addition to consuming them from the Camera HAL as well.
    hardware::configureRpcThreadpool(5, /*willjoin*/ false);

    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    ALOGI("ServiceManager: %p", sm.get());
    CameraService::instantiate();
    ALOGI("ServiceManager: %p done instantiate", sm.get());
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

在cameraserver的服务启动过程中,就包含了服务注册的部分,主要包含以下几个步骤:

1.获取ProcessState对象,用于连接底层binder驱动;

2.获取ServiceManager实例,通过父类instantiate接口发布到Android系统中;

3.启动binder线程池,该线程池用于处理Binder IPC通信;

4.线程执行,此时可以处理Binder IPC请求;

获取ProcessState对象

这一步的目的其实是为了通过libbinder连接底层binder驱动(/dev/binder),涉及到的源码文件如下:

frameworks/native/libs/binder/include/binder/ProcessState.h //头文件
frameworks/native/libs/binder/ProcessState.cpp //源码文件

ProcessState类在源码中是一个单例实现,部分关键源码如下:

//frameworks/native/libs/binder/ProcessState.cpp

#ifdef __ANDROID_VNDK__
const char* kDefaultDriver = "/dev/vndbinder";
#else
const char* kDefaultDriver = "/dev/binder";
#endif

//native 服务使用该接口进行binder初始化,如
sp<ProcessState> ProcessState::self()
{
    return init(kDefaultDriver, false /*requireDefault*/);
}
//init 函数作为主入口
sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
{
    [[clang::no_destroy]] static sp<ProcessState> gProcess;
    [[clang::no_destroy]] static std::mutex gProcessMutex;
    if (driver == nullptr) {
        std::lock_guard<std::mutex> l(gProcessMutex);
        return gProcess;
    }
    [[clang::no_destroy]] static std::once_flag gProcessOnce;
    std::call_once(gProcessOnce, [&](){
        if (access(driver, R_OK) == -1) {
            ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
            driver = "/dev/binder";
        }
        std::lock_guard<std::mutex> l(gProcessMutex);
        //use sp<CLASS>::make to construct an sp object
        gProcess = sp<ProcessState>::make(driver);
    });
    if (requireDefault) {
        // Detect if we are trying to initialize with a different driver, and
        // consider that an error. ProcessState will only be initialized once above.
        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 constructor
ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mWaitingForThreads(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mStarvationStartTimeMs(0)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
    , mCallRestriction(CallRestriction::NONE)
{
    if (mDriverFD >= 0) {
        // 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();
        }
    }
#ifdef __ANDROID__
    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened.  Terminating.", driver);
#endif
}
//构造函数列表初始化中通过open_driver连接驱动
static int open_driver(const char *driver)
{
    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;
        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;
}

在Native Service启动时,我们通过ProcessState::self()获取到单例对象,再通过 ProcessState 的拷贝构造函数赋值给proc,从而得到名为proc指向 ProcessState 的智能指针。

获取ServiceManager实例

获取IServiceManager实例是为了后续将服务添加到ServiceManager中,这一步涉及到的源码文件如下:

/frameworks/native/libs/binder/include/binder/IServiceManager.h  //头文件
/frameworks/native/libs/binder/IServiceManager.cpp  //源文件

IServiceManager自身也是单例实现,其实现部分的代码如下:

using AidlServiceManager = android::os::IServiceManager;
sp<IServiceManager> defaultServiceManager()
{
//通过std::call_once确保在多线程并行调用情况下也只会执行一次
    std::call_once(gSmOnce, []() {
        sp<AidlServiceManager> sm = nullptr;
        while (sm == nullptr) {
            sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
            if (sm == nullptr) {
                ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
                sleep(1);
            }
        }
        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
    });

    return gDefaultServiceManager;
}

在defaultServiceManager函数实现中,首先通过std::call_once来确保多线程并发调用的情况下函数主体只会调用一次,并且通过while循环来确保在serviceManager进程启动慢时通过sleep休眠来暂缓获取的过程,其中最为关键的接口在于getContextObject函数,其具体内容如下:


sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    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;

    AutoMutex _l(mLock);

    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;
                status_t status = ipc->transact(
                        0, IBinder::PING_TRANSACTION, data, nullptr, 0);
                ipc->setCallRestriction(originalCallRestriction);
                if (status == DEAD_OBJECT)
                   return nullptr;
            }
            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;
}

getContextObject中通过getStrongProxyForHandle函数来获取IBinder的sp对象,而其实际上是通过BpBinder::create(handle)来进行获取的,不过在这一步得到的对象是指向BpBinder的sp,我们将上面的代码进行简化,可以得到如下的内容:

//原始内容
sp<AidlServiceManager> sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr))

//简化内容
sp<android::os::IServiceManager> sm = interface_cast<android::os::IServiceManager>(BpBinder::create(0))

这里通过interface_cast将BpBinder::create(0)转换为了android::os::IServiceManager,具体的转换过程可以看看interface_cast的源码实现,其本身属于类模板函数,源码位于frameworks/native/libs/binder/include/binder/IInterface.h内,具体内容如下:

/**
 * If this is a local object and the descriptor matches, this will return the
 * actual local object which is implementing the interface. Otherwise, this will
 * return a proxy to the interface without checking the interface descriptor.
 * This means that subsequent calls may fail with BAD_TYPE.
 */
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

我们将其中的INTERFACE模板做相应替换后,可以得到如下内容:

sp<android::os::IServiceManager> sm = android::os::IServiceManager::asInterface(BpBinder::create(0))

我们再关注一下IServiceManager类的内部,可以看到如下方法:

/**
* Retrieve an existing service, blocking for a few seconds
* if it doesn't yet exist.
*/
virtual sp<IBinder>         getService( const String16& name) const = 0;

/**
* Retrieve an existing service, non-blocking.
*/
virtual sp<IBinder>         checkService( const String16& name) const = 0;

/**
* Register a service.
*/
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t addService(const String16& name, const sp<IBinder>& service,
                                bool allowIsolated = false,
                                int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0;

/**
* Return list of all existing services.
*/
// NOLINTNEXTLINE(google-default-arguments)
virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;

/**
* Efficiently wait for a service.
*
* Returns nullptr only for permission problem or fatal error.
*/
virtual sp<IBinder> waitForService(const String16& name) = 0;

这部分方法都是与服务获取、使用相关的,且都属于纯虚函数,具体的实现逻辑在其子类ServiceManagerShim内。

服务注册

接下来就是服务注册了,这部分可能也是最让人困惑的。从整个代码调用上来看,服务注册最直观的调用应该属于CameraService::instantiate();这一句,但即使我们翻遍CameraService的源码也是无法找到 instantiate的具体实现的,原因就在于 instantiate 方法其实是来自于父类的public方法,我们在相应的头文件内可以看到:

//
class CameraService :
    public BinderService<CameraService>,
    public virtual ::android::hardware::BnCameraService,
    public virtual IBinder::DeathRecipient,
    public virtual CameraProviderManager::StatusListener
{
  ......
}

事实上instantiate方法就是类模板BinderService的公有方法 ,其代码实现如下:

//frameworks/native/libs/binder/include/binder/BinderService.h
template<typename SERVICE>
class BinderService
{
public:
    static status_t publish(bool allowIsolated = false,
                            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,dumpFlags);
    }

    static void publishAndJoinThreadPool(
            bool allowIsolated = false,
            int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
        publish(allowIsolated, dumpFlags);
        joinThreadPool();
    }

    static void instantiate() { publish(); }

    static status_t shutdown() { return NO_ERROR; }

private:
    static void joinThreadPool() {
        sp<ProcessState> ps(ProcessState::self());
        ps->startThreadPool();
        ps->giveThreadPoolName();
        IPCThreadState::self()->joinThreadPool();
    }
};

这里 instantiate方法其实就是封装了一下publish方法,在publish方法内,通过IServiceManager的addService方法添加服务,这里有两个小细节是需要注意的:一个是我们实现的服务必须要实现getServiceName方法,且该方法必须为public static方法;另一个是我们实现的服务必须要显式实现默认构造函数且必须为public可见,新手一般会在这两个地方踩坑。具体原因,我们只需要看sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,dumpFlags);这一行就知道为什么了。

启动与加入Binder线程池

在将服务注册到ServiceManager之后,我们需要启动服务侧的binder线程池,由于是多Client并发请求的,线程池是必须的,

// 启动binder线程池
ProcessState::self()->startThreadPool();
// 加入到Binder线程池
IPCThreadState::self()->joinThreadPool();

首先看看startThreadPool内的实现:

//frameworks/native/libs/binder/ProcessState.cpp
void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        //通过true设定为主线程
        spawnPooledThread(true);
    }
}

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        sp<Thread> t = sp<PoolThread>::make(isMain);
        t->run(name.string());
    }
}

//PoolThread为内部类,继承自Android自行封装的Thread类
class PoolThread : public Thread
{
public:
    explicit PoolThread(bool isMain)
        : mIsMain(isMain)
    {
    }

protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
    }

    const bool mIsMain;
};

从其实现我们可以看到,startThreadPool调用就会开启线程执行,并且是作为主线程执行;接着我们看看joinThreadPool的实现:

//frameworks/native/libs/binder/IPCThreadState.cpp
void IPCThreadState::joinThreadPool(bool isMain)
{
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
    //设定线程状态,mOut属于Parcel对象
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

    mIsLooper = true;
    status_t result;
    do {
        processPendingDerefs();
        // now get the next command to be processed, waiting if necessary
        result = getAndExecuteCommand();

        if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
            LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                  mProcess->mDriverFD, result);
        }

        // Let this thread exit the thread pool if it is no longer
        // needed and it is not the main process thread.
        if(result == TIMED_OUT && !isMain) {
            break;
        }
    } while (result != -ECONNREFUSED && result != -EBADF);

    LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%d\n",
        (void*)pthread_self(), getpid(), result);

    mOut.writeInt32(BC_EXIT_LOOPER);
    mIsLooper = false;
    talkWithDriver(false);
}

//从binder中获取command并执行
status_t IPCThreadState::getAndExecuteCommand()
{
    status_t result;
    int32_t cmd;

    result = talkWithDriver();
    if (result >= NO_ERROR) {
        //mIn属于Parcel对象,从中获取binder driver传递的command
        size_t IN = mIn.dataAvail();
        if (IN < sizeof(int32_t)) return result;
        cmd = mIn.readInt32();
        IF_LOG_COMMANDS() {
            alog << "Processing top-level Command: "
                 << getReturnString(cmd) << endl;
        }

        pthread_mutex_lock(&mProcess->mThreadCountLock);
        mProcess->mExecutingThreadsCount++;
        if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&
                mProcess->mStarvationStartTimeMs == 0) {
            mProcess->mStarvationStartTimeMs = uptimeMillis();
        }
        pthread_mutex_unlock(&mProcess->mThreadCountLock);

        result = executeCommand(cmd);

        pthread_mutex_lock(&mProcess->mThreadCountLock);
        mProcess->mExecutingThreadsCount--;
        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
                mProcess->mStarvationStartTimeMs != 0) {
            int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;
            if (starvationTimeMs > 100) {
                ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms",
                      mProcess->mMaxThreads, starvationTimeMs);
            }
            mProcess->mStarvationStartTimeMs = 0;
        }

        // Cond broadcast can be expensive, so don't send it every time a binder
        // call is processed. b/168806193
        if (mProcess->mWaitingForThreads > 0) {
            pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
        }
        pthread_mutex_unlock(&mProcess->mThreadCountLock);
    }
    return result;
}

整个实现过程中最为关键的函数为executeCommand,其内部实现简单来讲就是根据mIn传递的binder驱动指令(BR_XXX)执行相关动作,再将执行结果(BC_XXX)通过mOut返回至binder驱动。

总结

这里我们再简单总结一下如何实现一个安卓Native Service:

1.在头文件中include以下头文件:

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/BinderService.h>

声明MyOwnService类,并使其继承public BinderService<MyOwnService>,并将BinderService<MyOwnService>设置为友元类;并实现如下函数:

MyOwnService();//默认构造函数
static char const* getServiceName();  //用于定义service名称

如果我们需要在MyOwnService中实现AIDL接口,如IMyOwnService.aidl,需要继承BnMyOwnService类,并覆写 IMyOwnService.aidl中所定义的接口。

如果需要处理BinderDied这种异常情况,则需要继承IBinder::DeathRecipient,覆写binderDied接口。如下所示:

//for service register
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/BinderService.h>

class MyOwnService :public BinderService<MyOwnService>,public BnMyOwnService,public 
                     virtual IBinder::DeathRecipient{
public:
      MyOwnService();
      static char const* getServiceName();
      .....
private:
      void binderDied(const wp<IBinder>& who) override;
      .....
}

2.Main函数编写:

void main(int argc,char * argv[])
{
   configureRpcThreadpool(3, false /* callerWillJoin */);
   sp<ProcessState> proc(ProcessState::self());
   sp<IServiceManager> sm = defaultServiceManager();
   myOwnService::instantiate();

//这两句一定放在服务准备工作完成之后,否则后续的语句不会执行
   ProcessState::self()->startThreadPool();
   IPCThreadState::self()->joinThreadPool();
}

至此服务就能注册到ServiceManager中,并可进行binder通信了。

如果我们要在远端获取service,在Java层可以采用如下方式:

import android.os.IBinder;
import android.os.ServiceManager;

//字符串必须与service实现的getServiceName接口所返回的一致
IBinder binder = ServiceManager.getService("myOwnService");
//将IBinder通过asInterface转换为具体的service远端对象
mMyOwnService = IMyOwnService.Stub.asInterface(binder);

关于IMyOwnService.Stub.asInterface接口的由来,可以参考我的另一篇文章

Happy
Happy
100 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
FranzKafka95
FranzKafka95

极客,文学爱好者。如果你也喜欢我,那你大可不必害羞。

文章: 85

留下评论

您的电子邮箱地址不会被公开。 必填项已用*标注

zh_CNCN