- 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つのタスクは、次のように順番にリストされています。
- 新しいCameraServiceオブジェクト
- CameraService onFirstRefクラスメソッドをトリガーする
- 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の起動プロセスを完了したで。
要約:
- CameraServiceオブジェクトを作成する
- CameraServiceがServiceManagerに登録されると、CameraService :: onFirstRefが最初にトリガーされます
- CameraServiceをServiceManagerに登録する
- 新しいバインダースレッドプールを作成し、継続的に/ dev / binderを読み取ります。メッセージがある場合、BBinder :: transactを呼び出し、CameraServiceのonTransactメソッドをトリガーします