CameraService笔记

发布于:2025-09-09 ⋅ 阅读:(20) ⋅ 点赞:(0)

camera 结构图

camera 结构图

1. 启动CameraServer

1.1 注册media.camera服务

将media.camera注册到ServiceManager。
在这里插入图片描述

1.2 构造CameraService

  1. AttributionAndPermissionUtilsEncapsulator:
  2. mCameraServiceProxyWrapper:
  3. mEventLog:打开或者关闭camera的event log;
  4. mNumberOfCameras:camera的数量;
  5. mNumberOfCamerasWithoutSystemCamera:剔除systemCamera以后得数量;
  6. mSoundRef:控制mAudioRestriction;
  7. mInitialized:是否已经做了mInitialized;

构造完之后会执行onFirstRef。

1.3 CameraService::onFirstRef

在这里插入图片描述

  • notifier.noteResetCamera、notifier.noteResetFlashlight:统计camera、Flashlight的使用时长,重置统计使用时长的Timer;
  • enumerateProviders:跟hal进程交互;
  • mUidPolicy->registerSelf:registerSelf–>registerUidObserverForUids,UidPolicy向ActivityManger调用registerUidObserverForUids,监听使用camera的UID变化,如果UID不是active,不允许使用camera,为了保护用户隐私;
  • mSensorPrivacyPolicy->registerSelf:判断SensorPrivacy是否启用了隐私,如果启用就阻止所有进程使用camera;
  • mAppOps.setCameraAudioRestriction`:设置声音;
  • hcs->registerAsService:注册C++层的HidlCameraService,让vndk可以获取到CameraServer,向hal提供访问CameraServer的接口;
  • mCameraServiceProxyWrapper->pingCameraServiceProxy:CameraServiceProxy会通知CameraService是否有user switch和device state(更新sensor orientation);
    • CameraServiceProxyWrapper是system_server进程中的一个服务,协助处理多用户、usb camera、折叠屏等场景;

1.4 CameraService::enumerateProviders:前置准备知识

看enumerateProviders前,先了解前置准备知识:

  • 1.4.1-p1 CameraHALProvider接口
  • 1.4.1-p2 CameraService与CameraProviderManager的关系

1.4.1 准备知识:CameraHALProvider接口
CameraHALProvider接口分成HIDL和AIDL两种。

代码路径:/hardware/interfaces/camera/
AIDL代码:
在这里插入图片描述

HIDL代码:
在这里插入图片描述
主要接口:
在这里插入图片描述
作用:

  1. ICameraProvider:由CameraHALProvider实现,帮助cameraserver调到CameraHALProvider;管理多个ICameraDevice;
  2. ICameraProviderCallback:由CameraServer实现,帮助CameraHALProvider调到cameraserver;
  3. ICameraDevice:代表并管理某一个CameraDevice(Physical Camera、Logical Camera);
  4. ICameraDeviceSession:打开camera后,hal device操作device;
  5. ICameraDeviceCallback:帮助device回调到hal device;

创建时机:
初始化时,创建ICameraProvider、ICameraDevice;
open camera/close camera时,创建ICameraDeviceSession;

关系:通过ICameraProvider获取ICameraDevice,通过ICameraDevice获取ICameraDeviceSession;
在这里插入图片描述

1.4.1-p2 准备知识:CameraService与CameraProviderManager的关系

  • CameraService通过CameraProviderManager管理Camera HAL Provider;

  • Camera HAL Provider通过CameraProvicerManager::StatusListener回调到CameraService;
    在这里插入图片描述
    1.4.1-p3 准备知识:ProviderInfo
    CameraProviderManager::ProviderInfo

  • CameraProviderManager抽象出ProviderInfo来屏蔽HIDL和AIDL Provider的差异,将差异部分交给HidlProviderInfo和AidlProviderInfo去处理。
    在这里插入图片描述
    前置准备知识已经看完了,开始看enumerateProviders

1.4 CameraService::enumerateProviders:Provider和Device初始化

  1. 什么时候调用enumerateProviders

    • CameraServer进程启动时调用CameraService::onFirstRef;
    • CameraServer进程启动后,有新的Provider注册到ServiceManager时调用CameraService::onNewProviderRegistered;
  2. enumerateProviders

    • 创建CameraProviderManager,并调用initialize完成初始化;
    • 初始化VendorTags;
    • 初始化Flashlight,完成枚举动作;
    • 获取所有deviceId,把deviceId设置成PRESENT,即设置成可用状态;
    • 针对前/后摄,为SPerfClass过滤CameraCharacteristics;
      • SPerfClass是为不同安卓手机定义的Performmance的级别,为了满足CDD要求过滤CameraCharacteristics;
  3. CameraHALProvider初始化流程
    在这里插入图片描述
    Add Hidl Provider重要流程:

    1. 在registerForNotifications方法中,向hwservicemanager/ServiceManager.cpp注册ICameraProvider的HidlService的Notification,如果HidlService注册到hwservicemanager;
      • registerForNotifications的回调方法是onRegistration,如果收到onRegistration回调通知,会调到CameraServer::onNewProviderRegistered,告诉CameraServer注册成功,也会做addHidlProviderLocked操作;
    2. 用listServices方法查找hwservicemanager中有多少是ICameraProvider的HidlService,然后做addHidlProviderLocked操作,创建HidlProviderInfo;
  • registerForNotifications方法的作用:
    • CameraServer监听Provider,防止hal进程比CameraServer启动慢;
    • 防止hal进程发生crash重启,hal进程会重启并重新注册到HwServiceManager,CameraServer会收到hal进程重新注册回调;

1.4.1 initializeHidlProvider:HIDL Provider初始化

HidlProviderInfo::initializeHidlProvider

  1. castFrom:判断ICameraProvider的mMinorVersion;
  2. setCallback:Cameraserver接收hal的ICameraProviderCallback的回调;
  3. linkToDeath:这是监听HidlService挂掉,上面的onRegistration是监听注册成功,在HidlProviderInfo::serviceDied方法处理HidlService挂掉后的异常,从mProviders 中删掉Provider;
  4. notifyDeviceStateChange:通知HAL进程,当前摄像头的状态(NORMAL/BACK_COVERED被盖住/FRONT_COVERED前置被盖住/FOLDED折叠状态,可以一次性通知多个状态),只有在Provider 2.5及之后的版本才有;
  5. setUpVendorTags:调用ICameraProvider的getVendorTags方法拿到VendorTagSection,然后创建VendorTagDescriptor,通过VendorTagDescriptor就能知道有哪些Vendor Tag了;
  6. interface->getCameraIdList:获取当前Provider有多少Camera Device,解析出Camera ID存放在mProviderPublicCameraIds(interface = ICameraProvider);
  7. getConcurrentCameraIdsInternalLocked:如果Provider >= 2.6,获取哪些Camera可以同时做ConfigureStream,存放在mConcurrentCameraIdCombinations;
  8. interface->isSetTorchModeSupported:判断是否支持手电筒,结果存放在mSetTorchModeSupported;
  9. initializeProviderInfoCommon:完成Device的初始化;

1 initializeProviderInfoCommon

CameraProviderManager::ProviderInfo::initializeProviderInfoCommon
在这里插入图片描述

主要完成2件事情:

  1. 调用addDevice将CameraDevice保持在mDevices中;
  2. 处理cachedStatus回调,就是初始化Provider过程中,Device状态发生变化,先把状态缓存起来,初始化Provider结束后再做状态变化操作;

1.4.2 addDevice:HIDL Device初始化

CameraProviderManager::ProviderInfo::addDevice

  1. 检查CameraDevice的版本是否正确:
    1. 根据device的name解析出的Camera ID、MajorVersion、IPCTransport都必须唯一;
    2. IPCTransport::HIDL的对应的Device MajorVersion必须为3,IPCTransport::AIDL的对应的Device MajorVersion必须为1;
  2. initializeDeviceInfo:初始化Camera Device Info,由AIDLProviderInfo/HIDLProviderInfo实现;(重点)
  3. notifyDeviceStateChange:根据手机状态去更新ANDROID_SENSOR_ORIENTATION,这里的DeviceState不是手机摄像头状态,是指手机状态;
  4. isAPI1Compatible:判断是否支持API1,根据 ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT、ANDROID_REQUEST_AVAILABLE_CAPABILITIES判断;
    • 如果ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT是NIR(Near Infrared Filter,近红外sensor,捕获波长大约在750纳米和1400纳米之间的光线),则这种sensor不支持API1
1.4.2.1 initializeDeviceInfo

HidlProviderInfo::initializeDeviceInfo

  1. 获取到ICameraDevice的实例:调用ICameraProvider的getCameraDeviceInterface_V3_x获取到ICameraDevice的实例,不会每次都调用Provider接口,HidlDeviceInfo3会缓存ICameraDevice实例;
  2. cameraInterface->getResourceCost:调用ICameraDevice的getResourceCost获取到ResourceCost,ResourceCost是指统计打开camera消耗的资源得分,超过100就禁止打开;
  3. new HidlDeviceInfo3:处理静态信息,比如获取SystemCameraKind和修复/更新mCameraCharacteristics(重点)
1.4.2.2 new HidlDeviceInfo3
  1. 获取CameraCharacteristics:调用getCameraCharacteristics获取metadata放入mCameraCharacteristics(Characteristics:静态信息)
  2. 获取DeviceStateOrientationMap:获取 ANDROID_INFO_DEVICE_STATE_ORIENTATIONS的值,保存在mDeviceStateOrientationMap
  3. 获取到mSystemCameraKind:调用getSystemCameraKind获取到mSystemCameraKind
    • 如果Capability是ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA,则返回SystemCameraKind::HIDDEN_SECURE_CAMERA
    • 如果Capability有ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA,则返回SystemCameraKind::SYSTEM_ONLY_CAMERA
    • 其他情况返回SystemCameraKind::PUBLIC
  4. 修复/更新mCameraCharacteristics:fixupMonochromeTags、addDynamicDepthTags、deriveHeicTags、addRotateCropTags、addPreCorrectionActiveArraySize、overrideZoomRatioTags、fixupTorchStrengthTags、queryPhysicalCameraIds(重点)
  5. 修复/更新未Public出去的PhysicalCameraCharacteristics: overrideZoomRatioTags(重点)
1.4.2.3 修复/更新 mCameraCharacteristics
  1. CameraProviderManager::ProviderInfo::DeviceInfo3::fixupMonochromeTags(黑白camera)
  • 如果Camera Device < 3.5 并且包含Monochrome(HAL 3.3新增)
    • 更新ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT为ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO
    • 删除不需要的metadata(Static Keys,Request Keys,Result Keys)
    • ANDROID_SENSOR_BLACK_LEVEL_PATTERN的4个通道设为同一个值。
  1. CameraProviderManager::ProviderInfo::DeviceInfo3::addDynamicDepthTags(景深信息)
  • 是指包含Depth信息的JPEG,在Camera Framework完成Jpeg和Depth Buffer的合成,在这里填相关静态Metadata,HAL不会填,筛选规则是:Jpeg和Depth Size相同(或宽高相近)的Streams
    • ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS
    • ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS
    • ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS
  1. CameraProviderManager::ProviderInfo::DeviceInfo3::deriveHeicTags
  • HEIC是Camera Framework调用Encoder的接口压成HEIC的,因此相关静态Metadata需要补上
  • ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS
  • ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS
  • ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS
  1. CameraProviderManager::ProviderInfo::DeviceInfo3::addRotateCropTags
  • 如果ANDROID_SCALER_AVAILABLE_ROTATE_AND_CROP_MODES没有填,则至少填一个值:ANDROID_SCALER_ROTATE_AND_CROP_NONE
  1. ameraProviderManager::ProviderInfo::DeviceInfo3::addPreCorrectionActiveArraySize
  • 如果ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE没有填,则获取ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE的值填进去
  1. ZoomRatioMapper::overrideZoomRatioTags
  • 如果HAL不支持ANDROID_CONTROL_ZOOM_RATIO_RANGE,则通过ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM来构造一个ZoomRatioRange更新到ANDROID_CONTROL_ZOOM_RATIO_RANGE。并增加ZoomRatio相关的Static/Request/Result Keys
  1. CameraProviderManager::ProviderInfo::DeviceInfo3::fixupTorchStrengthTags
  • 如果没有填ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL,则填成1
  • 如果没有填ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL,则填成1
  1. CameraProviderManager::ProviderInfo::DeviceInfo3::queryPhysicalCameraIds
  • 如果支持LogicalCamera,则从ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS获取到PhysicalCameraIds放到mPhysicalIds
  1. 修复/更新 PhysicalCamera Characteristics
  • 如果支持LogicalCamera
  • getPhysicalCameraCharacteristics
  • overrideZoomRatioTags

1.4.5 CameraDeviceStatus:前置准备知识

看CameraDeviceStatus前,先了解前置准备知识:

  • p1 CameraDeviceStatus流程
  • p2 HIDL Camera Device Status
  • p3 Framework Camera Device Status
  • p4 Logical VS Physical VS Logical MultiCam

p1. CameraDeviceStatus流程
在这里插入图片描述

p2. HIDL Camera Device Status
在这里插入图片描述
代码位置:hardware/interfaces/camera/common/aidl/android/hardware/camera/common/CameraDeviceStatus.aidl
- NOT_PRESENT: CameraDevice没有连接物理设备;
- ENUMERATING: CameraDevice已经连接物理设备,暂时还不能使用,等enumerateProviders结束;
- PRESENT: CameraDevice已经连接物理设备,可以使用,调用getCameraIdList可以发现该CameraDevice;

p3. Framework Camera Device Status
代码位置:frameworks/av/camera/aidl/android/hardware/ICameraServiceListener.aidl

  • STATUS_NOT_PRESENT: CameraDevice没有连接物理设备;
  • STATUS_PRESENT: CameraDevice已经连接物理设备,可以被使用;
  • STATUS_ENUMERATING: CameraDevice已经连接物理设备,暂时还不能使用,需要等enumerateProviders结束;
  • STATUS_NOT_AVAILABLE:其他APP在占用CameraDevice;
  • STATUS_UNKNOWN:仅用于初始化变量,无意义;

p4. Logical VS Physical VS Logical MultiCam

  1. APP只能看见LogicalCameraId或者LogicalCameraDevice,如果APP看到的是LogicalMultiCamera,逻辑上是一个CameraDevice,但是有多个CameraDevice硬件;

  2. logical 和 physical有值的对应关系。

    1. APP能看到5颗Camera,实际只有3颗物理Camera
    • Logical 0,1,2都对应一个PhysicalCamera;
    • Logical multicam 3和4分别对应2个PhysicalCamera;
      在这里插入图片描述

1.4.5 CameraDeviceStatus的处理流程

在这里插入图片描述

  • 在providerManager中用mDevices管理cameraDevice的状态,在cameraservice里面通过mCameraStates管理cameraDevice的状态。

1 initializeProviderInfoCommon
CameraProviderManager::ProviderInfo::initializeProviderInfoCommon:

  1. initializeProviderInfoCommon主要完成2件事情:

    • 调用addDevice将CameraDevice保持在mDevices中;
    • 处理CachedStatus回调;
      前面的课程已经介绍了addDevice的逻辑,这里介绍处理Cached Status回调。
  2. 什么时候会有Cache Status:

    • 在CameraServer初始化Provider过程中,HAL通知CameraService的CameraDeviceStatus发生physicalCameraDeviceStatusChange或cameraDeviceStatusChange(logical)
开始处理CachedStatus回调

在这里插入图片描述

1 physicalCameraDeviceStatusChangeLocked

CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChangeLocked:
1. 拿logical cameraDeviceId;
2. 检查physicalCameraDevice是否合法;
参数:
cameraDeviceName: logical cameraDeviceName;
physicalCameraDeviceName: physical cameraDeviceName;
在这里插入图片描述

2 onDeviceStatusChanged
CameraService::onDeviceStatusChanged

三个参数的方法是physical使用
SystemCameraKind:
PUBLIC: 所有拥有Camera权限的进程可使用,比如三方相机;
SYSTEM_ONLY_CAMERA: 系统自带相机,三方APP不可用,且必须有SYSTEM_CAMERA权限;
HIDDEN_SECURE_CAMERA: 只给vender分区(HAL进程)使用,hal层的相机,比如人脸解锁;
在这里插入图片描述

3 cameraDeviceStatusChangeLocked

CameraProviderManager::ProviderInfo::cameraDeviceStatusChangeLocked

  1. 在mDevices中根据cameraDeviceName找到对应的DeviceInfo;
    • 如果找到,状态为NOT_PRESENT,执行removeDevice;
    • 如果没有找到,状态为PRESENT,执行addDevice;
  2. reCacheConcurrentStreamingCameraIdsLocked;
  3. 返回cameraId;

4 onDeviceStatusChanged
CameraService::onDeviceStatusChanged

  1. getCameraState(cameraId):获取cameraDevice的状态;
    • 如果获取的state为空,执行addStates、updateStatus;
  2. 如果state不为空,newStatus == StatusInternal::NOT_PRESENT;
    • 如果是,执行updateStatus,把cameraId的状态更新成NOT_PRESENT;
      • logDeviceRemoved: cameraserver里的logEvent都可以用dumpsys media.camera打印出来;
      • removeClientsLocked,包括online和offline;
      • disconnectClients,包括onlin和offline;
      • removeStates(cameraId);
    • 如果不是,并且oldStatus == StatusInternal::NOT_PRESENT,执行添加状态;addStates(cameraId);执行updateStatus,把cameraId的状态更新成NOT_PRESENT;

CameraService::onDeviceStatusChanged,两个参数的方法是logical使用。

5 updateStatus
CameraService::updateStatus

  1. 获取cameraId状态
  2. getSystemCameraKind:是系统分区的camera,还是vender分区的camera;
  3. getCameraCharacteristics;
  4. state->updateStatus;
    • 如果新的状态不是ENUMERATING,需要检查这颗camera的TorchModeStatus是否发生变化,如果有变化则调用onTorchStatusChangedLocked,最终会通过i->getListener()->onTorchStatusChanged调到app;
    • 调用notifyPhysicalCameraStatusLocked,如果拿不到logicalCameraIds则不会调用这个方法,调这个方法的原因是一个PhysicalCamera可能会映射到多个LogicalCamera;
    • 针对每一个Listener调用listener->getListener()->onStatusChanged,调到app;

6 addStates
CameraService::addStates

  • 有一个新的camera来了,需要构建一个cameraStates对象,步骤:
  1. mCameraProviderManager->getResourceCost;
  2. mCameraProviderManager->getSystemCameraKind;
  3. mCameraProviderManager->isLogicalCamera;
  4. 执行updateCameraNumAndIds,更新mCameraStates、mTorchStatusMap、mNumberOfCameras、mNormalDeviceIds: 能兼容api1和api2;
  5. logDeviceAdded: 打印event log;

7 removeStates
CameraService::removeStates

  1. updateCameraNumAndIds:更新cameraNumber、cameraId;
    • mCameraProviderManager->getCameraCount();
    • 更新mNumberOfCameras、mNormalDeviceIds;
  2. 从mTorchStatusMap、mCameraStates中erase cameraId;

1.4.6 CameraID和CameraDevice相关的变量

1 CameraProviderManager里面CameraId、CameraDevice相关的变量

  • CameraProviderManager.cpp:
    • mProviders:表示所有的ProviderInfo,包含HIDLProviderInfo、AIDLProviderInfo;
      • mDevices:表示所有的DeviceInfo,保存支持的cameraDevice;
        • mPublicCameraIds:表示所有的存放该Provider的PublicCameraIds,它和下面的mProviderPublicCameraIds相同;
      • mProviderPublicCameraIds:表示provider初始的CameraIds,来自getCameraIdList;
      • mUniqueCameraIds:存放当前Provider所有可用的CameraDevice的CameraID,cameraId会在addDevice时增加,removeDevice时减少;
      • mUniqueAPI1CompatibleCameraIds:存放该Provider所有兼容API1 Device的CameraId;

2 CameraService里面CameraID和CameraDevice相关的变量
CameraService里面的CameraID和CameraDevice都来自CameraProviderManager,下面是CameraService的变量来自CameraProviderManager的哪些变量;

  • mNumberOfCameras、mNumberOfCamerasWithoutSystemCamera:来自所有Provider的mUniqueCameraIds总和,当前hal支持的所有camera的数量,去除HIDDEN_SECURE_CAMERA;

    • mNumberOfCameras:表示有多少颗cameraDevice,只会取PUBLIC、SYSTEM_ONLY_CAMERA类型,去除HIDDEN_SECURE_CAMERA类型;
    • mNumberOfCamerasWithoutSystemCamera:表示有多少颗cameraDevice,只会取PUBLIC类型,去除HIDDEN_SECURE_CAMERA、SYSTEM_ONLY_CAMERA类型;
    • 使用的地方CameraService::updateCameraNumAndIds --> mCameraProviderManager->getCameraCount;
  • mNormalDeviceIds、mNormalDeviceIdsWithoutSystemCamera:来自所有Provider的mUniqueAPI1CompatibleCameraIds总和,会去除HIDDEN_SECURE_CAMERA,针对Logical Multi-Camera每个Facing只暴露一个logicalCameraId出去;

    • 使用的地方:CameraService::updateCameraNumAndIds --> mCameraProviderManager->getAPI1CompatibleCameraDeviceIds;
    • getAPI1CompatibleCameraDeviceIds:处理兼容API1的CameraDeviceId;把所有的DeviceId过滤一遍,把HIDDEN_SECURE_CAMERA、Logical Multi-Camera类型去除,然后再把DeviceId分成两组,分成publicDeviceId和systemDeviceId依次写入deviceIds;
  • mCameraStates:当定义LogicalDevice的onDeviceStatusChanged时,会执行addStates往mCameraStates添加state;

    • 是一个map,key:cameraId, value:cameraState,对变量操作的方法:removeStates、addStates;
  • mTorchStatusMap:定义LogicalDevice的onDeviceStatusChanged;

    • 是一个map,key:cameraId, value:torchStatus,操作变量的方法:removeStates、addStates,这两个变量是跟mCameraStates走的;
  • mPerfClassPrimaryCameraIds:mUniqueCameraIds;

    • 表示根据当前CameraDevice的Perform等级把PrimaryCameraId存入mPerfClassPrimaryCameraIds,参考前面的mNormalDeviceIdsWithoutSystemCamera;
    • 操作变量的方法:filterSPerfClassCharacteristicsLocked

1.4.7 AIDL CameraProvider和CameraDevice初始化

AIDL Camera Provider初始化

CameraProviderManager::tryToAddAidlProvidersLocked

  1. 每个AIDL Provider都要注册一次sm->registerForNotifications,多个HIDL只会注册一次;
  2. tryToInitializeAidlProviderLocked–>initializeAidlProvider;
  3. initializeAidlProvider:
    1. 不需要像HIDL判断版本,aidl只有一个版本,直接调用setCallback方法,接收ICameraProvider的回调;
    2. 调用AIBinder_linkToDeath方法,监听binderDied方法,处理Hal进程挂掉后的异常;HIDL是监听serviceDied方法处理hal挂掉后的异常;
    3. notifyDeviceStateChange:更新state
    4. setUpVendorTags
    5. getCameraIdList
    6. getConcurrentCameraIdsInternalLocked
    7. 直接将mSetTorchModeSupported = true;HIDL调用isSetTorchModeSupported,判断是否有一个cameraDevice是否支持TorchMode,AIDL不需要,因为在各自的device会判断是否支持touch;
    8. initializeProviderInfoCommon

AIDL CameraDevice初始化

AidlProviderInfo::initializeDeviceInfo,AIDL初始化CameraDevice和HIDL初始化CameraDevice的流程一样。

  1. 获取ICameraDevice的实例:调用ICameraProvider的getCameraDeviceInterface获取到ICameraDevice的实例;
    • startDeviceInterface–>interface->getCameraDeviceInterface
  2. 调用ICameraDevice的getResourceCost获取到ResourceCost;
  3. 创建AidlDeviceInfo3:处理静态信息,比如获取SystemCameraKind和修复/更新mCameraCharacteristics;

创建AidlDeviceInfo3完成5件事情

AidlDeviceInfo3::AidlDeviceInfo3

  1. 获取CameraCharacteristics:调用getCameraCharacteristics对mCameraCharacteristics赋值;
  2. 获取DeviceStateOrientationMap:获取ANDROID_INFO_DEVICE_STATE_ORIENTATIONS的值,保存在mDeviceStateOrientationMap;
  3. 获取到mSystemCameraKind:调用getSystemCameraKind获取到mSystemCameraKind – 如果Capability是ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA,则返回SystemCameraKind::HIDDEN_SECURE_CAMERA – 如果Capability有ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA,则返回SystemCameraKind::SYSTEM_ONLY_CAMERA – 其他情况返回SystemCameraKind::PUBLIC
  4. 修复/更新 mCameraCharacteristics:fixupMonochromeTags、addDynamicDepthTags、deriveHeicTags、addRotateCropTags、addPreCorrectionActiveArraySize、overrideZoomRatioTags、fixupTorchS
  5. 修复/更新 未Public 出去的PhysicalCamera Characteristics:
  6. overrideZoomRatioTags

1.4.8 初始化VendorTags, Flashlight和PerfClass

1 创建VendorTagDescriptorCache

主要工作:创建VendorTagDescriptorCache,把provider的VendorTag存进去。

VendorTag:是vender厂商自定义的metadata,这种情况会用到vendorTag。vendor厂商定义了metadata之后,会有venderTag的管理者,管理metadata供app、framework使用。

enumerateProviders–>mCameraProviderManager->setUpVendorTags:

  • 创建VendorTagDescriptorCache
  • VendorTagDescriptorCache::setAsGlobalVendorTagCache:将provider里面的mProviderTagid和mVendorTagDescriptor放入VendorTagDescriptorCache里面,然后把当前的tagCache setAsGlobalVendorTagCache,把对应的vendorTag的Ops传入metadata类里面去。

VendorTagDescriptorCache是管理venderTag的Manager,管理厂商自定义的metadata供app、framework使用,管理不同Provider里面的VendorTagDescriptor,VendorTagDescriptor维护管理所有VendorTags的Section、Name、Type,ID之间的关系:

key value
vendorId1 VendorTagDescriptor1

2 Flashlight初始化

主要工作:判断每颗camera里面是否有flashUnit这个硬件单元。

CameraServer通过CameraFlashlight来管理各个CameraDevice的Flashligh:
在这里插入图片描述

通过CameraFlashlight::findFlashUnits完成Flashlight的初始化,流程如下:
CameraFlashlight::findFlashUnits:

  1. mProviderManager->getCameraDeviceIds:拿到所有支持的Id;
  2. 遍历所有cameraIds,如果cameraId在mHasFlashlightMap不存在,执行createFlashlightControl;
    1. createFlashlightControl:查询CameraProviderManager是否支持设置TorchMode,如果支持则创建ProviderFlashControl;
    2. 执行mFlashControl->hasFlashUnit(id, &hasFlash):判断是否支持Flash,更新hasFlash,最终是从ProviderInfo的mCameraCharacteristics读取ANDROID_FLASH_INFO_AVAILABLE来给mHasFlashUnit赋值;
    3. 执行mHasFlashlightMap.add(id, hasFlash):把cameraId和是否支持Flash写入mHasFlashlightMap;

3 为SPerfClass过滤Characteristics

主要工作:针对performance_class做jpeg size以及Dynamic Depth size的过滤,把小于1080p的全部过滤掉。

CameraService::filterSPerfClassCharacteristicsLocked

执行条件:ro.odm.build.media_performance_class >= 31 (android S)

执行动作:针对主后置和主前置,过滤掉小于1080p的JPEG尺寸

CTS(SPerfClassTest.java):testSPerfClassJpegSizesByCamera

CameraService::filterSPerfClassCharacteristicsLocked
流程:

  1. 初始化firstRearCameraSeen、firstFrontCameraSeen
  2. 遍历mNormalDeviceIdsWithoutSystemCamera,去掉SystemCamera
    1. getDeviceVersion获取到Facing
    2. 如果Facing是back或者front且是第一次执行,调用mCameraProviderManager->filterSmallJpegSizes(cameraId)
      • filterSmallJpegSizes:更新jpeg和Dynamic Depth的如下三个Tag,过滤掉小于1080P的STREAM_CONFIGURATIONS、MIN_FRAME_DURATIONS、STALL_DURATIONS

2. Java层 Camera Framework AIDL

1 文件路径
/frameworks/av/camera/aidl/android/hardware/
在这里插入图片描述

2 AIDL产生的库/文件
在这里插入图片描述

  • libcamera client.so:包含客户端代码,也包含服务端代码;

    • 如果是客户端代码,会被Libcamera2ndk.so实现;
    • 如果是服务端代码,会被Libcameraservice.so实现,比如Binder客户端framework-minus-apex.jar的IcameraService的connect方法会先调到Binder服务端libcamera_client.so的IcameraService的connect然后再调用到libcameraservice.so的connect方法;
  • AIDL产生的Java源文件:

    • out\soong.intermediates\frameworks\base\framework-minus-apex\android_common\gen\aidl\ aidl36.srcjar
  • AIDL产生的C++源文件:

    • out\soong.intermediates\frameworks\av\camera\libcamera_client\android_arm64_armv8-a_shared_cfi\gen\aidl\android\hardware

3 AIDL核心类
ICameraService.aidl:Cameraserver进程对外提供的接口入口;
ICameraServiceListener.aidl:ICameraService的回调类,CameraService相关状态通知到上层APP;
ICameraDeviceUser.aidl:CameraDevice的封装接口,用于操作一颗CameraDevice;
ICameraDeviceCallbacks.aidl:CameraDevice的回调,通知上层APP;

AIDL核心类之间的调用关系如下图所示:
在这里插入图片描述

2.1 ICameraService.aidl

1 ICameraService.aidl类图

ICameraService.aidl产生的Java或C++代码,相关类图如下所示:
在这里插入图片描述
java端的ICameraService.Stub:是抽象类,如果实现Stub的是其他Java端进程,调用者是其他java端、c++端,比如c++端回调的ICameraServiceLisenter、CameraDeviceCallback,java端要实现这个Stub,c++端调Bp端的BpCameraService,会调到Stub;

2 调用端获取ICameraService对象:

Java端获取ICameraService.Stub.Proxy对象:

//cameraServiceBinder就是mRemote变量
IBinder cameraServiceBinder = ServiceManager.getService("media.camera");
//返回的是ICameraService.Stub.Proxy,asInterface传入的是就是上面的mRemote
ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);

C++端获取BpCameraService对象:

//binder就是BnCameraService
sp<IBinder> binder = sm->getService(String16("media.camera"));
//mCameraService是BpCameraService
mCameraService = interface_cast<hardware::ICameraService>(binder);
  • Interface_cast获取的是BpCameraService的实例,但是从ServiceManager获取的binder是BnCameraService的实例。
/frameworks/native/include/binder/IInterface.h
//第三个参数是BP类型
DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(PARENT::I##INTERFACE, I##INTERFACE, PARENT::Bp##INTERFACE)

//构造Bp类型的对象BpCameraService
::android::sp<ITYPE> ITYPE::asInterface(const ::android::sp<::android::IBinder>& obj) {
    ::android::sp<ITYPE> intr;
    if (obj != nullptr) {
        intr = ::android::sp<ITYPE>::cast(obj->queryLocalInterface(ITYPE::descriptor));
        if (intr == nullptr) {
            intr = ::android::sp<BPTYPE>::make(obj);
        }
    }
    return intr;
}

inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

3 ICameraService.aidl主要的接口详解:

  1. int getNumberOfCameras(int type);
    • 获取当前平台支持多少颗Camera,废弃;
  2. CameraInfo getCameraInfo(int cameraId);
    • 获取某颗Camera的基本信息(facing和orientation),API2不使用该API;
  3. ICamera connect()
    • Open某颗Camera,获取到ICamera 实例,API2不使用该API;
  4. ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks, String cameraId, String opPackageName, String featureId, int clientUid, int oomScoreOffset, int targetSdkVersion);
    • Open Camera,获取到ICameraDeviceUser实例;
    • callbacks:回调CameraDevice的状态信息;
    • featureId:AppContext里面获取的属性Tag,权限管理时传入OpManager里去;
  5. CameraStatus[] addListener(ICameraServiceListener listener);
    • 注册Listener,监听CameraService状态变化,比如CameraDevice、Torch变化;
  6. ConcurrentCameraIdCombination[] getConcurrentCameraIds();
    • 获取可以并发访问的Camera ID组合;
  7. boolean isConcurrentSessionConfigurationSupported( in CameraIdAndSessionConfiguration[] sessions, int targetSdkVersion);
    • 同时使用多颗Camera时,判断并发SessionConfiguration是否支持;
  8. void removeListener(ICameraServiceListener listener);
    • 删除Listener,取消监听CameraService状态变化;
  9. CameraMetadataNative getCameraCharacteristics(String cameraId, int targetSdkVersion);
    • 获取指定Camera的静态CameraMetadata;
  10. VendorTagDescriptor getCameraVendorTagDescriptor();
    • 获取VendorTagDescriptor,在CameraMetadataNative解析Vendor Tag时需要用到;
  11. VendorTagDescriptorCache getCameraVendorTagCache();
    • 获取VendorTagDescriptorCache,其中存放不同VendorID的VendorTagDescriptor,在CameraMetadataNative解析Vendor Tag时需要用到
  12. boolean supportsCameraApi(String cameraId, int apiVersion);
    • 判断当前平台是否支持HAL3;
  13. boolean isHiddenPhysicalCamera(String cameraId);
    • 判断指定的Camera是否是隐藏的PhysicalCamera,针对隐藏的PhysicalCamera,CamcorderProfile可能不可用,因此使用Stream configurationMap来获取最大录像size(MandatoryStreamCombination)。
  14. ICameraInjectionSession injectCamera(String packageName, String internalCamId, String externalCamId, in ICameraInjectionCallback CameraInjectionCallback);
    • 注入外部Camera来取代内部Camera,同一颗CameraID可以在Internal或External Camera间切换。
  15. void setTorchMode(String cameraId, boolean enabled, IBinder clientBinder);
    • 控制手电筒模式的ON/OFF
  16. void turnOnTorchWithStrengthLevel(String cameraId, int strengthLevel, IBinder clientBinder);
    • 调整手电筒的强度;
  17. int getTorchStrengthLevel(String cameraId);
    • 获取当前手电筒模式的强度。
  18. oneway void notifySystemEvent(int eventId, in int[] args);
    • 向CameraService通知系统操作事件(多用户切换、USB设备插拔事件),CameraServiceProxy调用。
  19. oneway void notifyDisplayConfigurationChange();
    • 向CameraService通知Display窗口配置发生变化,CameraServiceProxy调用;
  20. oneway void notifyDeviceStateChange(long newState);
    • 向CameraService通知设备状态发生变化(如折叠屏发生折叠,前镜头/后镜头被挡住),CameraServiceProxy调用。

以上Api只有connectDevice需要openCamera,其他方法不需要openCamera可以直接调用。

2.2 ICameraServiceListener.aidl

1 ICameraServiceListener.aidl类图
在这里插入图片描述

2 Android AIDL oneway修饰符
在 Android AIDL中,oneway 是一种修饰符,用于声明一个方法是单向的(one-way)。

使用oneway修饰符声明的方法不会阻塞调用线程,而是立即返回并在后台运行,因此不需要等待方法执行完成。

这种方式适用于客户端和服务端之间不需要进行同步通信的情况,例如通知服务端某项任务已经完成。

需要注意的是,在客户端调用带有oneway修饰符的方法时,无法得知方法是否返回成功或失败,因为该方法会立即返回,而不会等待服务端响应。因此,建议将 oneway 修饰符仅用于不需要接收服务端响应的方法。

3 ICameraServiceListener.aidl接口详解

  1. oneway void onTorchStatusChanged(int status, String cameraId)
    • 回调通知FlashTorch模式的状态变化;
  2. oneway void onTorchStrengthLevelChanged(String cameraId, int newTorchStrength)
    • 回调通知FlashTorch的强度发生变化;
  3. oneway void onCameraAccessPrioritiesChanged()
    • 当进程的adj或前后台状态发生变化时,会回调该方法,CameraService的任何一个client进程。
  4. oneway void onCameraOpened(String cameraId, String clientPackageId)
    • 回调通知某个client打开了某颗Camera,每一个client都有包名。
    • client需要有android.permission.CAMERA_OPEN_CLOSE_LISTENER权限。
  5. oneway void onCameraClosed(String cameraId)
    • 回调通知某颗Camera被关闭了。
    • 需要有android.permission.CAMERA_OPEN_CLOSE_LISTENER权限。

2.3 ICameraDeviceUser.aidl

在这里插入图片描述

1 ICameraDeviceUser.aidl是什么

  • 获取:CameraApp执行openCamera,Java层CameraFWK调用ICameraService.aidl的connectDevice方法返回ICameraDeviceUser对象。
  • ICameraDeviceUser代表的就是一颗CameraDevice,后续的Camera操作流程就是基于ICameraDeviceUser对象,所有的拍照、创建session都是通过ICameraDeviceUser执行。
    在这里插入图片描述

2 ICameraDeviceUser.aidl类图&调用
在这里插入图片描述

  • java层ICameraDeviceUser和c++层CameraDeviceClient都有相同的方法名互相对应。

3 ICameraDeviceUser.aidl接口详解:
java层CameraDevice代码路径:framework/base/core/java/android/hardware/camera2/CameraDevice.java

CameraDevice的createCaptureSession对应的ICameraDeviceUser的API:

  1. void waitUntilIdle();
    • createCaptureSession时会先调stopRepeating,然后用该API等待上一次Session为IDLE;
  2. void beginConfigure()
    • 开始创建Session;
  3. int createStream(in OutputConfiguration outputConfiguration);
    • 根据OutputConfiguration创建OutputStream;
  4. void deleteStream(int streamId);
    • 根据streamId删除未配置的Stream;
  5. int createInputStream(int width, int height, int format, boolean isMultiResolution);
    • 在Reprocess流程中,根据宽/高/format等信息创建Input Stream;
  6. int[] endConfigure(int operatingMode, in CameraMetadataNative sessionParams, long startTimeMs);
    • 结束创建Session;
    • 这是createCaptureSession最耗时的一步,传给把参数传给NativeFramework,然后完成真正的Session创建;

ICameraDeviceUser中与Buffer有关的API:

  1. boolean isSessionConfigurationSupported(in SessionConfiguration sessionConfiguration);
    • 对应CameraDevice的isSessionConfigurationSupported;
    • 判断指定的SessionConfiguration是否支持,可以在创建Session之前判断config的宽高、format、buffer的路数是否支持,找到底层支持的;sessionConfiguration;
  2. void prepare(int streamId);
    • 对应CameraCaptureSession的prepare;
    • 预申请某路流的Buffers, 这样能提升第一帧到来的性能;
  3. void prepare2(int maxCount, int streamId);
    • 对应CameraCaptureSession的prepare;
    • 预申请某路流的Buffers,可以指定最大张数;prepare2是对prepare的补充;
  4. void updateOutputConfiguration(int streamId, in OutputConfiguration outputConfiguration);
    • 对应CameraCaptureSession的updateOutputConfiguration;
    • 更新OutputConfiguration;
  5. void finalizeOutputConfigurations(int streamId, in OutputConfiguration outputConfiguration);
    • 对应CameraCaptureSession的finalizeOutputConfigurations;
    • 最终决定OutputConfiguration;
  6. 对应CameraMetadataNative createDefaultRequest(int templateId);
    • CameraDevice的createCaptureRequest;
    • 根据templateId创建默认的CaptureRequest;
  7. SubmitInfo submitRequestList(in CaptureRequest[] requestList, boolean streaming)
    • 对应CameraCaptureSession的capture/captureBurst/setRepeatingRequest/setRepeatingBurst;
    • 向Framework送CaptureRequests;
  8. long cancelRequest(int requestId)
    • 对应CameraCaptureSession的stopRepeating;
    • 停止CaptureRequests,取消正在repeating的CaptureRequest,已经送到hal的继续执行;
  9. long flush();
    • 对应CameraCaptureSession的abortCaptures;
    • 放弃正在处理队列中,未被处理的Requests,Framework还在排队准备送hal的session,送到hal还没有处理的request也能结束;

ICameraDeviceUser中与OfflineSession和AudioRestriction相关的API:

  1. ICameraOfflineSession switchToOffline(in ICameraDeviceCallbacks callbacks, in int[] offlineOutputIds);
    • 对应CameraCaptureSession的switchToOffline;
    • 将当前的CameraCaptureSession切换到后台继续运行,应对快拍需求;
  2. Surface getInputSurface();
    • 对应CameraCaptureSession的getInputSurface;
    • 在Reprocess流程中,创建接受Input Buffer的Surface;
    • 意思是上层APP给底层送buffer,需要给APP提供一个InputSurface,APP往InputSurface quee buffer,底层就能收到;
  3. void setCameraAudioRestriction(int mode);
    • 对应CameraDevice 的 setCameraAudioRestriction;
    • 设置当前CameraDevice的Audio限制策略;
  4. int getGlobalAudioRestriction();
    • 对应CameraDevice的getCameraAudioRestriction;
    • 获取当前CameraDevice的Audio限制策略;
  5. void disconnect()
    • 对应CameraDevice#close;
    • 关闭CameraDevice;

2.4 ICameraDeviceCallbacks.aidl详解

1 ICameraDeviceCallbacks是什么
ICameraDeviceCallbacks是ICameraDeviceUser的回调类,回调以下信息给App:

  • CameraDevice的状态;
  • 每一个CaptureRequest的状态以及回调CaptureResult;

2 ICameraDeviceCallbacks.aidl类图
在这里插入图片描述

3 ICameraDeviceCallbacks.aidl接口详解

  1. oneway void onPrepared(int streamId)
    • prepare/prepare2的回调函数,说明执行streamId的Stream已经prepare完成;
  2. oneway void onCaptureStarted( in CaptureResultExtras resultExtras, long timestamp);
    • 通知App,HAL开始处理一个CaptureRequest, 其中resultExtras存放的sequenceId,frameNumber等信息;timestamp是sencer开始曝光的时间点。
  3. oneway void onResultReceived( in CameraMetadataNative result, in CaptureResultExtras resultExtras, in PhysicalCaptureResultInfo[] physicalCaptureResultInfos);
    • 通知App,HAL处理这个Request的进度,Java层CameraFWK会根据resultExtras来判断是否是PartialResult,如果是PartialResult就会回调onCaptureProgressed给APP,如果不是PartialResult表示这一帧的Result已经处理结束,回调onCaptureCompleted给APP;
  4. oneway void onRepeatingRequestError( in long lastFrameNumber, in int repeatingRequestId);
    • 每次CameraServer送repeatingRequest给hal,都会从Surface dequee一张buffer,在dequee之前CameraServer会检查repeatingRequest里面的Surface是否出现Abandon了,Abandon就是App是否把这个Surface销毁了,如果销毁就不能拿到buffer,就会回调通知给App当前RepeatingRequest出现Error,通知停止repeating动作;App收到Error通知需要检查repeatingRequest里设置的Surface的生命周期出现问题;
  5. oneway void onRequestQueueEmpty();
    • CameraServer的Repeating的RequestQueue队列为空,通知给App;
    • CameraServer有一个是Repeating的RequestQueue:拍照使用,另一个是Repeating的RequestQueue:预览使用;
  6. oneway void onDeviceError( int errorCode, in CaptureResultExtras resultExtras)
    • 通知CameraApp,CameraDevice出现error,具体的error在errorCode里面描述;
  7. oneway void onDeviceIdle();
    • CameraDevice已经处理完所有的Request(Buffer都已收到),CameraDevice处于IDLE状态了,等待App送CaptureRequest下来处理;

2.5 Parcel对象相关的AIDL

Camera2 Java FWK AIDL有哪些自定义的Parcel对象

  • 在AIDL的客户端和服务端通信的过程中,除了方法调用外,我们还需要传递不同类型的数据,这些数据的类型都必须实现parcelable接口,重载这两个方法writeToParcel、readFromParcel。

自定义的Parcel对象:

  • frameworks/av/aidl/camera/aidl/android/hardware/camera2/impl/
    • CameraMetadataNative.aidl
    • CaptureResultExtras.aidl
    • PhysicalCaptureResultInfo.aidl
  • frameworks/av/aidl/camera/aidl/android/hardware/camera2/params/
    • OutputConfiguration.aidl
    • SessionConfiguration.aidl
    • VendorTagDescriptor.aidl
    • VendorTagDescriptorCache.aidl
  • frameworks/av/aidl/camera/aidl/android/hardware/camera2/utils/
    • CameraIdAndSessionConfiguration.aidl
    • ConcurrentCameraIdCombination.aidl
    • SubmitInfo.aidl
  • CaptureRequest.aidl

Camera2 Java FWK不会生成中间文件的AIDL文件说明

  • 如果一个AIDL文件没有被放在android.bp文件中,而仅仅是被其他AIDL文件import引用的话,在编译时不会生成对应的源代码(Java/C++)。
  • 因为在Android编译系统中,根据aidl规则,当一个AIDL文件被import引用时,并不会单独处理该文件,而是一起处理引用它的AIDL文件。即使在被引用的AIDL文件中定义了parcelable或interface关键字,也不会单独生成对应的源代码(Java/C++)。

Camera2的Java层Parcel AIDL与C++ Parcel AIDL一一对应关系

以下是需要自己写的AIDL的类:

  1. impl/CameraMetadataNative.aidl
    • CameraMetadataNative.java
    • CameraMetadata.cpp
  2. impl/CaptureResultExtras.aidl
    • CaptureResultExtras.java
    • CaptureResult.cpp
  3. impl/PhysicalCaptureResultInfo.aidl
    • PhysicalCaptureResultInfo.java
    • CaptureResult.cpp
  4. params/OutputConfiguration.aidl
    • OutputConfiguration.java
    • OutputConfiguration.cpp
  5. params/SessionConfiguration.aidl
    • SessionConfiguration.java
    • SessionConfiguration.cpp
  6. params/VendorTagDescriptor.aidl
    • VendorTagDescriptor.java
    • VendorTagDescriptor.cpp
  7. params/VendorTagDescriptorCache.aidl
    • VendorTagDescriptorCache.java
    • VendorTagDescriptor.cpp
  8. utils/CameraIdAndSessionConfiguration.aidl
    • CameraIdAndSessionConfiguration.java
    • ConcurrentCamera.cpp
  9. utils/ConcurrentCameraIdCombination.aidl
    • ConcurrentCameraIdCombination.java
    • ConcurrentCamera.cpp
  10. utils/SubmitInfo.aidl
    • SubmitInfo.java
    • SubmitInfo.cpp
  11. CaptureRequest.aidl
    • CaptureRequest.java
    • CaptureRequest.cpp

为什么要自己写Parcel对象的Java/C++端代码

  • writeToParcel、readFromParcel逻辑复杂,无法通过代码生成;
  • 在Java/C++端,Parcel对象中有非Binder通信调用的方法;

上面的Parcel对象主要用途:

  1. CameraMetadataNative
    • 本质上是CameraMetadata,封装成camera_metadata_t;
  2. CaptureResultExtras
    • 存放CaptureResult各种索引信息,比如partialResultCount, requestId,回调给APP时会使用;
  3. PhysicalCaptureResultInfo
    • 把PhysicalCamera和PhysicalCameraMetadata做一个映射关系;
  4. OutputConfiguration
    • 描述一个OutputStream的配置信息(比如宽/高/是否shared等);
  5. SessionConfiguration
    • Session配置信息;
  6. VendorTagDescriptor
    • VendorTag的描述信息,Java端的没有使用;
  7. VendorTagDescriptorCache
    • 按VendorID存放VendorTagDescriptor,Java端的没有使用;
  8. CameraIdAndSessionConfiguration
    • 并行多颗Camera做ConfigureSession使用,可以并行做ConfigureSession的ID和SessionConfiguration;
  9. ConcurrentCameraIdCombination
    • 描述可以并行ConfigureSession的ID;
  10. SubmitInfo
    • 包括RequestId和LastFrameNumber,是submitRequestList的返回信息;
  11. CaptureRequest
    • 描述一次CaptureRequest,包括mPhysicalCameraSettings和mSurfaceList等信息;

3. libcameraservice

3.1 C++层CameraService总体架构

在这里插入图片描述
Camera VNDK Client:vender分区的客户端,比如人脸解锁;

1 LibCameraService目录结构:
framework/services/camera/libcameraservice/
在这里插入图片描述
hidl:是和上层Camera VNDK Client通信的接口;
fuzzer:google测试框架;

3 libcameraservice主要模块关系
在这里插入图片描述

  • CameraService:常驻的一个CameraService的服务;

  • Client:是指CameraService自己的Client实例;

  • 使用步骤:

    1. 如果有OpenCamera动作,OpenCamera–>Client–>CameraDevice–>平台选择HIDL/AIDL–>HAL;
    2. open结束后把CameraService的Client实例给到上层APP或者vender客户端,上层APP或者vender客户端操作Client就能操作CameraDevice,然后发送request到HAL,HAL处理结束后在把结果返回给CameraDevice,CameraDevice–>Client–>Callback给上层APP或者vender客户端;

3.2 C++层CameraService和Client架构

1 CameraService与CameraProviderManager的关系

  • CameraService对上实现BnCameraService,就是实现java层CameraService提供的AIDL接口IcameraService.aidl;
  • CameraService对下与CameraProviderManager交互,通过CameraProviderManager调用HAL层的实现,HAL层会实现AIDL或HIDL的ICameraProvider/ICameraDevice。
    在这里插入图片描述

2 ClientManager类图

  • CameraClientManager:管理处于Active状态的所有CameraClient对象;
  • ClientDescriptor:描述当前CameraClient对象的信息;
    • BasicClient:描述当前处于active状态的Client实例;
  • CameraClient:可以通过sCameraService静态属性调到CameraService.cpp;
  • CameraService里面的mActiveClientManager可以调到具体的CameraClient对象;
  • ClientEventListener:监听Client的add和remove;
    在这里插入图片描述

3 CameraClient的类图

  • 所有Client都继承BasicClient;
  • API1/API2的Client都抽象出一个类实现对上的接口;
  • Camera2ClientBase主要封装对CameraDevice的操作;

3.1 CameraClient API2
在这里插入图片描述

  • Camera2ClientBase:模版类,模版是CameraDeviceClientBase,下面API1模版是Client,封装API1和API2操作CameraDevice的common部分;

3.2 CameraClient API1
在这里插入图片描述

3.3 C++层CameraService的Device架构介绍

CameraDevice主要交互逻辑

  1. java层调用c++层:提供接口给上层控制操作CameraDevice,主要接口是CameraDeviceBase;
    • 调用过程:APP先调用Client,然后通过CameraDeviceBase调用CameraDevice,最后调到HAL;
  2. c++层回调java层:回调ResultMetadata和ImageBuffer给上层,主要接口是FrameProcessor和Stream。
    • 有两条回调通路:
    • 一条通路:CameraDevice处理完某一帧后,有一个或者多个metadata存放在一个ResultQueue里面,FrameProcessor是一个线程,这个线程不停的向ResultQueue询问是否有可用的metadata,如果有就取出metadata处理,这是异步操作;
    • 另一条通路:CameraDevice处理完某一路流后,会调用Stream的QueueBuffer接口,因为Stream是对BufferQueue的封装,整张图就会到BufferQueue的Consumer那边,通知消费者去取buffer,这是同步操作;
      在这里插入图片描述

1 java层调用c++层的接口–>CameraDeviceBase

  1. CameraDeviceBase继承FrameProducer,FrameProducer是获取某一帧的ResultMetadata;
  2. CameraDeviceBase接口用于Client操作HAL2/HAL3 Device, Camera2Device是过渡产品,代码已经废弃;
  3. HidlCamera3Device对接HIDL HAL层接口,AidlCamera3Device对接AIDL HAL层接口,他们都继承自Camera3Device;
    在这里插入图片描述

2 c++层回调java层,回调部分的ResultMetadata架构–>FrameProcessor

  1. 核心是FrameProcessorBase,它相当一个线程循环的处理FrameProducer的waitForNextFrame和getNextResult从mResultQueue里面获取CaptureResult
  2. Camera API2的ResultMetadata处理逻辑在FrameProcessorBase里面;
  3. Camera API1的ResultMetadata处理逻辑在FrameProcessor里面;
  • 处理流程:
    1. Camera3Device不停的往FrameProducer的mResultQueue插入ResultMetadata,FrameProcessorBase循环从FrameProducer的mResultQueue获取ResultMetadata;
    2. FrameProcessorBase会调用FrameProducer的waitForNextFrame获取下一帧,获取到后调用getNextResult从mResultQueue里面获取CaptureResult;
    3. 处理完帧后,调用FrameProcessorBase::FilteredListener,最终会调用API2的CameraDeviceClient,这里面实现了onResultAvailable,它会把CaptureResult返回到上层APP;
      在这里插入图片描述

3 c++层回调java层,API2回调部分的ImageBuffer架构 -->CameraStream

  1. Camera3Device根据hal的配置信息决定创建Camera3InputStream、Camera3OutputStream、Camera3SharedOutputStream;
  2. camera_stream:是一个结构体,camera_stream装载hel传上来的buffer流,是和hal层的stream长得一样的结构体;
  3. Camera3Stream:
    1. 是InputStream和OutputStream的基类,继承camera_stream,能把hal层的stream转换成c++层cameraservice的stream;
    2. 维护Stream的状态机切换;
    3. 提供接口访问Stream的信息,比如ID、width、height、usage、dataspace等等;
    4. 提供接口转换成hal层的stream;
  4. Camera3IOStreamBase:是InputStream和OutputStream的基类,管理整个stream的buffer状态,哪些在hal,哪些已经回给我了,维护当前这路stream,一个stream有很多张buffer;
  5. Camera3OutputStreamInterface:
    1. Camera3Device对InputStream和OutputStream操作的流程完全不一样,所以将OutputStream的特殊操作抽象出来放到Camera3OutputStreamInterface;
    2. 对InputStream的操作还是放在Camera3Stream;
      在这里插入图片描述

4 c++层回调java层,API1回调部分的ImageBuffer架构–>Processor

  • 上层使用API1时,hal把Buffer送到我们的Stream后,要么直接送给上层这三类直接送给上层:StreamingProcessor、JpegProcessor、带surface的CallbackProcessor;要么送给Processor取出Buffer通过binder回调给上层java层。
  • Processor:
  1. StreamingProcessor:用于预览,创建PreviewStream和RecordingStream,上层APP会创建一个surface传给c++层cameraservice,当hal3把buffer填充到我们的Stream后,Processor把buffer从Stream取出来,把buffer送到上层APP的surface;
  2. JpegProcessor:用于Jpeg拍照,创建一路Jpeg的Stream接收hal3传上来的JpegBuffer,取出来JpegBuffer回调到上层;
  3. CallbackProcessor:用于预览Callback,和StreamingProcessor一样,创建一路Callback的Stream接收hal3上传buffer,取出来buffer回调到上层;
  4. ZslProcessor:用于拍照时可以选到靠前的用户看到的那张图,用zslQueue做缓存,当拍照时从队列取出来;
    在这里插入图片描述

3.4 C++层CameraService的API1和API2调用HAL3流程

1. API1 call HAL3,参数设置流程
在这里插入图片描述

  • 第一步:上层APP调用Camera2Client的setParameters方法将参数送到C++层CameraService;
  • 第二步:创建默认CaptureRequest,Camera2Client会将参数送给StreamingProcessor,再交给Parameters把参数更新到CaptureRequest;
  • 第三步:更新后的CaptureRequest ,如mPreviewRequestmRecordingRequest,保存在StreamingProcessor中;

2. API1 call HAL3,startPreview流程
在这里插入图片描述

  • 第一步:调用StreamingProcessor和JPEG/Callback/ZSL Processor的updateStream,创建OutputStream,StreamingProcessor是创建预览流,JPEG/Callback/ZSL Processor是创建拍照流;
  • 第二步:再次更新mPreviewRequestmRecordingRequest
  • 第三步:调用StreamingProcessor的startStream,将Request送给Camera3Device,Camera3Device执行ConfigureStream,调到hal3执行configStream,然后调用setRepeatingRequests,让RepeatingRequest队列转起来不停的向hal3送CaptureRequest;

3. HAL3 call back API1,参数回调流程
在这里插入图片描述

  • 第一步:FrameProcessorBase有一个线程不停查询CameraDeviceBase是否有可用的CaptureResult,就是调用waitForNextFrame方法等待有可用的一帧,然后调用getNextResult获取metadata;
  • 第二步:处理FaceDetect回调和向Parameters更新3A State:拿到可用的CaptureResult和metadata后调用FrameProcessor::processSingleFrame开始处理,先调用processFaceDetect检查是否有人脸信息,如果有就通过binder call告诉上层APP有人脸信息到了;然后调用process3aState更新到Camera2Client的Parameters。

4. HAL3 call back API1,图像数据回调流程

4.1 HAL3 call back API1,图像数据回调流程 – 预览/录像

StreamingProcessor:预览/录像
在这里插入图片描述

  • 预览/录像:
  • 第一步:上层APP传递一个surface下来给到StreamingProcessor,用surface创建一个outputStream,当hal层的processCaptureResult上来,CaptureResult里面如果有buffer就会找到outputStream,告诉outputStream buffer已经来了,outputStream就是Camera3OutputStream;
  • 第二步:然后Camera3OutputStream就会调用BufferQueue的queueBuffer方法,通知到BufferQueue,这张buffer已经ready;
  • 第三步:然后跨binder通知Consumer进程的onFrameAvailable方法有buffer来了,把buffer从bufferQueue里面取出这张buffer图使用,Consumer通常是APP/SurfaceFlinger/录像(VideoEncoder)。

CallbackProcessor:预览
在这里插入图片描述

  • 有两种,一种是使用setPreviewCallbackTarget方式接收回调预览buffer,和上面的StreamingProcessor一样,就是使用BufferQueue的方式传递buffer;
  • 这里讨论另一种,不使用setPreviewCallbackTarget方式接收回调预览buffer:
    • 第一步:需要c++层cameraservice自己创建BufferQueue,名字是Camera2-CallbackConsumer,然后用这个BufferQueue去创建Camera3OutputStream,hal3执行processCaptureResult,将buffer发给Camera2-CallbackConsumer;
    • 第二步:自己创建BufferQueue的Consumer端在自己进程,Camera2-CallbackConsumer在CallbackProcessor.cpp里,然后执行CallbackProcessor的onFrameAvailable把buffer取出来,执行dataCallback跨binder将这张图发送给APP。

4.2 HAL3 call back API1,图像数据回调流程 – 拍照
在这里插入图片描述
Google创建了一个CaptureSequencer.cpp来维护拍照的状态机,通过不同的函数切换状态。

  • 第一步:有线程在manageIdle等待触发拍照,当用户触发拍照,执行startCapture,将状态从manageIdle切到manageStart,在manageStart方法会判断拍照是zsl还是Non-zsl;
  • 第二步:如果拍zsl,切换到manageZslStart状态,执行manageZslStart函数,会从zsl队列选一张图能不能满足拍zsl的条件,比如要求AE/AF是收敛的,如果zsl队列里面所有的图都是没有收敛就选不到,选不到就会切换到manageStandardStart,如果能选到zsl就会触发zsl拍照,会走pushToReprocess流程,把图再灌回给hal,hal这边重新处理,处理完之后就回调一张jpeg图,状态切换成manageStandardCaptureWait等待pushToReprocess产生的jpeg图,最后状态切换成manageDone取出Jpeg,然后调用callback,将jpeg送回上层APP。
  • 第二步:如果拍Non-zsl,切换到manageStandardStart判断flush状态,判断是否要做AEPrecapture,如果要做AEPrecapture会触发AEPrecaptureTrigger,然后切换到manageStandardPrecaptureWait等待AEPrecapture做完,做完后切换到manageStandardCapture做拍照动作,如果不需要做AEPrecapture直接从manageStandardStart切到manageStandardCapture,切换成manageStandardCaptureWait等待Jpeg产生,最后状态切换成manageDone取出Jpeg,然后调用callback,将jpeg送回上层APP。

4.2.1 HAL3 call back API1,拍照回图的Non-ZSL&&Non-AEPrecapture流程
在这里插入图片描述

  • 非ZSL且不做AEPrepareTrigger的拍照流程如上图所示,整个拍照过程由CaptureSequencer来驱动,JpegProcessor收到拍照图像后,通知给CaptureSequencer负责回调给App。
  • 第一步:首先APP触发tackPicture,在Camera2Client里面会调用startCapture,将CaptureSequencer从manageIdle切换到manageSart,在manageStart里面判断是否走zsl,不走zsl切换到manageStandardCapture,然后是触发拍照流程,执行JpegProcessor的getStreamId、updateStream,就是检查JpegStreasm是否存在,如果存在就拿到这个StreamId,否则创建一个Stream,然后将StreamId更新到CaptureRequest里面,执行CameraDeviceBase::capture,拍照流程结束。
  • 第二步:状态切换到manageStandardCaptureWait,等待Jpeg产生,当hal层执行到processCaptureResult向我们回调data时,会回调到JpegProcessor的onFrameAvailable,也就是这张Jpeg已经ready,会调用CaptureSequencer::onCaptureAvailable告诉CaptureSequencer这张图已经拍好,状态切换到manageDone把这张图取出来,通过dataCallback回调到上层APP。

1 API2 call HAL3,控制流程与参数回调
在这里插入图片描述

  • 第一步:APP调用hal,调用createCaptureSession,在java层cameraservice最后一步会调用到endConfigure,在endConfigure会调用Camera3Device::configureStreams接着调到hal层的HalInterface::configureStreams,完成整个streamConfig,其他比如submitRequest、flush,流程和这个一样的。
  • 第二步:参数回调,FrameProcessorBase这个线程一直在waitForNextFrame,等到后执行processNewFrames拿到ResultMetadata,拿到以后在自己的实现类调用CameraDeviceClient::onResultAvailable某一帧的resultMetadata已经ready,执行onResultReceived将metadata送到java层cameraservice。

2 HAL3 call back API2,数据流回调
在这里插入图片描述

  • API2中,所有数据流都走BufferQueue传递,这个更高效,和上面的API1的StreamingProcessor一样;
  • 步骤:hal回图告诉Camera3Device通知Camera3Stream这张buffer图已经ready,执行queueBuffer给BufferQueue,进而Consumer就会被通知到有Buffer上来了,Consumer通常是APP/SurfaceFlinger/录像(VideoEncoder)。

4. C++层CameraService的Camera2流程

1. C++层Camera2获取CameraCharacteristic

1. C++层CameraService的getCameraCharacteristics总流程
getCameraCharacteristics:

  • 获取静态metadata,这颗CameraDevice支持的参数,比如JpegSize;
  • 如果是call HAL3的getCameraCharacteristics,可以不需要openCamera;
    在这里插入图片描述
  • 使用步骤:
  • 第一步:Cameraserver进程刚起来做enumerate时会将CameraCharacteristics存放在CameraProviderManager的DeviceInfo3里面的mCameraCharacteristics,因为当C++层CameraService启动后,CameraDevice的静态metadata不会改变;
  • 第二步:上层APP问CameraService要CameraCharacteristics时,CameraService就从DeviceInfo3对象中直接获取,不会调用到HAL去,可以减少binder call hal的次数;

1.1 CameraProvider初始化mCameraCharacteristics流程:
在这里插入图片描述
步骤:

  • 第一步:C++层CameraService启动时,会问hal有多少颗CameraDevice,对每颗cameraDevice都执行addDevice,每一颗CameraDevice会去获取CameraCharacteristics,保存在mCameraCharacteristics;
  • 第二步:如果是Logical MultiCamera,会针对每一颗Physical Camera调用HAL层的getPhysicalCameraCharacteristics,保存在mPhysicalCameraCharacteristics Map中;

1.2 CameraProvider初始化mCameraCharNoPCOverride流程:
在这里插入图片描述
步骤:

  • C++层CameraService启动时,在enumerateProviders会调用CameraProviderManager的filterSmallJpegSizes,这个方法是剔除小于1080P的JpegSize,目的是兼容老的hal版本,剔除前会保留mCameraCharacteristics到mCameraCharNoPCOverride,然后删除mCameraCharacteristics里小于1080P的JpegSize;
    • 如果APP TargetSdkVersion小于S,使用mCameraCharNoPCOverride,如果大于S,使用mCameraCharacteristics;

2. CameraService的getCameraCharacteristics逻辑
在这里插入图片描述
步骤:

  • 第一步:根据SystemCameraKind判断是否要拒绝访问,如果不拒绝,则通过上层APP传入的TargetSDK获取overrideForPerfClass,然后传递给CameraProviderManager获取CameraCharacteristics;
  • 第二步:判断是否有Camera权限,如果没有Camera权限,删除必须要有Camera权限才能访问的静态metadata,然后再返回静态metadata(这里可以优化下,将无静态权限才能访问的静态Metadata缓存起来,不用每次都去操作Metadata);

2.1 shouldRejectSystemCameraConnection逻辑,获取SystemCameraKind的权限:
在这里插入图片描述
SystemCameraKind:

  • PUBLIC:对所有应用程序和系统组件都是可见;
  • SYSTEM_ONLY_CAMERA:只对有android.permission.SYSTEM_CAMERA权限的进程可见,比如系统相机,不会暴露给第三方应用程序;
  • HIDDEN_SECURE_CAMERA:只对HAL应用可见,比如人脸解锁(通过hwbinder连接);
    步骤:
  1. 第一步:获取调用者的PID/UID/SystemCameraKind/以及是否是systemClient;
  2. 第二步:如果是c++层cameraserver自己调用自己,则不拒绝,这种情况一般出现在hal调用c++层cameraserver再调用自己,不会拒绝;
  3. 第三步:如果是systemClient,则不拒绝,uid小于10000都是systemClient;
  4. 第四步:如果systemCameraKind是PUBLIC,则不拒绝;
    • 如果systemCameraKind是HIDDEN_SECURE_CAMERA,拒绝,因为走到这里说明不是hal调用过来,所以拒绝;
    • 如果systemCameraKind是SYSTEM_ONLY_CAMERA,并且有SYSTEM_CAMERA权限,则不拒绝,没有SYSTEM_CAMERA权限则拒绝;

2.2 CameraProviderManager的getCameraCharacteristics逻辑
在这里插入图片描述
步骤:

  • 第一步:判断是否要为PerfClass做Override;如果要做Override,则返回mCameraCharacteristics,否则返回mCameraCharNoPCOverride;
  • 第二步:则根据CameraId从mPhysicalCameraCharacteristics里面获取hidden physical camera characteristics;

2. C++层Camera2获取addListener

1 addListener总体流程

  • 作用:实时监听手机每颗camera的状态,每颗camera都保持一个状态,比如打开相机,手机摔到了某颗camera,camera不能使用了,CameraService可以立刻返回一个状态给客户端,如果有多个客户端使用,可以通知到多个客户端。

  • ICameraService.aidl的addListener:

    • CameraStatusAndId[] addListener(in ICameraServiceListener listener);
      在这里插入图片描述
  • 直接调用addListenerHelper就是vendorListener,直接调addListener就不是vendorListener

1.1 CameraService::addListener方法详解
在这里插入图片描述

  • 步骤:
  • 第一步:检查调用者进程是否有监听Camera Open和Close权限,如果没有就不会告诉调用者哪颗camera打开、关闭,不会调用onCameraOpened、onCameraClosed;
  • 第二步:判断调用者进程是否已经add过Listener,如果没有add过,构造ServiceListener并调用initialize方法,将ServiceListener保存在mListenerList,然后向UidPolicy注册Monitor事件,监听UID的变化;
  • 第三步:遍历mCameraStates,将结果存放入输出对象cameraStatuses中,然后erase掉需要对调用者隐藏的CameraStates;最后执行listener->onTorchStatusChanged,更新TorchModeStatus给调用者进程;

CameraStatus:
cameraId:Camera设备的Id;
status:Camera设备当前的状态;
unavailablePhysicalIds:针对LogicalMulticamera情况,存放不可用的PhysicalCameraID;
clientPackage:如果拥有监控Opened/Closed权限,返回CameraDevice被哪个进程正在使用;

1.2 removeListener流程详解
在这里插入图片描述

  • 步骤:
  • 第一步:CameraService会保存每一个调用者客户端的ServiceListener对象,都会监听对端客户端的binderDied,当对端died,CameraService这边的binderDied会被调用,然后调用CameraService::removeListener,将这个客户端的ServiceListener从mListener移除;
  • 第二步:注销UidPolicy监听对端进程状态,注销binder监听,删除mListenerList的ServiceListener;

3. C++层Camera2 OpenCamera

1. OpenCamera总体流程
在这里插入图片描述

  • 步骤:
  • 第一步:检查权限,权限包括camera自己的权限、手机对camera的限制(比如DevicePolicy)、censer隐私权限;
  • 第二步:调用者需要打开的Camera和已经打开Camera的关系,如果两个调用者进程都去打开一个Camera,就会有两个进程抢占;
  • 第三步:做openCamera动作,主要是cameraClient初始化,调用hal真正做openCamera,给Camera做上电动作;
  • 第四步:初始化cameraDevice;
    正常耗时30ms左右,如果hal异步做就不耗时;

2. CameraService::connectDevice,都是从这里开始

  • API2用connectDevice–>检查权限–>ConnectHelper,这里说API2;
  • API1用connect–>ConnectHelper;
    在这里插入图片描述
  • 步骤:
  • 第一步:通过CallingUid判断是否是systemNativeClient,systemNativeClient主要针对VendorClient,hal端的Client,比如人脸解锁,在流程上做一些特殊处理,VendorClient没有包名,可以不用对包名做检查权限;
  • 第二步:通过UserId判断是否当前User被DevicePolicy限制使用Camera,一般在多用户场景,如果限制就会报错结束,如果不限制继续往下走,判断是否有权限通过oomScoreOffset降低抢占权限,意思用oomScoreOffset降低抢占优先级,这种只是为了SystemCamera,如果是SystemCamera但是没有oomScoreOffset也会结束退出;
  • 第三步:执行ConnectHelper完成OpenCamera流程(重点),然后重置匿名共享内存文件mMemFd,mMemFd是记录上一次openSession的信息,调用AMS的logFgsApiBegin,logFgsApiBegin表示有ForegroundService在使用Camera,closeCamera是logFgsApiEnd;

3. CameraService::connectHelper(重点)
在这里插入图片描述

  • 步骤:
  • 第一步:为非SystemNDKClient获取clientPackageName,定位那个进程在使用camera,然后记录openCamera开始时间点openTimeNs里,在connectHelper结束时会记录OpenCamera的耗时openLatencyMs,传递给mCameraServiceProxyWrapper->logOpen,没有log打印耗时。
  • 绿色方框里面部分:
    1. 抢到mServiceLockWrapper这把锁,超时时间是3s,保证同一时刻只有一个客户端在openCamera,如果这里超时看一下上次openCamera时候这把锁是不是没有释放,也有可能close卡主,mServiceLockWrapper被持有的地方比较多都要查;
    2. 检查权限和CameraId:validateConnectLocked(重点);
    3. 处理抢占逻辑:handleEvictionsLocked(重点);
    4. 准备创建cameraClient,准备参数:
      • deviceVersionAndTransport:是指hidl的deviceVersion、Transport;
      • portaitRotation:旋转多少度是竖屏;
      • facing:打开camera是前置还是后置;
      • orientation:设备角度;
      • overrideForPerfClass:对参数做的修改;
    5. 把准备的参数传入makeClient,这里会区分API1或者API2,API1创建camera2Client,API2创建cameraDeviceClient,这里看API2;client->initialize,会传入monitorTags,monitorTags:可以监听每一帧里面的metadata变化,debug时使用,比如dumpsys media.camera。(重点)
    6. CameraService watchdog:监听函数的耗时;rotate-and-crop override behaviour:是否要做override行为;autoframing override behaviour:自动选帧;camera muting behavior:camera没有关闭,但是不能出正常的图像,比如显示黑屏或者测试图片,如果isCameraPrivacyEnabled=true就不能出正常的图像,接着如果supportsCameraMute=ture启流时需要mute,否则关闭camera。 client->setImageDumpMask;client->setStreamUseCaseOverrides;client->setZoomOverride,这3个都是debug使用。
    7. finishConnectLocked:把打开后的CameraClient添加到ActiveClientManager中,ActiveClientManager监听CameraClient进程是否挂掉;
      • logConnected:dumpsys 可以看到;linkToDeath:监听调用者进程是否挂掉,调用者挂掉CameraService就会disconnect;
    8. mInjectionInitPending:是指外接的camera可以动态切换,暂时没人用。

3.1 validateConnectLocked
在这里插入图片描述

  • 步骤:
  • 第一步:validateClientPermissionsLocked:获取调用者客户端的UID和PID;执行shouldRejectSystemCameraConnection对SystemCamera的权限进行检查,前面说过这个;检查非系统camera的权限,是否已经有Camera权限;检查调用者UID是否处于Active状态;检查调用者SensorPrivacy是否Enable,如果没有就不能使用;检查当前用户是否在mAllowedUsers里面,多用户场景,
    • mAllowedUsers赋值:
CameraService::onFirstRef
	mCameraServiceProxyWrapper->pingCameraServiceProxy
CameraServiceProxyWrapper::pingCameraServiceProxy
	proxyBinder->pingForUserUpdate
binder call java层
CameraServiceProxy.java
	notifySwitchWithRetries
	notifySwitchWithRetriesLocked
	notifyCameraserverLocked(ICameraService.EVENT_USER_SWITCHED, ..)
		mCameraServiceRaw.notifySystemEvent(eventType, ..)
binder call c++层
CameraService::notifySystemEvent
	ICameraService::EVENT_USER_SWITCHED:
		doUserSwitch(/*newUserIds*/ args);
	CameraService::doUserSwitch(.. newUserIds)
		mAllowedUsers = std::move(newAllowedUsers);
  • 第二步:根据CameraId获取CameraState,检查CameraId是否合法;
  • 第三步:根据CameraState检查当前CameraDevice是否可用,CameraDevice的状态:PRESENT、NOT_PRESENT、ENUMERATING;

3.2 handleEvictionsLocked
在这里插入图片描述

  • 步骤:
  • 第一步:新的客户端进程打开camera时,获取所有已经连接camera客户端进程的oom_adj scores和process state,这两个都是实时变化的,更新各ClientPriority。比如有多个客户端进程连接camera,每一个客户端进程都持有一个client,这个client就是ActiveClient,客户端进程的pid就是ActivePid,保存在数组里面。
  • 第二步:根据当前客户端进程想打开的camera创建一个ClientDescriptor,每个连接camera的进程都有一个ClientDescriptor,然后调用CameraClientManager的wouldEvict方法拿到需要被抢占的调用者进程的evicted列表,wouldEvict是抢占逻辑的核心。比如已经有进程连接camera,新的进程也想要连接camera,把所有的进程都放入wouldEvict做裁决谁连接camera。
  • 第三步:如果想打开camera的客户端进程在evicted列表中,就返回CAMERA_IN_USE(被人占用)或MAX_CAMERAS_IN_USE(没人占用,自己优先级低也不能打开)。开camera的客户端进程不在evicted列表,就表示打不开,当前进程优先级不够。
  • 第三步:如果evicted列表只有已经连接camera的进程,遍历evicted列表,给每一个进程发送ERROR_CAMERA_DISCONNECTED,断开连接camera,然后执行clearCllingIdentity清空远程调用端的uid和pid,用cameraserver进程的uid和pid替代,下面执行disconnect时检查callingPid和调用者pid如果不一样就直接返回。
  • 第四步:再遍历evicted列表,调用每个已经连接的Client的disconnect方法关闭Camera,通过restoreCallingIdentity恢复远程调用端的uid和pid,正好和clearCallingIdentity相反。调用waitUnitlRemoved等待所有evictedClientDisconnect完成。
  • 最后,再次检查当前CameraId对应的Device是否可用。

3.3 ClientDescriptor
描述一颗CameraClient对象。

  • KEY:当前CameraClient对应的CameraId;
  • VALUE:当前CameraClient对象;
  • cost:打开当前Camera需要耗费的resourceCost,用resourceCost描述打开相机需要的资源;
  • conflictingKeys:与上面KEY的值必须相同,如果不同就表示不能打开camera,
    • 比如:
    • KEY=0,conflictingKeys=(1,2),表示当前进程已经打开了camera 0,想再打开camera 1、2,就打不开;
    • 进程A:KEY=0,conflictingKeys=(1,2),进程B:KEY=2,表示进程B已经打开的camera 2涵盖在进程A想再打开的camera 1、2,这样也会冲突;
  • score:打开当前Camera的客户端进程oom_adj score,这个值越大越容易被LMK干掉,前台进程这个值为0;
  • ownerId:打开当前Camera的客户端进程pid;
  • state:打开当前Camera的客户端进程的状态,值越小优先级越高;
  • isVendorClient:打开当前Camera的客户端是否是Vendor进程;

3.4 ClientPriority
描述一颗CameraClient客户端进程的优先级。

  • score:打开当前Camera的客户端进程oom_adj score,这个值越大越容易被LMK干掉,前台进程这个值为0;
  • state:打开当前Camera的客户端进程的状态,值越小优先级越高;
  • isVendorClient:打开当前Camera的客户端是否是Vendor进程;

这个类重载了比较运算符,比如 >,>=,<,<=,通过score和state来判断大小,ClientPriority值越小,优先级越高。

//小于运算符
bool operator< (const ClientPriority& rhs)  const {
    if (this->mScore == rhs.mScore) {
        return this->mState < rhs.mState;
    } else {
        return this->mScore < rhs.mScore;
    }
}

4. Camera抢占逻辑

conflicting表示是否有冲突:当前进程想要打开的key和已经打开的curKey相等就有冲突;当前进程的client想要打开的key是否已经包含在已经打开camera的client的conflictingKeys里面。

bool conflicting = (curKey == key || i->isConflicting(key) ||
                    client->isConflicting(curKey));
  • 抢占逻辑:
  • 想打开的camera与已打开camera存在冲突
    • 如果是同一个进程打开camera有冲突;
      • 在不同时间点想打开同一颗Camera,可以随时时打开;
      • 想打开不同颗Camera,本来就有冲突,不能同时打开,用之前的camera;
    • 如果是不同进程打开camera有冲突;
      • 已打开camera进程优先级低,当前进程优先级高,可以打开camera;
      • 已打开camera进程优先级高,当前进程想打开camera会失败,无法打开;
  • 如果是同进程或者不同进程打开camera,想打开的camera与已打开的camera不存在冲突,就使用resourceCost做限制,最大resourceCost是100;
    • 如果打开camera进程的Total cost超过最大值100,比如:进程A已经打开了camera0,使用的resourceCost=51,进程B想打开camera1,使用的resourceCost=50,这两个resourceCost之和是101,就判定这两个进程打开camera有冲突;
      • 已打开camera进程优先级低,当前进程优秀级高,可以打开camera;
      • 已打开camera进程优先级高,当前进程想打开camera会失败,无法打开;
    • 如果Total cost未超过最大值,当前进程直接打开camera。比如:进程A已经打开了camera0,使用的resourceCost=40,进程B想打开camera1,使用的resourceCost=40,这两个resourceCost之和是80,就判定这两个进程打开camera没有冲突;

疑问:

  • 同一进程能否重复打开同一颗Camera?Yes
  • 同一进程能否同时打开不同颗Camera?Yes,如果打开的2颗camera不冲突,可以用resourceCost做限制,如果resourceCost超过100看进程优先级,resourceCost不超过100,能同时打开不同颗Camera。
  • 不同进程能否重复打开同一颗Camera?Yes
  • 不同进程能否同时打开不同颗Camera?Yes,如果打开的2颗camera不冲突,可以用resourceCost做限制,如果resourceCost超过100看进程优先级,resourceCost不超过100,能同时打开不同颗Camera。

5. CameraDeviceClient初始化

5.1 API2 makeClient流程
在这里插入图片描述

5.2 API2 CameraClient类图:CameraDeviceClient
在这里插入图片描述

  • API2/API1 CameraClient各个类的职责:
  • CameraDeviceClient:API2,负责处理与API2相关的业务逻辑;
  • CameraDeviceClientBase:负责继承API2的ICameraDeviceUser;
  • Camera2ClientBase:负责处理API1和API2共用的逻辑且与CameraDevice操作有关系;
  • CameraService::BasicClient:负责处理API1和API2共用的逻辑且与CameraDevice操作无关;
  • Camera2Client:负责处理与API1相关的业务逻辑;
  • CameraService::Client:负责继承API1的ICamera(BnCamera);

5.3 API2 CameraDeviceClient成员变量

  • mFrameProcessor::FrameProcessorBase:从cameraDevice获取每帧的ResultMetadata;
  • mSupportedPhysicalRequestKeys::vector:PhysicalCamera支持设置的RequestKeys,上层送submitRequest时用于过滤掉不支持的Request设置;
  • mStreamMap::KeyedVector<sp, StreamSurfaceId>:以Map方式存值,key是GraphicBufferProducer,相当于一个surface或者stream,value是StreamId和SurfaceId的组合,使用组合的原因是在sharedStream的情况,一个stream有多个surface,比如hal发送一个stream,cameraserver接收多个输出surfaceId;
  • mConfiguredOutputs::KeyedVector<int32_t, OutputConfiguration>:上层APP下发配置的流时,每个流保存在OutputConfiguration列表,key是streamId,value是OutputConfiguration;
  • mDynamicProfileMap::map<int64_t, int64_t>:key是profileId,value是SupportedDynamicProfiles BitMap,bitMap是多个profileId用或连接的,存放当前这颗camera支持的dynamicRangeProfiles,上层APP送submitRequest时会对设置的值做检查,做检查的原因是cameraserver不知道上层下发的dynamicRangeProfile是否合法,需要向hal查询是否支持,dynamicRangeProfile放在OutputConfiguration;
  • mInputStream::InputStreamConfiguration:存放InputStream,上层APP把buffer回灌到hal,只支持一路InputStream;
  • mStreamingRequestId::int32_t:存放最新Streaming的RequestId,每次调用submitRequestList后,cameraserver会有一个mRequestIdCounter++,用于判断当前stream或repeatingRequest是否处于Active;
  • mRequestIdCounter::int32_t:submitRequestList时++,唯一标识当前的这次submitRequest行为;
  • mPhysicalCameraIds::vector:存放当前这颗Camera支持的PhysicalCamera的Id,对logicalMultiCamera有效;
  • mDeferredStreams::Vector:存放处于Defer状态的OutputStream,SurfaceReady后会move到mStreamMap,比如这条stream的serface没有ready,等ready后上层APP再重新送下来,一旦SurfaceReady就会把serface从mDeferredStreams删除,然后放入mStreamMap,有助于提高启动性能;
  • mStreamInfoMap::map<int32_t, OutputStreamInfo>:key是streamId,value是outputStreamInfo的map,记录每路outputStream的info;
  • mHighResolutionCameraIdToStreamIdSet::map<std::string, std::unordered_set>:key是高分辨率(>=24M)的camera id (logical/physical) ,value是list of stream ids,检查Request里面设置的SensorPixelModel与OutputConfiguration里面的SensorPixelMode是否一致;
  • mHighResolutionSensors::set:用于判断是否支持高分辨率Stream的Camera,用ULTRA_HIGH_RESOLUTION_SENSOR的capability;
  • mCompositeStreamMap::KeyedVector<sp, sp>:用于合成流再给回APP,等价于mStreamMap,存放3中需要合成的Stream:HEIC,JPEG_DEPTH(Jpeg with XMP depth metadata),JpegR(Jpeg with Recovery map);
  • mProviderManager::CameraProviderManager:存放CameraProviderManager的实例,用于判断是否是logical multi-cam和isSessionConfigurationSupported;
  • mOverrideForPerfClass::bool:是否要Override the camera characteristics for performance class primary cameras,在isSessionConfigurationSupported使用;
  • mUserTag::string:上层送request时执行CaptureRequest.setTag记录最新设置的mUserTag,记录在event log里面;
  • mVideoStabilizationMode::int:记录最新的VideoStabilizationMode,记录在event log里面;

5.4 API2 CameraDeviceClient与Stream的变量

  • outPutStream:
    • mConfiguredOutputs:保存streamId映射 OutputConfiguration,OutputConfiguration是上层app下发的stream信息,上层要求的stream格式;
    • mStreamMap:保存IGraphicsBufferProducer binder映射streamId和surfaceId;
    • mStreamInfoMap:保存streamId映射OutputStreamInfo,OutputStreamInfo是指cameraserver要求的stream格式;
    • mDeferredStreams:保存streamId;
  • InputSream:
    • mInputStream

5.5 API2 CameraDeviceClientBase成员变量

  • mRemoteCallback::ICameraDeviceCallbacks:保存给App进程的回调对象实例;

5.6 API2 Camera2ClientBase成员变量

  • mSharedCameraCallbacks::SharedCameraCallbacks:保存回调到App的对象;
  • mInitialClientPid::pid_t:记录初始化CameraClient时传递的ClientPID;
  • mOverrideForPerfClass::bool:是否要Override the camera characteristics for performance class primary cameras;
  • mLegacyClient::bool:Client是否是API1;
  • mCameraServiceProxyWrapper::CameraServiceProxyWrapper:CameraServiceProxy对象,用于与之交互;
  • mDevice::CameraDeviceBase:存放CameraDeviceBase的实例;
  • mDeviceActive::bool:标识当前CameraDevice是否处于Active状态;
  • mApi1CameraId::int:API1的Camera ID,如果是API2,这个值为-1;
  • mCameraServiceWatchdog::CameraServiceWatchdog:CameraClient的WatchDog,监控disconnect是否timeout;

5.7 API2 CameraService::BasicClient成员变量

  • sCameraService::CameraService:保存CameraService的实例,用于Client回调CameraService;
  • mCameraIdStr::String8:CameraID;
  • mCameraFacing::int:Camera的面向,前置或者后置;
  • mOrientation::int:Camera sensor的安装角度;
  • mClientPackageName::String16:客户端进程的package name;
  • mSystemNativeClient::bool:是否是SystemNativeClient,如果UID小于AID_APP_START的Native进程;
  • mClientFeatureId::String16:Client进程的feature id,上层app设置的mContext.getAttributionTag(),调用AppOpsManager使用;
  • mClientPid::pid_t:Client的PID;
  • mClientUid::uid_t:Client的UID;
  • mServicePid::pid_t:CameraService的PID;
  • mDisconnected::bool:当前Client是否处于Disconnect状态;
  • mUidIsTrusted::bool:UID是否是可信的,白名单,这些可信mediaserver, cameraserver, telephony;
  • mOverrideToPortrait::bool:是否要将Stream通过Rotate和Crop成Portrait,兼容性考虑;
  • mAudioRestriction::int32_t:对Audio的限制策略;
  • mRemoteBinder::IBinder:保存给App进程的回调对象实例;
  • mAppOpsManager::AppOpsManager:AppOpsManager实例,用于检查Client是否有Camera操作权限;
  • mOpsCallback::OpsCallback:AppOps的回调,用于通知App的操作权限变化;
  • mOpsActive::bool:是否开始监听CameraOps;
  • mOpsStreaming::bool:是否开始执行CameraOps;

5.8 API2 clientPackageName赋值逻辑
调用者进程的包名
在这里插入图片描述

  1. openCamera时,上层Java层APP会传递Client package name到CameraService;
  2. 如果是NativeClient,传递的package name为空字符串,cameraservice会主动获取包名;
  3. connectHelper是API1和API2通用的逻辑;

5.9 AppOpsManager处理逻辑
AppOpsManager是应用程序执行某个操作权限的管理类,有两个目的

  • 运行时的访问权限控制,比如某个APP是否有权限执行某个操作;
  • 运行时的访问权限跟踪,比如某个APP在使用camera的过程中发生camera操作权限的变更,允许openCamera但在使用过程中不允许使用camera,比如分屏时一个屏幕显示预览,另一个屏幕操作settings把camera权限关掉;
    在这里插入图片描述
  • 第一步:检查是否是mSystemNativeClient,如果不是mSystemNativeClient创建mAppOpsManager,如果是mSystemNativeClient后面的步骤可以不用操作;
  • 第二步:initialize时执行notifyCameraOpening,告诉AppOpsManager调用者客户端需要openCamera,检查客户端是否有openCamera的权限,开始跟踪操作camera的权限;
    • startWatchingMode:开始监听调用者APP进程在使用过程中是否有操作权限的变化;
    • checkOp:检查调用者的uid和packagename是否能匹配;
    • handleAppOpMode:下面说;
  • 第三步:Preview Started,送request让hal上帧出图,执行startCameraStreamingOps;
    • startOpNoThrow:执行更严格的检查,检查camera相关的全部权限,不符合就会返回appOpMode回来;
  • 第四步:Preview Stopped,执行finishCameraStreamingOps,finishOp:告诉AppOpsManager上一次的start到到这执行结束;
  • 第五步:Close Camera,执行finishCameraOps,stopWatchingMode,对应openCamera的startWatchingMode;

handleAppOpMode

  • 第一步:针对MODE_ERRORED和MODE_IGNORED两种Mode做了处理;
    • 如果mode是MODE_ERRORED,返回PERMISSION_DENIED,没有权限不允许openCamera;
    • 如果mode是MODE_IGNORED,表示AppOpsManager忽略了检查或者检查不到,比如Client是native service,不属于上层java层APP,就会忽略检查返回MODE_IGNORED,如果是后台应用程序也会返回MODE_IGNORED;
  • 第二步:检查mUidIsTrusted,如果uid不是Trusted,就读取isUidActive、isCameraPrivacyEnabled;
    • isUidActive如果为true表示APP在前台,如果为false表示在后台;
    • isCameraPrivacyEnabled如果为true表示camera的隐私权限被打开了,预览流的图像不能呈现给用户,但是可以openCamera,如果为false表示随便看camera预览图像;
  • 第三步:如果Camera Privacy Enabled,这里趋向于继续让OpenCamera正常执行(不返回-EACCES),后续做mute动作;
    在这里插入图片描述

监听Camera预览过程中操作权限发生改变

  • 第一步:判断mAppOpsManager是否为空,如果不为空判断op是否为OP_CAMERA,如果是就调用checkOp获取到mode;
  • 第二步:针对MODE_ERRORED、MODE_IGNORED和MODE_ALLOWED三种Mode做了处理;
    • MODE_ERRORED在使用camera过程中不允许使用camera,block()关闭Camera;
    • MODE_IGNORED下面说,mute camera或block camera或者什么都不做,mute意思是hal返回test pattern的图像或者一张黑图,block是会直接关闭Camera;
    • MODE_ALLOWED表示opchange,之前不允许现在允许,设置override mute mode;
      在这里插入图片描述

MODE_IGNORED

  • 读取isUidActive、isCameraPrivacyEnabled,如果不是mUidIsTrusted,如果是isUidActive,如果隐私打开,检查是否支持mute.
    在这里插入图片描述

5.10 UidPolicy控制逻辑

Android 如何查看进程的UID

  • 可以通过ps –A来查看,一个UID下面可以有多个进程
  • ps -A |grep com.android.camera

单用户情况

  • 比如命令显示u0_a001表示该应用是use0下面的应用,user0是主用户,id是001
  • 普通应用程序的UID都是从10000开始的,所以最终计算出的UID就是10001

多用户情况

  • 比如命令显示可以看到其他用户u14_a001,userID是14,计算方式是:100000*14+10106=1410106

UidPolicy与AMS的交互

  • UidPolicy类是CameraService创建的,用于监控Client UID的状态变化,当UID状态为IDLE时不允许使用Camera。
    UidPolicy与AMS的交互逻辑,监控uid的变化:
    在这里插入图片描述
  • 第一步:CameraService起来后会用linkToDeath监控AMS是否有crash,registerUidObserverForUids告诉AMS需要监控哪些uid,第一次注册时发送的uid列表是空的;
  • 第二步:有调用者client端开始addListener/openCamera就会执行registerMonitorUid,监控调用者client端;
  • 第三步:在camera运行过程中AMS会回调uid状态的变化;
  • 第四步:调用者client端不使用camera时removeListener/CloseCamera会调到removeUidFromObserver,最后调用者client结束时执行unregisterUidObserver/unlinkToDeath;

UidPolicy成员变量

  • mRegistered:是否向AMS注册了监听uid,如果AMS比CameraService后启动或AMS突然挂了,这个变量可能会为False;
  • mActiveUids:处于Active状态的uid列表;
  • mMonitoredUids:正在监控的uid列表;
  • mOverrideUids:保存UID的Override状态,用于debug,通过cmd命令设置;

UidPolicy方法

  • registerSelf()/unregisterSelf():注册/注销UID Observer,CameraService::onFirstRef call registerSelf,CameraService::~CameraService call unregisterSelf;
  • isUidActive(uid_t uid, String16 callingPackage):判断当前UID是否处于Active状态;
  • getProcState(uid_t uid):获取当前UID的ProcState;
  • IUidObserver的回调方法:处理UID状态发生变化;
  • addOverrideUid/removeOverrideUid:设置/移除某个UID的Override状态,修改mOverrideUids列表,用于debug;
  • registerMonitorUid/unregisterMonitorUid:注册/注销监听某个Uid的状态变化;
  • onServiceRegistration:监听AMS服务注册上了,有可能AMS比CameraService起来得慢一些/AMS挂掉重启,因此需要AMS启动后才能去注册监听UID状态;
  • binderDied:AMS服务挂掉了,等AMS重启后要重新注册;

IUidObserver回调接口

  • void onUidGone(int uid, boolean disabled);:当前UID的所有进程没有运行;
  • void onUidActive(int uid);:当前UID的所有进程在前台运行,处于Active状态;
  • void onUidIdle(int uid, boolean disabled);:当前UID处于IDLE状态,UID的进程在后台运行了一段时间了或者UID的进程都未运行,需要把client和cameraservice block,因为IDLE状态的client禁止使用camera;
  • void onUidStateChanged(int uid, int procState, long procStateSeq, int capability);:当前UID的procState发生变化;
  • void onUidProcAdjChanged(int uid, int adj);:当前UID的所有进程oom adj值发生变化;

onUidIdle处理流程

  • 当Camera App从前台切到后台时,如果没有close camera,onUidIdle回调会被调用,如果uid没在mActiveUids里面,执行blockClientsForUid,阻止调用者client端使用cameraservice,从而防止在后台使用Camera;
    在这里插入图片描述

onUidStateChanged处理流程

  • UID的所有进程ProcState发生变化,就会执行onUidStateChanged,如果从mMonitoredUids检查当前UID的所有进程ProcState发生变化,会通知所有客户端的onCameraAccessPrioritiesChanged;
    • onCameraAccessPrioritiesChanged:如果其他调用者客户端收到这个接口的回调,可以重新再openCamera,可能之前和其他进程抢占某颗camera没有成功,自己进程优先级低,可以再次重新连接这颗camera;
      在这里插入图片描述

onUidProcAdjChanged处理流程

  • 当ProcAdj发生变化时,判断当前uid的进程是否在mMonitoredUids,判断当前uid的进程是否在使用camera,如果在使用camera,将自己及adj小于自己的UID放在notifyUidSet,会通知放在notifyUidSet里面Listener的onCameraAccessPrioritiesChanged;
    在这里插入图片描述

5.11 SensorPrivacyPolicy

SensorPrivacyPolicy的作用

  • SensorPrivacyPolicy用于控制sensor隐私,SensorPrivacy和CameraPrivacy;
  • SensorPrivacy: 启用后,不允许所有App使用Camera,包括正在使用Camera的App,会强制关闭/不允许打开Camera;
  • CameraPrivacy: 启用后,先判断这颗Camera是否支持mute,如果支持MuteCamera则直接Mute,返回黑图,否则会关闭Camera/不允许打开Camera;

SensorPrivacyPolicy与SensorPrivacyManager的交互
在这里插入图片描述

  • 第一步:CameraService::onFirstRef起来时,执行linkToDeath连接systemserver监听systemserver挂掉,调用addSensorPrivacyListener监听systemserver的Litener,如果调用者客户端断开连接CameraService,CameraService销毁时会调用removeSensorPrivacyListener;CameraService::onFirstRef起来时也会执行isSensorPrivacyEnabled,表示监听的Sensor有一个SensorPrivacyEnabled就返回true;
  • 第二步:在CameraService::connectHelper时会主动判断camera的SensorPrivacy是否Enabled,如果有enable,在connectHelper时会走CameraSensorPrivacy的逻辑,如果在使用过程中,SensorPrivacy发生改变,更新mSensorPrivacyEnabled,如果隐私权限打开了关闭所有camera;

SensorPrivacyPolicy方法详解

  • registerSelf()/unregisterSelf():注册/注销SensorPrivacyListener;
  • isSensorPrivacyEnabled():判断是否有一个SensorPrivacy是否使能了;
  • isCameraPrivacyEnabled():判断是否有一个CameraPrivacy是否使能了;
  • onSensorPrivacyChanged:SPM回调通知sensorPrivacy发生变化了;
  • onServiceRegistration:如果SPM挂掉或者比cameraservice后起来,会执行onServiceRegistration,重新注册SPM;
  • binderDied:SPM服务挂掉了,等SPM重启后要重新注册;

5.12 CameraDeviceClient

CameraDeviceClient初始化

  • 第一步: Camera2ClientBase初始化:创建CameraDeviceBase,startCameraOps,启动Camera2ClientBaseWatchdog监控Camera2ClientBase;
  • 第二步:FrameProcessor初始化;
  • 第三步:CameraDeviceClient用到的静态Metadata初始化;
    在这里插入图片描述

Camera2ClientBase初始化
在这里插入图片描述

  • 第一步:根据providerTransport拿到是HIDL/AIDL创建HidlCamera3Device/AidlCamera3Device,执行mDevice->initialize;

  • 第二步:执行startCameraOps和AppOpsManager交互,再次检查调用者客户端是否有使用Camera的权限,如果没有权限还要closeCamera;

  • 第三步:mDevice->setNotifyCallback将NotificationListener设置给CameraDevice,CameraDevice通知回调;

  • 第四步:启动Camera2ClientBase的Watchdog,监听disconnect是否超时;

  • NotificationListener给CameraDevice回调通知

  • notifyError:通知错误,比如hal发生错误,不能生成buffer、hal crash,回调到Camera2Client这边,在回调到调用者Client APP;

  • notifyPhysicalCameraChange:如果使用logical multi-camera,通知回调当前哪颗physical camera目前处于Active状态;

  • notifyActive:通知CameraDevice处于Active出流状态;

  • notifyIdle:通知CameraDevice处于IDLE不出流状态;

  • notifyShutter:只有API2才有通知每帧的shutter事件;

  • notifyPrepared:通知某路流prepare结束,prepare是指提前申请streambuffer;

  • notifyRequestQueueEmpty:通知RequestQueue空了;

  • notifyAutoFocus/notifyAutoExposure/notifyAutoWhitebalance:只有API1使用,FrameProcessor通知3A信息;

  • notifyRepeatingRequestError:对Repeating用的Surface发生abandon了,abandon是指Surface消费端,比如serfaceflinger、appEncoder主动把bufferqueue释放掉了,cameraservice就不能送buffer;

FrameProcessor初始化

  • FrameProcessor处理回调的Metadata的架构
  • FrameProcessorBase启动一个线程调用FrameProducer,Camera3Device继承FrameProducer,就是调到Camera3Device的waitForNextFrame和getNextResult从ResultQueue里面获取可用的CaptureResult;
FrameProcessorBase.h
    struct FilteredListener: virtual public RefBase {
        virtual void onResultAvailable(const CaptureResult &result) = 0;
    };
  • FrameProcessor用RangeListener封装filteredListener,来管理每个客户端对Metadata的需求;
FrameProcessorBase.h
struct RangeListener {
    int32_t minId;
    int32_t maxId;
    wp<FilteredListener> listener;
    bool sendPartials;
};
List<RangeListener> mRangeListeners;
  • 如果是API1,FrameProcessor的RangeListener可以同时注册多个Listener客户端,如果是API2会调用CameraDeviceClient注册一个listener到FrameProcessorBase;
    在这里插入图片描述

CameraDeviceClient用到的静态Metadata初始化

  • mSupportedPhysicalRequestKeys:如果是logical multi-camera,它对应的PhysicalCamera支持哪些RequestKeys,上层submitRequest时,把某颗PhysicalCamera不支持的Request参数remove掉;
  • mDynamicProfileMap:针对hdr,key:profile id, value:Supported dynamic profiles bit map,存放支持的DynamicRangeProfiles,submitRequest时会对设置的值做检查;
  • mHighResolutionSensors:支持高分辨率流的CameraDevice,前提要有ULTRA_HIGH_RESOLUTION_SENSOR capability,上层submitRequest时会对CONTROL_SENSOR_PIXEL_MODE做检查,要求Request和configure时填的值是一样的;

5.13 Camera3Device

Camera3Device架构
在这里插入图片描述

  • client和device是一对一的关系,一个Camera2Client或者CameraDeviceClient就对应一个Camera3Device;
  • 第一步:上层调用端使用cameraserver API先到client这边,如果需要client操作device,就会使用CameraDeviceBase,如果device有状态回调到client,通过FrameProducer主动调用,也可以用Camera3Device持有的NotificationListener回调;
  • 第二步:Camera3Device调用hal时使用AidlCamera3Device或者HidlCamera3Device,都是在创建device时判断接口类型是AIDL/HIDL。AidlCamera3Device依赖AidlCameraDeviceCallbacks,HidlCamera3Device继承ICameraDeviceCallback;
  • 第三步:hal回调返回的数据,如果是数据流,Camera3Device里面的outputStream可以调用stream的接口,比如returnbuffer,把buffer送到consumer端;如果是metadata,返回给client,再送给上层调用者APP;

Camera3Device核心内部类
Camera3Device::RequestThread:用于维护送给HAL的CaptureRequest的线程;
Camera3Device::HalInterface:Camera HAL ICameraDeviceSession类的封装;
Camera3Device::Camera3DeviceInjectionMethods:Inject Camera使用,意思是把外部的camera替换到内部camera,把HalInterfaceh对象换成mInjectedCamHalInterface从而调用ICameraInjectionSession。
- ICameraInjectionSession:提供了一种机制,允许外部Camera设备无缝地替代内部Camera,同时保持与原有Camera配置的兼容性。
- 这对于需要临时使用外部Camera(如USB Camera)替代内置Camera的场景非常有用。

CameraDeviceBase成员变量

  • mImageDumpMask::bool:用于debug,如果是true,表示dump某个image,dumpsys media.camera会使用,可以把mImageDumpMask设置为turue,设置给Output Stream,用于标识是否打开Jpeg Image Dump功能;
  • mStreamUseCaseOverrides::vector<int64_t>:用于debug,dumpsys media.camera会使用,设置给Output Stream,用于记录Stream的Usecase覆盖列表;

ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES如下:

system/media/camera/include/system/camera_metadata_tags.h
typedef enum camera_metadata_enum_android_scaler_available_stream_use_cases {
    ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT                = 0x0, // HIDL v3.8
    ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW                = 0x1, // HIDL v3.8
    ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE          = 0x2, // HIDL v3.8
    ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD           = 0x3, // HIDL v3.8
    ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL    = 0x4, // HIDL v3.8
    ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL             = 0x5, // HIDL v3.8
    ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW            = 0x6, // HIDL v3.9
    ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VENDOR_START           = 0x10000, // HIDL v3.8
} camera_metadata_enum_android_scaler_available_stream_use_cases_t;

Camera3Device成员变量

  • mCameraServiceProxyWrapper::CameraServiceProxyWrapper:在Camer3Device中使用这个的目的: 1. 用于产生唯一的logId,调用AIDL HAL configureStreams时使用;2. 用于记录reconfigureCamera的耗时;
  • mId::String8:当前Camera3Device的ID;
  • mLegacyClient::bool:表示是否是Camera API1的Client;
  • mOperatingMode::int:Configure streams带下来的OperationMode;
  • mSessionParams::CameraMetadataNative:ConfigureStreams带下来的SessionParameter;
  • mIsConstrainedHighSpeedConfiguration::bool:标识是否是HighSpeedConfiguration,有一些逻辑需要特殊处理;
  • mInterface::HalInterface:Camera HAL ICameraDeviceSession类的封装;
  • mDeviceInfo::CameraMetadata:存放当前Camera的静态信息;
  • mPhysicalDeviceInfoMap::unordered_map<std::string, CameraMetadata>:key是pysicalCameraId,如果是Logical multi-cam,存放每个PhysicalCamera的静态信息;
  • mSupportNativeZoomRatio::bool:是否支持通过ZoomRatio来控制Zoom;
  • mIsCompositeJpegRDisabled::bool:是否支持JPEG_R的Stream。 JPEG_R结合了传统的JPEG压缩图像和嵌入式恢复映射(recovery map)。这种格式主要用于支持Ultra HDR(高动态范围)图像。
  • mRequestTemplateCache::CameraMetadata:缓存默认的CaptureRequest,可存放不同Template的CaptureRequest;
  • mStatus::enum Status:记录当前CameraDevice的状态;
  • mRecentStatusUpdates::Vector:记录最近更新的Status,在waitUntilStateThenRelock方法使用;
  • mOutputStreams::StreamSet:当前CameraDevice配置的输出流;
  • mInputStream::Camera3Stream:当前CameraDevice配置的输入流;
  • mSessionStatsBuilder::SessionStatsBuilder:统计Stream的Stats,产生直方图,可以分析黑屏问题;
  • mGroupIdPhysicalCameraMap::std::map<int32_t, std::set>:Stream GroupID与Physical Camera ID的映射关系 针对Multi Resolution的Stream才有GroupID,请求Physical Camera Stream时使用;
  • mNextStreamId::int:单调递增,用于产生Stream ID;
  • mNeedConfig::bool:标识是否需要执行config stream,如果条件未变,不重复configure;
  • mFakeStreamId::int:针对configure stream时mOutputStreams size为0的规避解法,解决bug时使用;
  • mPauseStateNotify::bool:用于内部做reconfiguration时,skip掉state更新通知,比如session parameters改变时需要做reconfiguration;
  • mDeletedStreams::Vector<sp< camera3::Camera3StreamInterface>>:持有待删除的Stream,直到configure结束。有可能在configure的过程中发生Flush,这时也需要对被即将Delete的Stream做Flush;
  • mUsePartialResult::bool:标识HAL是否使用Partial Result,就是hal是否把Result拆成多包回调;
  • mNumPartialResults::uint32_t:有多少包PartialResult,cameraserver会把PartialResult缓存下来,默认值是1;
  • mDeviceTimeBaseIsRealtime::bool:TimestampSource是否是Realtime,如果是需要对timestamp进行矫正;
  • mTimestampOffset::nsecs_t:MonotonicTime到BootTime的偏移值;
  • mRequestThread::sp:处理下发Request的线程;
  • mInFlightMap::InFlightRequestMap:送给HAL,正在被HAL处理的RequestList;
  • mExpectedInflightDuration::nsecs_t:用于判断HAL处理request是否发生Timeout,最小5秒;
  • mStatusTracker::wp:跟踪Camera3Device的状态切换;
  • mBufferManager::sp:管理OutputStream的GraphicBuffer,OutputStream不是通过bufferqueue申请,是由cameraserver通过Graphic接口申请,,一个Camera3Device只有一个BufferManager。为了优化内存用量而使用,比如configStream有16;
  • mPreparerThread::sp:用于执行streamPrepare的线程;
  • mResultQueue::std::list:用于存放HAL送上来的CaptureResult;
  • mListener::wp:用于Camera3Device回调Client;
  • mDistortionMappers::std::unordered_map<std::string, camera3::DistortionMapper>:对于支持畸变矫正的Camera,对CaptureRequest和CaptureResult进行修正;
  • mZoomRatioMappers::std::unordered_map<std::string, camera3::ZoomRatioMapper>:处理Zoom Ration与Crop Region之间的转换,对CaptureRequest和CaptureResult进行修正;
  • mUHRCropAndMeteringRegionMappers::std::unordered_map<std::string, camera3::UHRCropAndMeteringRegionMapper>:对于支持ULTRA HIGH RESOLUTION的Camera,对CaptureRequest进行修正;
  • mRotateAndCropMappers::std::unordered_map<std::string, camera3::RotateAndCropMapper>:对于支持Auto rotate-and-crop的Camera,对CaptureRequest和CaptureResult进行修正;
  • mRotateAndCropOverride::camera_metadata_enum_android_scaler_rotate_and_crop_t: dumpsys media.camera Debug使用,强制设置RotateAndCrop Mode;
  • mTagMonitor::TagMonitor:Debug使用,用于跟踪CaptureRequest/CaptureResult中的Metadata变化情况;
  • mVendorTagId::metadata_vendor_id_t:标识Vendor Tag的ID,不同Camera可以有不同的Vendor Tag ID,用于操作Vendor Tag;
  • mLastTemplateId::int:存放最后一次获取默认CaptureRequest的Template ID,如果configure streams没有带session parameters,则以这个CaptureRequest设置为session parameters;
  • mAutoframingOverride::camera_metadata_enum_android_control_autoframing:dumpsys media.camera Debug使用,强制设置Autoframing Mode;
  • mActivePhysicalId::std::string:如果当前使用的是Logical Multicam的情况,记录目前正在使用的Physical Camera ID;
  • mInjectionMethods::sp:Inject Camera时使用;

5.14 Camera3Device初始化

Camera API2 Open
在这里插入图片描述
CameraAPP调用CameraManager的openCamera方法,调用到CameraService的connectDevice,然后创建CameraDeviceClient,在Camera2ClientBase的initializeImpl中创建AidlCamera3Device,然后在AidlCamera3Device的initialize方法中调用CameraProviderManager的openAidlSession方法,进而通过ICameraDevice的open方法调用到HAL去执行openCamera动作。

AidlCamera3Device::initialize()
在这里插入图片描述

  • 创建Session:与HAL交互打开Camera;
  • CAMERA CHARACTERISTICS:获取静态Metadata,判断是否支持mSupportNativeZoomRatio、mIsCompositeJpegRDisabled;
  • LOGICAL MULTI-CAMERA CONFIGURATION:如果是LogicalMulticam,则对mPhysicalDeviceInfoMap、mDistortionMappers、mZoomRatioMappers、mUHRCropAndMeteringRegionMappers进行相应的赋值;
  • METADATA QUEUES:初始化MetadataQueue,MetadataQueue包含request和result,通过FMQ (Fast Message Queue) 用共享内存的方式来传递CaptureRequest和CaptureResultMetadataBuffer,共享内存更快,不能用IPC机制拷贝,太慢了;

Camera3Device::initializeCommonLocked()
在这里插入图片描述
CameraDevice线程管理:

  • StatusTracker:监控request状态和device状态;
  • RequestThread:送request,包括从里面拿buffer,比如bufferqueue没有buffer,再去获取buffer就会被block;
  • PreparerThread:送request之前把某一路buffer,提前Preparer出来,能优化整个性能;
  • CameraServiceWatchdog:监控cameraDevice;

网站公告

今日签到

点亮在社区的每一天
去签到