首先说api1的预览流程
CameraActivity的onCreate先区分是不是安全模式(锁屏进入就是安全模式),如果是安全模式会设置flag
indowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED这个flag会在锁屏的时候显示出来
if (mSecureCamera) {
// Change the window flags so that secure camera can show when locked
Window win = getWindow();
WindowManager.LayoutParams params = win.getAttributes();
params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
if (intent.getComponent().getClassName().equals(GESTURE_CAMERA_NAME)) {
params.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
PowerManager pm = ((PowerManager) getSystemService(POWER_SERVICE));
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mWakeLock.acquire();
Log.d(TAG, "acquire wake lock");
}
win.setAttributes(params);
}
然后给moduleIndex赋值,第一次进入会赋值ModuleSwitcher.PHOTO_MODULE_INDEX
然后这里会有个api2的选择,如果你把开发者选项(设置里的红眼消除按五下)里的Camera2 Mode打开就会选择api2,也就是
moduleIndex 的值赋了 ModuleSwitcher.CAPTURE_MODULE_INDEX;
boolean cam2on = mSettingsManager.isCamera2On();
if (cam2on && moduleIndex == ModuleSwitcher.PHOTO_MODULE_INDEX)
moduleIndex = ModuleSwitcher.CAPTURE_MODULE_INDEX;
然后进入SetModuleFromIndex,通过moduleIndex给实例赋值,这里以拍照的module为例,如果是第一次进入就会走
mPhotoModule.init(this, mCameraPhotoModuleRootView);这里的PhotoModule就是mvc里的m.
case ModuleSwitcher.PHOTO_MODULE_INDEX:
if (mPhotoModule == null) {
mPhotoModule = new PhotoModule();
mPhotoModule.init(this, mCameraPhotoModuleRootView);
} else {
mPhotoModule.reinit();
}
mCurrentModule = mPhotoModule;
mCameraPhotoModuleRootView.setVisibility(View.VISIBLE);
break;
然后我们进入PhotoModule的init,在进入之前先看一下PhotoModule的定义,实现了10个接口,再看每一个类之前最好有看定义的习惯,能大体的知道这个类里面都干了什么
public class PhotoModule
implements
CameraModule,//拍照,录像都要实现的接口,装饰者模式的
PhotoController,// 按钮的点击事件处理接口ShutterButton.OnShutterButtonListener
FocusOverlayManager.Listener,//处理所有焦点的类
CameraPreference.OnPreferenceChangedListener,//处理
ShutterButton.OnShutterButtonListener,//按钮的点击事件处理接口
MediaSaveService.Listener,//
OnCountDownFinishedListener,//
LocationManager.Listener,//
SensorEventListener,//
MakeupLevelListener {//
现在看init,就是做了初始化ui和开启openCamera线程.
mUI = new PhotoUI(activity, this, parent);
if (mOpenCameraThread == null) {
mOpenCameraThread = new OpenCameraThread();
mOpenCameraThread.start();
}
这里的ui就是mvc里的view,负责显示所有的控件,包括surfaceview和mSurfaceHolder的初始化
mSurfaceView = (SurfaceView) mRootView.findViewById(R.id.mdp_preview_content);
mSurfaceView.setVisibility(View.VISIBLE);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
这里要说一下SurfaceView和SurfaceHolder,surface的关系,SurfaceView可以理解成比普通的view多个surface,然后SurfaceView通过SurfaceHolder控制surface,surface就是用来显示camera的图像的,SurfaceHolder有三个callback,分别是
surfaceChanged(),surface首次显示在屏幕上调用该方法
surfaceCreated(),surfaceview的视图层级结构被放到屏幕上时调用该方法
surfaceDestroyed(),surface销毁时调用
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.v(TAG, "surfaceChanged: width =" + width + ", height = " + height);
RectF r = new RectF(mSurfaceView.getLeft(), mSurfaceView.getTop(),
mSurfaceView.getRight(), mSurfaceView.getBottom());
mController.onPreviewRectChanged(CameraUtil.rectFToRect(r));
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v(TAG, "surfaceCreated");
mSurfaceHolder = holder;
mController.onPreviewUIReady();
mActivity.updateThumbnail(mThumbnail);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v(TAG, "surfaceDestroyed");
mSurfaceHolder = null;
mController.onPreviewUIDestroyed();
}
然后我们继续看mOpenCameraThread,这个thread调用了openCamera
private class OpenCameraThread extends Thread {
@Override
public void run() {
openCamera();
startPreview();
}
}
openCamera里调用了
mCameraDevice = CameraUtil.openCamera(
mActivity, mCameraId, mHandler,
mActivity.getCameraOpenErrorCallback());
然后CameraUtil里调用了CameraHolder.instance().open(handler, cameraId, cb);
public static CameraManager.CameraProxy openCamera(
Activity activity, final int cameraId,
Handler handler, final CameraManager.CameraOpenErrorCallback cb) {
try {
throwIfCameraDisabled(activity);
return CameraHolder.instance().open(handler, cameraId, cb);
} catch (CameraDisabledException ex) {
handler.post(new Runnable() {
@Override
public void run() {
cb.onCameraDisabled(cameraId);
}
});
}
return null;
}
CameraHolder的open又调用了
mCameraDevice = CameraManagerFactory .getAndroidCameraManager().cameraOpen(handler, cameraId, cb);
mCameraDevice = CameraManagerFactory
.getAndroidCameraManager().cameraOpen(handler, cameraId, cb);
而这个CameraManagerFactory .getAndroidCameraManager()返回的是AndroidCameraManagerImpl的实例
public class CameraManagerFactory {
private static AndroidCameraManagerImpl sAndroidCameraManager;
/**
* Returns the android camera implementation of {@link CameraManager}.
*
* @return The {@link CameraManager} to control the camera device.
*/
public static synchronized CameraManager getAndroidCameraManager() {
if (sAndroidCameraManager == null) {
sAndroidCameraManager = new AndroidCameraManagerImpl();
}
return sAndroidCameraManager;
}
}
所以openCamera其实最终调用的是AndroidCameraManagerImpl里的cameraOpen方法,也就是通过反射调用的camera的openLegacy,就是api1的标准接口,现在就和底层通信上了
try {
Method openMethod = Class.forName("android.hardware.Camera").getMethod(
"openLegacy", int.class, int.class);
mCamera = (android.hardware.Camera) openMethod.invoke(
null, msg.arg1, CAMERA_HAL_API_VERSION_1_0);
} catch (Exception e) {
/* Retry with open if openLegacy doesn't exist/fails */
Log.v(TAG, "openLegacy failed due to " + e.getMessage()
+ ", using open instead");
mCamera = android.hardware.Camera.open(msg.arg1);
}
然后子线程继续调用startPreview,主要做的就是1,把camera和SurfaceHolder绑定上,mCameraDevice.setPreviewDisplay(sh);2,设置camera的参数setCameraParameters. 3开始预览mCameraDevice.startPreview();
private void startPreview() {
if (mPaused || mCameraDevice == null || mParameters == null) {
return;
}
synchronized (mCameraDevice) {
SurfaceHolder sh = null;
Log.v(TAG, "startPreview: SurfaceHolder (MDP path)");
if (mUI != null) {
sh = mUI.getSurfaceHolder();
}
// Let UI set its expected aspect ratio
mCameraDevice.setPreviewDisplay(sh);//camera和SurfaceHolder绑定上
}
if (!mCameraPreviewParamsReady) {
Log.w(TAG, "startPreview: parameters for preview are not ready.");
return;
}
mErrorCallback.setActivity(mActivity);
mCameraDevice.setErrorCallback(mErrorCallback);
// ICS camera frameworks has a bug. Face detection state is not cleared 1589
// after taking a picture. Stop the preview to work around it. The bug
// was fixed in JB.
if (mCameraState != PREVIEW_STOPPED && mCameraState != INIT) {
stopPreview();
}
if (!mSnapshotOnIdle) {
mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
}
setCameraParameters(UPDATE_PARAM_ALL);
mCameraDevice.setOneShotPreviewCallback(mHandler,
new CameraManager.CameraPreviewDataCallback() {
@Override
public void onPreviewFrame(byte[] data, CameraProxy camera) {
mUI.hidePreviewCover();
}
});
Log.w("fy","startPreview--"+Log.getStackTraceString(new Throwable()));
mCameraDevice.startPreview();
mHandler.sendEmptyMessage(ON_PREVIEW_STARTED);
setDisplayOrientation();
if (!mSnapshotOnIdle && !mInstantCaptureSnapShot) {
// If the focus mode is continuous autofocus, call cancelAutoFocus to
// resume it because it may have been paused by autoFocus call.
if (CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())) {
mCameraDevice.cancelAutoFocus();
}
} else {
Log.v(TAG, "Trigger snapshot from start preview.");
mHandler.post(mDoSnapRunnable);
}
}
这里的setCameraParameters会调用了updateCameraParametersPreference,主要的功能就是将数据库中的数据
PictureSize,PreviewSize,flash,照片质量等数据设置给camera,mCameraDevice.setParameters(mParameters);
这个时候主线程也同时调用cameraActivity的onResume,会调用mCurrentModule.onResumeBeforeSuper();和
mCurrentModule.onResumeAfterSuper();
@Override
public void onResume() {
...
mCurrentModule.onResumeBeforeSuper();
super.onResume();
mPaused = false;
mCurrentModule.onResumeAfterSuper();
在PhotoModule的onResumeAfterSuper里调用了onResumeTasks();
@Override
public void onResumeAfterSuper() {
mLastPhotoTakenWithRefocus = false;
mUI.showSurfaceView();
// Add delay on resume from lock screen only, in order to to speed up
// the onResume --> onPause --> onResume cycle from lock screen.
// Don't do always because letting go of thread can cause delay.
String action = mActivity.getIntent().getAction();
if (MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA.equals(action)
|| MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action)) {
Log.v(TAG, "On resume, from lock screen.");
// Check if there is a need to take a snapshot without
// waiting for the shutter click
if (isInstantCaptureEnabled()) {
mInstantCaptureSnapShot = true;
}
// Note: onPauseAfterSuper() will delete this runnable, so we will
// at most have 1 copy queued up.
mHandler.postDelayed(new Runnable() {
public void run() {
onResumeTasks();
}
}, ON_RESUME_TASKS_DELAY_MSEC);
} else {
Log.v(TAG, "On resume.");
onResumeTasks();
}
而onResumeTasks里主要是调用了initializeSecondTime,作用是初始化MediaSaveService和NameImage用来保存的
private void initializeSecondTime() {
// Start location update if needed.
boolean recordLocation = RecordLocationPreference.get(mPreferences);
mLocationManager.recordLocation(recordLocation);
MediaSaveService s = mActivity.getMediaSaveService();
if (s != null) {
s.setListener(this);
}
mNamedImages = new NamedImages();
if (!mIsImageCaptureIntent) {
mUI.showSwitcher();
}
mUI.initializeSecondTime(mParameters);
}
这样预览的整个流程就走下来了。
总结:
1在xml布局中定义一个SurfaceView,用于预览相机采集的数据
2给SurfaceHolder添加回调,在surfaceCreated(holder: SurfaceHolder?)回调中打开相机
3成功打开相机后,设置相机参数。比如:对焦模式,预览大小,照片保存大小等等
4设置相机预览时的旋转角度,然后调用startPreview()开始预览
拍照流程先看ShutterButton的performClick,调用了mListener.onShutterButtonClick();
@Override
public boolean performClick() {
boolean result = super.performClick();
if (mListener != null && getVisibility() == View.VISIBLE) {
mListener.onShutterButtonClick();
}
return result;
}
而PhotoModule实现了这个接口,最终调用了PhotoModule的onShutterButtonClick
先看是不是倒计时拍照,不是就调用initiateSnap();
@Override
public synchronized void onShutterButtonClick() {
...
String timer = mPreferences.getString(
CameraSettings.KEY_TIMER,
mActivity.getString(R.string.pref_camera_timer_default));
boolean playSound = mPreferences.getString(CameraSettings.KEY_TIMER_SOUND_EFFECTS,
mActivity.getString(R.string.pref_camera_timer_sound_default))
.equals(mActivity.getString(R.string.setting_on_value));
int seconds = Integer.parseInt(timer);
// When shutter button is pressed, check whether the previous countdown is
// finished. If not, cancel the previous countdown and start a new one.
if (mUI.isCountingDown()) {
mUI.cancelCountDown();
}
if (seconds > 0) {
String zsl = mPreferences.getString(CameraSettings.KEY_ZSL,
mActivity.getString(R.string.pref_camera_zsl_default));
mUI.overrideSettings(CameraSettings.KEY_ZSL, zsl);
mUI.startCountDown(seconds, isShutterSoundOn());
} else {
mSnapshotOnIdle = false;
initiateSnap();
}
}
然后在initiateSnap中要看是不是自拍,是自拍要启线程调用mFocusManager.doSnap();不是自拍直接调用mFocusManager.doSnap()
private void initiateSnap() {
if (mPreferences.getString(CameraSettings.KEY_SELFIE_FLASH,
mActivity.getString(R.string.pref_selfie_flash_default))
.equalsIgnoreCase("on") &&
mCameraId == CameraHolder.instance().getFrontCameraId()) {//自拍闪光灯
mUI.startSelfieFlash();
if (selfieThread == null) {
selfieThread = new SelfieThread();
selfieThread.start();
}
} else {
mFocusManager.doSnap();
}
}
然后doSnap会调用capture,会最终调用mListener.capture().
public void doSnap() {
if (!mInitialized) return;
// If the user has half-pressed the shutter and focus is completed, we
// can take the photo right away. If the focus mode is infinity, we can
// also take the photo.
if (!needAutoFocusCall() || (mState == STATE_SUCCESS || mState == STATE_FAIL)) {
capture();
} else if (mState == STATE_FOCUSING) {
// Half pressing the shutter (i.e. the focus button event) will
// already have requested AF for us, so just request capture on
// focus here.
mState = STATE_FOCUSING_SNAP_ON_FINISH;
} else if (mState == STATE_IDLE) {
// We didn't do focus. This can happen if the user press focus key
// while the snapshot is still in progress. The user probably wants
// the next snapshot as soon as possible, so we just do a snapshot
// without focusing again.
capture();
}
}
这个mListener是PhotoModule,所以调用了PhotoModule的capture()
首先调用了mCaptureStartTime = System.currentTimeMillis();记录系统的当前时间
mReceivedSnapNum = 0;是当前的张数,最终调用了mCameraDevice.takePicture(mHandler, new ShutterCallback(!animateBefore), mRawPictureCallback, mPostViewPictureCallback, new JpegPictureCallback(loc));
@Override
public boolean capture() {
// If we are already in the middle of taking a snapshot or the image save request
// is full then ignore.
Log.w(TAG,"capture");
if (mCameraDevice == null || mCameraState == SNAPSHOT_IN_PROGRESS
|| mCameraState == SWITCHING_CAMERA
|| mActivity.getMediaSaveService() == null
|| mActivity.getMediaSaveService().isQueueFull()) {
return false;
}
mCaptureStartTime = System.currentTimeMillis();
mPostViewPictureCallbackTime = 0;
mJpegImageData = null;
final boolean animateBefore = (mSceneMode == CameraUtil.SCENE_MODE_HDR);
if(mHiston) {
if (mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL) {
mHiston = false;
mCameraDevice.setHistogramMode(null);
}
mActivity.runOnUiThread(new Runnable() {
public void run() {
if(mGraphView != null)
mGraphView.setVisibility(View.INVISIBLE);
}
});
}
if (animateBefore) {
animateAfterShutter();
}
if (mCameraState == LONGSHOT) {
mCameraDevice.setLongshot(true);
}
// Set rotation and gps data.
int orientation = mOrientation;
mJpegRotation = CameraUtil.getJpegRotation(mCameraId, orientation);
String pictureFormat = mParameters.get(KEY_PICTURE_FORMAT);
Location loc = getLocationAccordPictureFormat(pictureFormat);
synchronized (mCameraDevice) {
if (mCameraId == CAMERA_ID_MAIN) {
mParameters.setFlashMode(Parameters.FLASH_MODE_OFF);
}
mParameters.setRotation(mJpegRotation);
CameraUtil.setGpsParameters(mParameters, loc);
if (mRefocus) {
mParameters.set(CameraSettings.KEY_QC_LEGACY_BURST,
CameraSettings.KEY_QC_RE_FOCUS_COUNT);
} else {
mParameters.remove(CameraSettings.KEY_QC_LEGACY_BURST);
}
// Unlock AE&AWB, if they continue
// to be locked during snapshot, then
// side effects could be triggered w.r.t.
// flash.
mFocusManager.setAeAwbLock(false);
setAutoExposureLockIfSupported();
setAutoWhiteBalanceLockIfSupported();
mCameraDevice.setParameters(mParameters);
mParameters = mCameraDevice.getParameters();
}
mBurstSnapNum = mParameters.getInt("num-snaps-per-shutter");
mReceivedSnapNum = 0;
mPreviewRestartSupport = SystemProperties.getBoolean(
PERSIST_PREVIEW_RESTART, false);
mPreviewRestartSupport &= CameraSettings.isInternalPreviewSupported(
mParameters);
mPreviewRestartSupport &= (mBurstSnapNum == 1);
// Restart is needed if HDR is enabled
mPreviewRestartSupport &= !CameraUtil.SCENE_MODE_HDR.equals(mSceneMode);
mPreviewRestartSupport &= PIXEL_FORMAT_JPEG.equalsIgnoreCase(
pictureFormat);
// We don't want user to press the button again while taking a
// multi-second HDR photo. For longshot, no need to disable.
if (mCameraState != LONGSHOT) {
mUI.enableShutter(false);
}
if (!isShutterSoundOn()) {
mCameraDevice.enableShutterSound(false);
} else {
mCameraDevice.enableShutterSound(!mRefocus);
}
Log.w(TAG,"mCameraState="+mCameraState);
if (mCameraState == LONGSHOT) {
mLongShotCaptureCountLimit = SystemProperties.getInt(
"persist.camera.longshot.shotnum", 0);
mLongShotCaptureCount = 1;
Log.w(TAG,"mLongshotSave1="+mLongshotSave);
if(mLongshotSave) {
mCameraDevice.takePicture(mHandler,
new LongshotShutterCallback(),
mRawPictureCallback, mPostViewPictureCallback,
new LongshotPictureCallback(loc));
} else {
mCameraDevice.takePicture(mHandler,
new LongshotShutterCallback(),
mRawPictureCallback, mPostViewPictureCallback,
new JpegPictureCallback(loc));
}
} else {
mCameraDevice.takePicture(mHandler,
new ShutterCallback(!animateBefore),
mRawPictureCallback, mPostViewPictureCallback,
new JpegPictureCallback(loc));
setCameraState(SNAPSHOT_IN_PROGRESS);
}
mNamedImages.nameNewImage(mCaptureStartTime, mRefocus);
if (mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL) {
mFaceDetectionStarted = false;
}
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
UsageStatistics.ACTION_CAPTURE_DONE, "Photo", 0,
UsageStatistics.hashFileName(mNamedImages.mQueue.lastElement().title + ".jpg"));
return true;
}
这里的takePicture(shutter, raw, postView, jpeg)里面的参数分别是
shutter是在加工处理原始图像数据且没有存储之前,图像捕捉时刻的回调,或为空
raw原始(未压缩)图像数据的回调
postview包含postview图像数据的回调(一般需要硬件支持)
jpeg jpeg图像数据的回调
骁龙camera里只实现了shutter和jpeg数据的回调,shutter主要做的事情