在Camera中,autofocus是个很重要的知识点,一般有移动对焦,点击聚焦和长按聚焦,这里我们以展锐平台相机的点击聚焦为例,分析下聚焦在app层的流程。
点击屏幕事件的触发
PhotoModule.java的onSingleTapUp中
public void onSingleTapUp(View view, int x, int y) {
......
//调用FocusManager的singletap
mFocusManager.onSingleTapUp(x, y);
}
FocusOverlayManager.java的onSingleTapUp中
public void onSingleTapUp(int x, int y) {
lastSingleTap.set(x,y);
//如果当前已经是定焦的,取消定焦,重新对焦
if(isAFLock) {
sendCancleMsg(false);
mListener.setAELock(false);
isAFLock = false;
}
//没有初始化或者拍照前的聚焦的状态,直接返回
if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
return;
}
//让用户可以取消掉之前未消失的触摸聚焦
if ((mFocusArea != null) && (mState == STATE_FOCUSING ||
mState == STATE_SUCCESS || mState == STATE_FAIL)) {
cancelAutoFocus();
}
if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) {
return;
}
// Initialize variables.
if (mAutoChasingSupported && mAutoChasingEnable){
boolean isChasing = isAutoChasing();
if (isChasing) {
initializeAutoChasingRegion(0,0);
Log.d(TAG,"set chasing Region x = 0 , y = 0");
mListener.setAutoChasingParameters();
}
}
//初始化聚焦的区域
// Initialize mFocusArea.
if (mFocusAreaSupported) {
initializeFocusAreas(x, y);
mFocusRing.setFocusLocation(x, y);
}
// Initialize mMeteringArea.
if (mMeteringAreaSupported) {
initializeMeteringAreas(x, y);
}
// Log manual tap to focus.
mTouchCoordinate = new TouchCoordinate(x, y, mPreviewRect.width(), mPreviewRect.height());
mTouchTime = System.currentTimeMillis();
//停止人脸识别,因为要进行识别聚焦和测量area
mListener.stopFaceDetection();
//设置聚焦区域&测量区域
mListener.setFocusParameters();
if (mFocusAreaSupported) {
autoFocus();//开始对焦
} else { // Just show the indicator in all other cases.
// Reset the metering area in 4 seconds.
mHandler.removeMessages(RESET_TOUCH_FOCUS);
mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS);
}
}
接着看FocusOverlayManager这里的autoFocus()方法
private void autoFocus(int focusingState) {
//监听autofocus,这里autofocus的实现是PhotoModule中
mListener.autoFocus();
//当前focus的状态设置成正在focus
mState = focusingState;
//更新正在对焦的对焦框ui
updateFocusUI();
mHandler.removeMessages(RESET_TOUCH_FOCUS);
initializeCameraSound();
}
在PhotoMudule.java中的autoFocus()中
@Override
public void autoFocus() {
if (mCameraDevice == null) {
return;
}
mNeedCancelAutoFocus = true;
mFocusStartTime = System.currentTimeMillis();
//设置Camera的回调聚焦
mCameraDevice.autoFocus(mHandler, mAutoFocusCallback);
//设置相机的状态为FOCUSING
setCameraState(FOCUSING);
}
接着看上层对于聚焦的回调处理,在PhotoModule中有内部类AutoFocusCallback
private final class AutoFocusCallback implements CameraAFCallback {
@Override
public void onAutoFocus(boolean focused, CameraProxy camera) {
//如果是暂停状态,不聚焦
if (mPaused) {
return;
}
//算出当前到聚焦开始的时间差
mAutoFocusTime = System.currentTimeMillis() - mFocusStartTime;
//设置Camera状态为IDLE
setCameraState(IDLE);
//调用FocusManager中的onAutoFocus
mFocusManager.onAutoFocus(focused, false);
}
}
接着去看聚焦完成的具体处理
在FocusManager的onAutoFocus中
public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
//正在进行聚焦,拍照动作必须再聚焦完之后
if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
// 无论聚焦成功还是失败,都会拍照。如果要进行拍照发声,就无需AF发声了
if (focused) {
//聚焦成功
mState = STATE_SUCCESS;
} else {
//聚焦失败
mState = STATE_FAIL;
}
//更新聚焦完成的ui以及各种状态的设置
updateFocusUI();
//拍照,mState的状态变为STATE_IDLE
capture();
//如果是聚焦中的状态
} else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
//此状态的发生分为两种,half-pressing按压聚焦或者触摸聚焦被触发,这个时候不要发生拍照动作
if (focused) {
mState = STATE_SUCCESS;
} else {
mState = STATE_FAIL;
}
//如果是触摸聚焦,需要延迟一下取消掉聚焦
if (mFocusArea != null) {
mFocusLocked = true;
if(!isAFLock) {
mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS);
}
}
//更新聚焦完成的ui
if(!isAFLock) {
updateFocusUI();
autoChase();
} else {
mFocusRing.setAELockColor(true);
}
if (shutterButtonPressed) {
// Lock AE & AWB so users can half-press shutter and recompose.
lockAeAwbIfNeeded();
}
} else if (mState == STATE_IDLE) {
// User has released the focus key before focus completes.
// Do nothing.
}
}
在FocusManager()中的cancleAutofocus()
private void cancelAutoFocus() {
//清除聚焦区域
clearAfArea();
mMeteringArea = null;
//监听cancelAutoFocus,在PhotoModule中实现
mListener.cancelAutoFocus();
//重置聚焦,聚焦框恢复到屏幕中间
resetTouchFocus();
//改变聚焦状态
mState = STATE_IDLE;
mFocusLocked = false;
//移除msg
mHandler.removeMessages(RESET_TOUCH_FOCUS);
}
在PhotoModule的cancelAutoFocus()中
public void cancelAutoFocus() {
if (mCameraDevice == null) {
return;
}
//取消底层聚焦
mCameraDevice.cancelAutoFocus();
//设置相机状态
setCameraState(IDLE);
if (mFace != null && mFace
&& isCameraIdle() && !isHdr() ) {
//开始人脸检测
startFaceDetection();
}
setCameraParameters(UPDATE_PARAM_PREFERENCE);
}
以上就是app层聚焦的大致流程
前面有好几处有更新ui的操作,我们来看一下具体做了些什么,其实就是对于聚焦框的改变与展示。
在FucusManager的updateFocusUI中:
public void updateFocusUI() {
//没有初始化完成
if (!mInitialized) {
// Show only focus indicator or face indicator.
return;
}
//聚焦开始,mFocusRing为聚焦框,可自定义
if (mState == STATE_IDLE) {
if (mFocusArea != null) {
mFocusRing.startActiveFocus();
}
//正在聚焦
} else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
if (mFocusArea == null) {
mFocusRing.centerFocusLocation();
}
mFocusRing.startActiveFocus();
} else {
//聚焦成功
if (mState == STATE_SUCCESS) {
//拍照
if (mTouchListener != null) {
mTouchListener.touchCapture();
}
//聚焦完成显示的对焦框
mFocusRing.startActiveFocusedFocus();
//聚焦成功的声音
if (mFocusArea != null) {
if (mAppController.isPlaySoundEnable()) {
mCameraSound.play(MediaActionSound.FOCUS_COMPLETE);
}
} else {
mFocusRing.centerFocusLocation();
}
//聚焦失败
} else if (mState == STATE_FAIL) {
if (mTouchListener != null) {
mTouchListener.touchCapture();
}
mFocusRing.startActiveFocusedFocus();
}
}
}
聚焦过程中,相机状态的改变和聚焦状态的改变
在PhotoModule中设置相机状态:
protected void setCameraState(int state) {
mCameraState = state;
switch (state) {
case PREVIEW_STOPPED:
case SNAPSHOT_IN_PROGRESS:
case SWITCHING_CAMERA:
// TODO: Tell app UI to disable swipe
break;
case PhotoController.IDLE:
// TODO: Tell app UI to enable swipe
break;
}
}
STATE_IDLE:空闲状态
capture():空闲状态可以执行拍照
onAutoFocus(boolean focused):用户再聚焦完成前放掉了聚焦按钮,所以不做任何事。
onPreviewStarted(),onPreviewStopped():状态都变为空闲
cancelAutoFocus():取消聚焦,状态变为空闲
updateFocusUI():如果空闲&有聚焦区域,显示聚焦框
STATE_FOCUSING:正在对焦
onShutterUp():如果是focusmode为自动聚焦,状态为正在聚焦,则取消掉聚焦
capture():如果是正在聚焦状态,将状态改为聚焦完拍照状态
onAutoFocus(boolean focused, boolean shutterButtonPressed):判断focused,为true变为聚焦成功状态,为false变为聚焦失败状态
onSingleTapUp(int x, int y):如果正在聚焦&之前有手动聚焦了,则取消掉之前的聚焦
autoFocus():状态变为聚焦状态
updateFocusUI():显示聚焦框
STATE_FOCUSING_SNAP_ON_FINISH:聚焦完拍照
onShutterUp():状态不是聚焦完拍照,可以设置FocusParameters
onAutoFocus(boolean focused, boolean shutterButtonPressed):判断focused,为true变为聚焦成功状态,为false变为聚焦失败状态,更新聚焦框UI
onSingleTapUp(int x, int y):直接不继续操作下去
updateFocusUI():显示聚焦框
STATE_SUCCESS:聚焦成功
onShutterDown():如果是自动聚焦mode,并且不为聚焦成功状态,执行聚焦
onShutterUp(): 如果是自动聚焦mode,并且为聚焦成功状态,执行取消聚焦
capture():拍照
onSingleTapUp(int x, int y):让用户可以取消掉之前未消失的触摸聚焦
updateFocusUI():聚焦框显示成功
STATE_FAIL:聚焦失败
onShutterDown():如果是自动聚焦mode,并且不为聚焦失败状态,执行聚焦
onShutterUp(): 如果是自动聚焦mode,并且为聚焦失败状态,执行取消聚焦
capture():拍照
onSingleTapUp(int x, int y):让用户可以取消掉之前未消失的触摸聚焦
updateFocusUI():聚焦框显示失败
关于底层的实现,主要是聚焦命令的下发(开始聚焦和结束聚焦),以及聚焦完成的回调
//开始聚焦
mCameraDevice.autoFocus(mHandler, mAutoFocusCallback);//mCameraDevice为CameraProxy的引用,mAutoFocusCallback为聚焦完成的回调
//取消聚焦
mCameraDevice.cancelAutoFocus();
CameraProxy为CameraAgent的内部类
具体实现又在AndroidCamera2AgentImpl中,有兴趣的朋友可以自行查看源码