一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

CameraService服務(wù)啟動流程

 新用戶8389DdzY 2021-09-22

啟動rc腳本文件

//frameworks\av\camera\cameraserver\cameraserver.rc

service cameraserver /system/bin/cameraserver

1

2

進程入口:

//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);

    //創(chuàng)建ProcessState單例對象

    sp<ProcessState> proc(ProcessState::self());

    //獲取IServiceManager服務(wù)代理對象BpServiceManager

    //代碼在/frameworks/native/libs/binder/IServiceManager.cpp

    sp<IServiceManager> sm = defaultServiceManager();

    ALOGI("ServiceManager: %p", sm.get());

    //1、創(chuàng)建CameraService

    //2、觸發(fā)CameraService::onFirstRef()

    //3、將CameraService注冊給IServiceManager

    CameraService::instantiate();

    //創(chuàng)建一個子線程并加入binder線程池

    ProcessState::self()->startThreadPool();

    //將主線程加入binder線程池

    IPCThreadState::self()->joinThreadPool();

}

下邊對CameraService::instantiate()方法進行詳細介紹下.

首先給出CameraService的類圖,如下:

CameraService::instantiate()調(diào)用的是其父類BinderService的方法

// /frameworks/native/include/binder/BinderService.h

static void instantiate() { publish(); }

1

2

接著調(diào)用了publish()方法

// /frameworks/native/include/binder/BinderService.h

    static status_t publish(bool allowIsolated = false) {

    //獲取IServiceManager服務(wù)代理對象BpServiceManager

        sp<IServiceManager> sm(defaultServiceManager());

        //注冊服務(wù)SERVICECameraService

        return sm->addService(

                String16(SERVICE::getServiceName()),

                new SERVICE(), allowIsolated);

    }

在注冊服務(wù)時,首先調(diào)用CameraService::getServiceName()獲取CameraService的服務(wù)名稱–"media.camera",然后新建CameraService對象。

下邊介紹下BpServiceManageraddService方法。

//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;

    }

發(fā)現(xiàn)addService的第二個形參為const sp& service。而傳入的CameraService對象。因此會調(diào)用spAndroid智能指針,不做詳細介紹了)的自動類型轉(zhuǎn)換構(gòu)造函數(shù)

//system\core\libutils\include\utils\StrongPointer.h

//TIBinderUCameraService

template<typename T> template<typename U>

sp<T>::sp(U* other)

        : m_ptr(other) {

        //類型轉(zhuǎn)換后調(diào)用incStrong方法

    if (other)

        (static_cast<T*>(other))->incStrong(this);

}

incStrong會觸發(fā)onFirstRef方法,代碼如下

//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);

   //觸發(fā)onFirstRef方法

    refs->mBase->onFirstRef();

}

接著會觸發(fā)CameraService::onFirstRef()

void CameraService::onFirstRef()

{

    ALOGI("CameraService process starting");

    BnCameraService::onFirstRef();

    ...

    //在以前的文章中介紹過,不做詳細介紹了

    res = enumerateProviders();

    ...

    CameraService::pingCameraServiceProxy();

}

enumerateProviders()函數(shù)的作用在

CameraService啟動流程-獲取ICameraProvider服務(wù)代理對象BpHwCameraProvider并由此獲取所有相機設(shè)備代理對象BpHwCameraDevice的流程中詳細介紹了。這里不做詳細介紹了。

至此分析完了CameraService::instantiate()的流程

總結(jié):CameraService::instantiate()完成的三個任務(wù),按先后順序排列,有:

新建CameraService對象

觸發(fā)CameraService onFirstRef類方法

注冊服務(wù)給ServiceManager

下面繼續(xù)分析下ProcessState::self()->startThreadPool();

代碼如下:

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

void ProcessState::startThreadPool()

{

    AutoMutex _l(mLock);

    if (!mThreadPoolStarted) {

        mThreadPoolStarted = true;

        //創(chuàng)建一個新的線程

        spawnPooledThread(true);

    }

}

接著分析下spawnPooledThread,代碼如下:

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

//isMaintrue,說明是主線程

void ProcessState::spawnPooledThread(bool isMain)

{

    if (mThreadPoolStarted) {

         //創(chuàng)建線程的名字Binder:PID_%X

        String8 name = makeBinderThreadName();

        ALOGV("Spawning new pooled thread, name=%s\n", name.string());

        //創(chuàng)建一個新線程并啟動

        sp<Thread> t = new PoolThread(isMain);

        t->run(name.string());

    }

}

接著分析下線程循環(huán)threadLoop

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

class PoolThread : public Thread

{

public:

    explicit PoolThread(bool isMain)

        : mIsMain(isMain)

    {

    }

protected:

    //子線程循環(huán)

    virtual bool threadLoop()

    {   //子線程開啟循環(huán),不斷讀取/dev/binder以獲取其他進程發(fā)來的命令并執(zhí)行

        IPCThreadState::self()->joinThreadPool(mIsMain);

        return false;

    }

    const bool mIsMain;

};

接著會調(diào)用`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線程池中。

    //在上邊的代碼中可知,現(xiàn)在是將子線程加入到Binder線程池

    //maintrue

    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

    status_t result;

    //開啟循環(huán),與dev/binder通訊,將mOut中的cmd寫入binder驅(qū)動

    do {

        processPendingDerefs();

        //獲取命令并執(zhí)行或者等待命令

        // 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);

        //執(zhí)行命令

        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) {

     ...

        //其他進程發(fā)來的消息

    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)) {

                    //調(diào)用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的啟動流程

總結(jié)下:

創(chuàng)建CameraService對象

CameraService注冊給ServiceManager時,首先觸發(fā)了CameraService::onFirstRef

CameraService注冊給ServiceManager

新建binder線程池,不斷讀取/dev/binder。如果有消息會調(diào)用BBinder::transact并觸發(fā)CameraServiceonTransact方法

————————————————

版權(quán)聲明:本文為CSDN博主「gaojian.shi」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/u010116586/java/article/details/96476132

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产欧美性成人精品午夜| 极品熟女一区二区三区| 国产不卡最新在线视频| 日韩丝袜诱惑一区二区| 日本妇女高清一区二区三区| 国产福利一区二区三区四区| 偷自拍亚洲欧美一区二页| 日木乱偷人妻中文字幕在线| 午夜精品久久久免费视频| 久久精品一区二区少妇| 人人爽夜夜爽夜夜爽精品视频| 国产成人国产精品国产三级| 中文字幕有码视频熟女| 免费在线观看激情小视频| 精品国产av一区二区三区不卡蜜 | 冬爱琴音一区二区中文字幕| 欧美成人精品一区二区久久| 麻豆精品视频一二三区| 国产精品欧美在线观看| 欧美色欧美亚洲日在线| 黄色国产一区二区三区| 在线观看那种视频你懂的| 果冻传媒精选麻豆白晶晶| 欧美大胆美女a级视频| 日韩精品区欧美在线一区| 在线观看视频日韩精品| 香蕉网尹人综合在线观看| 亚洲一区二区三区熟女少妇| 99热九九在线中文字幕| 黑鬼糟蹋少妇资源在线观看| 99热九九热这里只有精品| 久久99国产精品果冻传媒| 开心五月激情综合婷婷色| 午夜精品一区二区av| 老熟妇乱视频一区二区| 美女黄片大全在线观看| 91福利免费一区二区三区| 99福利一区二区视频| 日韩人妻中文字幕精品| 亚洲中文字幕高清视频在线观看| 日韩中文字幕有码午夜美女|