Android Camera 流程学习记录(二)—— Camera Open 调用流程

简介

  • 这一章里,咱们将 Camera.java 中的 open() 方法做为切入点。做为打开摄像头的方法,不管哪一种 Camera 应用都须要调用到它。
  • 从 Camera.open() 被调用开始,这一指令是如何经过 Framework 层走到 C/C++ 层,又是如何进入 HAL 层从而使得指令可以到达设备端。
  • 经过追踪源码,咱们能够比较清晰地了解整个过程。
  • 接下来按照 Framework -> Android Runtime -> C/C++ Libraries -> HAL 的顺序去分析整个调用流程。
  • NOTE: 



Open flow



1. Framework


1.1 Camera.java

  • 路径:frameworks/base/core/java/android/hardware/Camera.java
  • 首先从 Open() 方法开始: 
    • 获取 Camera 设备的个数。
    • 依次获取设备信息,若是是获取到后置摄像头(默认),则调用 new Camera(int) 构造对应的摄像头实例。
  • 注释翻译: 
    • 构造一个新的摄像头对象,以获取第一个后置摄像头。
    • 若设备中没有后置摄像头,则返回 null 。
  • NOTE:还有一个方法 open(int) ,它能够直接指定打开的摄像头。
 
  1. /*** java

  2. * Creates a new Camera object to access android

  3. * the first back-facing camera on the shell

  4. * device. If the device does not have a back-facing camera,api

  5. * this returns null. 架构

  6. * @see #open(int) ide

  7. */函数

  8. public static Camera open() {oop

  9. int numberOfCameras = getNumberOfCameras(); 源码分析

  10. CameraInfo cameraInfo = new CameraInfo();ui

  11. for (int i = 0; i < numberOfCameras; i++) {

  12. getCameraInfo(i, cameraInfo);

  13. if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {

  14. return new Camera(i);

  15. }

  16. }

  17. return null;

  18. }

  • Camera(int cameraId): 
    • 经过调用 cameraInitNormal(Id) 方法对指定摄像头进行初始化。
 
  1. /** used by Camera#open, Camera#open(int) */

  2. Camera(int cameraId) {

  3. int err = cameraInitNormal(cameraId);

  4. if (checkInitErrors(err)) {

  5. if (err == -EACCES) {

  6. throw new RuntimeException("Fail to connect to camera service");

  7. } else if (err == -ENODEV) {

  8. throw new RuntimeException("Camera initialization failed");

  9. }

  10. // Should never hit this.

  11. throw new RuntimeException("Unknown camera error");

  12. }

  13. }

  • cameraInitNormal(int cameraId): 
    • 指定 halVersion 参数。
    • 调用 cameraInitVersion(int cameraId, int halVersion)
 
  1. private int cameraInitNormal(int cameraId) {

  2. return cameraInitVersion(cameraId,

  3. CAMERA_HAL_API_VERSION_NORMAL_CONNECT);

  4. }

  • cameraInitVersion(int cameraId, int halVersion): 
    • 将各个回调函数置空。
    • Looper 的做用没有仔细研究,从代码逻辑上看,可能与事件的监听(须要循环操做)有关。
    • 经过 Looper 对事件处理对象进行实例化后,就调用 native_setup 方法进入 JNI(Java Native Interface) 库中调用对应的函数。
    • 至此,open() 方法开始进入 Android Runtime 层。
 
  1. private int cameraInitVersion(int cameraId,

  2. int halVersion) {

  3. mShutterCallback = null;

  4. mRawImageCallback = null;

  5. mJpegCallback = null;

  6. mPreviewCallback = null;

  7. mPostviewCallback = null;

  8. mUsingPreviewAllocation = false;

  9. mZoomListener = null;

  10. Looper looper;

  11. if ((looper = Looper.myLooper()) != null) {

  12. mEventHandler = new EventHandler(this, looper);

  13. } else if ((looper = Looper.getMainLooper()) != null) {

  14. mEventHandler = new EventHandler(this, looper);

  15. } else {

  16. mEventHandler = null;

  17. }

  18. return native_setup(new WeakReference<Camera>(this),

  19. cameraId, halVersion,

  20. ActivityThread.currentOpPackageName());

  21. }


1.2 Framework 中流程简图

流程简图



