From d0d3c4845bef94bb91e0c346c0f0048ba06be309 Mon Sep 17 00:00:00 2001 From: Sascha Haeberling Date: Mon, 4 Nov 2013 12:11:34 -0800 Subject: Check for media service being present before capture. Bug: 11508325 Change-Id: I0997f9bff63b1cdb3c33272acc8617b30c07424a --- src/com/android/camera/PhotoModule.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index 09d5dc64c..ed13aa57b 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -869,6 +869,7 @@ public class PhotoModule // is full then ignore. if (mCameraDevice == null || mCameraState == SNAPSHOT_IN_PROGRESS || mCameraState == SWITCHING_CAMERA + || mActivity.getMediaSaveService() == null || mActivity.getMediaSaveService().isQueueFull()) { return false; } -- cgit v1.2.3 From 23f4d40f6d8800b293360f8c7f840d3f7ab041ed Mon Sep 17 00:00:00 2001 From: Sascha Haeberling Date: Wed, 6 Nov 2013 14:03:17 -0800 Subject: Don't crash Photo Sphere on back button press in filmstrip. Bug: 11554580 Change-Id: I983713eecbd6f13bd90f94b24a0fa1ecc26e1c56 --- src/com/android/camera/SurfaceTextureRenderer.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/android/camera/SurfaceTextureRenderer.java b/src/com/android/camera/SurfaceTextureRenderer.java index 66f7aa219..331504393 100644 --- a/src/com/android/camera/SurfaceTextureRenderer.java +++ b/src/com/android/camera/SurfaceTextureRenderer.java @@ -51,8 +51,10 @@ public class SurfaceTextureRenderer { @Override public void run() { synchronized (mRenderLock) { - mFrameDrawer.onDrawFrame(mGl); - mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); + if (mEglDisplay != null && mEglSurface != null) { + mFrameDrawer.onDrawFrame(mGl); + mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); + } mRenderLock.notifyAll(); } } -- cgit v1.2.3 From 9666bc6027ab17d28b14b18e0fea8f03108f288b Mon Sep 17 00:00:00 2001 From: ztenghui Date: Wed, 6 Nov 2013 14:20:31 -0800 Subject: Decouple the visibility check for system UI from action bar And make sure we toggle system UI when reload. bug:11539377 Change-Id: I4d251557c1d68a173cabb652e0beaa3ee89cb6f0 --- src/com/android/camera/CameraActivity.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index a8c4bd850..e1d2a924f 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -339,6 +339,7 @@ public class CameraActivity extends Activity @Override public void onReload() { setPreviewControlsVisibility(true); + CameraActivity.this.setSystemBarsVisibility(false); } @Override @@ -466,13 +467,17 @@ public class CameraActivity extends Activity */ private void setSystemBarsVisibility(boolean visible, boolean hideLater) { mMainHandler.removeMessages(HIDE_ACTION_BAR); - boolean currentlyVisible = mActionBar.isShowing(); - if (visible != currentlyVisible) { - int visibility = DEFAULT_SYSTEM_UI_VISIBILITY | (visible ? View.SYSTEM_UI_FLAG_VISIBLE - : View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN); - mAboveFilmstripControlLayout.setSystemUiVisibility(visibility); + int currentSystemUIVisibility = mAboveFilmstripControlLayout.getSystemUiVisibility(); + int newSystemUIVisibility = DEFAULT_SYSTEM_UI_VISIBILITY | + (visible ? View.SYSTEM_UI_FLAG_VISIBLE : + View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN); + if (newSystemUIVisibility != currentSystemUIVisibility) { + mAboveFilmstripControlLayout.setSystemUiVisibility(newSystemUIVisibility); + } + boolean currentActionBarVisibility = mActionBar.isShowing(); + if (visible != currentActionBarVisibility) { if (visible) { mActionBar.show(); } else { -- cgit v1.2.3 From 01341ec00c03577c6d8a1652463e1a6aaef16270 Mon Sep 17 00:00:00 2001 From: Erin Dahlgren Date: Wed, 6 Nov 2013 11:57:51 -0800 Subject: Parallelize opening the camera with view handling in photo mode. Bug: 11255097 Change-Id: I8da16a97ee46555267ae8cfee0e7940d3f53f98f --- src/com/android/camera/PhotoModule.java | 239 +++++++++++++++++++++++--------- src/com/android/camera/PhotoUI.java | 33 +++-- 2 files changed, 192 insertions(+), 80 deletions(-) diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index 9523c9429..ce0deed54 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -40,6 +40,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.MessageQueue; @@ -103,6 +104,10 @@ public class PhotoModule private static final int OPEN_CAMERA_FAIL = 9; private static final int CAMERA_DISABLED = 10; private static final int SWITCH_TO_GCAM_MODULE = 11; + private static final int CAMERA_PREVIEW_DONE = 12; + + private static final int OPEN_CAMERA_ASYNC = 1; + private static final int START_PREVIEW_ASYNC = 2; // The subset of parameters we need to update in setCameraParameters(). private static final int UPDATE_PARAM_INITIALIZE = 1; @@ -238,6 +243,14 @@ public class PhotoModule private String mSceneMode; private final Handler mHandler = new MainHandler(); + + /** A thread separate from the UI thread for camera startup. */ + private HandlerThread mOpenCameraThread; + /** A handler to run on the camera startup thread. */ + private Handler mOpenCameraHandler; + /** This lock should always protect openCamera and closeCamera. */ + private final Object mCameraOpenLock = new Object(); + private PreferenceGroup mPreferenceGroup; private boolean mQuickCapture; @@ -279,11 +292,84 @@ public class PhotoModule } } + /** + * This Handler is used to open the camera. + */ + private class OpenCameraHandler extends Handler { + public OpenCameraHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case OPEN_CAMERA_ASYNC: { + // Prevent closeCamera from thinking the camera + // is already closed when it is still opening. + // + // This happens during the lockscreen sequence: + // onResume -> onPause -> onResume. + synchronized (mCameraOpenLock) { + Log.v(TAG, "openCamera"); + if (mCameraDevice != null) { + throw new IllegalArgumentException("Camera already open."); + } + + mCameraDevice = CameraUtil.openCamera( + mActivity, mCameraId, mHandler, + mActivity.getCameraOpenErrorCallback()); + + if (mCameraDevice == null) { + Log.e(TAG, "Failed to open camera:" + mCameraId); + break; + } + mParameters = mCameraDevice.getParameters(); + + initializeCapabilities(); + if (mFocusManager == null) { + initializeFocusManager(); + } + + // The views can't be updated from a non UI thread. + mHandler.sendEmptyMessage(CAMERA_OPEN_DONE); + + setCameraParameters(UPDATE_PARAM_ALL); + mCameraPreviewParamsReady = true; + + // This will exit early if the surface texture + // isn't ready. We also need to protect the surface + // texture from concurrent updates/checks. + startPreview(); + } + break; + } + + case START_PREVIEW_ASYNC: { + if (mCameraDevice == null) { + throw new IllegalStateException("Camera not yet opened."); + } + + startPreview(); + mHandler.sendEmptyMessage(CAMERA_PREVIEW_DONE); + break; + } + + default: { + throw new UnsupportedOperationException("Unknown message " + msg.what); + } + } + }; + } + /** * This Handler is used to post message back onto the main thread of the * application */ private class MainHandler extends Handler { + public MainHandler() { + super(Looper.getMainLooper()); + } + @Override public void handleMessage(Message msg) { switch (msg.what) { @@ -345,6 +431,12 @@ public class PhotoModule case SWITCH_TO_GCAM_MODULE: { mActivity.onModuleSelected(ModuleSwitcher.GCAM_MODULE_INDEX); + break; + } + + case CAMERA_PREVIEW_DONE: { + // Modifies views, so must be executed on the UI thread. + onPreviewStarted(); } } } @@ -413,7 +505,8 @@ public class PhotoModule @Override public void onPreviewUIReady() { - startPreview(); + // Requires that OPEN_CAMERA_ASYNC has been already sent. + mOpenCameraHandler.sendEmptyMessage(START_PREVIEW_ASYNC); } @Override @@ -453,7 +546,11 @@ public class PhotoModule setCameraId(mCameraId); // from onPause - closeCamera(); + mOpenCameraHandler.removeMessages(OPEN_CAMERA_ASYNC); + mOpenCameraHandler.removeMessages(START_PREVIEW_ASYNC); + synchronized (mCameraOpenLock) { + closeCamera(); + } mUI.collapseCameraControls(); mUI.clearFaces(); if (mFocusManager != null) mFocusManager.removeMessages(); @@ -461,9 +558,12 @@ public class PhotoModule // Restart the camera and initialize the UI. From onCreate. mPreferences.setLocalId(mActivity, mCameraId); CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); - mCameraDevice = CameraUtil.openCamera( + synchronized (mCameraOpenLock) { + Log.v(TAG, "openCamera"); + mCameraDevice = CameraUtil.openCamera( mActivity, mCameraId, mHandler, mActivity.getCameraOpenErrorCallback()); + } if (mCameraDevice == null) { Log.e(TAG, "Failed to open camera:" + mCameraId + ", aborting."); return; @@ -1161,47 +1261,25 @@ public class PhotoModule mPaused = false; } - /** - * Opens the camera device. - * - * @return Whether the camera was opened successfully. - */ - private boolean prepareCamera() { - // We need to check whether the activity is paused before long - // operations to ensure that onPause() can be done ASAP. - mCameraDevice = CameraUtil.openCamera( - mActivity, mCameraId, mHandler, - mActivity.getCameraOpenErrorCallback()); - if (mCameraDevice == null) { - Log.e(TAG, "Failed to open camera:" + mCameraId); - return false; - } - 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; - } - - @Override public void onResumeAfterSuper() { Log.v(TAG, "On resume."); if (mOpenCameraFail || mCameraDisabled) return; + if (mOpenCameraThread == null) { + Log.e("DEBUG", "new OpenCameraThread"); + mOpenCameraThread = new HandlerThread("OpenCameraThread"); + mOpenCameraThread.start(); + mOpenCameraHandler = new OpenCameraHandler(mOpenCameraThread.getLooper()); + } + mJpegPictureCallbackTime = 0; mZoomValue = 0; resetExposureCompensation(); - if (!prepareCamera()) { - // Camera failure. - return; - } + + mOpenCameraHandler.sendEmptyMessage(OPEN_CAMERA_ASYNC); + mOnResumeTime = SystemClock.uptimeMillis(); + checkDisplayRotation(); // If first time initialization is not finished, put it in the // message queue. @@ -1259,6 +1337,9 @@ public class PhotoModule if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { mCameraDevice.cancelAutoFocus(); } + // If the camera has not been opened asynchronously yet, + // and startPreview hasn't been called, then this is a no-op. + // (e.g. onResume -> onPause -> onResume). stopPreview(); mNamedImages = null; @@ -1272,7 +1353,18 @@ public class PhotoModule // Remove the messages and runnables in the queue. mHandler.removeCallbacksAndMessages(null); - closeCamera(); + // Postpones actually releasing for KEEP_CAMERA_TIMEOUT, + // so if onResume is directly called after this, the camera + // simply needs to reconnect (takes about 2-5ms). + mOpenCameraHandler.removeMessages(OPEN_CAMERA_ASYNC); + mOpenCameraHandler.removeMessages(START_PREVIEW_ASYNC); + synchronized (mCameraOpenLock) { + closeCamera(); + } + // Stop the long running open camera thread. + mOpenCameraThread.quitSafely(); + mOpenCameraThread = null; + Log.e(TAG, "Done quiting safely."); resetScreenOn(); mUI.onPause(); @@ -1434,6 +1526,7 @@ public class PhotoModule } private void closeCamera() { + Log.v(TAG, "closeCamera"); if (mCameraDevice != null) { mCameraDevice.setZoomChangeListener(null); mCameraDevice.setFaceDetectionCallback(null, null); @@ -1473,48 +1566,58 @@ public class PhotoModule startPreview(); } - // This can only be called by UI Thread. private void startPreview() { - if (mPaused || mCameraDevice == null) { + if (mCameraState != PREVIEW_STOPPED) { + Log.v(TAG, "Already previewing"); return; } - SurfaceTexture st = mUI.getSurfaceTexture(); - if (st == null) { - Log.w(TAG, "startPreview: surfaceTexture is not ready."); - return; - } - if (!mCameraPreviewParamsReady) { - Log.w(TAG, "startPreview: parameters for preview is not ready."); + + if (mPaused || mCameraDevice == null) { return; } - mCameraDevice.setErrorCallback(mErrorCallback); - // ICS camera frameworks has a bug. Face detection state is not cleared - // after taking a picture. Stop the preview to work around it. The bug - // was fixed in JB. - if (mCameraState != PREVIEW_STOPPED) stopPreview(); + Object textureLock = mUI.getSurfaceTextureLock(); - setDisplayOrientation(); + // Any decisions we make based on the surface texture state + // need to be protected. + synchronized (textureLock) { + SurfaceTexture st = mUI.getSurfaceTexture(); + if (st == null) { + Log.w(TAG, "startPreview: surfaceTexture is not ready."); + return; + } - if (!mSnapshotOnIdle) { - // 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(); + if (!mCameraPreviewParamsReady) { + Log.w(TAG, "startPreview: parameters for preview is not ready."); + return; } - mFocusManager.setAeAwbLock(false); // Unlock AE and AWB. - } - setCameraParameters(UPDATE_PARAM_ALL); - // Let UI set its expected aspect ratio - mCameraDevice.setPreviewTexture(st); + mCameraDevice.setErrorCallback(mErrorCallback); - Log.v(TAG, "startPreview"); - mCameraDevice.startPreview(); - mFocusManager.onPreviewStarted(); - onPreviewStarted(); + setDisplayOrientation(); - if (mSnapshotOnIdle) { - mHandler.post(mDoSnapRunnable); + if (!mSnapshotOnIdle) { + // 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(); + } + 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(); + + // Since the preview actually started, remove any messages to + // start it again. + mOpenCameraHandler.removeMessages(START_PREVIEW_ASYNC); + mFocusManager.onPreviewStarted(); + + if (mSnapshotOnIdle) { + mHandler.post(mDoSnapRunnable); + } } } diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index ffb19d4e1..524cd4654 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -117,6 +117,7 @@ public class PhotoUI implements PieListener, private Matrix mMatrix = null; private float mAspectRatio = 4f / 3f; private View mPreviewCover; + private final Object mSurfaceTextureLock = new Object(); public interface SurfaceTextureSizeChangedListener { public void onSurfaceTextureSizeChanged(int uncroppedWidth, int uncroppedHeight); @@ -277,16 +278,22 @@ public class PhotoUI implements PieListener, mController.onPreviewRectChanged(CameraUtil.rectFToRect(previewRect)); } + protected Object getSurfaceTextureLock() { + return mSurfaceTextureLock; + } + @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - Log.v(TAG, "SurfaceTexture ready."); - mPreviewCover.setVisibility(View.GONE); - mSurfaceTexture = surface; - mController.onPreviewUIReady(); - // Workaround for b/11168275, see b/10981460 for more details - if (mPreviewWidth != 0 && mPreviewHeight != 0) { - // Re-apply transform matrix for new surface texture - setTransformMatrix(mPreviewWidth, mPreviewHeight); + synchronized (mSurfaceTextureLock) { + Log.v(TAG, "SurfaceTexture ready."); + mPreviewCover.setVisibility(View.GONE); + mSurfaceTexture = surface; + mController.onPreviewUIReady(); + // Workaround for b/11168275, see b/10981460 for more details + if (mPreviewWidth != 0 && mPreviewHeight != 0) { + // Re-apply transform matrix for new surface texture + setTransformMatrix(mPreviewWidth, mPreviewHeight); + } } } @@ -297,10 +304,12 @@ public class PhotoUI implements PieListener, @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - mSurfaceTexture = null; - mController.onPreviewUIDestroyed(); - Log.w(TAG, "SurfaceTexture destroyed"); - return true; + synchronized (mSurfaceTextureLock) { + mSurfaceTexture = null; + mController.onPreviewUIDestroyed(); + Log.w(TAG, "SurfaceTexture destroyed"); + return true; + } } @Override -- cgit v1.2.3 From 5eefffdfb0b93f7a1b3d4c167c25d8a2a4a68d08 Mon Sep 17 00:00:00 2001 From: Erin Dahlgren Date: Thu, 7 Nov 2013 11:35:10 -0800 Subject: Show chooser on EDIT intents that have no activity for action. Bug: 11571947 Change-Id: I40ef0f9ae6b4567557064d91b9c3942cd524a60b --- src/com/android/camera/CameraActivity.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index e1d2a924f..11e7610d0 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -1394,7 +1394,12 @@ public class CameraActivity extends Activity Intent intent = new Intent(Intent.ACTION_EDIT) .setDataAndType(data.getContentUri(), data.getMimeType()) .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - startActivityForResult(intent, REQ_CODE_DONT_SWITCH_TO_PREVIEW); + try { + startActivityForResult(intent, REQ_CODE_DONT_SWITCH_TO_PREVIEW); + } catch (ActivityNotFoundException e) { + startActivityForResult(Intent.createChooser(intent, null), + REQ_CODE_DONT_SWITCH_TO_PREVIEW); + } } /** -- cgit v1.2.3 From 2b55bb3092ca5517906ef62bdb5de4c7711666d9 Mon Sep 17 00:00:00 2001 From: Erin Dahlgren Date: Thu, 7 Nov 2013 11:55:49 -0800 Subject: Fix photo mode is getting stuck in a single CameraState. Bug: 11574716 Change-Id: Ieb3622103798077071bb9350773851b7acbff756 --- src/com/android/camera/PhotoModule.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index ce0deed54..347244ebe 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -350,7 +350,6 @@ public class PhotoModule } startPreview(); - mHandler.sendEmptyMessage(CAMERA_PREVIEW_DONE); break; } @@ -1566,12 +1565,8 @@ public class PhotoModule startPreview(); } + /** This can run on a background thread, post any view updates to MainHandler. */ private void startPreview() { - if (mCameraState != PREVIEW_STOPPED) { - Log.v(TAG, "Already previewing"); - return; - } - if (mPaused || mCameraDevice == null) { return; } @@ -1592,6 +1587,12 @@ public class PhotoModule return; } 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) { + stopPreview(); + } setDisplayOrientation(); @@ -1618,6 +1619,7 @@ public class PhotoModule if (mSnapshotOnIdle) { mHandler.post(mDoSnapRunnable); } + mHandler.sendEmptyMessage(CAMERA_PREVIEW_DONE); } } -- cgit v1.2.3 From 2c5ab5eaa9d79a0fb1cf3b32fdc7ee283676cced Mon Sep 17 00:00:00 2001 From: Andy Huibers Date: Wed, 6 Nov 2013 14:37:26 -0800 Subject: hide preview cover on arrival of new preview data if hidden Bug: 11433257 Change-Id: I7225ebf1d84bbefd2f952cfa524720a7e76e7181 --- src/com/android/camera/PhotoUI.java | 6 ++++-- src/com/android/camera/VideoUI.java | 5 ++++- src/com/android/camera/WideAnglePanoramaUI.java | 5 ++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index 524cd4654..744802f64 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -286,7 +286,6 @@ public class PhotoUI implements PieListener, public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { synchronized (mSurfaceTextureLock) { Log.v(TAG, "SurfaceTexture ready."); - mPreviewCover.setVisibility(View.GONE); mSurfaceTexture = surface; mController.onPreviewUIReady(); // Workaround for b/11168275, see b/10981460 for more details @@ -314,7 +313,10 @@ public class PhotoUI implements PieListener, @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { - // Do nothing. + // Make sure preview cover is hidden if preview data is available. + if (mPreviewCover.getVisibility() != View.GONE) { + mPreviewCover.setVisibility(View.GONE); + } } public View getRootView() { diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java index 02b256754..8b01ba4b8 100644 --- a/src/com/android/camera/VideoUI.java +++ b/src/com/android/camera/VideoUI.java @@ -718,7 +718,6 @@ public class VideoUI implements PieRenderer.PieListener, @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { mSurfaceTexture = surface; - mPreviewCover.setVisibility(View.GONE); mController.onPreviewUIReady(); } @@ -736,6 +735,10 @@ public class VideoUI implements PieRenderer.PieListener, @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { + // Make sure preview cover is hidden if preview data is available. + if (mPreviewCover.getVisibility() != View.GONE) { + mPreviewCover.setVisibility(View.GONE); + } } // SurfaceHolder callbacks diff --git a/src/com/android/camera/WideAnglePanoramaUI.java b/src/com/android/camera/WideAnglePanoramaUI.java index 1546958de..268c82b2b 100644 --- a/src/com/android/camera/WideAnglePanoramaUI.java +++ b/src/com/android/camera/WideAnglePanoramaUI.java @@ -226,7 +226,6 @@ public class WideAnglePanoramaUI implements @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) { mSurfaceTexture = surfaceTexture; - mPreviewCover.setVisibility(View.GONE); mController.onPreviewUIReady(); } @@ -245,6 +244,10 @@ public class WideAnglePanoramaUI implements @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + // Make sure preview cover is hidden if preview data is available. + if (mPreviewCover.getVisibility() != View.GONE) { + mPreviewCover.setVisibility(View.GONE); + } } private void hideDirectionIndicators() { -- cgit v1.2.3 From 2820eca8825d6767b283f22c321c8f777ba572ae Mon Sep 17 00:00:00 2001 From: Sascha Haeberling Date: Thu, 7 Nov 2013 13:43:33 -0800 Subject: Add GCam progress indicator. Bug: 11505806 Change-Id: I823c44b3761bb3c6dce56b1ec1b8d667023da820 --- res/values/dimens.xml | 2 + src/com/android/camera/ui/PieRenderer.java | 25 ++++--- src/com/android/camera/ui/ProgressRenderer.java | 86 +++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 src/com/android/camera/ui/ProgressRenderer.java diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 692a87fbf..e2d4246df 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -74,6 +74,8 @@ 26dp 36dp 18dp + 25dp + 3dp 80dp 48dp 12dp diff --git a/src/com/android/camera/ui/PieRenderer.java b/src/com/android/camera/ui/PieRenderer.java index 3967f7946..58bee94d6 100644 --- a/src/com/android/camera/ui/PieRenderer.java +++ b/src/com/android/camera/ui/PieRenderer.java @@ -42,10 +42,13 @@ import android.view.animation.Transformation; import com.android.camera.drawable.TextDrawable; import com.android.camera2.R; +/** + * An overlay renderer that is used to display focus state and progress state. + */ public class PieRenderer extends OverlayRenderer implements FocusIndicator { - private static final String TAG = "CAM Pie"; + private static final String TAG = "PieRenderer"; // Sometimes continuous autofocus starts and stops several times quickly. // These states are used to make sure the animation is run for at least some @@ -143,7 +146,7 @@ public class PieRenderer extends OverlayRenderer private int mAngleZone; private float mCenterAngle; - + private ProgressRenderer mProgressRenderer; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { @@ -226,6 +229,7 @@ public class PieRenderer extends OverlayRenderer mLabel.setDropShadow(true); mDeadZone = res.getDimensionPixelSize(R.dimen.pie_deadzone_width); mAngleZone = res.getDimensionPixelSize(R.dimen.pie_anglezone_width); + mProgressRenderer = new ProgressRenderer(ctx); } private PieItem getRoot() { @@ -308,6 +312,10 @@ public class PieRenderer extends OverlayRenderer return mState == STATE_PIE && isVisible(); } + public void setProgress(int percent) { + mProgressRenderer.setProgress(percent); + } + private void fadeIn() { mFadeIn = new ValueAnimator(); mFadeIn.setFloatValues(0f, 1f); @@ -517,6 +525,8 @@ public class PieRenderer extends OverlayRenderer @Override public void onDraw(Canvas canvas) { + mProgressRenderer.onDraw(canvas, mFocusX, mFocusY); + float alpha = 1; if (mXFade != null) { alpha = (Float) mXFade.getAnimatedValue(); @@ -911,17 +921,6 @@ public class PieRenderer extends OverlayRenderer setCircle(mFocusX, mFocusY); } - public void alignFocus(int x, int y) { - mOverlay.removeCallbacks(mDisappear); - mAnimation.cancel(); - mAnimation.reset(); - mFocusX = x; - mFocusY = y; - mDialAngle = DIAL_HORIZONTAL; - setCircle(x, y); - mFocused = false; - } - public int getSize() { return 2 * mCircleSize; } diff --git a/src/com/android/camera/ui/ProgressRenderer.java b/src/com/android/camera/ui/ProgressRenderer.java new file mode 100644 index 000000000..1783c70b5 --- /dev/null +++ b/src/com/android/camera/ui/ProgressRenderer.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; + +import com.android.camera2.R; + +/** + * Renders a circular progress bar on the screen. + */ +public class ProgressRenderer { + private final int mProgressRadius; + private final Paint mProgressBasePaint; + private final Paint mProgressPaint; + + private RectF mArcBounds = new RectF(0, 0, 1, 1); + private int mProgressAngleDegrees = 270; + private boolean mVisible = false; + + public ProgressRenderer(Context context) { + mProgressRadius = context.getResources().getDimensionPixelSize(R.dimen.pie_progress_radius); + int pieProgressWidth = context.getResources().getDimensionPixelSize( + R.dimen.pie_progress_width); + mProgressBasePaint = createProgressPaint(pieProgressWidth, 0.2f); + mProgressPaint = createProgressPaint(pieProgressWidth, 1.0f); + } + + private static Paint createProgressPaint(int width, float alpha) { + Paint paint = new Paint(); + paint.setAntiAlias(true); + // 20% alpha. + paint.setColor(Color.argb((int) (alpha * 255), 255, 255, 255)); + paint.setStrokeWidth(width); + paint.setStyle(Paint.Style.STROKE); + return paint; + } + + /** + * Shows a progress indicator. If the progress is '100', the progress + * indicator will be hidden. + * + * @param percent the progress in percent (0-100). + */ + public void setProgress(int percent) { + // Clamp the value. + percent = Math.min(100, Math.max(percent, 0)); + mProgressAngleDegrees = (int) ((360f / 100) * percent); + + // Hide when processing reached 100 percent. + mVisible = percent < 100; + } + + /** + * Draw the current progress (if < 100%) centered at the given location. + */ + public void onDraw(Canvas canvas, int centerX, int centerY) { + if (!mVisible) { + return; + } + mArcBounds = new RectF(centerX - mProgressRadius, centerY - mProgressRadius, centerX + + mProgressRadius, + centerY + mProgressRadius); + + canvas.drawCircle(centerX, centerY, mProgressRadius, mProgressBasePaint); + canvas.drawArc(mArcBounds, -90, mProgressAngleDegrees, false, mProgressPaint); + } +} -- cgit v1.2.3