本讲是android camera native framework专题的第13讲,我们介绍cameraserver进程启动之physicalcameradevicestatuschange。
更多资源:
资源 | 描述 |
---|---|
在线课程 | |
知识星球 | 星球名称:深入浅出android camera 星球id: 17296815 |
极客笔记圈 |
initializeproviderinfocommon
initializeproviderinfocommon主要完成2件事情:
- 调用adddevice将cameradevice保持在mdevices中
- 处理cached status回调
前面的课程已经介绍了adddevice的逻辑,本讲介绍处理cached status回调。
什么时候会有cache status
- 在cameraserver初始化provider过程中,hal通知发生了physicalcameradevicestatuschange 或 cameradevicestatuschange
process cache status callbacks
上面流程的逻辑来自android 13:
// process cached status callbacks
std::unique_ptr> cachedstatus =
std::make_unique>();
{
std::lock_guard lock(minitlock);
for (auto& statusinfo : mcachedstatus) {
std::string id, physicalid;
status_t res = ok;
if (statusinfo.isphysicalcamerastatus) {
res = physicalcameradevicestatuschangelocked(&id, &physicalid,
statusinfo.cameraid, statusinfo.physicalcameraid, statusinfo.status);
} else {
res = cameradevicestatuschangelocked(&id, statusinfo.cameraid, statusinfo.status);
}
if (res == ok) {
cachedstatus->emplace_back(statusinfo.isphysicalcamerastatus,
id.c_str(), physicalid.c_str(), statusinfo.status);
}
}
mcachedstatus.clear();
minitialized = true;
}
// the cached status change callbacks cannot be fired directly from this
// function, due to same-thread deadlock trying to acquire minterfacemutex
// twice.
if (listener != nullptr) {
minitialstatuscallbackfuture = std::async(std::launch::async,
&cameraprovidermanager::providerinfo::notifyinitialstatuschange, this,
listener, std::move(cachedstatus));
}
physicalcameradevicestatuschangelocked
上面流程的逻辑来自android 13:
status_t cameraprovidermanager::providerinfo::physicalcameradevicestatuschangelocked(
std::string* id, std::string* physicalid,
const std::string& cameradevicename,
const std::string& physicalcameradevicename,
cameradevicestatus newstatus) {
bool known = false;
std::string cameraid;
for (auto& deviceinfo : mdevices) {
if (deviceinfo->mname == cameradevicename) {
cameraid = deviceinfo->mid;
if (!deviceinfo->mislogicalcamera) {
aloge("%s: invalid combination of camera id %s, physical id %s",
__function__, cameraid.c_str(), physicalcameradevicename.c_str());
return bad_value;
}
if (std::find(deviceinfo->mphysicalids.begin(), deviceinfo->mphysicalids.end(),
physicalcameradevicename) == deviceinfo->mphysicalids.end()) {
aloge("%s: invalid combination of camera id %s, physical id %s",
__function__, cameraid.c_str(), physicalcameradevicename.c_str());
return bad_value;
}
alogi("camera device %s physical device %s status is now %s",
cameradevicename.c_str(), physicalcameradevicename.c_str(),
frameworkdevicestatustostring(newstatus));
known = true;
break;
}
}
// previously unseen device; status must not be not_present
if (!known) {
alogw("camera provider %s says an unknown camera device %s-%s is not present. curious.",
mprovidername.c_str(), cameradevicename.c_str(),
physicalcameradevicename.c_str());
return bad_value;
}
*id = cameraid;
*physicalid = physicalcameradevicename.c_str();
return ok;
}
physical ondevicestatuschanged
关于systemcamerakind的说明如下:
systemcamerakind | description |
---|---|
public | 所有拥有camera权限的进程可使用 |
system_only_camera | 三方app不可用,且必须有system_camera权限 |
hidden_secure_camera | 只给vendor client(hal进程)使用 |
上面流程的逻辑来自android 13:
void cameraservice::ondevicestatuschanged(const string8& id,
const string8& physicalid,
cameradevicestatus newhalstatus) {
alogi("%s: status changed for cameraid=%s, physicalcameraid=%s, newstatus=%d",
__function__, id.string(), physicalid.string(), newhalstatus);
statusinternal newstatus = maptointernal(newhalstatus);
std::shared_ptr state = getcamerastate(id);
if (state == nullptr) {
aloge("%s: physical camera id %s status change on a non-present id %s",
__function__, id.string(), physicalid.string());
return;
}
statusinternal logicalcamerastatus = state->getstatus();
if (logicalcamerastatus != statusinternal::present &&
logicalcamerastatus != statusinternal::not_available) {
aloge("%s: physical camera id %s status %d change for an invalid logical camera state %d",
__function__, physicalid.string(), newhalstatus, logicalcamerastatus);
return;
}
bool updated = false;
if (newstatus == statusinternal::present) {
updated = state->removeunavailablephysicalid(physicalid);
} else {
updated = state->addunavailablephysicalid(physicalid);
}
if (updated) {
string8 idcombo = id " : " physicalid;
if (newstatus == statusinternal::present) {
logdeviceadded(idcombo,
string8::format("device status changed to %d", newstatus));
} else {
logdeviceremoved(idcombo,
string8::format("device status changed to %d", newstatus));
}
// avoid calling getsystemcamerakind() with mstatuslistenerlock held (b/141756275)
systemcamerakind devicekind = systemcamerakind::public;
if (getsystemcamerakind(id, &devicekind) != ok) {
aloge("%s: invalid camera id %s, skipping", __function__, id.string());
return;
}
string16 id16(id), physicalid16(physicalid);
mutex::autolock lock(mstatuslistenerlock);
for (auto& listener : mlistenerlist) {
if (shouldskipstatusupdates(devicekind, listener->isvendorlistener(),
listener->getlistenerpid(), listener->getlisteneruid())) {
alogv("skipping discovery callback for system-only camera device %s",
id.c_str());
continue;
}
listener->getlistener()->onphysicalcamerastatuschanged(maptointerface(newstatus),
id16, physicalid16);
}
}
}