2. Android Runtime


2.1 android_hardware_Camera.cpp

  • 路径:frameworks/base/core/jni/android_hardware_Camera.cpp
  • native_setup(): 
    • 刚开始要先把 clientPackageName 作一个类型转换,变成 clientName
    • 创建一个 Camera 类型的 StrongPointer(sp)
    • 经过函数 Camera::connect() 或 Camera::connectLegacy(),让客户端与服务端进行链接,并返回相应的 Camera 实例。
    • 最后对返回的实例进行一些基本的检查,并保存上下文。
    • 在 connect() 的时候,就进入了 C/C++ Libraries 的 C/S 结构中,而 Camera 则属于 Client
 
  1. // connect to camera service

  2. static jint android_hardware_Camera_native_setup(JNIEnv *env,

  3. jobject thiz, jobject weak_this,

  4. jint cameraId, jint halVersion,

  5. jstring clientPackageName)

  6. {

  7. // convert jstring to String16(clientPackageName -> clientName)

  8. ......

  9. ......

  10. sp<Camera> camera;

  11. if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {

  12. /***** NOTE THIS *****/

  13. // Default path: hal version is don't care, do normal camera connect.

  14. camera = Camera::connect(cameraId, clientName,

  15. Camera::USE_CALLING_UID,

  16. Camera::USE_CALLING_PID);

  17. } else {

  18. jint status = Camera::connectLegacy(cameraId,

  19. halVersion, clientName,

  20. Camera::USE_CALLING_UID, camera);

  21. if (status != NO_ERROR) {

  22. return status;

  23. }

  24. }

  25. if (camera == NULL) {

  26. return -EACCES;

  27. }

  28.  
  29. // make sure camera hardware is alive

  30. if (camera->getStatus() != NO_ERROR) {

  31. return NO_INIT;

  32. }

  33.  
  34. // save context in opaque field

  35. ......

  36. ......

  37. }


2.2 Runtime 中流程简图

Runtime 简图



3. C/C++ Libraries


3.1 Camera

3.1.1 Camera.h

  • 位置:frameworks/av/include/camera/Camera.h
  • 注意 CameraTraits<Camera> 的结构体:
 
  1. template <>

  2. struct CameraTraits<Camera>

  3. {

  4. typedef CameraListener TCamListener;

  5. typedef ::android::hardware::ICamera TCamUser;

  6. typedef ::android::hardware::ICameraClient TCamCallbacks;

  7. typedef ::android::binder::Status(::android::hardware::ICameraService::*TCamConnectService)

  8. (const sp<::android::hardware::ICameraClient>&,

  9. int, const String16&, int, int,

  10. /*out*/

  11. sp<::android::hardware::ICamera>*);

  12. static TCamConnectService fnConnectService;

  13. };

3.1.2 Camera.cpp

  • 位置:framework/av/camera/Camera.cpp
  • 注意 fnConnectService 是对应到 ICameraService::connect 函数的。
 
  1. CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =

  2. &::android::hardware::ICameraService::connect;

  • 1
  • 2
  • Camera::connect : 
    • 这里直接调用了 CameraBaseT::connect() 这是定义在 CameraBase.cpp 中的函数。
 
  1. sp<Camera> Camera::connect(int cameraId,

  2. const String16& clientPackageName,

  3. int clientUid, int clientPid)

  4. {

  5. return CameraBaseT::connect(cameraId,

  6. clientPackageName, clientUid, clientPid);

  7. }


3.2 CameraBase

3.2.1 CameraBase.h

  • 位置:frameworks/av/include/camera/CameraBase.h
  • 注意模板信息: 
    • TCam 对应 Camera
    • TCamTraits 对应 CameraTraits<Camera>
template <typename TCam, typename TCamTraits = CameraTraits<TCam> >
  • 1
  • 注意类成员变量声明部分: 
    • 便可知道 CameraBaseT 对应 CameraBase<Camera>
 
  1. sp<TCamUser> mCamera;

  2. status_t mStatus;

  3. sp<TCamListener> mListener;

  4. const int mCameraId;

  5.  
  6. /***** NOTE THIS *****/

  7. typedef CameraBase<TCam> CameraBaseT;

