summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/layout/photo_module.xml2
-rw-r--r--res/menu/operations.xml67
-rw-r--r--res/values/styles.xml3
-rw-r--r--src/com/android/camera/CameraActivity.java130
-rw-r--r--src/com/android/camera/PhotoController.java18
-rw-r--r--src/com/android/camera/PhotoModule.java248
-rw-r--r--src/com/android/camera/PhotoUI.java50
-rw-r--r--src/com/android/camera/VideoModule.java57
-rw-r--r--src/com/android/camera/data/CameraDataAdapter.java8
-rw-r--r--src/com/android/camera/data/FixedFirstDataAdapter.java4
-rw-r--r--src/com/android/camera/ui/FilmStripView.java1
11 files changed, 358 insertions, 230 deletions
diff --git a/res/layout/photo_module.xml b/res/layout/photo_module.xml
index 390863a71..f5525b832 100644
--- a/res/layout/photo_module.xml
+++ b/res/layout/photo_module.xml
@@ -48,4 +48,4 @@
<include layout="@layout/camera_controls"
android:layout_gravity="center"
style="@style/CameraControls"/>
-</merge> \ No newline at end of file
+</merge>
diff --git a/res/menu/operations.xml b/res/menu/operations.xml
new file mode 100644
index 000000000..bcebbb47b
--- /dev/null
+++ b/res/menu/operations.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/action_share"
+ android:icon="@drawable/ic_menu_share_holo_light"
+ android:title="@string/share"
+ android:visible="false"
+ android:actionProviderClass="android.widget.ShareActionProvider"
+ android:showAsAction="ifRoom">
+ </item>
+ <item android:id="@+id/action_delete"
+ android:icon="@drawable/ic_menu_trash_holo_light"
+ android:title="@string/delete"
+ android:visible="false"
+ android:showAsAction="never" />
+ <item android:id="@+id/action_edit"
+ android:title="@string/edit"
+ android:showAsAction="never"
+ android:visible="false" />
+ <item android:id="@+id/action_trim"
+ android:title="@string/trim_action"
+ android:showAsAction="never"
+ android:visible="false" />
+ <item android:id="@+id/action_mute"
+ android:title="@string/mute_action"
+ android:showAsAction="never"
+ android:visible="false" />
+ <item android:id="@+id/action_rotate_ccw"
+ android:showAsAction="never"
+ android:visible="false"
+ android:title="@string/rotate_left" />
+ <item android:id="@+id/action_rotate_cw"
+ android:showAsAction="never"
+ android:visible="false"
+ android:title="@string/rotate_right" />
+ <item android:id="@+id/action_crop"
+ android:title="@string/crop_action"
+ android:showAsAction="never"
+ android:visible="false" />
+ <item android:id="@+id/action_setas"
+ android:title="@string/set_image"
+ android:showAsAction="never"
+ android:visible="false" />
+ <item android:id="@+id/action_details"
+ android:icon="@drawable/ic_menu_info_details"
+ android:title="@string/details"
+ android:visible="false"
+ android:showAsAction="never" />
+ <item android:id="@+id/action_show_on_map"
+ android:title="@string/show_on_map"
+ android:showAsAction="never"
+ android:visible="false" />
+</menu>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index dede2391b..946329070 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -55,6 +55,9 @@
</style>
<style name="Theme.Camera" parent="Theme.CameraBase">
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowTitleSize">0dp</item>
+ <item name="android:windowActionBarOverlay">true</item>
<item name="android:windowBackground">@android:color/black</item>
<item name="android:colorBackground">@android:color/black</item>
<item name="android:colorBackgroundCacheHint">@android:color/black</item>
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 82d10a98b..099b5035f 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -37,6 +37,9 @@ import android.provider.Settings;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.ViewGroup;
@@ -77,6 +80,19 @@ public class CameraActivity extends Activity
// panorama. If the extra is not set, it is in the normal camera mode.
public static final String SECURE_CAMERA_EXTRA = "secure_camera";
+ // Supported operations at FilmStripView. Different data has different
+ // set of supported operations.
+ private static final int SUPPORT_DELETE = 1 << 0;
+ private static final int SUPPORT_ROTATE = 1 << 1;
+ private static final int SUPPORT_INFO = 1 << 2;
+ private static final int SUPPORT_CROP = 1 << 3;
+ private static final int SUPPORT_SETAS = 1 << 4;
+ private static final int SUPPORT_EDIT = 1 << 5;
+ private static final int SUPPORT_TRIM = 1 << 6;
+ private static final int SUPPORT_MUTE = 1 << 7;
+ private static final int SUPPORT_SHOW_ON_MAP = 1 << 8;
+ private static final int SUPPORT_ALL = 0xffffffff;
+
/** This data adapter is used by FilmStirpView. */
private LocalDataAdapter mDataAdapter;
/** This data adapter represents the real local camera data. */
@@ -104,6 +120,7 @@ public class CameraActivity extends Activity
private PanoramaViewHelper mPanoramaViewHelper;
private CameraPreviewData mCameraPreviewData;
private ActionBar mActionBar;
+ private Menu mActionBarMenu;
private class MyOrientationEventListener
extends OrientationEventListener {
@@ -195,6 +212,9 @@ public class CameraActivity extends Activity
hidePanoStitchingProgress();
return;
}
+ int type = currentData.getLocalDataType(dataID);
+ updateActionBarMenu(type);
+
Uri contentUri = currentData.getContentUri();
if (contentUri == null) {
hidePanoStitchingProgress();
@@ -223,6 +243,64 @@ public class CameraActivity extends Activity
mBottomProgress.setProgress(progress);
}
+ /**
+ * According to the data type, make the menu items for supported operations
+ * visible.
+ * @param type : the data type for the current local data.
+ */
+ private void updateActionBarMenu(int type) {
+ if (mActionBarMenu == null) {
+ return;
+ }
+
+ int supported = 0;
+ switch (type) {
+ case LocalData.LOCAL_IMAGE:
+ supported |= SUPPORT_DELETE | SUPPORT_ROTATE | SUPPORT_INFO
+ | SUPPORT_CROP | SUPPORT_SETAS | SUPPORT_EDIT
+ | SUPPORT_SHOW_ON_MAP;
+ break;
+ case LocalData.LOCAL_VIDEO:
+ supported |= SUPPORT_DELETE | SUPPORT_INFO | SUPPORT_TRIM
+ | SUPPORT_MUTE;
+ break;
+ case LocalData.LOCAL_PHOTO_SPHERE:
+ supported |= SUPPORT_DELETE | SUPPORT_ROTATE | SUPPORT_INFO
+ | SUPPORT_CROP | SUPPORT_SETAS | SUPPORT_EDIT
+ | SUPPORT_SHOW_ON_MAP;
+ break;
+ default:
+ break;
+ }
+
+ setMenuItemVisible(mActionBarMenu, R.id.action_delete,
+ (supported & SUPPORT_DELETE) != 0);
+ setMenuItemVisible(mActionBarMenu, R.id.action_rotate_ccw,
+ (supported & SUPPORT_ROTATE) != 0);
+ setMenuItemVisible(mActionBarMenu, R.id.action_rotate_cw,
+ (supported & SUPPORT_ROTATE) != 0);
+ setMenuItemVisible(mActionBarMenu, R.id.action_crop,
+ (supported & SUPPORT_CROP) != 0);
+ setMenuItemVisible(mActionBarMenu, R.id.action_trim,
+ (supported & SUPPORT_TRIM) != 0);
+ setMenuItemVisible(mActionBarMenu, R.id.action_mute,
+ (supported & SUPPORT_MUTE) != 0);
+ setMenuItemVisible(mActionBarMenu, R.id.action_setas,
+ (supported & SUPPORT_SETAS) != 0);
+ setMenuItemVisible(mActionBarMenu, R.id.action_show_on_map,
+ (supported & SUPPORT_SHOW_ON_MAP) != 0);
+ setMenuItemVisible(mActionBarMenu, R.id.action_edit,
+ (supported & SUPPORT_EDIT) != 0);
+ setMenuItemVisible(mActionBarMenu, R.id.action_details,
+ (supported & SUPPORT_INFO) != 0);
+ }
+
+ private void setMenuItemVisible(Menu menu, int itemId, boolean visible) {
+ MenuItem item = menu.findItem(itemId);
+ if (item != null)
+ item.setVisible(visible);
+ }
+
private Runnable mDeletionRunnable = new Runnable() {
@Override
public void run() {
@@ -324,8 +402,57 @@ public class CameraActivity extends Activity
}
@Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu items for use in the action bar
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.operations, menu);
+ mActionBarMenu = menu;
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle presses on the action bar items
+ switch (item.getItemId()) {
+ case R.id.action_delete:
+ // TODO: add the functionality.
+ return true;
+ case R.id.action_edit:
+ // TODO: add the functionality.
+ return true;
+ case R.id.action_trim:
+ // TODO: add the functionality.
+ return true;
+ case R.id.action_mute:
+ // TODO: add the functionality.
+ return true;
+ case R.id.action_rotate_ccw:
+ // TODO: add the functionality.
+ return true;
+ case R.id.action_rotate_cw:
+ // TODO: add the functionality.
+ return true;
+ case R.id.action_crop:
+ // TODO: add the functionality.
+ return true;
+ case R.id.action_setas:
+ // TODO: add the functionality.
+ return true;
+ case R.id.action_details:
+ // TODO: add the functionality.
+ return true;
+ case R.id.action_show_on_map:
+ // TODO: add the functionality.
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
public void onCreate(Bundle state) {
super.onCreate(state);
+ getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.camera_filmstrip);
mActionBar = getActionBar();
// Hide action bar first since we are in full screen mode first.
@@ -400,6 +527,7 @@ public class CameraActivity extends Activity
if (!mSecureCamera) {
mDataAdapter = mWrappedDataAdapter;
+ mFilmStripView.setDataAdapter(mDataAdapter);
mDataAdapter.requestLoad(getContentResolver());
} else {
// Put a lock placeholder as the last image by setting its date to 0.
@@ -414,8 +542,8 @@ public class CameraActivity extends Activity
0, 0));
// Flush out all the original data.
mDataAdapter.flush();
+ mFilmStripView.setDataAdapter(mDataAdapter);
}
- mFilmStripView.setDataAdapter(mDataAdapter);
}
private void setRotationAnimation() {
diff --git a/src/com/android/camera/PhotoController.java b/src/com/android/camera/PhotoController.java
index bc824d917..f32d2d967 100644
--- a/src/com/android/camera/PhotoController.java
+++ b/src/com/android/camera/PhotoController.java
@@ -16,7 +16,6 @@
package com.android.camera;
-import android.view.SurfaceHolder;
import android.view.View;
import com.android.camera.ShutterButton.OnShutterButtonListener;
@@ -53,8 +52,6 @@ public interface PhotoController extends OnShutterButtonListener {
public void onSingleTapUp(View view, int x, int y);
- public void onSurfaceCreated(SurfaceHolder holder);
-
public void onCountDownFinished();
public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight);
@@ -62,4 +59,19 @@ public interface PhotoController extends OnShutterButtonListener {
public void updateCameraOrientation();
public void enableRecordingLocation(boolean enable);
+
+ /**
+ * This is the callback when the UI or buffer holder for camera preview,
+ * such as {@link android.graphics.SurfaceTexture}, is ready to be used.
+ * The controller can start the camera preview after or in this callback.
+ */
+ public void onPreviewUIReady();
+
+
+ /**
+ * This is the callback when the UI or buffer holder for camera preview,
+ * such as {@link android.graphics.SurfaceTexture}, is being destroyed.
+ * The controller should try to stop the preview in this callback.
+ */
+ public void onPreviewUIDestroyed();
}
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index 8d68320bf..1b0432f51 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -16,15 +16,6 @@
package com.android.camera;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Formatter;
-import java.util.List;
-
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentProviderClient;
@@ -46,7 +37,6 @@ import android.location.Location;
import android.media.CameraProfile;
import android.net.Uri;
import android.os.Bundle;
-import android.os.ConditionVariable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -56,7 +46,6 @@ import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.view.OrientationEventListener;
-import android.view.SurfaceHolder;
import android.view.View;
import android.view.WindowManager;
@@ -65,10 +54,10 @@ import com.android.camera.CameraManager.CameraAFMoveCallback;
import com.android.camera.CameraManager.CameraPictureCallback;
import com.android.camera.CameraManager.CameraProxy;
import com.android.camera.CameraManager.CameraShutterCallback;
-import com.android.camera.util.ApiHelper;
import com.android.camera.ui.CountDownView.OnCountDownFinishedListener;
import com.android.camera.ui.PopupManager;
import com.android.camera.ui.RotateTextToast;
+import com.android.camera.util.ApiHelper;
import com.android.camera.util.CameraUtil;
import com.android.camera.util.UsageStatistics;
import com.android.camera2.R;
@@ -76,6 +65,14 @@ import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.exif.Rational;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
public class PhotoModule
implements CameraModule,
PhotoController,
@@ -95,14 +92,12 @@ public class PhotoModule
private static final int FIRST_TIME_INIT = 2;
private static final int CLEAR_SCREEN_DELAY = 3;
private static final int SET_CAMERA_PARAMETERS_WHEN_IDLE = 4;
- private static final int CHECK_DISPLAY_ROTATION = 5;
- private static final int SHOW_TAP_TO_FOCUS_TOAST = 6;
- private static final int SWITCH_CAMERA = 7;
- private static final int SWITCH_CAMERA_START_ANIMATION = 8;
- private static final int CAMERA_OPEN_DONE = 9;
- private static final int START_PREVIEW_DONE = 10;
- private static final int OPEN_CAMERA_FAIL = 11;
- private static final int CAMERA_DISABLED = 12;
+ private static final int SHOW_TAP_TO_FOCUS_TOAST = 5;
+ private static final int SWITCH_CAMERA = 6;
+ private static final int SWITCH_CAMERA_START_ANIMATION = 7;
+ private static final int CAMERA_OPEN_DONE = 8;
+ private static final int OPEN_CAMERA_FAIL = 9;
+ private static final int CAMERA_DISABLED = 10;
// The subset of parameters we need to update in setCameraParameters().
private static final int UPDATE_PARAM_INITIALIZE = 1;
@@ -143,7 +138,7 @@ public class PhotoModule
private boolean mMeteringAreaSupported;
private boolean mAeLockSupported;
private boolean mAwbLockSupported;
- private boolean mContinousFocusSupported;
+ private boolean mContinuousFocusSupported;
// The degrees of the device rotated clockwise from its natural orientation.
private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
@@ -169,10 +164,6 @@ public class PhotoModule
}
};
- private final StringBuilder mBuilder = new StringBuilder();
- private final Formatter mFormatter = new Formatter(mBuilder);
- private final Object[] mFormatterArgs = new Object[1];
-
/**
* An unpublished intent flag requesting to return as soon as capturing
* is completed.
@@ -245,8 +236,8 @@ public class PhotoModule
private float[] mR = new float[16];
private int mHeading = -1;
- CameraStartUpThread mCameraStartUpThread;
- ConditionVariable mStartPreviewPrerequisiteReady = new ConditionVariable();
+ // True if all the parameters needed to start preview is ready.
+ private boolean mCameraPreviewParamsReady = false;
private MediaSaveService.OnMediaSavedListener mOnMediaSavedListener =
new MediaSaveService.OnMediaSavedListener() {
@@ -258,46 +249,22 @@ public class PhotoModule
}
};
- // The purpose is not to block the main thread in onCreate and onResume.
- private class CameraStartUpThread extends Thread {
- private volatile boolean mCancelled;
-
- public void cancel() {
- mCancelled = true;
- interrupt();
- }
-
- public boolean isCanceled() {
- return mCancelled;
+ private void checkDisplayRotation() {
+ // Set the display orientation if display rotation has changed.
+ // Sometimes this happens when the device is held upside
+ // down and camera app is opened. Rotation animation will
+ // take some time and the rotation value we have got may be
+ // wrong. Framework does not have a callback for this now.
+ if (CameraUtil.getDisplayRotation(mActivity) != mDisplayRotation) {
+ setDisplayOrientation();
}
-
- @Override
- public void run() {
- try {
- // We need to check whether the activity is paused before long
- // operations to ensure that onPause() can be done ASAP.
- if (mCancelled) return;
- mCameraDevice = CameraUtil.openCamera(mActivity, mCameraId);
- mParameters = mCameraDevice.getParameters();
- // Wait until all the initialization needed by startPreview are
- // done.
- mStartPreviewPrerequisiteReady.block();
-
- initializeCapabilities();
- if (mFocusManager == null) initializeFocusManager();
- if (mCancelled) return;
- setCameraParameters(UPDATE_PARAM_ALL);
- mHandler.sendEmptyMessage(CAMERA_OPEN_DONE);
- if (mCancelled) return;
- startPreview();
- mHandler.sendEmptyMessage(START_PREVIEW_DONE);
- mOnResumeTime = SystemClock.uptimeMillis();
- mHandler.sendEmptyMessage(CHECK_DISPLAY_ROTATION);
- } catch (CameraHardwareException e) {
- mHandler.sendEmptyMessage(OPEN_CAMERA_FAIL);
- } catch (CameraDisabledException e) {
- mHandler.sendEmptyMessage(CAMERA_DISABLED);
- }
+ if (SystemClock.uptimeMillis() - mOnResumeTime < 5000) {
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ checkDisplayRotation();
+ }
+ }, 100);
}
}
@@ -330,21 +297,6 @@ public class PhotoModule
break;
}
- case CHECK_DISPLAY_ROTATION: {
- // Set the display orientation if display rotation has changed.
- // Sometimes this happens when the device is held upside
- // down and camera app is opened. Rotation animation will
- // take some time and the rotation value we have got may be
- // wrong. Framework does not have a callback for this now.
- if (CameraUtil.getDisplayRotation(mActivity) != mDisplayRotation) {
- setDisplayOrientation();
- }
- if (SystemClock.uptimeMillis() - mOnResumeTime < 5000) {
- mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100);
- }
- break;
- }
-
case SHOW_TAP_TO_FOCUS_TOAST: {
showTapToFocusToast();
break;
@@ -366,13 +318,7 @@ public class PhotoModule
break;
}
- case START_PREVIEW_DONE: {
- onPreviewStarted();
- break;
- }
-
case OPEN_CAMERA_FAIL: {
- mCameraStartUpThread = null;
mOpenCameraFail = true;
CameraUtil.showErrorAndFinish(mActivity,
R.string.cannot_connect_camera);
@@ -380,7 +326,6 @@ public class PhotoModule
}
case CAMERA_DISABLED: {
- mCameraStartUpThread = null;
mCameraDisabled = true;
CameraUtil.showErrorAndFinish(mActivity,
R.string.camera_disabled);
@@ -400,11 +345,6 @@ public class PhotoModule
mContentResolver = mActivity.getContentResolver();
- // To reduce startup time, open the camera and start the preview in
- // another thread.
- mCameraStartUpThread = new CameraStartUpThread();
- mCameraStartUpThread.start();
-
// Surface texture is from camera screen nail and startPreview needs it.
// This must be done before startPreview.
mIsImageCaptureIntent = isImageCaptureIntent();
@@ -413,9 +353,6 @@ public class PhotoModule
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
// we need to reset exposure for the preview
resetExposureCompensation();
- // Starting the preview needs preferences, camera screen nail, and
- // focus area indicator.
- mStartPreviewPrerequisiteReady.open();
initializeControlByIntent();
mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false);
@@ -431,7 +368,6 @@ public class PhotoModule
}
private void onPreviewStarted() {
- mCameraStartUpThread = null;
setCameraState(IDLE);
startFaceDetection();
locationFirstRun();
@@ -458,6 +394,20 @@ public class PhotoModule
: RecordLocationPreference.VALUE_OFF);
}
+ @Override
+ public void onPreviewUIReady() {
+ startPreview();
+ }
+
+ @Override
+ public void onPreviewUIDestroyed() {
+ if (mCameraDevice == null) {
+ return;
+ }
+ mCameraDevice.setPreviewTexture(null);
+ stopPreview();
+ }
+
private void setLocationPreference(String value) {
mPreferences.edit()
.putString(CameraSettings.KEY_RECORD_LOCATION, value)
@@ -607,20 +557,6 @@ public class PhotoModule
keepMediaProviderInstance();
}
- @Override
- public void onSurfaceCreated(SurfaceHolder holder) {
- // Do not access the camera if camera start up thread is not finished.
- if (mCameraDevice == null || mCameraStartUpThread != null)
- return;
-
- mCameraDevice.setPreviewDisplay(holder);
- // This happens when onConfigurationChanged arrives, surface has been
- // destroyed, and there is no onFullScreenChanged.
- if (mCameraState == PREVIEW_STOPPED) {
- setupPreview();
- }
- }
-
private void showTapToFocusToastIfNeeded() {
// Show the tap to focus toast if this is the first start.
if (mFocusAreaSupported &&
@@ -851,7 +787,6 @@ public class PhotoModule
private static class NamedImages {
private ArrayList<NamedEntity> mQueue;
- private boolean mStop;
private NamedEntity mNamedEntity;
public NamedImages() {
@@ -1208,18 +1143,37 @@ public class PhotoModule
mPaused = false;
}
+ private void prepareCamera() {
+ try {
+ // 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);
+ mParameters = mCameraDevice.getParameters();
+
+ initializeCapabilities();
+ if (mFocusManager == null) initializeFocusManager();
+ setCameraParameters(UPDATE_PARAM_ALL);
+ mHandler.sendEmptyMessage(CAMERA_OPEN_DONE);
+ mCameraPreviewParamsReady = true;
+ startPreview();
+ mOnResumeTime = SystemClock.uptimeMillis();
+ checkDisplayRotation();
+ } catch (CameraHardwareException e) {
+ mHandler.sendEmptyMessage(OPEN_CAMERA_FAIL);
+ } catch (CameraDisabledException e) {
+ mHandler.sendEmptyMessage(CAMERA_DISABLED);
+ }
+ }
+
+
@Override
public void onResumeAfterSuper() {
if (mOpenCameraFail || mCameraDisabled) return;
mJpegPictureCallbackTime = 0;
mZoomValue = 0;
- // Start the preview if it is not started.
- if (mCameraState == PREVIEW_STOPPED && mCameraStartUpThread == null) {
- resetExposureCompensation();
- mCameraStartUpThread = new CameraStartUpThread();
- mCameraStartUpThread.start();
- }
+ resetExposureCompensation();
+ prepareCamera();
// If first time initialization is not finished, put it in the
// message queue.
@@ -1246,19 +1200,6 @@ public class PhotoModule
}
}
- void waitCameraStartUpThread() {
- try {
- if (mCameraStartUpThread != null) {
- mCameraStartUpThread.cancel();
- mCameraStartUpThread.join();
- mCameraStartUpThread = null;
- setCameraState(IDLE);
- }
- } catch (InterruptedException e) {
- // ignore
- }
- }
-
@Override
public void onPauseBeforeSuper() {
mPaused = true;
@@ -1275,9 +1216,6 @@ public class PhotoModule
@Override
public void onPauseAfterSuper() {
- // Wait the camera start up thread to finish.
- waitCameraStartUpThread();
-
// When camera is started from secure lock screen for the first time
// after screen on, the activity gets onCreate->onResume->onPause->onResume.
// To reduce the latency, keep the camera for a short time so it does
@@ -1302,16 +1240,8 @@ public class PhotoModule
// a picture, we just clear it in onPause.
mJpegImageData = null;
- // Remove the messages in the event queue.
- mHandler.removeMessages(SETUP_PREVIEW);
- mHandler.removeMessages(FIRST_TIME_INIT);
- mHandler.removeMessages(CHECK_DISPLAY_ROTATION);
- mHandler.removeMessages(SWITCH_CAMERA);
- mHandler.removeMessages(SWITCH_CAMERA_START_ANIMATION);
- mHandler.removeMessages(CAMERA_OPEN_DONE);
- mHandler.removeMessages(START_PREVIEW_DONE);
- mHandler.removeMessages(OPEN_CAMERA_FAIL);
- mHandler.removeMessages(CAMERA_DISABLED);
+ // Remove the messages and runnables in the queue.
+ mHandler.removeCallbacksAndMessages(null);
closeCamera();
@@ -1503,17 +1433,26 @@ public class PhotoModule
}
}
- // Only called by UI thread.
+ /** Only called by UI thread. */
private void setupPreview() {
mFocusManager.resetTouchFocus();
startPreview();
- setCameraState(IDLE);
- startFaceDetection();
}
- // This can be called by UI Thread or CameraStartUpThread. So this should
- // not modify the views.
+ // This can only be called by UI Thread.
private void startPreview() {
+ if (mPaused) {
+ 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.");
+ return;
+ }
mCameraDevice.setErrorCallback(mErrorCallback);
// ICS camera frameworks has a bug. Face detection state is not cleared
@@ -1533,15 +1472,12 @@ public class PhotoModule
}
setCameraParameters(UPDATE_PARAM_ALL);
// Let UI set its expected aspect ratio
- mUI.setPreviewSize(mParameters.getPreviewSize());
- Object st = mUI.getSurfaceTexture();
- if (st != null) {
- mCameraDevice.setPreviewTexture((SurfaceTexture) st);
- }
+ mCameraDevice.setPreviewTexture(st);
Log.v(TAG, "startPreview");
mCameraDevice.startPreview();
mFocusManager.onPreviewStarted();
+ onPreviewStarted();
if (mSnapshotOnIdle) {
mHandler.post(mDoSnapRunnable);
@@ -1739,7 +1675,7 @@ public class PhotoModule
mFocusManager.overrideFocusMode(mParameters.getFocusMode());
}
- if (mContinousFocusSupported && ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK) {
+ if (mContinuousFocusSupported && ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK) {
updateAutoFocusMoveCallback();
}
}
@@ -1889,7 +1825,7 @@ public class PhotoModule
mMeteringAreaSupported = CameraUtil.isMeteringAreaSupported(mInitialParams);
mAeLockSupported = CameraUtil.isAutoExposureLockSupported(mInitialParams);
mAwbLockSupported = CameraUtil.isAutoWhiteBalanceLockSupported(mInitialParams);
- mContinousFocusSupported = mInitialParams.getSupportedFocusModes().contains(
+ mContinuousFocusSupported = mInitialParams.getSupportedFocusModes().contains(
CameraUtil.FOCUS_MODE_CONTINUOUS_PICTURE);
}
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index f5748ba3d..4b353f1cf 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -79,7 +79,7 @@ public class PhotoUI implements PieListener,
private PreviewGestures mGestures;
private View mRootView;
- private Object mSurfaceTexture;
+ private SurfaceTexture mSurfaceTexture;
private PopupWindow mPopup;
private ShutterButton mShutterButton;
@@ -119,7 +119,6 @@ public class PhotoUI implements PieListener,
private TextureView mTextureView;
private Matrix mMatrix = null;
private float mAspectRatio = 4f / 3f;
- private final Object mLock = new Object();
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -197,7 +196,7 @@ public class PhotoUI implements PieListener,
mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
mSwitcher = (CameraSwitcher) mRootView.findViewById(R.id.camera_switcher);
mSwitcher.setCurrentIndex(CameraSwitcher.PHOTO_MODULE_INDEX);
- mSwitcher.setSwitchListener((CameraSwitchListener) mActivity);
+ mSwitcher.setSwitchListener(mActivity);
mMenuButton = mRootView.findViewById(R.id.menu);
if (ApiHelper.HAS_FACE_DETECTION) {
ViewStub faceViewStub = (ViewStub) mRootView
@@ -205,8 +204,7 @@ public class PhotoUI implements PieListener,
if (faceViewStub != null) {
faceViewStub.inflate();
mFaceView = (FaceView) mRootView.findViewById(R.id.face_view);
- setSurfaceTextureSizeChangedListener(
- (SurfaceTextureSizeChangedListener) mFaceView);
+ setSurfaceTextureSizeChangedListener(mFaceView);
}
}
mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls);
@@ -222,21 +220,6 @@ public class PhotoUI implements PieListener,
mSurfaceTextureSizeListener = listener;
}
- public void setPreviewSize(Size size) {
- int width = size.width;
- int height = size.height;
- if (width == 0 || height == 0) {
- Log.w(TAG, "Preview size should not be 0.");
- return;
- }
- if (width > height) {
- mAspectRatio = (float) width / height;
- } else {
- mAspectRatio = (float) height / width;
- }
- mHandler.sendEmptyMessage(UPDATE_TRANSFORM_MATRIX);
- }
-
private void setTransformMatrix(int width, int height) {
mMatrix = mTextureView.getTransform(mMatrix);
int orientation = CameraUtil.getDisplayRotation(mActivity);
@@ -269,26 +252,28 @@ public class PhotoUI implements PieListener,
mTextureView.setTransform(mMatrix);
}
+ @Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- synchronized (mLock) {
- mSurfaceTexture = surface;
- mLock.notifyAll();
- }
+ Log.v(TAG, "SurfaceTexture ready.");
+ mSurfaceTexture = surface;
+ mController.onPreviewUIReady();
}
+ @Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, Camera does all the work for us
}
+ @Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mSurfaceTexture = null;
- mController.stopPreview();
- Log.w(TAG, "surfaceTexture is destroyed");
+ mController.onPreviewUIDestroyed();
+ Log.w(TAG, "SurfaceTexture destroyed");
return true;
}
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- // Invoked every time there's a new Camera preview frame
+ // Do nothing.
}
public View getRootView() {
@@ -707,16 +692,7 @@ public class PhotoUI implements PieListener,
mActivity.setSwipingEnabled(enable);
}
- public Object getSurfaceTexture() {
- synchronized (mLock) {
- if (mSurfaceTexture == null) {
- try {
- mLock.wait();
- } catch (InterruptedException e) {
- Log.w(TAG, "Unexpected interruption when waiting to get surface texture");
- }
- }
- }
+ public SurfaceTexture getSurfaceTexture() {
return mSurfaceTexture;
}
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index b28b66ffd..0a6faba6a 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -49,7 +49,6 @@ import android.provider.MediaStore.Video;
import android.util.Log;
import android.view.KeyEvent;
import android.view.OrientationEventListener;
-import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
@@ -177,7 +176,6 @@ public class VideoModule implements CameraModule,
private LocationManager mLocationManager;
private OrientationManager mOrientationManager;
- private Surface mSurface;
private int mPendingSwitchCameraId;
private boolean mOpenCameraFail;
private boolean mCameraDisabled;
@@ -420,26 +418,35 @@ public class VideoModule implements CameraModule,
mOrientation).show();
return;
}
+ takeASnapshot();
+ }
- MediaSaveService s = mActivity.getMediaSaveService();
- if (mPaused || mSnapshotInProgress || effectsActive() || s == null || s.isQueueFull()) {
- return;
- }
+ private void takeASnapshot() {
+ // Only take snapshots if video snapshot is supported by device
+ if (CameraUtil.isVideoSnapshotSupported(mParameters) && !mIsVideoCaptureIntent) {
+ if (!mMediaRecorderRecording || mPaused || mSnapshotInProgress || effectsActive()) {
+ return;
+ }
+ MediaSaveService s = mActivity.getMediaSaveService();
+ if (s == null || s.isQueueFull()) {
+ return;
+ }
- // Set rotation and gps data.
- int rotation = CameraUtil.getJpegRotation(mCameraId, mOrientation);
- mParameters.setRotation(rotation);
- Location loc = mLocationManager.getCurrentLocation();
- CameraUtil.setGpsParameters(mParameters, loc);
- mCameraDevice.setParameters(mParameters);
+ // Set rotation and gps data.
+ int rotation = CameraUtil.getJpegRotation(mCameraId, mOrientation);
+ mParameters.setRotation(rotation);
+ Location loc = mLocationManager.getCurrentLocation();
+ CameraUtil.setGpsParameters(mParameters, loc);
+ mCameraDevice.setParameters(mParameters);
- Log.v(TAG, "Video snapshot start");
- mCameraDevice.takePicture(mHandler,
- null, null, null, new JpegPictureCallback(loc));
- showVideoSnapshotUI(true);
- mSnapshotInProgress = true;
- UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
- UsageStatistics.ACTION_CAPTURE_DONE, "VideoSnapshot");
+ Log.v(TAG, "Video snapshot start");
+ mCameraDevice.takePicture(mHandler,
+ null, null, null, new JpegPictureCallback(loc));
+ showVideoSnapshotUI(true);
+ mSnapshotInProgress = true;
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
+ UsageStatistics.ACTION_CAPTURE_DONE, "VideoSnapshot");
+ }
}
@Override
@@ -833,7 +840,6 @@ public class VideoModule implements CameraModule,
CameraUtil.showErrorAndFinish(mActivity, R.string.camera_disabled);
}
}
-
}
private void onPreviewStarted() {
@@ -1190,9 +1196,6 @@ public class VideoModule implements CameraModule,
// If the mCameraDevice is null, then this activity is going to finish
if (mCameraDevice == null) return;
- boolean inLandscape = (mActivity.getResources().getConfiguration().orientation
- == Configuration.ORIENTATION_LANDSCAPE);
-
CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
mEffectsDisplayResult = false;
@@ -1527,14 +1530,6 @@ public class VideoModule implements CameraModule,
mUI.showTimeLapseUI(false);
}
- private void hideAlert() {
- mUI.enableCameraControls(true);
- mUI.hideReviewUI();
- if (mCaptureTimeLapse) {
- mUI.showTimeLapseUI(true);
- }
- }
-
private boolean stopVideoRecording() {
Log.v(TAG, "stopVideoRecording");
mUI.setSwipingEnabled(true);
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
index c265e397e..2cdb2c172 100644
--- a/src/com/android/camera/data/CameraDataAdapter.java
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -276,6 +276,14 @@ public class CameraDataAdapter implements LocalDataAdapter {
}
private class QueryTask extends AsyncTask<ContentResolver, Void, List<LocalData>> {
+
+ /**
+ * Loads all the photo and video data in the camera folder in background
+ * and combine them into one single list.
+ *
+ * @param resolver {@link ContentResolver} to load all the data.
+ * @return An {@link ArrayList} of all loaded data.
+ */
@Override
protected List<LocalData> doInBackground(ContentResolver... resolver) {
List<LocalData> l = new ArrayList<LocalData>();
diff --git a/src/com/android/camera/data/FixedFirstDataAdapter.java b/src/com/android/camera/data/FixedFirstDataAdapter.java
index ecb9c1402..9f3c4107b 100644
--- a/src/com/android/camera/data/FixedFirstDataAdapter.java
+++ b/src/com/android/camera/data/FixedFirstDataAdapter.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.net.Uri;
import android.view.View;
-import com.android.camera.ui.FilmStripView;
import com.android.camera.ui.FilmStripView.DataAdapter;
import com.android.camera.ui.FilmStripView.ImageData;
@@ -32,6 +31,9 @@ import com.android.camera.ui.FilmStripView.ImageData;
public class FixedFirstDataAdapter extends AbstractLocalDataAdapterWrapper
implements DataAdapter.Listener {
+ @SuppressWarnings("unused")
+ private static final String TAG = "CAM_FixedFirstDataAdapter";
+
private LocalData mFirstData;
private Listener mListener;
diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java
index 5eceaa4f1..d99a4fcf5 100644
--- a/src/com/android/camera/ui/FilmStripView.java
+++ b/src/com/android/camera/ui/FilmStripView.java
@@ -516,6 +516,7 @@ public class FilmStripView extends ViewGroup {
public void onDraw(Canvas c) {
if (mViewInfo[mCurrentInfo] != null && mController.hasNewGeometry()) {
layoutChildren();
+ super.onDraw(c);
}
}