From 87b4a40d588a7ae8a61cb353c4cff8df37f7b483 Mon Sep 17 00:00:00 2001 From: Sai Kumar Sanagavarapu Date: Wed, 2 Jul 2014 11:59:05 +0530 Subject: Camera: open Camera and start Preview in a seperate thread. Start openCamera and start preview in a separate thread so that UI initialization and preview can run parallely. This is to improve camera cold start latency. Change-Id: I57af45bc90a4db1630c73449d543c3ff0992e55c --- src/com/android/camera/CameraActivity.java | 3 + src/com/android/camera/PhotoController.java | 2 +- src/com/android/camera/PhotoMenu.java | 3 +- src/com/android/camera/PhotoModule.java | 161 ++++++++++++++++++---------- src/com/android/camera/PhotoUI.java | 10 +- 5 files changed, 119 insertions(+), 60 deletions(-) diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index 36b5111ca..c40dacc0a 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -176,6 +176,7 @@ public class CameraActivity extends Activity private ViewGroup mUndoDeletionBar; private boolean mIsUndoingDeletion = false; private boolean mIsEditActivityInProgress = false; + protected boolean mIsModuleSwitchInProgress = false; private Uri[] mNfcPushUris = new Uri[1]; @@ -1428,6 +1429,7 @@ public class CameraActivity extends Activity return; } + mIsModuleSwitchInProgress = true; CameraHolder.instance().keep(); closeModule(mCurrentModule); setModuleFromIndex(moduleIndex); @@ -1442,6 +1444,7 @@ public class CameraActivity extends Activity // starts up. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.edit().putInt(CameraSettings.KEY_STARTUP_MODULE_INDEX, moduleIndex).apply(); + mIsModuleSwitchInProgress = false; } /** diff --git a/src/com/android/camera/PhotoController.java b/src/com/android/camera/PhotoController.java index c1c3a8562..b08f8c088 100644 --- a/src/com/android/camera/PhotoController.java +++ b/src/com/android/camera/PhotoController.java @@ -23,7 +23,7 @@ import com.android.camera.ShutterButton.OnShutterButtonListener; public interface PhotoController extends OnShutterButtonListener { - + public static final int INIT = -1; public static final int PREVIEW_STOPPED = 0; public static final int IDLE = 1; // preview is active // Focus is in progress. The exact focus state is in Focus.java. diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java index 096a8524e..3132a7928 100644 --- a/src/com/android/camera/PhotoMenu.java +++ b/src/com/android/camera/PhotoMenu.java @@ -254,7 +254,8 @@ public class PhotoMenu extends PieController } super.overrideSettings(keyvalues); - if ((mPopup1 == null) && (mPopup2 == null) && (mPopup3 == null)) initializePopup(); + if ((mPopup1 == null) || (mPopup2 == null) || (mPopup3 == null)) initializePopup(); + mPopup1.overrideSettings(keyvalues); mPopup2.overrideSettings(keyvalues); mPopup3.overrideSettings(keyvalues); diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index 422a28b61..35c5ebb15 100755 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -138,6 +138,7 @@ public class PhotoModule private static final int SET_PHOTO_UI_PARAMS = 12; private static final int SWITCH_TO_GCAM_MODULE = 13; private static final int CONFIGURE_SKIN_TONE_FACTOR = 14; + private static final int ON_PREVIEW_STARTED = 15; // The subset of parameters we need to update in setCameraParameters(). private static final int UPDATE_PARAM_INITIALIZE = 1; @@ -253,6 +254,15 @@ public class PhotoModule } }; + private class OpenCameraThread extends Thread { + @Override + public void run() { + openCamera(); + startPreview(); + } + } + + private OpenCameraThread mOpenCameraThread = null; /** * An unpublished intent flag requesting to return as soon as capturing * is completed. @@ -276,7 +286,7 @@ public class PhotoModule private boolean mFirstTimeInitialized; private boolean mIsImageCaptureIntent; - private int mCameraState = PREVIEW_STOPPED; + private int mCameraState = INIT; private boolean mSnapshotOnIdle = false; private ContentResolver mContentResolver; @@ -471,6 +481,10 @@ public class PhotoModule } break; } + case ON_PREVIEW_STARTED: { + onPreviewStarted(); + break; + } } } } @@ -480,7 +494,6 @@ public class PhotoModule public void init(CameraActivity activity, View parent) { mActivity = activity; mRootView = parent; - mUI = new PhotoUI(activity, this, parent); mPreferences = new ComboPreferences(mActivity); CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal()); mCameraId = getPreferredCameraId(mPreferences); @@ -495,6 +508,11 @@ public class PhotoModule mPreferences.setLocalId(mActivity, mCameraId); CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); + if (mOpenCameraThread == null && !mActivity.mIsModuleSwitchInProgress) { + mOpenCameraThread = new OpenCameraThread(); + mOpenCameraThread.start(); + } + mUI = new PhotoUI(activity, this, parent); initializeControlByIntent(); mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false); mLocationManager = new LocationManager(mActivity, mUI); @@ -534,6 +552,7 @@ public class PhotoModule private void onPreviewStarted() { setCameraState(IDLE); + mFocusManager.onPreviewStarted(); startFaceDetection(); locationFirstRun(); mUI.enableShutter(true); @@ -563,7 +582,20 @@ public class PhotoModule @Override public void onPreviewUIReady() { - startPreview(); + if (mPaused || mCameraDevice == null) { + return; + } + Log.v(TAG, "onPreviewUIReady"); + if (mCameraState == PREVIEW_STOPPED) { + startPreview(); + } else { + SurfaceTexture st = mUI.getSurfaceTexture(); + if (st == null) { + Log.w(TAG, "startPreview: surfaceTexture is not ready."); + return; + } + mCameraDevice.setPreviewTexture(st); + } } @Override @@ -571,6 +603,7 @@ public class PhotoModule if (mCameraDevice == null) { return; } + Log.v(TAG, "onPreviewUIDestroyed"); mCameraDevice.setPreviewTexture(null); stopPreview(); } @@ -585,12 +618,10 @@ public class PhotoModule } private void onCameraOpened() { - View root = mUI.getRootView(); - // These depend on camera parameters. - - int width = root.getWidth(); - int height = root.getHeight(); - mFocusManager.setPreviewSize(width, height); + if (mPaused) { + return; + } + Log.v(TAG, "onCameraOpened"); openCameraCommon(); resizeForPreviewAspectRatio(); } @@ -622,6 +653,7 @@ public class PhotoModule return; } mParameters = mCameraDevice.getParameters(); + mInitialParams = mParameters; initializeCapabilities(); CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); @@ -655,8 +687,6 @@ public class PhotoModule } updateCameraSettings(); showTapToFocusToastIfNeeded(); - - } @Override @@ -755,7 +785,6 @@ public class PhotoModule Log.d(TAG, "addIdleHandler in first time initialization"); addIdleHandler(); - mActivity.updateStorageSpaceAndHint(); } // If the activity is paused and resumed, this method will be called in @@ -811,6 +840,8 @@ public class PhotoModule @Override public void startFaceDetection() { + if (mCameraDevice == null) return; + if (mFaceDetectionEnabled == false || mFaceDetectionStarted || mCameraState != IDLE) return; if (mParameters.getMaxNumDetectedFaces() > 0) { @@ -1561,6 +1592,14 @@ public class PhotoModule } String reFocus = mParameters.get(CameraSettings.KEY_QC_RE_FOCUS); + + if (mFocusManager.isZslEnabled()) { + String pictureFormat = mActivity.getString(R.string. + pref_camera_picture_format_value_jpeg); + mUI.overrideSettings(CameraSettings.KEY_PICTURE_FORMAT, pictureFormat); + } else { + mUI.overrideSettings(CameraSettings.KEY_PICTURE_FORMAT, null); + } if ((ubiFocus != null && ubiFocus.equals(ubiFocusOn)) || (reFocus != null && reFocus.equals(reFocusOn)) || (chromaFlash != null && chromaFlash.equals(chromaFlashOn)) || @@ -1701,7 +1740,8 @@ public class PhotoModule if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return; int oldOrientation = mOrientation; mOrientation = CameraUtil.roundOrientation(orientation, mOrientation); - if (oldOrientation != mOrientation) { + if (oldOrientation != mOrientation && + oldOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) { Log.v(TAG, "onOrientationChanged, update parameters"); if (mParameters != null && mCameraDevice != null) { onSharedPreferenceChanged(); @@ -1973,28 +2013,28 @@ public class PhotoModule mPaused = false; } - private boolean prepareCamera() { + private void openCamera() { // We need to check whether the activity is paused before long // operations to ensure that onPause() can be done ASAP. + if (mPaused) { + return; + } Log.v(TAG, "Open camera device."); mCameraDevice = CameraUtil.openCamera( mActivity, mCameraId, mHandler, mActivity.getCameraOpenErrorCallback()); if (mCameraDevice == null) { Log.e(TAG, "Failed to open camera:" + mCameraId); - return false; + mHandler.sendEmptyMessage(OPEN_CAMERA_FAIL); + return; } mParameters = mCameraDevice.getParameters(); - - initializeCapabilities(); - if (mFocusManager == null) initializeFocusManager(); - setCameraParameters(UPDATE_PARAM_ALL); - mHandler.sendEmptyMessage(CAMERA_OPEN_DONE); mCameraPreviewParamsReady = true; - startPreview(); - mOnResumeTime = SystemClock.uptimeMillis(); - checkDisplayRotation(); - return true; + mInitialParams = mParameters; + if (mFocusManager == null) initializeFocusManager(); + initializeCapabilities(); + mHandler.sendEmptyMessageDelayed(CAMERA_OPEN_DONE,100); + return; } @Override @@ -2029,12 +2069,14 @@ public class PhotoModule Log.v(TAG, "Executing onResumeTasks."); if (mOpenCameraFail || mCameraDisabled) return; + if (mOpenCameraThread == null) { + mOpenCameraThread = new OpenCameraThread(); + mOpenCameraThread.start(); + } + mJpegPictureCallbackTime = 0; mZoomValue = 0; - if (!prepareCamera()) { - // Camera failure. - return; - } + resetExposureCompensation(); if (mSkinToneSeekBar != true) { @@ -2050,6 +2092,8 @@ public class PhotoModule } mUI.initDisplayChangeListener(); keepScreenOnAwhile(); + mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup, + mPreferences); UsageStatistics.onContentViewChanged( UsageStatistics.COMPONENT_CAMERA, "PhotoModule"); @@ -2063,6 +2107,9 @@ public class PhotoModule if (msensor != null) { mSensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_NORMAL); } + + mOnResumeTime = SystemClock.uptimeMillis(); + checkDisplayRotation(); } @Override @@ -2087,6 +2134,14 @@ public class PhotoModule Log.v(TAG, "On pause."); mUI.showPreviewCover(); + try { + if (mOpenCameraThread != null) { + mOpenCameraThread.join(); + } + } catch (InterruptedException ex) { + // ignore + } + mOpenCameraThread = null; // Reset the focus first. Camera CTS does not guarantee that // cancelAutoFocus is allowed after preview stops. if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { @@ -2141,6 +2196,12 @@ public class PhotoModule mInitialParams, this, mMirror, mActivity.getMainLooper(), mUI); } + View root = mUI.getRootView(); + // These depend on camera parameters. + + int width = root.getWidth(); + int height = root.getHeight(); + mFocusManager.setPreviewSize(width, height); } @Override @@ -2338,7 +2399,9 @@ public class PhotoModule mFaceDetectionStarted = false; mCameraDevice = null; setCameraState(PREVIEW_STOPPED); - mFocusManager.onCameraReleased(); + if (mFocusManager != null) { + mFocusManager.onCameraReleased(); + } } } @@ -2362,19 +2425,17 @@ public class PhotoModule startPreview(); } - /** This can run on a background thread, post any view updates to MainHandler. */ + /** This can run on a background thread, so don't do UI updates here. Post any + view updates to MainHandler or do it on onPreviewStarted() . */ private void startPreview() { if (mPaused || mCameraDevice == null) { return; } - // Any decisions we make based on the surface texture state - // need to be protected. + Log.v(TAG, "startPreview"); + SurfaceTexture st = mUI.getSurfaceTexture(); - if (st == null) { - Log.w(TAG, "startPreview: surfaceTexture is not ready."); - return; - } + mCameraDevice.setPreviewTexture(st); if (!mCameraPreviewParamsReady) { Log.w(TAG, "startPreview: parameters for preview is not ready."); @@ -2384,10 +2445,15 @@ public class PhotoModule // 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) { + if (mCameraState != PREVIEW_STOPPED && mCameraState != INIT) { stopPreview(); } + setCameraParameters(UPDATE_PARAM_ALL); + + mCameraDevice.startPreview(); + mHandler.sendEmptyMessage(ON_PREVIEW_STARTED); + setDisplayOrientation(); if (!mSnapshotOnIdle) { @@ -2397,17 +2463,7 @@ public class PhotoModule mCameraDevice.cancelAutoFocus(); } mFocusManager.setAeAwbLock(false); // Unlock AE and AWB. - } - setCameraParameters(UPDATE_PARAM_ALL); - // Let UI set its expected aspect ratio - mCameraDevice.setPreviewTexture(st); - - Log.v(TAG, "startPreview"); - mCameraDevice.startPreview(); - mFocusManager.onPreviewStarted(); - onPreviewStarted(); - - if (mSnapshotOnIdle) { + } else { mHandler.post(mDoSnapRunnable); } } @@ -2493,6 +2549,8 @@ public class PhotoModule mParameters.set(CameraSettings.KEY_QC_RE_FOCUS, reFocus); } } + + /** This can run on a background thread, so don't do UI updates here.*/ private void qcomUpdateCameraParametersPreference() { //qcom Related Parameter update //Set Brightness. @@ -2807,10 +2865,6 @@ public class PhotoModule //Raw picture format is not supported under ZSL mode mParameters.set(KEY_PICTURE_FORMAT, PIXEL_FORMAT_JPEG); - Editor editor = mPreferences.edit(); - editor.putString(CameraSettings.KEY_PICTURE_FORMAT, mActivity.getString(R.string.pref_camera_picture_format_value_jpeg)); - editor.apply(); - mUI.overrideSettings(CameraSettings.KEY_PICTURE_FORMAT, mActivity.getString(R.string.pref_camera_picture_format_entry_jpeg)); //Try to set CAF for ZSL if(CameraUtil.isSupported(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE, @@ -2972,6 +3026,7 @@ public class PhotoModule } } + /** This can run on a background thread, so don't do UI updates here.*/ private boolean updateCameraParametersPreference() { setAutoExposureLockIfSupported(); setAutoWhiteBalanceLockIfSupported(); @@ -3309,7 +3364,6 @@ public class PhotoModule } Storage.setSaveSDCard( mPreferences.getString(CameraSettings.KEY_CAMERA_SAVEPATH, "0").equals("1")); - mActivity.updateStorageSpaceAndHint(); } @Override @@ -3368,7 +3422,6 @@ public class PhotoModule } private void initializeCapabilities() { - mInitialParams = mCameraDevice.getParameters(); mFocusAreaSupported = CameraUtil.isFocusAreaSupported(mInitialParams); mMeteringAreaSupported = CameraUtil.isMeteringAreaSupported(mInitialParams); mAeLockSupported = CameraUtil.isAutoExposureLockSupported(mInitialParams); diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index 48458ba0a..423ddb954 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -252,10 +252,12 @@ public class PhotoUI implements PieListener, ratio = 1 / ratio; } - Log.d(TAG,"setAspectRatio() ratio["+ratio+"] mAspectRatio["+mAspectRatio+"]"); - mAspectRatio = ratio; - mAspectRatioResize = true; - mTextureView.requestLayout(); + if (mAspectRatio != ratio) { + Log.d(TAG,"setAspectRatio() ratio["+ratio+"] mAspectRatio["+mAspectRatio+"]"); + mAspectRatio = ratio; + mAspectRatioResize = true; + mTextureView.requestLayout(); + } } public void setSurfaceTextureSizeChangedListener(SurfaceTextureSizeChangedListener listener) { -- cgit v1.2.3