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相关推荐

  1. android camera(三):camera V4L2 FIMC

    关键词: android  camera CMM 模组 camera参数  CAMIF   V4L2   平台信息: 内核: linux 系统: android 平台:S5PV310(samsung ...

  2. Android Camera 五 Camera HAL v1

    Android Camera 一 源码路径 Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析 Android Camera 三 CameraService 和 Cli ...

  3. Android Camera 四 Camera HAL 分析

    Android Camera 一 源码路径 Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析 Android Camera 三 CameraService 和 Cli ...

  4. Camera HAL3学习: Android Camera System

    Android Camera硬件抽象层(HAL,Hardware Abstraction Layer)主要用于把底层camera drive与硬件和位于android.hardware中的framew ...

  5. android camera(二):摄像头工作原理、s5PV310 摄像头接口(CAMIF)

    关键词: android  camera CMM 模组 camera参数  CAMIF 平台信息: 内核: linux 系统: android 平台:S5PV310(samsung exynos 42 ...

  6. android camera(四):camera 驱动 GT2005

    关键词:android  camera CMM 模组 camera参数  GT2005 摄像头常见问题 平台信息: 内核:linux 系统:android 平台:S5PV310(samsung exy ...

  7. android camera fragment,Android Camera 模块分析(三)

    第三部分 Camera的主要实现分析 3.1 JAVA程序部分 在packages/apps/Camera/src/com/android/camera/ 目录的Camera.java文件中,包含了对 ...

  8. Android分享视频链接到VK无法打开

    android app分享视频链接到VK,突然发现有的链接没有显示视频预览图,并且无法打开(如下图1). 用其他手机去分享时,没问题(如下图2).后面经过排查是英文版的分享时出现问题,英文分享的文案中 ...

  9. Android Camera调用流程

    一个流程图画的非常好的文章 http://blog.csdn.net/lushengchu_luis/article/details/11033095 1.Packages/apps/到framewo ...

最新文章

  1. Chrome DevTools 之 Network,网络加载分析利器
  2. MySQL工作中的实际用_数据库在工作中的应用,以及什么是MySQL?
  3. 5款新颖的ReSharper插件
  4. android 自定义桌面图标大小设置,手机桌面图标尺寸可以改?OriginOS重新定义个性化...
  5. 前端工程师需要学习ps 吗_转行学习web前端开发,需要哪些工具和需要学习什么?...
  6. python项目开发实例-有趣的十个Python实战项目,让你瞬间爱上Python!
  7. java函数的定义方法_java函数的定义以及使用方法介绍
  8. 酷似js的java函数简写——lambda表达式
  9. matlab 阶乘函数代码
  10. USB Type C 接口引脚详解
  11. html5怎么给视频加字幕,怎么给视频添加文字 怎么用Premiere Pro cs6给视频中添加文字...
  12. java标签用setbounds_setBounds的用法
  13. Ios android crash report,iOS App 后台 Crash 调查
  14. 手动制作满足SARscape要求的_dem数据
  15. 文档排版软件CTex,Winedt10使用(一)---安装
  16. thinkpad重装系统不引导_联想Y400电脑装WIN7无法重装系统的解决方法
  17. 无监督学习-自编码器-补充|深度学习(李宏毅)(二十)
  18. Day10QRadiobutton2021-09-24
  19. 送给入门maven的愤怒青年:archetype-cattalog内容详解
  20. stm32简单小实例_煽动MCU/MPU市场,STM32的生态图

热门文章

  1. 去除迅雷极速版 提示升级的广告
  2. 【MFC】打开资源视图对话框,提示未注册控件
  3. 大智慧交易系统测试软件,均线交易系统测试
  4. 100天以前是几月几号
  5. 物理CPU与VCPU的关系梳理总结
  6. FAQ-NE40E BGP邻居状态中的no neg代表什么含义
  7. 高精度 双目视觉方案
  8. R数据分析:扫盲贴,什么是多重插补
  9. VMware Horizon 8 2111 部署系列(五)配置事件数据库
  10. 机器学习强基计划2-2:一文详解ID3、C4.5、CART决策树算法+ Python实现