始于谷歌的Treble开源项目,基于接口与实现的分离的设计原则,谷歌加入了Camera Provider这一抽象层,该层作为一个独立进程存在于整个系统中,并且通过HIDL这一自定义语言成功地将Camera Hal Module从Camera Service中解耦出来,承担起了对Camera HAL的封装工作,纵观整个Android系统,对于Camera Provider而言,对上是通过HIDL接口负责与Camera Service的跨进程通信,对下通过标准的HAL3接口下发针对Camera的实际操作,这俨然是一个中央枢纽般的调配中心的角色,而事实上正是如此,由此看来,对Camera Provider的梳理变得尤为重要,接下来就以我个人理解出发来简单介绍下Camera Provider。
Camera Provider通过提供标准的HIDL接口给Camera Service进行调用,保持与Service的正常通信,其中谷歌将HIDL接口的定义直接暴露给平台厂商进行自定义实现,其中为了极大地减轻并降低开发者的工作量和开发难度,谷歌很好地封装了其跨进程实现细节,同样地,Camera Provider通过标准的HAL3接口,向下控制着具体的Camera HAL Module,而这个接口依然交由平台厂商负责去实现,而进程内部则通过简单的函数调用,将HIDL接口与HAL3接口完美的衔接起来,由此构成了Provider整体架构。
/** * setCallback: * Provide a callback interface to the HAL provider to inform framework of * asynchronous camera events. The framework must call this function once * during camera service startup, before any other calls to the provider * (note that in case the camera service restarts, this method must be * invoked again during its startup). */ setCallback(ICameraProviderCallback callback) generates (Status status);
/** * getVendorTags: * Retrieve all vendor tags supported by devices discoverable through this * provider. The tags are grouped into sections. */ getVendorTags() generates (Status status, vec<VendorTagSection> sections);
/** * getCameraIdList: * Returns the list of internal camera device interfaces known to this * camera provider. These devices can then be accessed via the hardware * service manager. */ getCameraIdList() generates (Status status, vec<string> cameraDeviceNames);
/** * isSetTorchModeSupported: * Returns if the camera devices known to this camera provider support * setTorchMode API or not. If the provider does not support setTorchMode * API, calling to setTorchMode will return METHOD_NOT_SUPPORTED. */ isSetTorchModeSupported() generates (Status status, bool support);
/** * getCameraDeviceInterface_VN_x: * Return a android.hardware.camera.device@N.x/ICameraDevice interface for * the requested device name. This does not power on the camera device, but * simply acquires the interface for querying the device static information, * or to additionally open the device for active use. * * A separate method is required for each major revision of the camera device * HAL interface, since they are not compatible with each other. * * Valid device names for this provider can be obtained via either * getCameraIdList(), or via availability callbacks from * ICameraProviderCallback::cameraDeviceStatusChange(). */ getCameraDeviceInterface_V1_x(string cameraDeviceName) generates (Status status, android.hardware.camera.device@1.0::ICameraDevice device); getCameraDeviceInterface_V3_x(string cameraDeviceName) generates (Status status, android.hardware.camera.device@3.2::ICameraDevice device);
/** * cameraDeviceStatusChange: * * Callback to the camera service to indicate that the state of a specific * camera device has changed. * * On camera service startup, when ICameraProvider::setCallback is invoked, * the camera service must assume that all internal camera devices are in * the CAMERA_DEVICE_STATUS_PRESENT state. * * The provider must call this method to inform the camera service of any * initially NOT_PRESENT devices, and of any external camera devices that * are already present, as soon as the callbacks are available through * setCallback. */ cameraDeviceStatusChange(string cameraDeviceName, CameraDeviceStatus newStatus);
/** * torchModeStatusChange: * * Callback to the camera service to indicate that the state of the torch * mode of the flash unit associated with a specific camera device has * changed. At provider registration time, the camera service must assume * the torch modes are in the TORCH_MODE_STATUS_AVAILABLE_OFF state if * android.flash.info.available is reported as true via the * ICameraDevice::getCameraCharacteristics call. */ torchModeStatusChange(string cameraDeviceName, TorchModeStatus newStatus);
};
该文件中定义了ICameraProviderCallback回调接口类,该接口由Camera Service 中的CameraProviderManager::ProviderInfo继承并实现,在Camera Service 启动的时候被实例化,通过调用ICameraProvider::setCallback接口注册到Camera Provider中,其主要接口如下:
interface ICameraDevice { /** * Get camera device resource cost information. */ getResourceCost() generates (Status status, CameraResourceCost resourceCost);
/** * getCameraCharacteristics: * Return the static camera information for this camera device. This * information may not change between consecutive calls. */ getCameraCharacteristics() generates (Status status, CameraMetadata cameraCharacteristics);
/** * setTorchMode: * Turn on or off the torch mode of the flash unit associated with this * camera device. If the operation is successful, HAL must notify the * framework torch state by invoking * ICameraProviderCallback::torchModeStatusChange() with the new state. */ setTorchMode(TorchMode mode) generates (Status status);
/** * open: * Power on and initialize this camera device for active use, returning a * session handle for active operations. */ open(ICameraDeviceCallback callback) generates (Status status, ICameraDeviceSession session); dumpState(handle fd);
/** * processCaptureResult: * * Send results from one or more completed or partially completed captures * to the framework. * processCaptureResult() may be invoked multiple times by the HAL in * response to a single capture request. This allows, for example, the * metadata and low-resolution buffers to be returned in one call, and * post-processed JPEG buffers in a later call, once it is available. Each * call must include the frame number of the request it is returning * metadata or buffers for. Only one call to processCaptureResult * may be made at a time by the HAL although the calls may come from * different threads in the HAL. * * A component (buffer or metadata) of the complete result may only be * included in one process_capture_result call. A buffer for each stream, * and the result metadata, must be returned by the HAL for each request in * one of the processCaptureResult calls, even in case of errors producing * some of the output. A call to processCaptureResult() with neither * output buffers or result metadata is not allowed. * * The order of returning metadata and buffers for a single result does not * matter, but buffers for a given stream must be returned in FIFO order. So * the buffer for request 5 for stream A must always be returned before the * buffer for request 6 for stream A. This also applies to the result * metadata; the metadata for request 5 must be returned before the metadata * for request 6. */ processCaptureResult(vec<CaptureResult> results);
/** * notify: * Asynchronous notification callback from the HAL, fired for various * reasons. Only for information independent of frame capture, or that * require specific timing. Multiple messages may be sent in one call; a * message with a higher index must be considered to have occurred after a * message with a lower index. */ notify(vec<NotifyMsg> msgs);
/** * Camera device active session interface. * * Obtained via ICameraDevice::open(), this interface contains the methods to * configure and request captures from an active camera device. * */ interface ICameraDeviceSession extends @3.2::ICameraDeviceSession {
/** * configureStreams_3_3: * * Identical to @3.2::ICameraDeviceSession.configureStreams, except that: * * - The output HalStreamConfiguration now contains an overrideDataspace * field, to be used by the HAL to select a different dataspace for some * use cases when dealing with the IMPLEMENTATION_DEFINED pixel format. * * Clients may invoke either this method or * @3.2::ICameraDeviceSession.configureStreams() for stream configuration. * This method is recommended for clients to use since it provides more * flexibility. */ configureStreams_3_3(StreamConfiguration requestedConfiguration) generates (Status status, @3.3::HalStreamConfiguration halConfiguration);
/** * Camera device active session interface. * Obtained via ICameraDevice::open(), this interface contains the methods to * configure and request captures from an active camera device. * */ interface ICameraDeviceSession {
/** * constructDefaultRequestSettings: * Create capture settings for standard camera use cases. */ constructDefaultRequestSettings(RequestTemplate type) generates (Status status, CameraMetadata requestTemplate);
/** * configureStreams: * Reset the HAL camera device processing pipeline and set up new input and * output streams. This call replaces any existing stream configuration with * the streams defined in the streamList. This method must be called at * least once before a request is submitted with processCaptureRequest(). */ configureStreams(StreamConfiguration requestedConfiguration) generates (Status status, HalStreamConfiguration halConfiguration);
/** * processCaptureRequest: * Send a list of capture requests to the HAL. The HAL must not return from * this call until it is ready to accept the next set of requests to * process. Only one call to processCaptureRequest() must be made at a time * by the framework, and the calls must all be from the same thread. The * next call to processCaptureRequest() must be made as soon as a new * request and its associated buffers are available. In a normal preview * scenario, this means the function is generally called again by the * framework almost instantly. If more than one request is provided by the * client, the HAL must process the requests in order of lowest index to * highest index. */ processCaptureRequest(vec<CaptureRequest> requests, vec<BufferCache> cachesToRemove) generates (Status status, uint32_t numRequestProcessed);
/** * getCaptureRequestMetadataQueue: * Retrieves the queue used along with processCaptureRequest. If * client decides to use fast message queue to pass request metadata, */ getCaptureRequestMetadataQueue() generates (fmq_sync<uint8_t> queue);
/** * getCaptureResultMetadataQueue: * Retrieves the queue used along with * ICameraDeviceCallback.processCaptureResult. */ getCaptureResultMetadataQueue() generates (fmq_sync<uint8_t> queue);
/** * flush: * Flush all currently in-process captures and all buffers in the pipeline * on the given device. Generally, this method is used to dump all state as * quickly as possible in order to prepare for a configure_streams() call. */ flush() generates (Status status);
/** * close: * Shut down the camera device. */ close(); };
F:\Khadas_Edge_Android_Q\hardware\interfaces\camera\provider\2.4\default\android.hardware.camera.provider@2.4-service_64.rc service vendor.camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service class hal user cameraserver group audio camera input drmrpc ioprio rt 4 capabilities SYS_NICE writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
在android启动的过程中,init进程调用该脚本启动 camera provider 服务。根据该目录下的 Android.bp 可以知道,其实就是运行该目录下 service.cpp 编译的可执行文件,service.cpp 内容如下:
intmain() { ALOGI("CameraProvider@2.4 legacy service is starting."); // The camera HAL may communicate to other vendor components via // /dev/vndbinder android::ProcessState::initWithDriver("/dev/vndbinder"); status_t status; if (kLazyService) { status = defaultLazyPassthroughServiceImplementation<ICameraProvider>("legacy/0", /*maxThreads*/6); } else { status = defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0", /*maxThreads*/6); } return status; }
根据以上代码可以得知:
android::ProcessState::initWithDriver :camera HAL 通过 /dev/vndbinder 驱动可与其他模块的HAL进行通信
sp<IBase> base = getRawServiceInternal(IType::descriptor, instance, retry, getStub); ...... if (base->isRemote()) { // getRawServiceInternal guarantees we get the proper class return sp<IType>(new BpType(getOrCreateCachedBinder(base.get()))); }
/* 执行 HIDL_FETCH_ICameraProvider() 函数,该函数返回CameraProvider实例对象保存在ret, * 所以get()函数将返回 ret * */ ret = (*generator)(name.c_str());
if (ret == nullptr) { dlclose(handle); returntrue; // this module doesn't provide this instance name }
// Actual fqname might be a subclass. // This assumption is tested in vts_treble_vintf_test using ::android::hardware::details::getDescriptor; std::string actualFqName = getDescriptor(ret.get()); CHECK(actualFqName.size() > 0); registerReference(actualFqName, name); returnfalse; });
ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
// Setup vendor tags here so HAL can setup vendor keys in camera characteristics VendorTagDescriptor::clearGlobalVendorTagDescriptor(); if (!setUpVendorTags()) { ALOGE("%s: Vendor tag setup failed, will not be available.", __FUNCTION__); }
// Setup callback now because we are going to try openLegacy next err = mModule->setCallbacks(this); ...... mNumberOfLegacyCameras = mModule->getNumberOfCameras(); /* 将获取camera信息并保存,其中将有HAL version 信息,应用 * 层将会检查HAL层版本信息从而确认调用不同的API实现相机应用 */ for (int i = 0; i < mNumberOfLegacyCameras; i++) { structcamera_infoinfo; auto rc = mModule->getCameraInfo(i, &info); ...... char cameraId[kMaxCameraIdLen]; snprintf(cameraId, sizeof(cameraId), "%d", i); std::stringcameraIdStr(cameraId); mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;
addDeviceNames(i); }
returnfalse; // mInitFailed } F:\Khadas_Edge_Android_Q\hardware\interfaces\camera\common\1.0\default\CameraModule.cpp CameraModule::CameraModule(camera_module_t *module) : mNumberOfCameras(0) { if (module == NULL) { ALOGE("%s: camera hardware module must not be null", __FUNCTION__); assert(0); } mModule = module; }
intCameraModule::init(){ ATRACE_CALL(); int res = OK; if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 && mModule->init != NULL) { ATRACE_BEGIN("camera_module->init"); res = mModule->init(); ATRACE_END(); } mNumberOfCameras = getNumberOfCameras(); mCameraInfoMap.setCapacity(mNumberOfCameras); return res; }
01-18 08:50:15.868 264 264 I CamPrvdr@2.4-legacy: Loaded “Rockchip Camera3HAL Module” camera module
至此,已获得CameraProvider实例对象,最终返回赋值给 registerPassthroughServiceImplementation() 函数中的 service 。
在系统初始化的时候,系统会去运行android.hardware.camera.provider@2.4-service程序启动Provider进程,并加入HW Service Manager中接受统一管理,在该过程中实例化了一个LegacyCameraProviderImpl_2_4对象,并在其构造函数中通过hw_get_module标准方法获取HAL的camera_module_t结构体,并将其存入CameraModule对象中,之后通过调用该camera_modult_t结构体的init方法初始化HAL Module,紧接着调用其get_number_of_camera方法获取当前HAL支持的Camera数量,最后通过调用其set_callbacks方法将LegcyCameraProviderImpl_2_4(LegcyCameraProviderImpl_2_4继承了camera_modult_callback_t)作为参数传入camera.rk30board.so中,接受来自camera.rk30board.so中的数据以及事件,当这一系列动作完成了之后,Camera Provider进程便一直便存在于系统中,监听着来自Camera Service的调用。
接下来以上图为例简单介绍下Provider中几个重要流程:
Camera Service通过调用ICameraProvider的getCameraDeviceInterface_v3_x接口获取ICameraDevice,在此过程中,Provider会去实例化一个CameraDevice对象,并且将之前存有camera_modult_t结构体的CameraModule对象传入CameraDevice中,这样就可以在CameraDevice内部通过CameraModule访问到camera_module_t的相关资源,然后将CameraDevice内部类TrampolineSessionInterface_3_3(该类继承并实现了ICameraDevice接口)返回给Camera Service。
Camera Service通过之前获取的ICameraDevice,调用其open方法来打开Camera设备,接着在Provider中会去调用CameraDevice对象的open方法,在该方法内部会去调用camera_module_t结构体的open方法,从而获取到HAL部分的camera3_device_t结构体,紧接着Provider会实例化一个CameraDeviceSession对象,并且将刚才获取到的camera3_device_t结构体以参数的方式传入CameraDeviceSession中,在CameraDeviceSession的构造方法中又会调用CameraDeviceSession的initialize方法,在该方法内部又会去调用camera3_device_t结构体的ops内的initialize方法开始HAL部分的初始化工作,最后CameraDeviceSession对象被作为camera3_callback_ops的实现传入HAL,接收来自HAL的数据或者具体事件,当一切动作都完成后,Provider会将CameraDeviceSession::TrampolineDeviceInterface_3_2(该类继承并实现了ICameraDeviceSession接口)对象通过HIDL回调的方法返回给Camera Service中。
Camera Service通过调用ICameraDevcieSession的configureStreams_3_3接口进行数据流的配置,在Provider中,最终会通过调用之前获取的camera3_device_t结构体内ops的configure_streams方法下发到HAL中进行处理。
Camera Service通过调用ICameraDevcieSession的processCaptureRequest接口下发request请求到Provider中,在Provider中,最终依然会通过调用获取的camera3_device_t结构体内ops中的process_capture_request方法将此次请求下发到HAL中进行处理。
F:\Khadas_Edge_Android_Q\hardware\libhardware\include\hardware\hardware.h typedefstructhw_module_t { /** tag must be initialized to HARDWARE_MODULE_TAG */ uint32_t tag; /** * The API version of the implemented module. The module owner is * responsible for updating the version when a module interface has * changed. */ uint16_t module_api_version; #define version_major module_api_version uint16_t hal_api_version; #define version_minor hal_api_version
/** Identifier of module */ constchar *id;
/** Name of this module */ constchar *name;
/** Author/owner/implementor of the module */ constchar *author;
#ifdef __LP64__ uint64_t reserved[32-7]; #else /** padding to 128 bytes, reserved for future use */ uint32_t reserved[32-7]; #endif
} hw_module_t;
typedefstructhw_module_methods_t { /** Open a specific device */ int (*open)(const struct hw_module_t* module, constchar* id, struct hw_device_t** device);
F:\Khadas_Edge_Android_Q\hardware\libhardware\include\hardware\camera_common.h typedefstructcamera_module { /** * Common methods of the camera module. This *must* be the first member of * camera_module as users of this structure will cast a hw_module_t to * camera_module pointer in contexts where it's known the hw_module_t * references a camera_module. */ hw_module_t common;
/** * get_number_of_cameras: * Returns the number of camera devices accessible through the camera * module. The camera devices are numbered 0 through N-1, where N is the * value returned by this call. The name of the camera device for open() is * simply the number converted to a string. That is, "0" for camera ID 0, * "1" for camera ID 1. */ int (*get_number_of_cameras)(void);
/** * get_camera_info: * Return the static camera information for a given camera device. This * information may not change for a camera device. */ int (*get_camera_info)(int camera_id, struct camera_info *info);
/** * set_callbacks: * Provide callback function pointers to the HAL module to inform framework * of asynchronous camera module events. The framework will call this * function once after initial camera HAL module load, after the * get_number_of_cameras() method is called for the first time, and before * any other calls to the module. */ int (*set_callbacks)(constcamera_module_callbacks_t *callbacks);
/** * get_vendor_tag_ops: * Get methods to query for vendor extension metadata tag information. The * HAL should fill in all the vendor tag operation methods, or leave ops * unchanged if no vendor tags are defined. */ void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
/** * open_legacy: * Open a specific legacy camera HAL device if multiple device HAL API * versions are supported by this camera HAL module. For example, if the * camera module supports both CAMERA_DEVICE_API_VERSION_1_0 and * CAMERA_DEVICE_API_VERSION_3_2 device API for the same camera id, * framework can call this function to open the camera device as * CAMERA_DEVICE_API_VERSION_1_0 device. */ int (*open_legacy)(const struct hw_module_t* module, constchar* id, uint32_t halVersion, struct hw_device_t** device);
/** * set_torch_mode: * Turn on or off the torch mode of the flash unit associated with a given * camera ID. If the operation is successful, HAL must notify the framework * torch state by invoking * camera_module_callbacks.torch_mode_status_change() with the new state. */ int (*set_torch_mode)(constchar* camera_id, bool enabled);
/** * init: * This method is called by the camera service before any other methods * are invoked, right after the camera HAL library has been successfully * loaded. It may be left as NULL by the HAL module, if no initialization * in needed. */ int (*init)();
/** * get_physical_camera_info: * Return the static metadata for a physical camera as a part of a logical * camera device. This function is only called for those physical camera * ID(s) that are not exposed independently. In other words, camera_id will * be greater or equal to the return value of get_number_of_cameras(). */ int (*get_physical_camera_info)(int physical_camera_id, camera_metadata_t **static_metadata);
/** * is_stream_combination_supported: * Check for device support of specific camera stream combination. */ int (*is_stream_combination_supported)(int camera_id, constcamera_stream_combination_t *streams);
/** * notify_device_state_change: * * Notify the camera module that the state of the overall device has * changed in some way that the HAL may want to know about. */ void (*notify_device_state_change)(uint64_t deviceState);
/* reserved for future use */ void* reserved[2]; } camera_module_t;
F:\Khadas_Edge_Android_Q\hardware\libhardware\include\hardware\camera3.h typedefstructcamera3_stream_configuration { /** * The total number of streams requested by the framework. This includes * both input and output streams. The number of streams will be at least 1, * and there will be at least one output-capable stream. */ uint32_t num_streams;
/** * An array of camera stream pointers, defining the input/output * configuration for the camera HAL device. * * At most one input-capable stream may be defined (INPUT or BIDIRECTIONAL) * in a single configuration. * * At least one output-capable stream must be defined (OUTPUT or * BIDIRECTIONAL). */ camera3_stream_t **streams;
/** * >= CAMERA_DEVICE_API_VERSION_3_3: * * The operation mode of streams in this configuration, one of the value * defined in camera3_stream_configuration_mode_t. The HAL can use this * mode as an indicator to set the stream property (e.g., * camera3_stream->max_buffers) appropriately. For example, if the * configuration is * CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE, the HAL may * want to set aside more buffers for batch mode operation (see * android.control.availableHighSpeedVideoConfigurations for batch mode * definition). * */ uint32_t operation_mode;
/** * >= CAMERA_DEVICE_API_VERSION_3_5: * * The session metadata buffer contains the initial values of * ANDROID_REQUEST_AVAILABLE_SESSION_KEYS. This field is optional * and camera clients can choose to ignore it, in which case it will * be set to NULL. If parameters are present, then Hal should examine * the parameter values and configure its internal camera pipeline * accordingly. */ constcamera_metadata_t *session_parameters; } camera3_stream_configuration_t;
/***** * Set by framework before configure_streams() */
/** * The type of the stream, one of the camera3_stream_type_t values. */ int stream_type;
/** * The width in pixels of the buffers in this stream */ uint32_t width;
/** * The height in pixels of the buffers in this stream */ uint32_t height;
/** * The pixel format for the buffers in this stream. Format is a value from * the HAL_PIXEL_FORMAT_* list in system/core/include/system/graphics.h, or * from device-specific headers. */ int format;
/***** * Set by HAL during configure_streams(). */
/** * The gralloc usage flags for this stream, as needed by the HAL. The usage * flags are defined in gralloc.h (GRALLOC_USAGE_*), or in device-specific * headers. */ uint32_t usage;
/** * The maximum number of buffers the HAL device may need to have dequeued at * the same time. The HAL device may not have more buffers in-flight from * this stream than this value. */ uint32_t max_buffers;
/** * A handle to HAL-private information for the stream. Will not be inspected * by the framework code. */ void *priv;
/** * A field that describes the contents of the buffer. The format and buffer * dimensions define the memory layout and structure of the stream buffers, * while dataSpace defines the meaning of the data within the buffer. */ android_dataspace_t data_space;
int rotation;
/** * The physical camera id this stream belongs to. */ constchar* physical_camera_id;
typedefstructcamera3_stream_buffer { /** * The handle of the stream this buffer is associated with */ camera3_stream_t *stream;
/** * The native handle to the buffer */ buffer_handle_t *buffer;
/** * Current state of the buffer, one of the camera3_buffer_status_t * values. The framework will not pass buffers to the HAL that are in an * error state. In case a buffer could not be filled by the HAL, it must * have its status set to CAMERA3_BUFFER_STATUS_ERROR when returned to the * framework with process_capture_result(). */ int status;
/** * The acquire sync fence for this buffer. The HAL must wait on this fence * fd before attempting to read from or write to this buffer. */ int acquire_fence;
/** * The release sync fence for this buffer. The HAL must set this fence when * returning buffers to the framework, or write -1 to indicate that no * waiting is required for this buffer. */ int release_fence;
/** * initialize: * One-time initialization to pass framework callback function pointers to * the HAL. Will be called once after a successful open() call, before any * other functions are called on the camera3_device_ops structure. */ int (*initialize)(const struct camera3_device *, constcamera3_callback_ops_t *callback_ops);
/** * configure_streams: * * CAMERA_DEVICE_API_VERSION_3_0 only: * * Reset the HAL camera device processing pipeline and set up new input and * output streams. This call replaces any existing stream configuration with * the streams defined in the stream_list. This method will be called at * least once after initialize() before a request is submitted with * process_capture_request(). */ int (*configure_streams)(const struct camera3_device *, camera3_stream_configuration_t *stream_list);
/********************************************************************** * Request creation and submission */
/** * construct_default_request_settings: * * Create capture settings for standard camera use cases. * * The device must return a settings buffer that is configured to meet the * requested use case, which must be one of the CAMERA3_TEMPLATE_* * enums. All request control fields must be included. */ constcamera_metadata_t* (*construct_default_request_settings)( const struct camera3_device *, int type);
/** * process_capture_request: * * Send a new capture request to the HAL. The HAL should not return from * this call until it is ready to accept the next request to process. Only * one call to process_capture_request() will be made at a time by the * framework, and the calls will all be from the same thread. The next call * to process_capture_request() will be made as soon as a new request and * its associated buffers are available. In a normal preview scenario, this * means the function will be called again by the framework almost * instantly. */ int (*process_capture_request)(const struct camera3_device *, camera3_capture_request_t *request);
/** * get_metadata_vendor_tag_ops: * Get methods to query for vendor extension metadata tag information. The * HAL should fill in all the vendor tag operation methods, or leave ops * unchanged if no vendor tags are defined. */ void (*get_metadata_vendor_tag_ops)(const struct camera3_device*, vendor_tag_query_ops_t* ops);
void (*dump)(const struct camera3_device *, int fd);
a) initialize 该方法必须在camera_module_t中的open方法之后,其它camera3_device_ops中方法之前被调用,主要用来将上层实现的回调方法注册到HAL中,并且根据需要在该方法中加入自定义的一些初始化操作,另外,谷歌针对该方法在性能方面也有严格的限制,该方法需要在5ms内返回,最长不能超过10ms。
b) configure_streams 该方法在完成initialize方法之后,在调用process_capture_request方法之前被调用,主要用于重设当前正在运行的Pipeline以及设置新的输入输出流,其中它会将stream_list中的新的数据流替换之前配置的数据流。在调用该方法之前必须确保没有新的request下发并且当前request的动作已经完成,否则会引起无法预测的错误。一旦HAL调用了该方法,则必须在内部配置好满足当前数据流配置的帧率,确保这个流程的运行的顺畅性。 其中包含了两个参数,分别是camera3_device以及stream_list(camera3_stream_configuration_t ),其中第二个参数是上层传入的数据流配置列表,该列表中必须包含至少一个output stream,同时至多包含一个input stream。 另外,谷歌针对该方法有着严格的性能要求,平台厂商在实现该方法的时候,需要在500ms内返回,最长不能超过1000ms。
c) construct_default_request_settings 该方法主要用于构建一系列默认的Camera Usecase的capture 设置项,通过camera_metadata_t来进行描述,其中返回值是一个camera_metadata_t指针,其指向的内存地址是由HAL来进行维护的,同样地,该方法需要在1ms内返回,最长不能超过5ms。
/** * process_capture_result: * * Send results from a completed capture to the framework. * process_capture_result() may be invoked multiple times by the HAL in * response to a single capture request. This allows, for example, the * metadata and low-resolution buffers to be returned in one call, and * post-processed JPEG buffers in a later call, once it is available. Each * call must include the frame number of the request it is returning * metadata or buffers for. */ void (*process_capture_result)(const struct camera3_callback_ops *, constcamera3_capture_result_t *result);
/** * notify: * * Asynchronous notification callback from the HAL, fired for various * reasons. Only for information independent of frame capture, or that * require specific timing. The ownership of the message structure remains * with the HAL, and the msg only needs to be valid for the duration of this * call. */ void (*notify)(const struct camera3_callback_ops *, constcamera3_notify_msg_t *msg);
谷歌为了将系统框架和平台厂商的自定义部分相分离,在Android上推出了Treble项目,该项目直接将平台厂商的实现部分放入vendor分区中进行管理,进而与system分区保持隔离,这样便可以在相互独立的空间中进行各自的迭代升级,而互不干扰,而在相机框架体系中,便将Camera HAL Module从Camera Service中解耦出来,放入独立进程Camera Provider中进行管理,而为了更好的进行跨进程访问,谷歌针对Provider提出了HIDL机制用于Camera Servic对于Camera Provier的访问,而HIDL接口的实现是在Camera Provider中实现,针对Camera HAL Module的控制又是通过谷歌制定的Camera HAL3接口来完成,所以由此看来,Provider的职责也比较简单,通过HIDL机制保持与Camera Service的通信,通过HAL3接口控制着Camera HAL Module。
(四)、Camera Service启动流程概览
系统启动时,就会启动 CameraProvider 服务。它将 Camera HAL 从 cameraserver 进程中分离出来,作为一个独立进程 android.hardware.camera.provider@2.4-service 来控制 HAL。 这两个进程之间通过 HIDL 机制进行通信。它的主要功能(如下图所示)是将 service 与 HAL 隔离,以方便 HAL 部分进行独立升级。这其实和 APP 与 Framework 之间的 Binder 机制类似,通过引入一个进程间通信机制而针对不同层级进行解耦(从 Local call 变成了 Remote call)。
// Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls in // addition to consuming them from the Camera HAL as well. hardware::configureRpcThreadpool(5, /*willjoin*/false);
F:\Khadas_Edge_Android_Q\frameworks\av\services\camera\libcameraservice\CameraService.cpp voidCameraService::onFirstRef() { ALOGI("CameraService process starting");
BnCameraService::onFirstRef();
// Update battery life tracking if service is restarting BatteryNotifier& notifier(BatteryNotifier::getInstance()); notifier.noteResetCamera(); notifier.noteResetFlashlight();
status_t res = INVALID_OPERATION;
res = enumerateProviders(); if (res == OK) { mInitialized = true; }
mUidPolicy = new UidPolicy(this); mUidPolicy->registerSelf(); mSensorPrivacyPolicy = new SensorPrivacyPolicy(this); mSensorPrivacyPolicy->registerSelf(); sp<HidlCameraService> hcs = HidlCameraService::getInstance(this); if (hcs->registerAsService() != android::OK) { ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0", __FUNCTION__); }
// This needs to be last call in this function, so that it's as close to // ServiceManager::addService() as possible. CameraService::pingCameraServiceProxy(); ALOGI("CameraService pinged cameraservice proxy"); }
if (nullptr == mCameraProviderManager.get()) { mCameraProviderManager = new CameraProviderManager(); res = mCameraProviderManager->initialize(this); if (res != OK) { ALOGE("%s: Unable to initialize camera provider manager: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } }
// Setup vendor tags before we call get_camera_info the first time // because HAL might need to setup static vendor keys in get_camera_info // TODO: maybe put this into CameraProviderManager::initialize()? mCameraProviderManager->setUpVendorTags();
if (nullptr == mFlashlight.get()) { mFlashlight = new CameraFlashlight(mCameraProviderManager, this); }
res = mFlashlight->findFlashUnits(); if (res != OK) { ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res); } //遍历mProviders deviceIds = mCameraProviderManager->getCameraDeviceIds(); }
for (auto& cameraId : deviceIds) { String8 id8 = String8(cameraId.c_str()); if (getCameraState(id8) == nullptr) { onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT); } }
return OK; }
首先将 CameraProviderManager 实例化,然后调用 initialize() 接口将其初始化,传入的参数是 this 指针,指向当前 CameraService 实例的地址。
// Registering will trigger notifications for all already-known providers bool success = mServiceProxy->registerForNotifications( /* instance name, empty means no filter */"", this); ......
for (constauto& instance : mServiceProxy->listServices()) { this->addProviderLocked(instance); }
IPCThreadState::self()->flushCommands();
return OK; } status_tCameraProviderManager::addProviderLocked(conststd::string& newProvider){ for (constauto& providerInfo : mProviders) { //检查已知的 Provider 中是否已有名为 `legacy/0` 的。 if (providerInfo->mProviderName == newProvider) { ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__, newProvider.c_str()); return ALREADY_EXISTS; } }
status_t CameraProviderManager::ProviderInfo::initialize( sp<provider::V2_4::ICameraProvider>& interface, hardware::hidl_bitfield<provider::V2_5::DeviceState> currentDeviceState) { status_t res = parseProviderName(mProviderName, &mType, &mId); ...... ALOGI("Connecting to new camera provider: %s, isRemote? %d", mProviderName.c_str(), interface->isRemote());
// Determine minor version auto castResult = provider::V2_5::ICameraProvider::castFrom(interface); if (castResult.isOk()) { mMinorVersion = 5; } else { mMinorVersion = 4; }
// cameraDeviceStatusChange callbacks may be called (and causing new devices added) // before setCallback returns hardware::Return<Status> status = interface->setCallback(this);
status_t CameraProviderManager::ProviderInfo::addDevice(conststd::string& name, CameraDeviceStatus initialStatus, /*out*/std::string* parsedId) { //CameraProviderManager: Enumerating new camera device: device@3.3/legacy/0 ALOGI("Enumerating new camera device: %s", name.c_str());
uint16_t major, minor; std::string type, id;
status_t res = parseDeviceName(name, &major, &minor, &type, &id); ......
...... // ICameraDevice 3.2 and 3.3 // Since some Treble HAL revisions can map to the same legacy HAL version(s), we default // to the newest possible Treble HAL revision, but allow for override if needed via // system property. switch (mPreferredHal3MinorVersion) { ...... case3: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.3 ALOGV("Constructing v3.3 camera device"); deviceImpl = new android::hardware::camera::device::V3_3::implementation::CameraDevice( mModule, cameraId, mCameraDeviceNames); .. break; } ...... }
//01-18 08:50:15.089 258 258 I CamPrvdr@2.4-legacy: Loaded "Rockchip Camera3HAL Module" camera module //01-18 08:50:15.091 258 258 V CamPrvdr@2.4-legacy: Preferred HAL 3 minor version is 3 //01-18 08:50:15.113 258 435 I CamPrvdr@2.4-legacy: LegacyCameraProviderImpl_2_4 getCameraDeviceInterface_V3_x //01-18 08:50:15.113 258 435 V CamPrvdr@2.4-legacy: Constructing v3.3 camera device
CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(conststd::string& name, constmetadata_vendor_id_t tagId, conststd::string &id, uint16_t minorVersion, const CameraResourceCost& resourceCost, sp<ProviderInfo> parentProvider, conststd::vector<std::string>& publicCameraIds, sp<InterfaceT> interface) : DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion}, publicCameraIds, resourceCost, parentProvider) { // Get camera characteristics and initialize flash unit availability Status status; hardware::Return<void> ret; ret = interface->getCameraCharacteristics([&status, this](Status s, device::V3_2::CameraMetadata metadata) { status = s; if (s == Status::OK) { camera_metadata_t *buffer = reinterpret_cast<camera_metadata_t*>(metadata.data()); size_t expectedSize = metadata.size(); int res = validate_camera_metadata_structure(buffer, &expectedSize); if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) { set_camera_metadata_vendor_id(buffer, mProviderTagid); mCameraCharacteristics = buffer; } else { ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__); status = Status::INTERNAL_ERROR; } } }); ...... mIsPublicallyHiddenSecureCamera = isPublicallyHiddenSecureCamera(); status_t res = fixupMonochromeTags(); ...... auto stat = addDynamicDepthTags(); ...... res = deriveHeicTags(); ...... camera_metadata_entry flashAvailable = mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE); ...... queryPhysicalCameraIds(); ...... if (mIsLogicalCamera) { for (auto& id : mPhysicalIds) { if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) != mPublicCameraIds.end()) { continue; }
hardware::hidl_string hidlId(id); ret = interface_3_5->getPhysicalCameraCharacteristics(hidlId, [&status, &id, this](Status s, device::V3_2::CameraMetadata metadata) { status = s; if (s == Status::OK) { camera_metadata_t *buffer = reinterpret_cast<camera_metadata_t*>(metadata.data()); size_t expectedSize = metadata.size(); int res = validate_camera_metadata_structure(buffer, &expectedSize); if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) { set_camera_metadata_vendor_id(buffer, mProviderTagid); mPhysicalCameraCharacteristics[id] = buffer; } ....... } }); ....... } }
if (!kEnableLazyHal) { // Save HAL reference indefinitely mSavedInterface = interface; } } //sp<InterfaceT> interface) : // DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion}, // publicCameraIds, resourceCost, parentProvider)
F:\Khadas_Edge_Android_Q\frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.h // Standard use case - call into the normal generated static methods which invoke // the real hardware service manager structHardwareServiceInteractionProxy :public ServiceInteractionProxy { virtualboolregisterForNotifications( conststd::string &serviceName, const sp<hidl::manager::V1_0::IServiceNotification> ¬ification)override{ return hardware::camera::provider::V2_4::ICameraProvider::registerForNotifications( serviceName, notification); } virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService( conststd::string &serviceName)override{ return hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName); }
F:\Khadas_Edge_Android_Q\system\libhidl\transport\ServiceManagement.cpp sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(conststd::string& descriptor, conststd::string& instance, bool retry, bool getStub){ using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport; using ::android::hidl::manager::V1_0::IServiceManager; sp<Waiter> waiter;
sp<IServiceManager1_1> sm; Transport transport = Transport::EMPTY; if (kIsRecovery) { transport = Transport::PASSTHROUGH; } else { sm = defaultServiceManager1_1(); ...... Return<Transport> transportRet = sm->getTransport(descriptor, instance); ...... transport = transportRet; }
for (int tries = 0; !getStub && (vintfHwbinder || vintfLegacy); tries++) { ...... //查询ICameraProvider这个hidl服务,得到IBase对象 Return<sp<IBase>> ret = sm->get(descriptor, instance); ...... sp<IBase> base = ret; if (base != nullptr) { Return<bool> canCastRet = details::canCastInterface(base.get(), descriptor.c_str(), true/* emitError */);
if (canCastRet.isOk() && canCastRet) { if (waiter != nullptr) { waiter->done(); } return base; // still needs to be wrapped by Bp class. }
if (!handleCastError(canCastRet, descriptor, instance)) break; }
...... } ...... if (getStub || vintfPassthru || vintfLegacy) { const sp<IServiceManager> pm = getPassthroughServiceManager(); if (pm != nullptr) { sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr); if (!getStub || trebleTestingOverride) { base = wrapPassthrough(base); } return base; } }
returnnullptr; }
F:\Khadas_Edge_Android_Q\system\libhidl\transport\include\hidl\HidlTransportSupport.h template <typename BpType, typename IType = typename BpType::Pure, typename = std::enable_if_t<std::is_same<i_tag, typename IType::_hidl_tag>::value>, typename = std::enable_if_t<std::is_same<bphw_tag, typename BpType::_hidl_tag>::value>> sp<IType> getServiceInternal(conststd::string& instance, bool retry, bool getStub) { using ::android::hidl::base::V1_0::IBase; //这里通过sm->get(ICameraProvider::descriptor, serviceName)查询ICameraProvider这个hidl服务,得到IBase对象后,再通过ICameraProvider::castFrom转换为ICameraProvider对象。 sp<IBase> base = getRawServiceInternal(IType::descriptor, instance, retry, getStub); ...... if (base->isRemote()) { // getRawServiceInternal guarantees we get the proper class /* 获取 CameraProvider 代理类对象(binder) */ return sp<IType>(new BpType(getOrCreateCachedBinder(base.get()))); } /* 转换为 BpHwCameraProvider 对象 */ return IType::castFrom(base); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
01-1808:50:15.779326326 I CameraProviderManager: Connecting to new camera provider: external/0, isRemote? 1 01-1808:50:15.779326326 V CameraProviderManager: initialize: Setting device state for external/0: 0x0 01-1808:50:15.780326326 V CameraProviderManager: Request to start camera provider: external/0 01-1808:50:15.780326326 I CameraProviderManager: Camera provider external/0 ready with 0 camera devices 01-1808:50:15.893326326 I CameraProviderManager: Connecting to new camera provider: legacy/0, isRemote? 1 01-1808:50:15.894326326 V CameraProviderManager: initialize: Setting device state for legacy/0: 0x0 01-1808:50:15.894326326 V CameraProviderManager: Request to start camera provider: legacy/0 01-1808:50:15.896326326 I CameraProviderManager: Enumerating new camera device: device@3.3/legacy/0 01-1808:50:15.896326326 V CameraProviderManager: Request to start camera provider: legacy/0 01-1808:50:15.905326326 E CameraProviderManager: DeviceInfo3: Converted ICameraDevice instance to nullptr 01-1808:50:15.905326326 I CameraProviderManager: Camera provider legacy/0 ready with 1 camera devices 01-18 08:50:15.905 326 422 W CameraProviderManager: addProviderLocked: Camera provider HAL with name 'external/0' already registered 01-1808:50:15.906326326 I CameraService: onDeviceStatusChanged: Status changed for cameraId=0, newStatus=1 01-1808:50:15.906326326 I CameraService: onDeviceStatusChanged: Unknown camera ID 0, a new camera is added 01-1808:50:15.906326422 I CameraService: onDeviceStatusChanged: Status changed for cameraId=0, newStatus=1 01-1808:50:15.907326326 V CameraService: updateStatus: Status has changed for camera ID 0 from 0 to 0x1 01-18 08:50:15.907 326 422 W CameraProviderManager: addProviderLocked: Camera provider HAL with name 'legacy/0' already registered