目录

  • 前言
  • 注册媒体服务初始路径
    • 1、signal函数
    • 2、设置hwbinder通信的线程数
    • 3、Binder机制-ProcessState过程
    • 4、defaultServiceManager()
      • 1.ProcessState::self()
      • 2.ProcessState::getContextObject(…)
      • 3.interface_cast(…)
    • 5、Camera Service初始化
    • 6、建立新线程并使子线程循环
  • 总结

前言

在 Android P 中,系统启动时,就会启动 CameraProvider 服务。它将 Camera HAL 从 cameraserver 进程中分离出来,作为一个独立进程 android.hardware.camera.provider@2.4-service 来控制 HAL。 这两个进程之间通过 HIDL 机制进行通信。

注册媒体服务初始路径

/frameworks/av/camera/cameraserver/main_cameraserver.cpp

int main(int argc __unused, char** argv __unused)
{signal(SIGPIPE, SIG_IGN);// Set 3 threads for HIDL callshardware::configureRpcThreadpool(3, /*willjoin*/ false);sp<ProcessState> proc(ProcessState::self());sp<IServiceManager> sm = defaultServiceManager();ALOGI("ServiceManager: %p", sm.get());CameraService::instantiate();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();
}

1、signal函数

1.signal(SIGPIPE,SIG_IGN);
信号,参数一是我们要处理的信号,参数二是处理的方式,防止僵尸进程,能够有效的init 。

2、设置hwbinder通信的线程数

2.hardware::configureRpcThreadpool(3, /*willjoin*/ false);
设置用于hwbinder通信的线程数,通知kernel当前进程最大允许的binder线程池为maxThreads ,这里为3
。

3、Binder机制-ProcessState过程

3.sp<ProcessState> proc(ProcessState::self());
设置用于hwbinder通信的线程数,通知kernel当前进程最大允许的binder线程池为maxThreads ,这里为3
。

其中,ProcessState::self()函数是ProcessState类中的一个静态函数(static),属于这个类,不属于某个具体对象。其函数体如下:

sp<ProcessState> ProcessState::self()
{Mutex::Autolock _l(gProcessMutex);if (gProcess != NULL) {return gProcess;}gProcess = new ProcessState("/dev/binder");return gProcess;
}

gProcess为一个全局变量,目的就是在一个进程中,只会唯一存在一个这样的变量gProcess,且内部语句也只会执行一次,即实例化一次ProcessState。

gProcess = new ProcessState("/dev/binder");

ProcessState构造函数如下:

ProcessState::ProcessState(const char *driver): mDriverName(String8(driver)), mDriverFD(open_driver(driver))
..., mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
...
{if (mDriverFD >= 0) {// mmap the binder, providing a chunk of virtual address space to receive transactions.mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

mDriverFD函数打开了设备驱动,并把设备驱动的fd保存在mDriverFD中。

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);...size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);...}...return fd;
}

这个函数做了一下工作:
1、同binder驱动建立链接
2、获得驱动的版本。
3、通知驱动,我最多可同时启动多少个线程来处理Client端的请求

fd = open(driver, O_RDWR | O_CLOEXEC)
//以读写方式打开传入的设备文件
status_t result = ioctl(fd, BINDER_VERSION, &vers);
//获取binder驱动版本信息
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//DEFAULT_MAX_BINDER_THREADS = 15
//设置Binder驱动的最大线程数量为15 。

4、defaultServiceManager()

sp<IServiceManager> sm = defaultServiceManager();

gDefaultServiceManager是全局的IServiceManager对象获取IServiceManager服务代理对象BpServiceManager 。
关键步骤可以分解为几步:
1.ProcessState::self()
2.ProcessState::getContextObject(…)
3.interface_cast(…)

1.ProcessState::self()

frameworks/native/libs/binder/ProcessState.cpp

sp<ProcessState> ProcessState::self()  // 这又是一个进程单体
{Mutex::Autolock _l(gProcessMutex);if (gProcess != NULL) {return gProcess;}gProcess = new ProcessState;  // 首次创建在这里return gProcess;
}