3.2.2 CameraBase.cpp

  • 位置:framework/av/camera/CameraBase.cpp
  • connect(): 
    • 实例化一个 Camera
    • 经过 Camera 获取 ICameraClient 指针。
    • 经过 getCameraService() 函数获取 ICameraService
    • 经过 ICameraService::connect() 函数得到一个 mCamera, 即 ICamera 实例。
    • 将 ICamera 实例与 Binder 创建联系。
 
  1. template <typename TCam, typename TCamTraits>

  2. sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,

  3. const String16& clientPackageName,

  4. int clientUid, int clientPid)

  5. {

  6. ALOGV("%s: connect", __FUNCTION__);

  7. /***** NOTE THIS *****/

  8. sp<TCam> c = new TCam(cameraId);

  9. sp<TCamCallbacks> cl = c;

  10. const sp<::android::hardware::ICameraService> cs = getCameraService();

  11.  
  12. binder::Status ret;

  13. if (cs != nullptr) {

  14. /***** NOTE THIS *****/

  15. TCamConnectService fnConnectService = TCamTraits::fnConnectService;

  16. ret = (cs.get()->*fnConnectService)(cl, cameraId,

  17. clientPackageName, clientUid,

  18. clientPid, /*out*/ &c->mCamera);

  19. }

  20. if (ret.isOk() && c->mCamera != nullptr) {

  21. /***** NOTE THIS *****/

  22. IInterface::asBinder(c->mCamera)->linkToDeath(c);

  23. c->mStatus = NO_ERROR;

  24. } else {

  25. ALOGW("An error occurred while connecting to camera %d: %s", cameraId,

  26. (cs != nullptr) ? "Service not available" : ret.toString8().string());

  27. c.clear();

  28. }

  29. return c;

  30. }

  • getCameraService(): 
    • 注意,gCameraService 是一个 ICameraService
    • 首先调用 ICameraService 的 get 函数,若是能获取到 ICameraService 则返回。
    • 若没有返回,则经过 IServiceManager 来获取一个 ICameraService,这个过程当中主要是经过 IBinder 来进行数据的获取的,其中机制暂时忽略,只要知道经过 Binder 咱们获取了一个 ICameraService 就好。
  1. // establish binder interface to camera service

  2. template <typename TCam, typename TCamTraits>

  3. const sp<::android::hardware::ICameraService> CameraBase<TCam, TCamTraits>::getCameraService()

  4. {

  5. Mutex::Autolock _l(gLock);

  6.  
  7. /***** NOTE THIS *****/

  8. if (gCameraService.get() == 0) {

  9. char value[PROPERTY_VALUE_MAX];

  10. property_get("config.disable_cameraservice", value, "0");

  11. if (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0) {

  12. return gCameraService;

  13. }

  14.  
  15. /***** NOTE THIS *****/

  16. sp<IServiceManager> sm = defaultServiceManager();

  17. sp<IBinder> binder;

  18. do {

  19. binder = sm->getService(String16(kCameraServiceName));

  20. if (binder != 0) {

  21. break;

  22. }

  23. ALOGW("CameraService not published, waiting...");

  24. usleep(kCameraServicePollDelay);

  25. } while(true);

  26.  
  27. if (gDeathNotifier == NULL) {

  28. gDeathNotifier = new DeathNotifier();

  29. }

  30. binder->linkToDeath(gDeathNotifier);

  31. /***** NOTE THIS *****/

  32. gCameraService = interface_cast<::android::hardware::ICameraService>(binder);

  33. }

  34. ALOGE_IF(gCameraService == 0, "no CameraService!?");

  35. return gCameraService;

  36. }


3.3 ICameraService

  • NOTE: 
    • 这一节主要是了解一下关于 Binder 通信中的一些内部逻辑。
    • 实际上在 CameraBase 中,所调用的 connect 对应的是 CameraService::connect() ,在下一节中再进行分析。

3.3.1 ICameraService.aidl

  • 位置:frameworks/av/camera/aidl/android/hardware/ICameraService.aidl
  • aidl 是一种内部进程通信的描述语言,经过它咱们能够定义通信的接口。
  • 注释: 
    • 这里定义了运行在媒体服务端的,本地摄像头服务的 Binder 接口
 
  1. /**

  2. * Binder interface for the native camera service running in mediaserver.

  3. *

  4. * @hide

  5. */

  • connect 接口: 
    • 这里的注释说明了,这个方法调用的是旧的 Camera API,即 API 1
 
  1. /**

  2. * Open a camera device through the old camera API

  3. */

  4. ICamera connect(ICameraClient client,

  5. int cameraId,

  6. String opPackageName,

  7. int clientUid, int clientPid);

