第14讲 cameraserver进程启动之LogicalDeviceStatusChange详解

本讲是Android Camera Native Framework专题的第14讲,我们介绍cameraserver进程启动之LogicalDeviceStatusChange。

更多资源:

资源 描述
在线课程 极客笔记在线课程
知识星球 星球名称:深入浅出Android Camera 星球ID: 17296815
Wechat 极客笔记圈

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<CameraState> 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<BasicClient> 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<StatusInternal> rejectSourceStates) {
    // Do not lock mServiceLock here or can get into a deadlock from
    // connect() -> disconnect -> updateStatus
auto state = getCameraState(cameraId);

if (state == nullptr) {
    ALOGW(&quot;%s: Could not update the status for %s, no such device exists&quot;, __FUNCTION__,
            cameraId.string());
    return;
}

// Avoid calling getSystemCameraKind() with mStatusListenerLock held (b/141756275)
SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
if (getSystemCameraKind(cameraId, &amp;deviceKind) != OK) {
    ALOGE(&quot;%s: Invalid camera id %s, skipping&quot;, __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-&gt;updateStatus(status, cameraId, rejectSourceStates, [this, &amp;deviceKind,
                    &amp;logicalCameraIds]
        (const String8&amp; 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, &amp;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&amp; listener : mListenerList) {
            bool isVendorListener = listener-&gt;isVendorListener();
            if (shouldSkipStatusUpdates(deviceKind, isVendorListener,
                    listener-&gt;getListenerPid(), listener-&gt;getListenerUid()) ||
                    isVendorListener) {
                ALOGV(&quot;Skipping discovery callback for system-only camera device %s&quot;,
                        cameraId.c_str());
                continue;
            }
            listener-&gt;getListener()-&gt;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<std::string> physicalCameraIds;
    mCameraProviderManager->isLogicalCamera(cameraId, &physicalCameraIds);
    std::set<String8> 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&lt;CameraState&gt;(id, cost.resourceCost,
            conflicting, deviceKind, physicalCameraIds));
}

if (mFlashlight-&gt;hasFlashUnit(id)) {
    Mutex::Autolock al(mTorchStatusMutex);
    mTorchStatusMap.add(id, TorchModeStatus::AVAILABLE_OFF);

    broadcastTorchModeStatus(id, TorchModeStatus::AVAILABLE_OFF, deviceKind);
}

updateCameraNumAndIds();
logDeviceAdded(id, &quot;Device added&quot;);

}

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);
}

}