CameraService服务启动流程

  • 启动rc脚本文件
//frameworks\av\camera\cameraserver\cameraserver.rc
service cameraserver /system/bin/cameraserver
  • 进程入口:
//frameworks\av\camera\cameraserver\main_cameraserver.cpp
int main(int argc __unused, char** argv __unused)
{
    signal(SIGPIPE, SIG_IGN);
    //以前讲过,会打开/dev/hwbinder,通知kernel,当前进程最大容许的binder线程池为maxThreads
    // Set 3 threads for HIDL calls
    hardware::configureRpcThreadpool(3, /*willjoin*/ false);
    //建立ProcessState单例对象
    sp<ProcessState> proc(ProcessState::self());
    //获取IServiceManager服务代理对象BpServiceManager
    //代码在/frameworks/native/libs/binder/IServiceManager.cpp
    sp<IServiceManager> sm = defaultServiceManager();
    ALOGI("ServiceManager: %p", sm.get());
    //一、建立CameraService
    //二、触发CameraService::onFirstRef()
    //三、将CameraService注册给IServiceManager
    CameraService::instantiate();
    //建立一个子线程并加入binder线程池
    ProcessState::self()->startThreadPool();
    //将主线程加入binder线程池
    IPCThreadState::self()->joinThreadPool();
}

下边对 CameraService::instantiate()方法进行详细介绍下.
首先给出CameraService的类图,以下:
在这里插入图片描述
CameraService::instantiate()调用的是其父类BinderService的方法web

// /frameworks/native/include/binder/BinderService.h
static void instantiate() { publish(); }

接着调用了publish()方法cookie

// /frameworks/native/include/binder/BinderService.h
    static status_t publish(bool allowIsolated = false) {
    //获取IServiceManager服务代理对象BpServiceManager
        sp<IServiceManager> sm(defaultServiceManager());
        //注册服务SERVICE为CameraService
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }

在注册服务时,首先调用CameraService::getServiceName()获取CameraService的服务名称–"media.camera",而后新建CameraService对象。ide

下边介绍下BpServiceManager的addService方法。svg

//frameworks\native\libs\binder\IServiceManager.cpp
    virtual status_t addService(const String16& name, const sp<IBinder>& service,
            bool allowIsolated)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeStrongBinder(service);
        data.writeInt32(allowIsolated ? 1 : 0);
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readExceptionCode() : err;
    }

发现addService的第二个形参为const sp& service。而传入的CameraService对象。所以会调用sp(Android智能指针,不作详细介绍了)的自动类型转换构造函数函数

//system\core\libutils\include\utils\StrongPointer.h
//T为IBinder;U为CameraService
template<typename T> template<typename U>
sp<T>::sp(U* other)
        : m_ptr(other) {
        //类型转换后调用incStrong方法
    if (other)
        (static_cast<T*>(other))->incStrong(this);
}

incStrong会触发onFirstRef方法,代码以下oop

//system/core/libutils/RefBase.cpp
void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->incWeak(id);
    
    refs->addStrongRef(id);
    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);

    if (c != INITIAL_STRONG_VALUE)  {
        return;
    }

    int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
            std::memory_order_relaxed);
   //触发onFirstRef方法
    refs->mBase->onFirstRef();
}

接着会触发CameraService::onFirstRef()fetch

void CameraService::onFirstRef()
{
    ALOGI("CameraService process starting");
    BnCameraService::onFirstRef();
    ...
    //在之前的文章中介绍过,不作详细介绍了
    res = enumerateProviders();
    ...
    CameraService::pingCameraServiceProxy();
}

enumerateProviders()函数的做用在
CameraService启动流程-获取ICameraProvider服务代理对象BpHwCameraProvider并由此获取全部相机设备代理对象BpHwCameraDevice的流程中详细介绍了。这里不作详细介绍了。ui

至此分析完了CameraService::instantiate()的流程
总结:CameraService::instantiate()完成的三个任务,按前后顺序排列,有:this

  1. 新建CameraService对象
  2. 触发CameraService onFirstRef类方法
  3. 注册服务给ServiceManager

下面继续分析下 ProcessState::self()->startThreadPool();
代码以下:spa

//frameworks\native\libs\binder\ProcessState.cpp
void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        //建立一个新的线程
        spawnPooledThread(true);
    }
}