3.3.2 ICameraService.cpp

  • 位置:out/target/product/generic/obj/SHARED_LIBRARIES/libcamera_client_intermediates/aidl-generated/src/aidl/android/hardware/ICameraService.cpp
  • out 文件夹是源码编译后才生成的.
  • 这个 ICameraService.cpp 以及其头文件 ICameraService.h 都是根据其对应的 aidl 文件自动生成的。
  • BpCameraService::connect(): 
    • 注意,这里是 BpCameraservice,它继承了 ICameraService,同时也继承了 BpInterface
    • Parcel 能够当作是 Binder 通信中的信息传递中介。
    • 首先把相应的数据写入 Parcel
    • 而后调用远程接口 remote() 中的处理函数 transact()
    • 最后经过返回的 reply 数据判断是否有 error
 
  1. ::android::binder::Status BpCameraService::connect(const ::android::sp<::android::hardware::ICameraClient>& client,

  2. int32_t cameraId, const ::android::String16& opPackageName,

  3. int32_t clientUid, int32_t clientPid,

  4. ::android::sp<::android::hardware::ICamera>* _aidl_return)

  5. {

  6. ::android::Parcel _aidl_data;

  7. ::android::Parcel _aidl_reply;

  8. ::android::status_t _aidl_ret_status = ::android::OK;

  9. ::android::binder::Status _aidl_status;

  10. _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());

  11.  
  12. /***** NOTE THIS *****/

  13. if (((_aidl_ret_status) != (::android::OK))) {

  14. goto _aidl_error;

  15. }

  16. _aidl_ret_status = _aidl_data.writeStrongBinder(::android::hardware::ICameraClient::asBinder(client));

  17. if (((_aidl_ret_status) != (::android::OK))) {

  18. goto _aidl_error;

  19. }

  20. _aidl_ret_status = _aidl_data.writeInt32(cameraId);

  21. if (((_aidl_ret_status) != (::android::OK))) {

  22. goto _aidl_error;

  23. }

  24. _aidl_ret_status = _aidl_data.writeString16(opPackageName);

  25. if (((_aidl_ret_status) != (::android::OK))) {

  26. goto _aidl_error;

  27. }

  28. _aidl_ret_status = _aidl_data.writeInt32(clientUid);

  29. if (((_aidl_ret_status) != (::android::OK))) {

  30. goto _aidl_error;

  31. }

  32. _aidl_ret_status = _aidl_data.writeInt32(clientPid);

  33. if (((_aidl_ret_status) != (::android::OK))) {

  34. goto _aidl_error;

  35. }

  36.  
  37. /***** NOTE THIS *****/

  38. _aidl_ret_status = remote()->transact(ICameraService::CONNECT, _aidl_data, &_aidl_reply);

  39. if (((_aidl_ret_status) != (::android::OK))) {

  40. goto _aidl_error;

  41. }

  42. _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);

  43. if (((_aidl_ret_status) != (::android::OK))) {

  44. goto _aidl_error;

  45. }

  46. if (!_aidl_status.isOk()) {

  47. return _aidl_status;

  48. }

  49. _aidl_ret_status = _aidl_reply.readStrongBinder(_aidl_return);

  50. if (((_aidl_ret_status) != (::android::OK))) {

  51. goto _aidl_error;

  52. }

  53. _aidl_error:

  54. _aidl_status.setFromStatusT(_aidl_ret_status);

  55. return _aidl_status;

  56. }

  • BnCameraService::onTransact(): 
    • 消息处理函数。
    • 这个函数太长,只截取 CONNECT 相关的一段。
    • BpCameraService 经过 Binder 封装了接口,而 BnCameraService 则具体实现接口。
    • 注意到这里一一接收了 Bp 传来的数据,而后调用了具体的 connect 函数获取 ICamera 而且返回。
 
  1. case Call::CONNECT:

  2. {

  3. ::android::sp<::android::hardware::ICameraClient> in_client;

  4. int32_t in_cameraId;

  5. ::android::String16 in_opPackageName;

  6. int32_t in_clientUid;

  7. int32_t in_clientPid;

  8. /***** NOTE THIS *****/

  9. ::android::sp<::android::hardware::ICamera> _aidl_return;

  10.  
  11. if (!(_aidl_data.checkInterface(this))) {

  12. _aidl_ret_status = ::android::BAD_TYPE;

  13. break;

  14. }

  15. _aidl_ret_status = _aidl_data.readStrongBinder(&in_client);

  16. if (((_aidl_ret_status) != (::android::OK))) {

  17. break;

  18. }

  19. _aidl_ret_status = _aidl_data.readInt32(&in_cameraId);

  20. if (((_aidl_ret_status) != (::android::OK))) {

  21. break;

  22. }

  23. _aidl_ret_status = _aidl_data.readString16(&in_opPackageName);

  24. if (((_aidl_ret_status) != (::android::OK))) {

  25. break;

  26. }

  27. _aidl_ret_status = _aidl_data.readInt32(&in_clientUid);

  28. if (((_aidl_ret_status) != (::android::OK))) {

  29. break;

  30. }

  31. _aidl_ret_status = _aidl_data.readInt32(&in_clientPid);

  32. if (((_aidl_ret_status) != (::android::OK))) {

  33. break;

  34. }

  35.  
  36. /***** NOTE THIS *****/

  37. ::android::binder::Status _aidl_status(connect(in_client, in_cameraId, in_opPackageName, in_clientUid, in_clientPid, &_aidl_return));

  38. _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);

  39. if (((_aidl_ret_status) != (::android::OK))) {

  40. break;

  41. }

  42. if (!_aidl_status.isOk()) {

  43. break;

  44. }

  45.  
  46. /***** NOTE THIS *****/

  47. _aidl_ret_status = _aidl_reply->writeStrongBinder(::android::hardware::ICamera::asBinder(_aidl_return));

  48. if (((_aidl_ret_status) != (::android::OK))) {

  49. break;

  50. }

  51. }

  52. break;


