AndroidR上展讯CameraAPP的openCamera流程
看展讯平台的Camera有一段时间了,今天来整理下openCamera的流程。
其实,CameraAPP的主要逻辑可分为两大部分:界面显示 + camera处理。
展讯和MTK平台CameraAPP的共同点是两者都有Module的概念,即不同的Module处理app中不同的模式,比如拍照模式、美颜模式、录像模式等等。
但是在与camera这个硬件设备打交道的时候,设计却明显不同。MTK平台app是将UI的处理与camera处理均放在当前Module中处理,而展讯平台是Module只处理与当前模式相关的界面逻辑,而将camera操作统一封装,由专门的类去处理。
如下是处理与camera相关逻辑的类的继承关系
从图明显看出,在CameraAgent处分支了,一支类名中带有2,一支没有,这是与camera使用api1还是api2有关的。显然我们现在都是使用的api2,因此我们关注左边的分支。
与camera相关的打开、预览、拍照、数据callback、关闭等操作均在这几个类里面处理。
现在我们以普通的photo模式为例,来看下openCamera流程调用。
从PhotoModule的resume开始,
@Override
public void resume() {Log.i(TAG, "resume start!");//---此处省略与UI相关的处理requestCameraOpen();
}
流程转到requestCameraOpen方法
/*** Uses the {@link CameraProvider} to open the currently-selected camera* device, using {@link GservicesHelper} to choose between API-1 and API-2.*/protected void requestCameraOpen() {/*** SPRD: fix bug47362 Log.v(TAG, "requestCameraOpen");*//** SPRD:Fix bug 513841 KEY_CAMERA_ID may be changed during the camera in* background if user do switch camera action in contacts, and then we* resume the camera, the init function will not be called, so the* mCameraId will not be the latest one. Which will cause the switch* camera function can not be used. @{*/int mCameraID = mDataModule.getInt(Keys.KEY_CAMERA_ID);if(mIsImageCaptureIntent) {mCameraID = mDataModule.getInt(Keys.KEY_INTENT_CAMERA_ID);}if(mCameraID != mCameraId){mCameraId = mCameraID;mActivity.getCameraAppUI().updateModeList();}if (mCameraId == DreamUtil.FRONT_CAMERA && isSupportSensoSelfShotModule()) {mCameraId = CameraUtil.SENSOR_SELF_SHOT_CAMERA_ID;}/* @} *//*start add for w+t*/if (CameraUtil.isWPlusTAbility(mActivity,mActivity.getCurrentModuleIndex(),mCameraId)){mCameraId = CameraUtil.BACK_W_PLUS_T_PHOTO_ID;}/*end add for w+t*/// if (mActivity.getCurrentModuleIndex() == SettingsScopeNamespaces.AUTO_PHOTO && !DreamUtil.isFrontCamera(mActivity,mCameraId)) {if (CameraUtil.isTcamAbility(mActivity,mActivity.getCurrentModuleIndex(),mCameraId)) {mCameraId = CameraUtil.BACK_TRI_CAMERA_ID;}/*** SPRD: Change for New Feature VGesture and dream camera* original code* @{mActivity.getCameraProvider().requestCamera(mCameraId,GservicesHelper.useCamera2ApiThroughPortabilityLayer(mActivity.getContentResolver()));*/Log.i(TAG, "requestCameraOpen mCameraId:" + mCameraId);doCameraOpen(mCameraId);/*** @}*/}
此方法的前半部分是对mCameraId各种情况下的校验,最后是调用doCameraOpen(mCameraId)
protected void doCameraOpen(int cameraId){mActivity.getCameraProvider().requestCamera(cameraId, useNewApi());}
doCameraOpen方法很简单,就是将流程又转到 requestCamera,这里我们关注下 mActivity.getCameraProvider()是个什么类型。
在CameraActivity中,我们看到getCameraProvider就是CameraController类, 去看下CameraController。
public class CameraController implements CameraAgent.CameraOpenCallback, CameraProvider
CameraController 内容不多,因为实现了CameraAgent.CameraOpenCallback,所以其主要内容是camera状态的回调,但是并不处理这些回调,是在在接收到回调后,转发给相应的处理者。
还是回到从PhotoModule跟过来的requestCamera方法。
@Overridepublic void requestCamera(int id, boolean useNewApi) {Log.i(TAG, "requestCamera id="+id);Log.i(TAG, "mRequestingCameraId = " + mRequestingCameraId + "mInfo = " + mInfo);if (mRequestingCameraId != EMPTY_REQUEST || mRequestingCameraId == id) {return;}mRequestingCameraId = id;mActiveCameraDeviceTracker.onCameraOpening(CameraId.fromLegacyId(id));// Only actually use the new API if it's supported on this device.useNewApi = mCameraAgentNg != null && useNewApi;CameraAgent cameraManager = useNewApi ? mCameraAgentNg : mCameraAgent;if (mCameraProxy == null) {// No camera yet.checkAndOpenCamera(cameraManager, id, mCallbackHandler, this);} else if (mCameraProxy.getCameraId() != id || mUsingNewApi != useNewApi) {boolean syncClose = GservicesHelper.useCamera2ApiThroughPortabilityLayer(mContext.getContentResolver());Log.v(TAG, "different camera already opened, closing then reopening");mCameraProxy = null;// Already has camera opened, and is switching cameras and/or APIs.if (mUsingNewApi) {if (mCameraAgentNg != null)mCameraAgentNg.closeCamera(mCameraProxy, true);} else {// if using API2 ensure API1 usage is also syncedmCameraAgent.closeCamera(mCameraProxy, syncClose);}checkAndOpenCamera(cameraManager, id, mCallbackHandler, this);} else {// The same camera, just do a reconnect.Log.v(TAG, "reconnecting to use the existing camera");mCameraProxy.reconnect(mCallbackHandler, this);mCameraProxy = null;}mUsingNewApi = useNewApi;}
有与CameraAgent相关的:
CameraAgent cameraManager = useNewApi ? mCameraAgentNg : mCameraAgent;
我们在CameraAPP中可以看到很多类似的,通过useNewApi 这个boolean值判断使用哪个Agent,这其实就是我们前面说的api1与api2的兼容处理。
我们以打开CameraAPP,第一次请求openCamera的流程来跟踪,那么 mCameraProxy == null 是符合的,进入第一个if分支:checkAndOpenCamera
private static void checkAndOpenCamera(CameraAgent cameraManager,final int cameraId, Handler handler, final CameraAgent.CameraOpenCallback cb) {Log.i(TAG, "checkAndOpenCamera");try {CameraUtil.throwIfCameraDisabled();cameraManager.openCamera(handler, cameraId, cb);} catch (CameraDisabledException ex) {handler.post(new Runnable() {@Overridepublic void run() {cb.onCameraDisabled(cameraId);}});}}
关键代码:cameraManager.openCamera(handler, cameraId, cb);
而cameraManager就是前面通过useNewApi的boolean值判断得来的api2的那支的CameraAgent。
还记得最前面的那张继承关系图吗?
现在就要从CameraController中的openCamera方法转到那张继承关系图中的类了。
因为是继承关系,我也不知道具体的openCamera方法是在继承关系中的哪个类实现的,我们就一个个找吧。
最终在CameraAgent中找到了openCamera的实现:
public void openCamera(final Handler handler, final int cameraId,final CameraOpenCallback callback) {Log.e(TAG,"openCamera "+android.util.Log.getStackTraceString(new Throwable()));try {getDispatchThread().runJob(new Runnable() {@Overridepublic void run() {synchronized (mOpenCloseSyncLock) {isOpeningAndCloseNeedWait = true;}getCameraHandler().obtainMessage(CameraActions.OPEN_CAMERA, cameraId, 0,CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();}});} catch (final RuntimeException ex) {getCameraExceptionHandler().onDispatchThreadException(ex);}}
看来CameraAgent的openCamera也没做什么事情,就是通过handler–message机制转发了下CameraActions.OPEN_CAMERA消息。
再来追CameraActions.OPEN_CAMERA消息的处理
我们在AndoridCamera2AgentImpl中找到了
case CameraActions.OPEN_CAMERA:{CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;int cameraIndex = msg.arg1;if (mCameraState.getState() > AndroidCamera2StateHolder.CAMERA_UNOPENED) {openCallback.onDeviceOpenedAlready(cameraIndex,generateHistoryString(cameraIndex));break;}mOpenCallback = openCallback;mCameraIndex = cameraIndex;/** SPRD: Fix bug 591216 that add new feature 3d range finding, only support API2 currently @{* Original Code*mCameraId = mCameraDevices.get(mCameraIndex);*/mCameraId = "" + mCameraIndex;/* @} */Log.i(TAG, String.format("Opening camera index %d (id %s) with camera2 API",cameraIndex, mCameraId));if (mCameraId == null) {mOpenCallback.onCameraDisabled(msg.arg1);break;}reconnect = false;mCameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, this);break;
}
mCameraManager.openCamera,追到了CameraManager了。至此APP端的openCamera流程已经完成了。
最后,我们将上述流程画成时序图来总结下:
AndroidR上展讯CameraAPP的openCamera流程相关推荐
- Android R上展讯平台CameraAPP的Settings设置项管理
CameraAPP的设置项管理是CameraAPP中客户需求比较偏重的一部分,一般客户要添加新功能,都需要提供一个设置项开关出来.今天我们来整理下设置项的逻辑,先来看下设置项的截图: 我们知道,不同M ...
- 展讯 Camera 驱动流程 576 i 480i CVBS NTSC 摄像头调试
本文主要研究展讯平台Camera驱动和HAL层代码架构,熟悉展讯Camera的控制流程. 平台:Sprd-展讯平台 Hal版本:[HAL3] 知识点如下: 从HAL层到deiver层 1.Camera ...
- 展讯软件开发的一般流程
在开始前,得先在XP系统中配置好展讯平台的编译环境,并装好相关软件.然后接到 任务,说要将MP3界面做成什么样子,或是将主菜单改成什么样子,或是将系统中的 List控件做成什么什么风格,或是开发一个独 ...
- 展讯sprd_battery.c 充电驱动
sprd_battery.c 是充电驱动,这个是充电功能的核心内容,电量显示策略.温度检测策略.充电保护机制等功能在这里实现,功能实现与硬件细节剥离,调用通用接口实现逻辑控制: 1 sprdbat_p ...
- 揭秘财报:展讯击退联发科第一波攻势
先看一组数据: 上表体现了自展讯CEO李力游自2009年2月上任以来合计七个季度财报的表现,其中2009年Q1为李力游刚刚上任,Q2展讯财报步入谷底,巨亏1310万美元,之后五个季度连续实现盈利,老杳 ...
- 上任半年股票涨四倍,展讯CEO做了啥?
2009年7月28日,展讯股票飙升23.5%达到每股3.15美元,距离展讯CEO李力游2月13日上任不到5个月时间,展讯股票已经由之前的不到8毛美金升幅接近四倍,李力游这几个月做了什么? 半年不到,展 ...
- [置顶] 展讯充电管理模块浅析(一)
展讯充电管理模块浅析 电池在电子产品中所占的地位就不用说了.不过电池在物理接口上比较简单,就两条线:正极.负极,这个小学生科普知识都知道:不过真正用到电子产品中时,有关电池方面的东西还是有点多的. 参 ...
- 展讯充电管理模块浅析(一)
展讯充电管理模块浅析 电池在电子产品中所占的地位就不用说了.不过电池在物理接口上比较简单,就两条线:正极.负极,这个小学生科普知识都知道:不过真正用到电子产品中时,有关电池方面的东西还是有点多的. 参 ...
- 展讯android智能机平台FDL1,FDL2,SPL文件下载问题简析
首先,我们要了解这样一个背景知识:展讯的每颗智能芯片(其他智能机平台应该也是如此)内部都有IROM和IRAM,IROM里有固化的Romcode(用于与PC端工具通讯,下载程序). 但是...... 但 ...
- 展讯平台-sensor驱动
驱动者,三分硬件,三分格式,四分软件. 在手机中,我们常将camera直接称为sensor,展讯平台的sensor就像lcd一样,已经十分的成熟了.沿袭前面的模式,先介绍一下硬件的基本 ...
最新文章
- 缓存技术比拼:Redis与Memcached的同与不同
- SmartQuery WebPart 2.0 发布。
- 中小学python、人工智能书籍(2022.02.02)
- Vmware拓展虚拟机硬盘容量
- ACCESS模糊查询出现的变态问题,不知道该问题的希望注意,知道内幕的高手还望给小弟一个解释 Thanks...
- 对象数组根据某属性列的灵活排序
- 转 Silverlight开发历程—(画刷与着色之线性渐变画刷)
- android 声音突然变小,手机明明没坏,为什么声音开到最大依然很小?这个方法你知道吗...
- a标签提交form表单_Web前端开发基础知识,HTML中表单元素的理解
- 光猫上网问题 看我如何解决
- c语言运算符优先级(c语言运算符优先级由高到低的顺序)
- 阿里云服务器公网带宽下载上传速度及测速Ping值测试工具
- 20sccm_SCCM 完全手册
- 投影仪买哪个好?家用投影仪哪种好
- UnExpected Error, Quitting
- itext文本域自动换行_iText+Flying Saucer生成pdf文档,中文不显示和不自动换行问题...
- 如何修改QColorDialog窗口的背景颜色和上面的字体
- ios 简书 获取通讯录信息_ios 各种权限整理
- Python使用 matplotlib的basemap绘图之一--几行代码画世界地图和中国地图
- Autodesk Inventor Routed Systems: Harness Autodesk Inventor Routed Systems: Harness Lynda课程中文字幕