ProcessState的构造函数frameworks/native/libs/binder/ProcessState.cpp

ProcessState::ProcessState(): mDriverFD(open_driver())  // 这里打开了/dev/binder文件,并返回文件描述符, mVMStart(MAP_FAILED), mThreadCountLock(PTHREAD_MUTEX_INITIALIZER), mThreadCountDecrement(PTHREAD_COND_INITIALIZER), mExecutingThreadsCount(0), mMaxThreads(DEFAULT_MAX_BINDER_THREADS), mManagesContexts(false), mBinderContextCheckFunc(NULL), mBinderContextUserData(NULL), mThreadPoolStarted(false), mThreadPoolSeq(1)
{if (mDriverFD >= 0) {// XXX Ideally, there should be a specific define for whether we// have mmap (or whether we could possibly have the kernel module// availabla).
#if !defined(HAVE_WIN32_IPC)// mmap the binder, providing a chunk of virtual address space to receive transactions.mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); if (mVMStart == MAP_FAILED) {// *sigh*ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");close(mDriverFD);mDriverFD = -1;}
#elsemDriverFD = -1;
#endif}LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

ProcessState的构造函数主要完成两件事:1、初始化列表里调用opern_driver(),打开了文件/dev/binder;2、将文件映射到内存。ProcessState::self()返回单体实例。

2.ProcessState::getContextObject(…)

frameworks/native/libs/binder/ProcessState.cpp

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{sp<IBinder> result;AutoMutex _l(mLock);handle_entry* e = lookupHandleLocked(handle);  //正常情况下总会返回一个非空实例  if (e != NULL) {// We need to create a new BpBinder if there isn't currently one, OR we// are unable to acquire a weak reference on this current one.  See comment// in getWeakProxyForHandle() for more info about this.IBinder* b = e->binder;if (b == NULL || !e->refs->attemptIncWeak(this)) {if (handle == 0) {  // 首次创建b为NULL,handle为0  (...) b = new BpBinder(handle); e->binder = b;if (b) e->refs = b->getWeakRefs();result = b;  // 返回的是BpBinder(0)  } else {// This little bit of nastyness is to allow us to add a primary// reference to the remote proxy when this team doesn't have one// but another team is sending the handle to us.result.force_set(b);e->refs->decWeak(this);}}return result;
}

result也就是b,也就是new BpBinder(handle),作为interface_cast的参数。

3.interface_cast(…)

interface_cast(…)函数在binder体系中非常常用,后面还会不断遇见。该函数定义在
frameworks/native/include/binder/IInterface.h

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{return INTERFACE::asInterface(obj);
}

asInterface()是通过DECLARE_META_INTERFACE()来声明,并通过IMPLEMENT_META_INTERFACE()来实现的。该函数藏在宏IMPLEMENT_META_INTERFACE中。

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
android::sp< IServiceManager > IServiceManager::asInterface(const android::sp<android::IBinder>& obj){android::sp< IServiceManager > intr;if (obj != NULL) {intr = static_cast< IServiceManager *>( obj->queryLocalInterface(IServiceManager::descriptor).get());if (intr == NULL) {  // 首次会走这里intr = new BpServiceManager(obj);}}return intr;}

因此它返回的就是new BpServiceManager(new BpBinder(0))。defaultServiceManager()的返回值即为new BpServiceManager(new BpBinder(0))。

总结来说,gDefaultServiceManager=>>IServiceManager =>>BpBinder=>>BpServiceManager,那也就是说以后调用IServiceManager->addService就是BpServiceManager->addService。

5、Camera Service初始化

CameraService::instantiate();

CameraService::instantiate()调用的是其父类BinderService的方法。

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

接着调用了publish()方法

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

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

随后调用BpServiceManager的addService方法

//frameworks\native\libs\binder\IServiceManager.cppvirtual 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;}

该方法写入Interface name,Service name,Service实例。
其中addService的第二个形参为const sp& service,而传入的CameraService对象。所以会调用sp的自动类型转换构造函数函数。

//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方法,是获取所有相机ICameraProvider代理对象BpHwCameraProvider的流程。

//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();
}
void CameraService::onFirstRef()
{ALOGI("CameraService process starting");BnCameraService::onFirstRef();...res = enumerateProviders();...CameraService::pingCameraServiceProxy();
}

enumerateProviders()函数的作用是在CameraService启动流程-获取ICameraProvider服务代理对象BpHwCameraProvider并由此获取全部相机设备代理对象BpHwCameraDevice。

status_t CameraService::enumerateProviders() {status_t res;std::vector<std::string> deviceIds;{Mutex::Autolock l(mServiceLock);if (nullptr == mCameraProviderManager.get()) {mCameraProviderManager = new CameraProviderManager();res = mCameraProviderManager->initialize(this);if (res != OK) {ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",__FUNCTION__, strerror(-res), res);return res;}}...

mCameraProviderManager->initialize 创建CameraProviderManager对象获取ICameraProvider代理对象BpHwCameraProvider,随后在addProviderLocked首先获取ICameraProvider服务,然后开始遍历所有相机设备,获取所有相机设备ICameraDevice代理对象BpHwCameraDevice。

至此分析完了CameraService::instantiate()的流程
总结:
CameraService::instantiate()完成的三个任务,按前后顺序排列,有:
1.this新建CameraService对象
2.触发CameraService onFirstRef类方法
3.注册服务给ServiceManager

6、建立新线程并使子线程循环

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.cppvoid ProcessState::spawnPooledThread(bool isMain)
{if (mThreadPoolStarted) {String8 name = makeBinderThreadName();ALOGV("Spawning new pooled thread, name=%s\n", name.string());//建立一个新线程并启动sp<Thread> t = new PoolThread(isMain);t->run(name.string());}
}

函数中isMain为true,说明是主线程,线程名为Binder:PID_%X。

ssl._create_default_https_context = ssl._create_unverified_context

随后会new一个PoolThread,子线程循环,不断读取/dev/binder以获取其他线程发来的命令,且函数内置循环,将当前线程(这里是主线程)加入到 binder线程池中。

//frameworks\native\libs\binder\ProcessState.cpp
class PoolThread : public Thread
{public:explicit PoolThread(bool isMain): mIsMain(isMain){}protected://子线程循环virtual bool threadLoop(){   IPCThreadState::self()->joinThreadPool(mIsMain);return false;}const bool mIsMain;
};

接着会调用IPCThreadState::self()->joinThreadPool(mIsMain),将当前线程加入到 binder线程池中。在下边的代码中可知,如今是将子线程加入到Binder线程池。随后开启循环,与dev/binder通信,将mOut中的cmd写入binder驱动,通过switch case结构处理发来的命令,执行相应方法。

//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());//main为truemOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);status_t result;do {processPendingDerefs();//获取命令并执行或者等待命令// now get the next command to be processed, waiting if necessaryresult = 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();}...

总结

至此分析完成了cameraserver的启动流程
总结下:
1.建立CameraService对象。
2.将CameraService注册给ServiceManager时,首先触发了CameraService::onFirstRef。
3.将CameraService注册给ServiceManager。
4.新建binder线程池,不断读取/dev/binder。若是有消息会调用BBinder::transact并触发CameraService的onTransact方法。

Camera service服务启动流程相关推荐

  1. VMware DHCP Service服务启动时报错:错误1068 依存服务或组无法启动

    VMware DHCP Service服务启动时报错:错误1068 依存服务或组无法启动 解决办法: 1.选择虚拟网络编辑器 ok了,问题解决 来自为知笔记(Wiz) 转载于:https://www. ...

  2. Httpd 服务启动流程

    Httpd 服务 1. 先检查本机的 httpd 服务是否开启, 使用命令: service --status-all | grep httpd 2. 开启 httpd 服务 启动httpd服务:se ...

  3. Win10 Network Setup Service服务启动后自动停止问题的解决方案

    问题描述 网卡属性界面为空白 解决方案 1.打开服务,找到Network Setup Service服务 2.在启动"Network Setup Service"服务的之后的瞬间, ...

  4. (一)swoole服务启动流程

    代码2.0 服务启动依赖于进程,在进程中用swoole_server来创建,源码中的别名函数为swoole_server_create,默认的sock_type是tcp,服务模式serv_mode为进 ...

  5. rc-local.service服务启动失败,导致rc.local中的开机启动服务不能启动

    chmod  +x   /etc/rc.d/rc.local 打开/etc/rc.local文件,将启动非后台执行的指令的最后添加 &,以使相关指令后台运行,然后启动服务 systemctl  ...

  6. 浅谈erlang游戏服务器项目--英雄远征服务启动流程

    1.看代码结构我们知道启动脚本run.sh,看脚本中的-s sd server_start我们知道启动接口在sd.erl的server_start函数. 2.我们打开sd.erl找到server_st ...

  7. 深入分析Android 9.0源代码——Service启动流程(startService方式)

    引言 点击此处查看<深入分析Android 9.0源代码>系列的组织结构和相关说明. 1 应用进程发起启动请求 本章的调用流程如下图所示: (Context)ContextWrapperC ...

  8. (七十)Android O Service启动流程梳理——bindService

    前言:最近在处理anr问题的时候迫切需要搞清楚service的启动流程,抽时间梳理一下. 1.service启动简述 service启动分三种,比较简单的就是startService,Android ...

  9. service启动activity_「 Android 10 四大组件 」系列—Service 的 quot; 启动流程 quot;

    作者:DeepCoder 核心源码 关键类路径 Service 的启动过程相对 Activity 的启动过程来说简单了很多,我们都知道怎么去创建和启动一个 Service, 那么你有没有从源码角度研究 ...

  10. 无法连接到本地计算机上,Windows无法启动VMware USB Arbitration Service服务(位于本地计算机上)。解决方法...

    在windows电脑上,我们在用VMware 的时候,都会遇到各种各样的问题,特别是VMware USB Arbitration Service服务这个问题: "VMware USB Arb ...

最新文章

  1. Dlib简介及在windows7 vs2013编译过程
  2. 未来的房地产,一边香港化,一边鹤岗化
  3. Ubuntu16.04LTS安装ROS Kinetic
  4. 从零认识单片机(9)
  5. 如何删除过期的数据库备份文件呢? .
  6. 设计模式:单件模式(Singleton Pattern)
  7. 嵌入式Linux内核优化裁剪
  8. mysql中的sql
  9. ** 安装好的Apache服务器不能在本地计算机启动
  10. snmp服务配置及其oid、mib文件解析
  11. CSDN博客喜遇中兴老同事
  12. 一个不明觉厉的貌似包含很多linux资料索引的网页
  13. sns.load_dataset报错解决
  14. 为什么我要建立自己的公众号?
  15. 链接h5代码_H5是什么?今天给大家做一个全面的解释
  16. paypal沙盒用户_如何使用PayPal实施用户登录
  17. WIN10下msi GE62 1077 无线热点掉线问题处理(更新:取消自动关闭热点
  18. iOS 相机调用后为英文的解决办法
  19. XTOOL EZ500全系统的诊断和特殊功能超越Xtool EZ400 EZ300 Xtool PAD
  20. Hybrid eye center localization using cascaded regression and hand-crafted model fitting

热门文章

  1. oracle字段Varchar2长度问题
  2. MySQL数据表操作思维导图
  3. 64位win10安装不了64位java(点了安装没反应)
  4. C语言从入门到放弃2022年8月3号
  5. 智能红绿灯自动控制系统分析
  6. python压缩图片和视频
  7. Power BI学习
  8. 【矩阵论】对称矩阵特征值的性质与直积
  9. 毕业设计——如何画系统功能结构图?
  10. IIR滤波器设计基础及Matlab设计示例