3.4 ICamera

  • 这一节咱们回到 CameraBase 关于 connect() 函数的调用中。

3.4.1 ICamera.cpp

  • 位置:frameworks/av/camera/ICamera.cpp
  • BpCamera 类只提供给 Client 调用的接口。
  • 在 BpCamera 类中,有 connect() 函数:
 
  1. virtual status_t connect(const sp<ICameraClient>& cameraClient)

  2. {

  3. Parcel data, reply;

  4. data.writeInterfaceToken(ICamera::getInterfaceDescriptor());

  5. data.writeStrongBinder(IInterface::asBinder(cameraClient));

  6. remote()->transact(CONNECT, data, &reply);

  7. return reply.readInt32();

  8. }

  • 而 BnCamera 类应负责实现接口,但这里有一点特殊,它是经过 CameraService::Client 来实现具体接口的。
  • 在 BnCamera 类中,onTransact 函数则有相应的处理:
 
  1. case CONNECT: {

  2. CHECK_INTERFACE(ICamera, data, reply);

  3. sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());

  4. reply->writeInt32(connect(cameraClient));

  5. return NO_ERROR;

  6. } break;

3.4.2 CameraService.cpp

  • 位置:frameworks/av/services/camera/libcameraservice/CameraService.cpp
  • connect(): 
    • 注意这里真正实现逻辑是在 connectHelper() 函数中。
    • 得到一个客户端实例而且经过 *device 返回。
 
  1. Status CameraService::connect(

  2. const sp<ICameraClient>& cameraClient,

  3. int cameraId,

  4. const String16& clientPackageName,

  5. int clientUid,

  6. int clientPid,

  7. /*out*/

  8. sp<ICamera>* device) {

  9.  
  10. ATRACE_CALL();

  11. Status ret = Status::ok();

  12. String8 id = String8::format("%d", cameraId);

  13. sp<Client> client = nullptr;

  14. ret = connectHelper<ICameraClient,Client>(cameraClient, id,

  15. CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1,

  16. /*legacyMode*/ false, /*shimUpdateOnly*/ false,

  17. /*out*/client);

  18.  
  19. if(!ret.isOk()) {

  20. logRejected(id, getCallingPid(), String8(clientPackageName),

  21. ret.toString8());

  22. return ret;

  23. }

  24.  
  25. *device = client;

  26. return ret;

  27. }