接着分析下spawnPooledThread,代码以下:

////frameworks\native\libs\binder\ProcessState.cpp
//isMain为true,说明是主线程
void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
         //建立线程的名字Binder:PID_%X
        String8 name = makeBinderThreadName();
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        //建立一个新线程并启动
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string());
    }
}

接着分析下线程循环threadLoop

//frameworks\native\libs\binder\ProcessState.cpp
class PoolThread : public Thread
{
public:
    explicit PoolThread(bool isMain)
        : mIsMain(isMain)
    {
    }
    
protected:
    //子线程循环
    virtual bool threadLoop()
    {   //子线程开启循环,不断读取/dev/binder以获取其余进程发来的命令并执行
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
    }
    const bool mIsMain;
};

接着会调用`IPCThreadState::self()->joinThreadPool(mIsMain)``,代码以下:

//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());
    //将当前线程加入到 binder线程池中。
    //在上边的代码中可知,如今是将子线程加入到Binder线程池
    //main为true
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

    status_t result;
    //开启循环,与dev/binder通信,将mOut中的cmd写入binder驱动
    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) {
            ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                  mProcess->mDriverFD, result);
            abort();
        }

        // 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);
    talkWithDriver(false);
}

接着分析下getAndExecuteCommand,代码以下:

//frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::getAndExecuteCommand()
{
    status_t result;
    int32_t cmd;
    //与/dev/binder通信
    result = talkWithDriver();
    if (result >= NO_ERROR) {
        size_t IN = mIn.dataAvail();
        if (IN < sizeof(int32_t)) return result;
        //获取cmd
        cmd = mIn.readInt32();
        ....

        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;
        }
        pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
        pthread_mutex_unlock(&mProcess->mThreadCountLock);
    }

    return result;
}

先将讲解下executeCommand,代码以下:

//frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::executeCommand(int32_t cmd)
{
    BBinder* obj;
    RefBase::weakref_type* refs;
    status_t result = NO_ERROR;

    switch ((uint32_t)cmd) {
     ...
        //其余进程发来的消息
    case BR_TRANSACTION:
        {
            binder_transaction_data tr;
            result = mIn.read(&tr, sizeof(tr));
            ALOG_ASSERT(result == NO_ERROR,
                "Not enough command data for brTRANSACTION");
            if (result != NO_ERROR) break;

            Parcel buffer;
            buffer.ipcSetDataReference(
                reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                tr.data_size,
                reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);

            const pid_t origPid = mCallingPid;
            const uid_t origUid = mCallingUid;
            const int32_t origStrictModePolicy = mStrictModePolicy;
            const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;

            mCallingPid = tr.sender_pid;
            mCallingUid = tr.sender_euid;
            mLastTransactionBinderFlags = tr.flags;

            //ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);

            Parcel reply;
            status_t error;
            .....
            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)) {
                    //调用BnCameraService的 transact方法
                    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                            &reply, tr.flags);
                    reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
                } else {
                    error = UNKNOWN_TRANSACTION;
                }

            } else {
                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
            }

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

            if ((tr.flags & TF_ONE_WAY) == 0) {
                LOG_ONEWAY("Sending reply to %d!", mCallingPid);
                if (error < NO_ERROR) reply.setError(error);
                sendReply(reply, 0);
            } else {
                LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
            }

            mCallingPid = origPid;
            mCallingUid = origUid;
            mStrictModePolicy = origStrictModePolicy;
            mLastTransactionBinderFlags = origTransactionBinderFlags;

           ......

        }
        break;

   ....

    default:
        ALOGE("*** BAD COMMAND %d received from Binder driver\n", cmd);
        result = UNKNOWN_ERROR;
        break;
    }

    if (result != NO_ERROR) {
        mLastError = result;
    }

    return result;
}

至于如何与binder通信的这里就不作详细介绍了,之后会专门研究。

至此分析完成了cameraserver的启动流程
总结下:

  1. 建立CameraService对象
  2. 将CameraService注册给ServiceManager时,首先触发了CameraService::onFirstRef
  3. 将CameraService注册给ServiceManager
  4. 新建binder线程池,不断读取/dev/binder。若是有消息会调用BBinder::transact并触发CameraService的onTransact方法