本讲是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);
}
}