3.4.3 CameraService.h

  • 位置:frameworks/av/services/camera/libcameraservice/CameraService.h
  • 注意这个文件中定义了 CameraService::Client 类,这个类经过它的子类 CameraClient 真正实现了 ICamera 的接口。
  • connectHelper(): 
    • 这个函数实现比较长,截取其中的一段。
    • 首先,若是客户端实例已经存在于 MediaRecorder ,则直接将其取出返回。
    • 若不存在,则先获取 deviceVersion,而后再调用 makeClient() 函数建立一个客户端。
    • 建立客户端后,须要调用其 initialize() 函数进行初始化,注意其传入的参数是 mModule,这个参数是链接 Libraries 与 HAL的关键参数。
 
  1. sp<BasicClient> clientTmp = nullptr;

  2. std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;

  3. if ((err = handleEvictionsLocked(cameraId,

  4. originalClientPid, effectiveApiLevel,

  5. IInterface::asBinder(cameraCb), clientName8,

  6. /*out*/&clientTmp,

  7. /*out*/&partial)) != NO_ERROR) {

  8. /***** do something *****/

  9. }

  10.  
  11. /***** NOTE THIS *****/

  12. if (clientTmp.get() != nullptr) {

  13. // Handle special case for API1 MediaRecorder where the existing client is returned

  14. device = static_cast<CLIENT*>(clientTmp.get());

  15. return ret;

  16. }

  17.  
  18. // give flashlight a chance to close devices if necessary.

  19. mFlashlight->prepareDeviceOpen(cameraId);

  20.  
  21. // TODO: Update getDeviceVersion + HAL interface to use strings for Camera IDs

  22. int id = cameraIdToInt(cameraId);

  23. if (id == -1) {

  24. ALOGE("%s: Invalid camera ID %s, cannot get device version from HAL.", __FUNCTION__,

  25. cameraId.string());

  26. return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,

  27. "Bad camera ID \"%s\" passed to camera open", cameraId.string());

  28. }

  29.  
  30. int facing = -1;

  31. /***** NOTE THIS *****/

  32. int deviceVersion = getDeviceVersion(id, /*out*/&facing);

  33. sp<BasicClient> tmp = nullptr;

  34. if(!(ret = makeClient(this, cameraCb,

  35. clientPackageName, id, facing, clientPid,

  36. clientUid, getpid(), legacyMode, halVersion,

  37. deviceVersion, effectiveApiLevel,

  38. /*out*/&tmp)).isOk()) {

  39. return ret;

  40. }

  41. client = static_cast<CLIENT*>(tmp.get());

  42.  
  43. LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",

  44. __FUNCTION__);

  45.  
  46. /***** NOTE THIS *****/

  47. if ((err = client->initialize(mModule)) != OK) {

  48. /***** do somthing *****/

  49. }

  50.  
  51. // Update shim paremeters for legacy clients

  52. if (effectiveApiLevel == API_1) {

  53. // Assume we have always received a Client subclass for API1

  54. sp<Client> shimClient = reinterpret_cast<Client*>(client.get());

  55. String8 rawParams = shimClient->getParameters();

  56. CameraParameters params(rawParams);

  57.  
  58. auto cameraState = getCameraState(cameraId);

  59. if (cameraState != nullptr) {

  60. cameraState->setShimParams(params);

  61. } else {

  62. ALOGE("%s: Cannot update shim parameters for camera %s, no such device exists.",

  63. __FUNCTION__, cameraId.string());

  64. }

  65. }

  66.  
  67. if (shimUpdateOnly) {

  68. // If only updating legacy shim parameters, immediately disconnect client

  69. mServiceLock.unlock();

  70. client->disconnect();

  71. mServiceLock.lock();

  72. } else {

  73. // Otherwise, add client to active clients list

  74. finishConnectLocked(client, partial);

  75. }

  76. } // lock is destroyed, allow further connect calls

  77.  
  78. // Important: release the mutex here so the client can call back into the service from its

  79. // destructor (can be at the end of the call)

  80. device = client;

