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());
    //1、创建CameraService
    //2、触发CameraService::onFirstRef()
    //3、将CameraService注册给IServiceManager
    CameraService::instantiate();
    //创建一个子线程并加入binder线程池
    ProcessState::self()->startThreadPool();
    //将主线程加入binder线程池
    IPCThreadState::self()->joinThreadPool();
}

CameraService :: instantiate()メソッドの詳細を以下に紹介します
まず、CameraServiceのクラス図を以下のように指定します:
ここに画像の説明を挿入
CameraService :: instantiate()は、親クラスBinderServiceのメソッドを呼び出します

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

次に、publish()メソッドが呼び出されます

// /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オブジェクトを作成します。

BpServiceManagerのaddServiceメソッドを以下に紹介します。

//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の2番目のパラメーターは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メソッドをトリガーします。コードは次のとおりです

//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()がトリガーされます

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

enumerateProviders()の関数
については、CameraService起動プロセス(ICameraProviderサービスプロキシオブジェクトBpHwCameraProviderを取得し、すべてのカメラデバイスプロキシオブジェクトBpHwCameraDeviceを取得するプロセス)で詳しく説明していますここでは詳しく紹介しません。

これまでのところ、CameraService :: instantiate()プロセスの分析は
完了しいます概要:CameraService :: instantiate()によって実行される3つのタスクは、次のように順番にリストされています。

  1. 新しいCameraServiceオブジェクト
  2. CameraService onFirstRefクラスメソッドをトリガーする
  3. ServiceManagerにサービスを登録する

次に、ProcessState :: self()-> startThreadPool();の分析を続けます。
コードは次のとおりです。

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

次に、スレッドループを分析します。

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

バインダーとのやり取りについては、ここでは詳しくは触れませんが、今後検討していきます。

これまでのところ、分析がcameraserverの起動プロセスを完了したで。
要約:

  1. CameraServiceオブジェクトを作成する
  2. CameraServiceがServiceManagerに登録されると、CameraService :: onFirstRefが最初にトリガーされます
  3. CameraServiceをServiceManagerに登録する
  4. 新しいバインダースレッドプールを作成し、継続的に/ dev / binderを読み取ります。メッセージがある場合、BBinder :: transactを呼び出し、CameraServiceのonTransactメソッドをトリガーします

おすすめ

転載: blog.csdn.net/u010116586/article/details/96476132