Android5.1 Camera Framework(一)
Android5.0 Camera Framework 简介
CameraService启动
CameraService是在MediaServer启动过程中进行的
main_mediaserver.cpp (frameworks\av\media\mediaserver)
......AudioFlinger::instantiate(); //audioflinger服务,音频相关MediaPlayerService::instantiate(); //mediaplayerservice,媒体播放相关CameraService::instantiate();//CameraServiceAudioPolicyService::instantiate(); //音频相关......
在 main函数中会执行到CameraService::instantiate(), CameraService 本身并没有实现这个方法
CameraService.cpp (frameworks\av\services\camera\libcameraservice)
CameraService.h (frameworks\av\services\camera\libcameraservice)
BinderService.h (frameworks\native\include\binder)
class CameraService : public BinderService<CameraService>, public BnCameraService, public IBinder::DeathRecipient, public camera_module_callbacks_t{ ......}
在其父类中寻找instantiate()函数,BinderService是一个模板类
template<typename SERVICE>class BinderService{public: static status_t publish(bool allowIsolated = false) { //BinderService::publish sp<IServiceManager> sm(defaultServiceManager()); //拿到ServiceManager的Bp return sm->addService( String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); //这里的SERVICE就是CameraService } ..... static void instantiate() { publish(); } //BinderService::instantiate .....};
这里会new CameraService(),
CameraService::CameraService() :mSoundRef(0), mModule(0){ ALOGI("CameraService started (pid=%d)", getpid()); gCameraService = this; //保存一个本地指针 for (size_t i = 0; i < MAX_CAMERAS; ++i) { mStatusList[i] = ICameraServiceListener::STATUS_PRESENT; } this->camera_device_status_change = android::camera_device_status_change;}
到这里,CameraService就启动了。
Camera连接过程
Camera.java (frameworks\base\core\java\android\hardware)
Camera.cpp (frameworks\av\camera)
android_hardware_Camera.cpp (frameworks\base\core\jni)
从java->jni->CPP的典型过程
首先从Camera.java入手,这里通过open()方法,创建Camera
public static Camera open(int cameraId) { return new Camera(cameraId); } public static Camera open() { int numberOfCameras = getNumberOfCameras(); CameraInfo cameraInfo = new CameraInfo(); for (int i = 0; i < numberOfCameras; i++) { getCameraInfo(i, cameraInfo); if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { return new Camera(i); } } return null; }
两个open()方法,默认打开后置摄像头,new Camera()对象,
Camera(int cameraId) { int err = cameraInitNormal(cameraId);//做事的主要地方 if (checkInitErrors(err)) { switch(err) { //通过返回的错误信息,抛不同的异常信息 case EACCESS: throw new RuntimeException("Fail to connect to camera service"); case ENODEV: throw new RuntimeException("Camera initialization failed"); default: // Should never hit this. throw new RuntimeException("Unknown camera error"); } } }
接下来看下代码,最后会落脚到哪一块呢?
private int cameraInitNormal(int cameraId) { //这里的CAMERA_HAL_API_VERSION_NORMAL_CONNECT后面会提到用来区别不同的connect return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT); } ...... private int cameraInitVersion(int cameraId, int halVersion) { mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; mPreviewCallback = null; mPostviewCallback = null; mUsingPreviewAllocation = false; mZoomListener = null; //初始化几个callback和一些变量 Looper looper; //mEventHandler后面会讲到是对底层上报内容的处理handler if ((looper = Looper.myLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else if ((looper = Looper.getMainLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else { mEventHandler = null; } String packageName = ActivityThread.currentPackageName(); return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName); }
可以看到native_setup是一个native方法,具体实现在
android_hardware_Camera.cpp (frameworks\base\core\jni)
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName){ ...... sp<Camera> camera; //之前在创建Camera对象的时候设置的一个常量,此时走到connect方法 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); } else { jint status = Camera::connectLegacy(cameraId, halVersion, clientName, Camera::USE_CALLING_UID, camera); if (status != NO_ERROR) { return status; } } ...... // We use a weak reference so the Camera object can be garbage collected. // The reference is only used as a proxy for callbacks. sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera); context->incStrong((void*)android_hardware_Camera_native_setup); camera->setListener(context);//listener用于处理底层数据上报 // save context in opaque field env->SetLongField(thiz, fields.context, (jlong)context.get()); return NO_ERROR;}
从JNI往下就是CPP,继续探寻Camera连接过程
Camera.cpp (frameworks\av\camera)
CameraBase.cpp (frameworks\av\camera)
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName, int clientUid){ //CameraBaseT为模板类 return CameraBaseT::connect(cameraId, clientPackageName, clientUid);}
CameraBase中connect函数模板替换成
sp<Camera> CameraBase<Camera, CameraTraits<Camera>>::connect(int cameraId, const String16& clientPackageName, int clientUid){ ALOGV("%s: connect", __FUNCTION__); sp<Camera> c = new Camera(cameraId); sp<ICameraClient> cl = c; status_t status = NO_ERROR; const sp<ICameraService>& cs = getCameraService();//获取CameraService的Bp if (cs != 0) { //这里TCamConncectService是一个函数指针,指向的是ICameraService中的connect方法 TCamConnectService fnConnectService = TCamTraits::fnConnectService; status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, /*out*/ c->mCamera); status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, /*out*/ c->mCamera); } if (status == OK && c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { ALOGW("An error occurred while connecting to camera: %d", cameraId); c.clear(); } return c;}
这里可能有点绕,稍微讲解一下,模板上
template
template <typename TCam>struct CameraTraits {};template <typename TCam, typename TCamTraits = CameraTraits<TCam> >
然后我们再到Camera.h中看
template <>
struct CameraTraits
{
typedef CameraListener TCamListener;
typedef ICamera TCamUser;
typedef ICameraClient TCamCallbacks;
typedef status_t (ICameraService::*TCamConnectService)(const sp&,
int, const String16&, int,
/out/
sp&);
static TCamConnectService fnConnectService;
};
中间有些过程,应该好理解了,这里绕了一下,最后落脚到ICameraService.cpp中的connect方法,这一部分涉及到Binder机制比较多,暂时先不讲解具体内容,注意调用的地方即可。
ICameraService.cpp (frameworks\av\camera)
// connect to camera service (android.hardware.Camera) virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId, const String16 &clientPackageName, int clientUid, /*out*/ sp<ICamera>& device) { Parcel data, reply; data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); data.writeStrongBinder(cameraClient->asBinder()); data.writeInt32(cameraId); data.writeString16(clientPackageName); data.writeInt32(clientUid); remote()->transact(BnCameraService::CONNECT, data, &reply);//通过binder远端调用传入的code为BnCameraservice::CONNECT if (readExceptionCode(reply)) return -EPROTO; status_t status = reply.readInt32(); if (reply.readInt32() != 0) { device = interface_cast<ICamera>(reply.readStrongBinder());//转换为BpCamera } return status; }
接下来或执行到BnCameraService的onTransact()方法,主要就是switch_case,上面传入的是CONNECT
status_t BnCameraService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ switch(code) { ...... case CONNECT: { CHECK_INTERFACE(ICameraService, data, reply); sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder()); int32_t cameraId = data.readInt32(); const String16 clientName = data.readString16(); int32_t clientUid = data.readInt32(); sp<ICamera> camera; status_t status = connect(cameraClient, cameraId, clientName, clientUid, /*out*/camera); //这里BnCameraService并没有实现connect函数,实际实现在CameraService中 reply->writeNoException(); reply->writeInt32(status); if (camera != NULL) { reply->writeInt32(1); reply->writeStrongBinder(camera->asBinder()); } else { reply->writeInt32(0); } return NO_ERROR; } break; ...... } }
我们来看一下CameraService中的connect方法到底做了哪些事情
status_t CameraService::connect( const sp<ICameraClient>& cameraClient, int cameraId, const String16& clientPackageName, int clientUid, /*out*/ sp<ICamera>& device) { String8 clientName8(clientPackageName); int callingPid = getCallingPid(); LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid, clientName8.string(), cameraId); //对当前连接请求合法性的判断 status_t status = validateConnect(cameraId, /*inout*/clientUid); if (status != OK) { return status; } //Client类继承BnCamera BasicClient sp<Client> client; { Mutex::Autolock lock(mServiceLock); sp<BasicClient> clientTmp; //判断当前设备是否被占有或者是重复请求 if (!canConnectUnsafe(cameraId, clientPackageName, cameraClient->asBinder(), /*out*/clientTmp)) { return -EBUSY;//从返回结果可以看出这个函数的用途 } else if (client.get() != NULL) { device = static_cast<Client*>(clientTmp.get()); return OK; } //考虑当前没有其他程序占用摄像头,走到下一步 status = connectHelperLocked(/*out*/client, cameraClient, cameraId, clientPackageName, clientUid, callingPid); if (status != OK) { return status; } } // important: release the mutex here so the client can call back // into the service from its destructor (can be at the end of the call) //赋值给device作为传出参数 device = client; return OK;}
继续跟踪到connectHelperLocked()函数中
status_t CameraService::connectHelperLocked( /*out*/ sp<Client>& client, /*in*/ const sp<ICameraClient>& cameraClient, int cameraId, const String16& clientPackageName, int clientUid, int callingPid, int halVersion, bool legacyMode) { int facing = -1; int deviceVersion = getDeviceVersion(cameraId, &facing); 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: //创建CameraClient对象 client = new CameraClient(this, cameraClient, clientPackageName, cameraId, facing, callingPid, clientUid, getpid(), legacyMode); break; case CAMERA_DEVICE_API_VERSION_2_0: case CAMERA_DEVICE_API_VERSION_2_1: case CAMERA_DEVICE_API_VERSION_3_0: case CAMERA_DEVICE_API_VERSION_3_1: case CAMERA_DEVICE_API_VERSION_3_2: client = new Camera2Client(this, cameraClient, clientPackageName, cameraId, facing, callingPid, clientUid, getpid(), legacyMode); break; case -1: ALOGE("Invalid camera id %d", cameraId); return BAD_VALUE; default: ALOGE("Unknown camera device HAL version: %d", deviceVersion); return INVALID_OPERATION; } } else { // A particular HAL version is requested by caller. Create CameraClient // based on the requested HAL version. if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 && halVersion == CAMERA_DEVICE_API_VERSION_1_0) { // Only support higher HAL version device opened as HAL1.0 device. client = new CameraClient(this, cameraClient, clientPackageName, cameraId, facing, callingPid, clientUid, getpid(), legacyMode); } else { // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet. ALOGE("Invalid camera HAL version %x: HAL %x device can only be" " opened as HAL %x device", halVersion, deviceVersion, CAMERA_DEVICE_API_VERSION_1_0); return INVALID_OPERATION; } } //主要是对CameraClient的初始化过程 status_t status = connectFinishUnsafe(client, client->getRemote()); if (status != OK) { // this is probably not recoverable.. maybe the client can try again return status; } //保存CameraClient对象到本地数组中,以备CameraService使用 mClient[cameraId] = client; LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid()); return OK;}
这里的client创建成功后会赋值给device,而device就是之前连接过程中的传入参数,到这里Camera的连接过程就基本完成了。
本文主要顺着代码理了一下过程,具体细节地方可能有所忽略。主要的流程图如下,欢迎交流指正。
本文中代码使用的是Android5.1原始代码
版权声明:本文为博主原创文章,未经博主允许不得转载。
更多相关文章
- android 五种Toast显示方法
- MTK android 下载及启动过程
- 关于AlertDialog中EditText不能弹出输入法解决方法
- android实现圆角矩形背景的方法
- Android RadioButton【单选按钮】的点击事件的两种方法
- android 跳转到系统相关应用的方法
- android屏幕信息获取的两种方法
- android os编译全过程
- Android中new Notification创建实例的最佳方法