3.4.4 CameraClient.cpp

  • 位置:frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
  • 从文件位置也能够看得出,咱们如今走的都是 Camera API 1 的流程。
  • CameraClient 继承了 CameraService::Client
  • CameraClient::initialize(): 
    • 获取 CameraHardwareInterface 实例。
    • 对 mHardware 进行初始化。
    • 设置三个回调函数(这里与数据流密切相关)
 
  1. status_t CameraClient::initialize(CameraModule *module) {

  2. int callingPid = getCallingPid();

  3. status_t res;

  4.  
  5. LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);

  6.  
  7. // Verify ops permissions

  8. res = startCameraOps();

  9. if (res != OK) {

  10. return res;

  11. }

  12.  
  13. char camera_device_name[10];

  14. snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);

  15.  
  16. /***** NOTE THIS *****/

  17. mHardware = new CameraHardwareInterface(camera_device_name);

  18. res = mHardware->initialize(module);

  19. if (res != OK) {

  20. ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",

  21. __FUNCTION__, mCameraId, strerror(-res), res);

  22. mHardware.clear();

  23. return res;

  24. }

  25.  
  26. mHardware->setCallbacks(notifyCallback,

  27. dataCallback,

  28. dataCallbackTimestamp,

  29. (void *)(uintptr_t)mCameraId);

  30.  
  31. // Enable zoom, error, focus, and metadata messages by default

  32. enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |

  33. CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);

  34.  
  35. LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);

  36. return OK;

  37. }

  • 至此,整个 Libraries 层的 open 流程就结束了,接下来进入到 HAL 层。

3.5 Libraries 中流程简图

流程简图


4. HAL

4.1 CameraHardwareInterface.h

  • 位置:frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
  • initialize(): 
    • 经过 module,从 HAL 层的库中调用相关的函数获取 Camera 设备信息。
    • 根据模块 API 的版本,判断是用 open 函数仍是用 openLegacy
    • 调用 open 后,经过 HAL 中的库,咱们的指令就能传递到 Linux Kernel,从而下达到具体的设备上。(与具体的驱动相关,暂时不去分析)
    • 最后初始化预览窗口。
 
  1. status_t initialize(CameraModule *module)

  2. {

  3. ALOGI("Opening camera %s", mName.string());

  4. camera_info info;

  5. status_t res = module->getCameraInfo(atoi(mName.string()), &info);

  6. if (res != OK) {

  7. return res;

  8. }

  9.  
  10. int rc = OK;

  11. if (module->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_3 &&

  12. info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {

  13. // Open higher version camera device as HAL1.0 device.

  14. rc = module->openLegacy(mName.string(),

  15. CAMERA_DEVICE_API_VERSION_1_0,

  16. (hw_device_t **)&mDevice);

  17. } else {

  18. rc = module->open(mName.string(), (hw_device_t **)&mDevice);

  19. }

  20. if (rc != OK) {

  21. ALOGE("Could not open camera %s: %d", mName.string(), rc);

  22. return rc;

  23. }

  24. initHalPreviewWindow();

  25. return rc;

  26. }

  • 至此,咱们所研究的 Camera Open 整个调用流程就已经比较清晰了。


小结

  • 在这篇笔记中,咱们主要是从 Camera.open() 方法被调用开始,对源码进行追溯,从而一层层地了解了它的一个调用的过程,与过程当中比较重要的一些逻辑。
  • 经过这一轮追溯,咱们就能够对 Camera 架构有一个更深入的认识,可是其中可能还有一些知识点没有理清,不过我认为不会影响对于整个架构的了解。

  • 我认为比较难去理解的就是 Libraries 中,关于客户端与服务端交互的部分。这一部分我在阅读源码的时候花了不少时间去理解,实际上目前为止,也只是有比较基础的概念。对这部分,还有不少更深刻的内容须要去探究,在系统源码分析1一书中,有关于 Binder的很详细的解析,经过深刻了解 Binder 机制,我认为应该能更清楚 C/S 相关的内容。

  • 实际上,在与 HAL 层接触的这一部分,mModule 这个变量很是关键,可是我认为它的相关内容单独放在一篇笔记中分析,会比较清晰,因此下一篇笔记就先探究 module 相关的内容。
相关文章
相关标签/搜索