各位早安
接着上个博客,今天继续跟踪代码.
在我跟踪代码的时候脑子里一直有个疑问,相机是怎么对焦的?今天就带着这个疑问来跟踪下代码解开心中的疑问.
第一步,先看下进入预览后相机是怎么启动对焦的
打开PhotoModule.java搜索关键字Focus
//这里需要给Camera Parameters传递一个FocusArea对象,代码对焦区域
private void setFocusAreasIfSupported() {
if (mFocusAreaSupported) {
mParameters.setFocusAreas(mFocusManager.getFocusAreas());
}
}
//FocusAreas对象在FocusOverlayManager里面创建
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void initializeMeteringAreas(int x, int y) {
if (mMeteringArea == null) {
mMeteringArea = new ArrayList<Object>();
mMeteringArea.add(new Area(new Rect(), 1));
}
// Convert the coordinates to driver format.
// AE area is bigger because exposure is sensitive and
// easy to over- or underexposure if area is too small.
calculateTapArea(x, y, 1.5f, ((Area) mMeteringArea.get(0)).rect);
}
//设置CameraParameters
// We separate the parameters into several subsets, so we can update only
// the subsets actually need updating. The PREFERENCE set needs extra
// locking because the preference can be changed from GLThread as well.
private void setCameraParameters(int updateSet) {
if (mCameraDevice == null) {
return;
}
synchronized (mCameraDevice) {
boolean doModeSwitch = false;
if ((updateSet & UPDATE_PARAM_INITIALIZE) != 0) {
updateCameraParametersInitialize();
}
if ((updateSet & UPDATE_PARAM_ZOOM) != 0) {
updateCameraParametersZoom();
}
if ((updateSet & UPDATE_PARAM_PREFERENCE) != 0) {
doModeSwitch = updateCameraParametersPreference();
}
mCameraDevice.setParameters(mParameters);
// Switch to gcam module if HDR+ was selected
if (doModeSwitch && !mIsImageCaptureIntent) {
mHandler.sendEmptyMessage(SWITCH_TO_GCAM_MODULE);
}
}
}
当预览界面被点击的时候会调用onSingleTapUp方法
// Preview area is touched. Handle touch focus.
@Override
public void onSingleTapUp(View view, int x, int y) {
if (mPaused || mCameraDevice == null || !mFirstTimeInitialized
|| mCameraState == SNAPSHOT_IN_PROGRESS
|| mCameraState == SWITCHING_CAMERA
|| mCameraState == PREVIEW_STOPPED) {
return;
}
//If Touch AF/AEC is disabled in UI, return
if(this.mTouchAfAecFlag == false) {
return;
}
// Check if metering area or focus area is supported.
if (!mFocusAreaSupported && !mMeteringAreaSupported) return;
if (! mFocusManager.getPreviewRect().contains(x, y)) return;
mFocusManager.onSingleTapUp(x, y);
}
//FocusOverlayManager类中的方法
public void onSingleTapUp(int x, int y) {
if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) return;
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_TOUCH_FOCUS, x + "," + y);
// Let users be able to cancel previous touch focus.
if ((mState == STATE_FOCUSING ||
mState == STATE_SUCCESS || mState == STATE_FAIL)) {
cancelAutoFocus();
}
if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) return;
// Initialize variables.
// Initialize mFocusArea.
if (mFocusAreaSupported) {
initializeFocusAreas(x, y);
}
// Initialize mMeteringArea.
if (mMeteringAreaSupported) {
initializeMeteringAreas(x, y);
}
// Use margin to set the focus indicator to the touched area.
mUI.setFocusPosition(x, y);
if (mZslEnabled) {
mTouchAFRunning = true;
}
// Stop face detection because we want to specify focus and metering area.
mListener.stopFaceDetection();
// Set the focus area and metering area.
mListener.setFocusParameters();//此处会更新Camera的参数,将新的对焦区域传给Camera
if (mFocusAreaSupported) {
autoFocus();
} else { // Just show the indicator in all other cases.
updateFocusUI();
// Reset the metering area in 3 seconds.
mHandler.removeMessages(RESET_TOUCH_FOCUS);
mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY);
}
}
这样Camera的参数被更新后预览界面就会刷新,就可以看到对焦成功的效果了.