Android Camera 三 CameraService 和 Client 链接到 HAL
Android Camera 一 源码路径
Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析
Android Camera 三 CameraService 和 Client 链接到 HAL
Android Camera 四 Camera HAL 分析
Android Camera 五 Camera HAL v1
Linux v4l2 一 应用层
Linux v4l2 二 驱动和 usb 摄像头
frameworks/av/camera/Camera.cpp
frameworks/av/camera/CameraBase.cpp
frameworks/av/services/camera/libcameraservice/CameraService.cpp
frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
在上一章 Android camera 二 中提到的 JNI 方法。
JNI是 JAVA 层和 native 层通讯的桥梁。在 Android 中叫 NDK (Native Development Kit )。
android_hardware_Camera_native_setup 中调用了 connect 方法,最终目标是连接到相机设备,并打开相机镜头。
// android_hardware_Camera.cpp
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{......sp<Camera> camera;if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {// Default path: hal version is don't care, do normal camera connect.camera = Camera::connect(cameraId, clientName,Camera::USE_CALLING_UID, Camera::USE_CALLING_PID);} else {jint status = Camera::connectLegacy(cameraId, halVersion, clientName,Camera::USE_CALLING_UID, camera);if (status != NO_ERROR) {return status;}}if (camera == NULL) {return -EACCES;}......
}
android_hardware_Camera_native_setup 创建 Camera 智能指针,调用 Camera::connect() 方法构造 Camera 类实例。
Camera 类中的 connect 方法调用 CameraBase 类的connect 方法获取系统的 cameraservice 并通过binder机制建立camera客户端链接。
// Camera.cpp
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,int clientUid, int clientPid)
{return CameraBaseT::connect(cameraId, clientPackageName, clientUid, clientPid);
}// CameraBase.cpp
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,const String16& clientPackageName,int clientUid, int clientPid)
{ALOGV("%s: connect", __FUNCTION__);sp<TCam> c = new TCam(cameraId);sp<TCamCallbacks> cl = c;// 获取 camera 的服务const sp<::android::hardware::ICameraService>& cs = getCameraService();binder::Status ret;if(cs != nullptr){/** 定义在 /frameworks/av/camera/Camera.cpp* CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =* &::android::hardware::ICameraService::connect;* 推测最终是对应 CameraService::connect**/TCamConnectService fnConnectService = TCamTraits::fnConnectService;ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,clientPid, /*out*/ &c->mCamera);}if(ret.isOk() && c->mCamera != nullptr){// Binder对象设置死亡代理。当出现和服务端连接发生故障时,系统将自动调用死亡代理函数binderDied()// 为Binder对象设置死亡代理IInterface::asBinder(c->mCamera)->linkToDeath(c);c->mStatus = NO_ERROR;}else{ALOGW("An error occurred while connecting to camera %d: %s", cameraId,(cs != nullptr) ? "Service not available" : ret.toString8().string());c.clear();}return c;
}
CameraBase 类的connect() 调用 getCameraService() 获取camera服务
// CameraBase.cpp
// establish binder interface to camera service
template <typename TCam, typename TCamTraits>
const sp<::android::hardware::ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
{Mutex::Autolock _l(gLock);if(gCameraService.get() == 0){// 获取系统服务列表sp<IServiceManager> sm = defaultServiceManager();sp<IBinder> binder;do{// 通过 kCameraServiceName 字符串获取相机服务binder = sm->getService(String16(kCameraServiceName));if(binder != 0){break;}ALOGW("CameraService not published, waiting...");usleep(kCameraServicePollDelay);}while(true);if(gDeathNotifier == NULL){gDeathNotifier = new DeathNotifier();}binder->linkToDeath(gDeathNotifier);// find -name ICameraService.h 在 out 目录下有这个文件,不知道为什么编译的out目录会生成这个文件// ./out/obj_arm/SHARED_LIBRARIES/libcamera_client_intermediates/aidl-generated/include/android/hardware/ICameraService.h// ./out/obj/SHARED_LIBRARIES/libcamera_client_intermediates/aidl-generated/include/android/hardware/ICameraService.hgCameraService = interface_cast<::android::hardware::ICameraService>(binder);}ALOGE_IF(gCameraService == 0, "no CameraService!?");return gCameraService;
}
Camera 框架使用 binder 机制和CameraListener类的纯虚函数,实现跨进程传输图像数据。这里不叙述 binder 机制。
简单介绍下 cameraservice 的 serivce 和 client 端是的调用关系,是怎么连接到HAL层。
相机的 CameraService 是提供相机服务端实现的类,从 CameraService::connect() 开始逐步靠近 HAL层的厂商相机注册函数集。
// frameworks/av/services/camera/libcameraservice/CameraService.cpp
Status CameraService::connect(const sp<ICameraClient>& cameraClient,int cameraId,const String16& clientPackageName,int clientUid,int clientPid,/*out*/sp<ICamera>* device) {ATRACE_CALL();Status ret = Status::ok();String8 id = String8::format("%d", cameraId);sp<Client> client = nullptr;// 模板 connectHelper 里获取 camera client 代理ret = connectHelper<ICameraClient,Client>(cameraClient, id,CAMERA_DEVICE_API_VERSION_1_0/* modified */, clientPackageName, clientUid, clientPid, API_1,/*legacyMode*/ true/* modified */, /*shimUpdateOnly*/ false,/*out*/client);if(!ret.isOk()) {logRejected(id, getCallingPid(), String8(clientPackageName),ret.toString8());return ret;}*device = client;return ret;
}
CameraService::connectHelper 模板里调用 makeClient() 函数
template<class CALLBACK, class CLIENT>
binder::Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,int halVersion, const String16& clientPackageName, int clientUid, int clientPid,apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,/*out*/sp<CLIENT>& device)
{......if(!(ret = makeClient(this, cameraCb, clientPackageName, id, facing, clientPid,clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,/*out*/&tmp)).isOk()){return ret;}......}
Android7 使用的Camera API 2.0,所以CameraService::makeClient() 调用 *client = new CameraDeviceClient 进入 CameraDeviceClient.cpp
Status CameraService::makeClient(const sp<CameraService>& cameraService,const sp<IInterface>& cameraCb, const String16& packageName, int cameraId,int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,int halVersion, int deviceVersion, apiLevel effectiveApiLevel,/*out*/sp<BasicClient>* client)
{if(halVersion < 0 || halVersion == deviceVersion){// Default path: HAL version is unspecified by caller, create CameraClient// based on device version reported by the HAL.switch(deviceVersion){case CAMERA_DEVICE_API_VERSION_1_0:if(effectiveApiLevel == API_1) // Camera1 API route{sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());*client = new CameraClient(cameraService, tmp, packageName, cameraId, facing,clientPid, clientUid, getpid(), legacyMode);}else // Camera2 API route{ALOGW("Camera using old HAL version: %d", deviceVersion);return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,"Camera device \"%d\" HAL version %d does not support camera2 API",cameraId, deviceVersion);}break;case CAMERA_DEVICE_API_VERSION_3_0:case CAMERA_DEVICE_API_VERSION_3_1:case CAMERA_DEVICE_API_VERSION_3_2:case CAMERA_DEVICE_API_VERSION_3_3:case CAMERA_DEVICE_API_VERSION_3_4:if(effectiveApiLevel == API_1) // Camera1 API route{sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());*client = new Camera2Client(cameraService, tmp, packageName, cameraId, facing,clientPid, clientUid, servicePid, legacyMode);}else // Camera2 API route 创建 CameraDeviceClient{sp<hardware::camera2::ICameraDeviceCallbacks> tmp =static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());*client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,facing, clientPid, clientUid, servicePid);}break;default:// Should not be reachableALOGE("Unknown camera device HAL version: %d", deviceVersion);return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,"Camera device \"%d\" has unknown HAL version %d",cameraId, deviceVersion);}}else{......}return Status::ok();
}
CameraDeviceClient类的构造函数调用 Camera2ClientBase 模板函数执行 mDevice = new Camera3Device(cameraId); 创建 Camera3Device类的实例。
// frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
// Interface used by CameraService
CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,const String16& clientPackageName,int cameraId,int cameraFacing,int clientPid,uid_t clientUid,int servicePid) :Camera2ClientBase(cameraService, remoteCallback, clientPackageName,cameraId, cameraFacing, clientPid, clientUid, servicePid),mInputStream(),mStreamingRequestId(REQUEST_ID_NONE),mRequestIdCounter(0)
{ATRACE_CALL();ALOGI("CameraDeviceClient %d: Opened", cameraId);
}// frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
// Interface used by CameraService
template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(const sp<CameraService>& cameraService,const sp<TCamCallbacks>& remoteCallback,const String16& clientPackageName,int cameraId,int cameraFacing,int clientPid,uid_t clientUid,int servicePid):TClientBase(cameraService, remoteCallback, clientPackageName,cameraId, cameraFacing, clientPid, clientUid, servicePid),mSharedCameraCallbacks(remoteCallback),mDeviceVersion(cameraService->getDeviceVersion(cameraId)),mDeviceActive(false)
{ALOGI("Camera %d: Opened. Client: %s (PID %d, UID %d)", cameraId,String8(clientPackageName).string(), clientPid, clientUid);mInitialClientPid = clientPid;mDevice = new Camera3Device(cameraId);LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
创建Camera3Device()实例; 在该类的初始化方法 Camera3Device::initialize(CameraModule *module) 中调用模块的open()函数,打开相机设备。进入 HAL 层。
// frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
Camera3Device::Camera3Device(int id):mId(id),mIsConstrainedHighSpeedConfiguration(false),mHal3Device(NULL),mStatus(STATUS_UNINITIALIZED),mStatusWaiters(0),mUsePartialResult(false),mNumPartialResults(1),mTimestampOffset(0),mNextResultFrameNumber(0),mNextReprocessResultFrameNumber(0),mNextShutterFrameNumber(0),mNextReprocessShutterFrameNumber(0),mListener(NULL)
{ATRACE_CALL();camera3_callback_ops::notify = &sNotify;camera3_callback_ops::process_capture_result = &sProcessCaptureResult;ALOGV("%s: Created device for camera %d", __FUNCTION__, id);
}// frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
// 该函数中 module->open() ,调用HAL层注册的相机模块 open 函数
status_t Camera3Device::initialize(CameraModule *module)
{ATRACE_CALL();Mutex::Autolock il(mInterfaceLock);Mutex::Autolock l(mLock);ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);if (mStatus != STATUS_UNINITIALIZED) {CLOGE("Already initialized!");return INVALID_OPERATION;}/** Open HAL device */status_t res;String8 deviceName = String8::format("%d", mId);camera3_device_t *device;ATRACE_BEGIN("camera3->open");res = module->open(deviceName.string(),reinterpret_cast<hw_device_t**>(&device)); // 打开相机设备ATRACE_END();if (res != OK) {SET_ERR_L("Could not open camera: %s (%d)", strerror(-res), res);return res;}/** Cross-check device version */if (device->common.version < CAMERA_DEVICE_API_VERSION_3_0) {SET_ERR_L("Could not open camera: ""Camera device should be at least %x, reports %x instead",CAMERA_DEVICE_API_VERSION_3_0,device->common.version);device->common.close(&device->common);return BAD_VALUE;}camera_info info;res = module->getCameraInfo(mId, &info);if (res != OK) return res;if (info.device_version != device->common.version) {SET_ERR_L("HAL reporting mismatched camera_info version (%x)"" and device version (%x).",info.device_version, device->common.version);device->common.close(&device->common);return BAD_VALUE;}......return OK;
}
至此代码进入 HAL 空间。 HAL 没有 Framework 那么复杂的。 Android其他模块代码的调用流程可参考 Camera 。如果做驱动开发又想了解 Android framework 框架,建议先跳过 Java 层代码。从 CPP 开始跟代码,逐步理解 Framework 与 HAL 的关系。然后再跟 Java 层的代码。
Android Camera 三 CameraService 和 Client 链接到 HAL相关推荐
- android camera(三):camera V4L2 FIMC
关键词: android camera CMM 模组 camera参数 CAMIF V4L2 平台信息: 内核: linux 系统: android 平台:S5PV310(samsung ...
- Android Camera 五 Camera HAL v1
Android Camera 一 源码路径 Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析 Android Camera 三 CameraService 和 Cli ...
- Android Camera 四 Camera HAL 分析
Android Camera 一 源码路径 Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析 Android Camera 三 CameraService 和 Cli ...
- Camera HAL3学习: Android Camera System
Android Camera硬件抽象层(HAL,Hardware Abstraction Layer)主要用于把底层camera drive与硬件和位于android.hardware中的framew ...
- android camera(二):摄像头工作原理、s5PV310 摄像头接口(CAMIF)
关键词: android camera CMM 模组 camera参数 CAMIF 平台信息: 内核: linux 系统: android 平台:S5PV310(samsung exynos 42 ...
- android camera(四):camera 驱动 GT2005
关键词:android camera CMM 模组 camera参数 GT2005 摄像头常见问题 平台信息: 内核:linux 系统:android 平台:S5PV310(samsung exy ...
- android camera fragment,Android Camera 模块分析(三)
第三部分 Camera的主要实现分析 3.1 JAVA程序部分 在packages/apps/Camera/src/com/android/camera/ 目录的Camera.java文件中,包含了对 ...
- Android分享视频链接到VK无法打开
android app分享视频链接到VK,突然发现有的链接没有显示视频预览图,并且无法打开(如下图1). 用其他手机去分享时,没问题(如下图2).后面经过排查是英文版的分享时出现问题,英文分享的文案中 ...
- Android Camera调用流程
一个流程图画的非常好的文章 http://blog.csdn.net/lushengchu_luis/article/details/11033095 1.Packages/apps/到framewo ...
最新文章
- Chrome DevTools 之 Network,网络加载分析利器
- MySQL工作中的实际用_数据库在工作中的应用,以及什么是MySQL?
- 5款新颖的ReSharper插件
- android 自定义桌面图标大小设置,手机桌面图标尺寸可以改?OriginOS重新定义个性化...
- 前端工程师需要学习ps 吗_转行学习web前端开发,需要哪些工具和需要学习什么?...
- python项目开发实例-有趣的十个Python实战项目,让你瞬间爱上Python!
- java函数的定义方法_java函数的定义以及使用方法介绍
- 酷似js的java函数简写——lambda表达式
- matlab 阶乘函数代码
- USB Type C 接口引脚详解
- html5怎么给视频加字幕,怎么给视频添加文字 怎么用Premiere Pro cs6给视频中添加文字...
- java标签用setbounds_setBounds的用法
- Ios android crash report,iOS App 后台 Crash 调查
- 手动制作满足SARscape要求的_dem数据
- 文档排版软件CTex,Winedt10使用(一)---安装
- thinkpad重装系统不引导_联想Y400电脑装WIN7无法重装系统的解决方法
- 无监督学习-自编码器-补充|深度学习(李宏毅)(二十)
- Day10QRadiobutton2021-09-24
- 送给入门maven的愤怒青年:archetype-cattalog内容详解
- stm32简单小实例_煽动MCU/MPU市场,STM32的生态图