第13讲 cameraserver进程启动之PhysicalCameraDeviceStatusChange详

2024年11月02日 第13讲 cameraserver进程启动之PhysicalCameraDeviceStatusChange详解 极客笔记

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

更多资源:

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

initializeProviderInfoCommon

initializeProviderInfoCommon主要完成2件事情:

  1. 调用addDevice将CameraDevice保持在mDevices中
  2. 处理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);
        }
    }
}

本文链接:http://so.lmcjl.com/news/16811/

展开阅读全文