本讲是android camera native framework专题的第14讲,我们介绍cameraserver进程启动之logicaldevicestatuschange。
更多资源:
资源 | 描述 |
---|---|
在线课程 | |
知识星球 | 星球名称:深入浅出android camera 星球id: 17296815 |
极客笔记圈 |
process cache status callbacks
本讲我们介绍logical cameradevice的status callback是逻辑。
cameradevicestatuschangelocked
上述流程图来自android 13:
status_t cameraprovidermanager::providerinfo::cameradevicestatuschangelocked(
std::string* id, const std::string& cameradevicename,
cameradevicestatus newstatus) {
bool known = false;
std::string cameraid;
for (auto& deviceinfo : mdevices) {
if (deviceinfo->mname == cameradevicename) {
mutex::autolock l(deviceinfo->mdeviceavailablelock);
alogi("camera device %s status is now %s, was %s", cameradevicename.c_str(),
frameworkdevicestatustostring(newstatus),
frameworkdevicestatustostring(deviceinfo->mstatus));
deviceinfo->mstatus = newstatus;
// todo: handle device removal (not_present)
cameraid = deviceinfo->mid;
known = true;
deviceinfo->misdeviceavailable =
(newstatus == cameradevicestatus::present);
deviceinfo->mdeviceavailablesignal.signal();
break;
}
}
// previously unseen device; status must not be not_present
if (!known) {
if (newstatus == cameradevicestatus::not_present) {
alogw("camera provider %s says an unknown camera device %s is not present. curious.",
mprovidername.c_str(), cameradevicename.c_str());
return bad_value;
}
adddevice(cameradevicename, newstatus, &cameraid);
} else if (newstatus == cameradevicestatus::not_present) {
removedevice(cameraid);
} else if (isexternallazyhal()) {
// do not notify cameraservice for present->present (lazy hal restart)
// because not_available is set on cameraservice::connect and a present
// notif. would overwrite it
return bad_value;
}
if (recacheconcurrentstreamingcameraidslocked() != ok) {
aloge("%s: cameraprovider %s could not re-cache concurrent streaming camera id list ",
__function__, mprovidername.c_str());
}
*id = cameraid;
return ok;
}
logical oncameradevicechanged
上述流程图来自android 13:
void cameraservice::ondevicestatuschanged(const string8& id,
cameradevicestatus newhalstatus) {
alogi("%s: status changed for cameraid=%s, newstatus=%d", __function__,
id.string(), newhalstatus);
statusinternal newstatus = maptointernal(newhalstatus);
std::shared_ptr state = getcamerastate(id);
if (state == nullptr) {
if (newstatus == statusinternal::present) {
alogi("%s: unknown camera id %s, a new camera is added",
__function__, id.string());
// first add as absent to make sure clients are notified below
addstates(id);
updatestatus(newstatus, id);
} else {
aloge("%s: bad camera id %s", __function__, id.string());
}
return;
}
statusinternal oldstatus = state->getstatus();
if (oldstatus == newstatus) {
aloge("%s: state transition to the same status %#x not allowed", __function__, newstatus);
return;
}
if (newstatus == statusinternal::not_present) {
logdeviceremoved(id, string8::format("device status changed from %d to %d", oldstatus,
newstatus));
// set the device status to not_present, clients will no longer be able to connect
// to this device until the status changes
updatestatus(statusinternal::not_present, id);
sp clienttodisconnectonline, clienttodisconnectoffline;
{
// don't do this in updatestatus to avoid deadlock over mservicelock
mutex::autolock lock(mservicelock);
// remove cached shim parameters
state->setshimparams(cameraparameters());
// remove online as well as offline client from the list of active clients,
// if they are present
clienttodisconnectonline = removeclientlocked(id);
clienttodisconnectoffline = removeclientlocked(kofflinedevice id);
}
disconnectclient(id, clienttodisconnectonline);
disconnectclient(kofflinedevice id, clienttodisconnectoffline);
removestates(id);
} else {
if (oldstatus == statusinternal::not_present) {
logdeviceadded(id, string8::format("device status changed from %d to %d", oldstatus,
newstatus));
}
updatestatus(newstatus, id);
}
}
cameraservice::updatestatus
上述流程图来自android 13:
void cameraservice::updatestatus(statusinternal status, const string8& cameraid,
std::initializer_list rejectsourcestates) {
// do not lock mservicelock here or can get into a deadlock from
// connect() -> disconnect -> updatestatus
auto state = getcamerastate(cameraid);
if (state == nullptr) {
alogw("%s: could not update the status for %s, no such device exists", __function__,
cameraid.string());
return;
}
// avoid calling getsystemcamerakind() with mstatuslistenerlock held (b/141756275)
systemcamerakind devicekind = systemcamerakind::public;
if (getsystemcamerakind(cameraid, &devicekind) != ok) {
aloge("%s: invalid camera id %s, skipping", __function__, cameraid.string());
return;
}
// collect the logical cameras without holding mstatuslock in updatestatus
// as that can lead to a deadlock(b/162192331).
auto logicalcameraids = getlogicalcameras(cameraid);
// update the status for this camera state, then send the onstatuschangedcallbacks to each
// of the listeners with both the mstatuslock and mstatuslistenerlock held
state->updatestatus(status, cameraid, rejectsourcestates, [this, &devicekind,
&logicalcameraids]
(const string8& cameraid, statusinternal status) {
if (status != statusinternal::enumerating) {
// update torch status if it has a flash unit.
mutex::autolock al(mtorchstatusmutex);
torchmodestatus torchstatus;
if (gettorchstatuslocked(cameraid, &torchstatus) !=
name_not_found) {
torchmodestatus newtorchstatus =
status == statusinternal::present ?
torchmodestatus::available_off :
torchmodestatus::not_available;
if (torchstatus != newtorchstatus) {
ontorchstatuschangedlocked(cameraid, newtorchstatus, devicekind);
}
}
}
mutex::autolock lock(mstatuslistenerlock);
notifyphysicalcamerastatuslocked(maptointerface(status), string16(cameraid),
logicalcameraids, devicekind);
for (auto& listener : mlistenerlist) {
bool isvendorlistener = listener->isvendorlistener();
if (shouldskipstatusupdates(devicekind, isvendorlistener,
listener->getlistenerpid(), listener->getlisteneruid()) ||
isvendorlistener) {
alogv("skipping discovery callback for system-only camera device %s",
cameraid.c_str());
continue;
}
listener->getlistener()->onstatuschanged(maptointerface(status),
string16(cameraid));
}
});
}
cameraservice::addstates
上述流程图来自android 13:
void cameraservice::addstates(const string8 id) {
std::string cameraid(id.c_str());
cameraresourcecost cost;
status_t res = mcameraprovidermanager->getresourcecost(cameraid, &cost);
if (res != ok) {
aloge("failed to query device resource cost: %s (%d)", strerror(-res), res);
return;
}
systemcamerakind devicekind = systemcamerakind::public;
res = mcameraprovidermanager->getsystemcamerakind(cameraid, &devicekind);
if (res != ok) {
aloge("failed to query device kind: %s (%d)", strerror(-res), res);
return;
}
std::vector physicalcameraids;
mcameraprovidermanager->islogicalcamera(cameraid, &physicalcameraids);
std::set conflicting;
for (size_t i = 0; i < cost.conflictingdevices.size(); i ) {
conflicting.emplace(string8(cost.conflictingdevices[i].c_str()));
}
{
mutex::autolock lock(mcamerastateslock);
mcamerastates.emplace(id, std::make_shared(id, cost.resourcecost,
conflicting, devicekind, physicalcameraids));
}
if (mflashlight->hasflashunit(id)) {
mutex::autolock al(mtorchstatusmutex);
mtorchstatusmap.add(id, torchmodestatus::available_off);
broadcasttorchmodestatus(id, torchmodestatus::available_off, devicekind);
}
updatecameranumandids();
logdeviceadded(id, "device added");
}
cameraservice::removestates
上述流程图来自android 13:
void cameraservice::removestates(const string8 id) {
updatecameranumandids();
if (mflashlight->hasflashunit(id)) {
mutex::autolock al(mtorchstatusmutex);
mtorchstatusmap.removeitem(id);
}
{
mutex::autolock lock(mcamerastateslock);
mcamerastates.erase(id);
}
}