summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChih-Chung Chang <chihchung@google.com>2010-06-15 16:41:33 +0800
committerChih-Chung Chang <chihchung@google.com>2010-06-23 12:44:35 +0800
commitac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5 (patch)
tree3afe1d6a8399087d1fc5c30065464828225a23da /src
parent186ff08e71d106e329171055accd4395760495ea (diff)
downloadLegacyCamera-ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5.zip
LegacyCamera-ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5.tar.gz
LegacyCamera-ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5.tar.bz2
Support switching between multiple cameras.
Change-Id: Id444ebcd780c67f4990bd6f6b96c74379b6859ab
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/Camera.java57
-rw-r--r--src/com/android/camera/CameraButtonIntentReceiver.java3
-rw-r--r--src/com/android/camera/CameraHolder.java25
-rw-r--r--src/com/android/camera/CameraSettings.java14
-rw-r--r--src/com/android/camera/MenuHelper.java15
-rw-r--r--src/com/android/camera/Util.java20
-rw-r--r--src/com/android/camera/VideoCamera.java64
7 files changed, 174 insertions, 24 deletions
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index c67f093..5c12abe 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -173,6 +173,7 @@ public class Camera extends NoSearchActivity implements View.OnClickListener,
private boolean mPreviewing;
private boolean mPausing;
+ private boolean mSwitching;
private boolean mFirstTimeInitialized;
private boolean mIsImageCaptureIntent;
private boolean mRecordLocation;
@@ -230,6 +231,10 @@ public class Camera extends NoSearchActivity implements View.OnClickListener,
private boolean mQuickCapture;
private CameraHeadUpDisplay mHeadUpDisplay;
+ // multiple cameras support
+ private int mNumberOfCameras;
+ private int mCameraId;
+
/**
* This Handler is used to post message back onto the main thread of the
* application
@@ -892,7 +897,8 @@ public class Camera extends NoSearchActivity implements View.OnClickListener,
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
CameraSettings.upgradePreferences(mPreferences);
- mQuickCapture = getQuickCaptureSettings();
+ mNumberOfCameras = CameraHolder.instance().getNumberOfCameras();
+ mCameraId = CameraSettings.readPreferredCameraId(this);
// comment out -- unused now.
//mQuickCapture = getQuickCaptureSettings();
@@ -968,7 +974,7 @@ public class Camera extends NoSearchActivity implements View.OnClickListener,
// becomes landscape.
Configuration config = getResources().getConfiguration();
if (config.orientation == Configuration.ORIENTATION_LANDSCAPE
- && !mPausing && mFirstTimeInitialized) {
+ && !mPausing && !mSwitching && mFirstTimeInitialized) {
if (mGLRootView == null) attachHeadUpDisplay();
} else if (mGLRootView != null) {
detachHeadUpDisplay();
@@ -1577,7 +1583,8 @@ public class Camera extends NoSearchActivity implements View.OnClickListener,
private void ensureCameraDevice() throws CameraHardwareException {
if (mCameraDevice == null) {
- mCameraDevice = CameraHolder.instance().open();
+ mCameraDevice = CameraHolder.instance().open(mCameraId);
+ Util.setCameraDisplayOrientation(this, mCameraId, mCameraDevice);
mInitialParams = mCameraDevice.getParameters();
}
}
@@ -2072,6 +2079,50 @@ public class Camera extends NoSearchActivity implements View.OnClickListener,
});
gallery.setIcon(android.R.drawable.ic_menu_gallery);
mGalleryItems.add(gallery);
+
+ if (mNumberOfCameras > 1) {
+ menu.add(Menu.NONE, Menu.NONE,
+ MenuHelper.POSITION_SWITCH_CAMERA_ID,
+ R.string.switch_camera_id)
+ .setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ switchCameraId();
+ return true;
+ }
+ }).setIcon(android.R.drawable.ic_menu_camera);
+ }
+ }
+
+ private void switchCameraId() {
+ mSwitching = true;
+
+ mCameraId = (mCameraId + 1) % mNumberOfCameras;
+ CameraSettings.writePreferredCameraId(this, mCameraId);
+
+ stopPreview();
+ closeCamera();
+ changeHeadUpDisplayState();
+
+ // Remove the messages in the event queue.
+ mHandler.removeMessages(RESTART_PREVIEW);
+
+ // Reset variables
+ mJpegPictureCallbackTime = 0;
+ mZoomValue = 0;
+
+ // Restart the preview.
+ resetExposureCompensation();
+ try {
+ startPreview();
+ } catch (CameraHardwareException e) {
+ showCameraErrorAndFinish();
+ return;
+ }
+
+ initializeZoom();
+
+ mSwitching = false;
+ changeHeadUpDisplayState();
}
private boolean switchToVideoMode() {
diff --git a/src/com/android/camera/CameraButtonIntentReceiver.java b/src/com/android/camera/CameraButtonIntentReceiver.java
index 38f9241..148542d 100644
--- a/src/com/android/camera/CameraButtonIntentReceiver.java
+++ b/src/com/android/camera/CameraButtonIntentReceiver.java
@@ -36,7 +36,8 @@ public class CameraButtonIntentReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// Try to get the camera hardware
CameraHolder holder = CameraHolder.instance();
- if (holder.tryOpen() == null) return;
+ int cameraId = CameraSettings.readPreferredCameraId(context);
+ if (holder.tryOpen(cameraId) == null) return;
// We are going to launch the camera, so hold the camera for later use
holder.keep();
diff --git a/src/com/android/camera/CameraHolder.java b/src/com/android/camera/CameraHolder.java
index a4c1537..fc6e687 100644
--- a/src/com/android/camera/CameraHolder.java
+++ b/src/com/android/camera/CameraHolder.java
@@ -47,6 +47,7 @@ public class CameraHolder {
private long mKeepBeforeTime = 0; // Keep the Camera before this time.
private final Handler mHandler;
private int mUsers = 0; // number of open() - number of release()
+ private int mNumberOfCameras;
// We store the camera parameters when we actually open the device,
// so we can restore them in the subsequent open() requests by the user.
@@ -90,14 +91,30 @@ public class CameraHolder {
HandlerThread ht = new HandlerThread("CameraHolder");
ht.start();
mHandler = new MyHandler(ht.getLooper());
+ mNumberOfCameras = android.hardware.Camera.getNumberOfCameras();
+
+ android.hardware.Camera.CameraInfo info =
+ new android.hardware.Camera.CameraInfo();
+ Log.v(TAG, "# of cameras:" + mNumberOfCameras);
+ for (int i = 0; i < mNumberOfCameras; i++) {
+ Log.v(TAG, "camera info #" + i);
+ android.hardware.Camera.getCameraInfo(i, info);
+ Log.v(TAG, "facing: " + info.mFacing);
+ Log.v(TAG, "orientation: " + info.mOrientation);
+ }
+ }
+
+ public int getNumberOfCameras() {
+ return mNumberOfCameras;
}
- public synchronized android.hardware.Camera open()
+ public synchronized android.hardware.Camera open(int cameraId)
throws CameraHardwareException {
Assert(mUsers == 0);
if (mCameraDevice == null) {
try {
- mCameraDevice = android.hardware.Camera.open();
+ Log.v(TAG, "open camera " + cameraId);
+ mCameraDevice = android.hardware.Camera.open(cameraId);
} catch (RuntimeException e) {
Log.e(TAG, "fail to connect Camera", e);
throw new CameraHardwareException(e);
@@ -122,9 +139,9 @@ public class CameraHolder {
* Tries to open the hardware camera. If the camera is being used or
* unavailable then return {@code null}.
*/
- public synchronized android.hardware.Camera tryOpen() {
+ public synchronized android.hardware.Camera tryOpen(int cameraId) {
try {
- return mUsers == 0 ? open() : null;
+ return mUsers == 0 ? open(cameraId) : null;
} catch (CameraHardwareException e) {
// In eng build, we throw the exception so that test tool
// can detect it and report it
diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java
index b32f077..6ac2e71 100644
--- a/src/com/android/camera/CameraSettings.java
+++ b/src/com/android/camera/CameraSettings.java
@@ -48,6 +48,7 @@ public class CameraSettings {
public static final String KEY_QUICK_CAPTURE = "pref_camera_quickcapture_key";
public static final String KEY_EXPOSURE = "pref_camera_exposure_key";
public static final String KEY_METERING_MODE = "pref_camera_meteringmode_key";
+ public static final String KEY_CAMERA_ID = "pref_camera_id";
public static final String QUICK_CAPTURE_ON = "on";
public static final String QUICK_CAPTURE_OFF = "off";
@@ -328,4 +329,17 @@ public class CameraSettings {
}
return DEFAULT_VIDEO_DURATION * 1000;
}
+
+ public static int readPreferredCameraId(Context context) {
+ SharedPreferences pref =
+ PreferenceManager.getDefaultSharedPreferences(context);
+ return pref.getInt(KEY_CAMERA_ID, 0);
+ }
+
+ public static void writePreferredCameraId(Context context, int cameraId) {
+ SharedPreferences.Editor editor = PreferenceManager
+ .getDefaultSharedPreferences(context).edit();
+ editor.putInt(KEY_CAMERA_ID, cameraId);
+ editor.commit();
+ }
}
diff --git a/src/com/android/camera/MenuHelper.java b/src/com/android/camera/MenuHelper.java
index e07f4f0..17755f9 100644
--- a/src/com/android/camera/MenuHelper.java
+++ b/src/com/android/camera/MenuHelper.java
@@ -58,20 +58,7 @@ public class MenuHelper {
public static final int POSITION_SWITCH_CAMERA_MODE = 1;
public static final int POSITION_GOTO_GALLERY = 2;
- public static final int POSITION_VIEWPLAY = 3;
- public static final int POSITION_CAPTURE_PICTURE = 4;
- public static final int POSITION_CAPTURE_VIDEO = 5;
- public static final int POSITION_IMAGE_SHARE = 6;
- public static final int POSITION_IMAGE_ROTATE = 7;
- public static final int POSITION_IMAGE_TOSS = 8;
- public static final int POSITION_IMAGE_CROP = 9;
- public static final int POSITION_IMAGE_SET = 10;
- public static final int POSITION_DETAILS = 11;
- public static final int POSITION_SHOWMAP = 12;
- public static final int POSITION_SLIDESHOW = 13;
- public static final int POSITION_MULTISELECT = 14;
- public static final int POSITION_CAMERA_SETTING = 15;
- public static final int POSITION_GALLERY_SETTING = 16;
+ public static final int POSITION_SWITCH_CAMERA_ID = 3;
public static final int NO_STORAGE_ERROR = -1;
public static final int CANNOT_STAT_ERROR = -2;
diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java
index 44d5681..de99562 100644
--- a/src/com/android/camera/Util.java
+++ b/src/com/android/camera/Util.java
@@ -23,6 +23,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.util.Log;
+import android.view.Surface;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
@@ -278,4 +279,23 @@ public class Util {
if (x < min) return min;
return x;
}
+
+ public static void setCameraDisplayOrientation(Activity activity,
+ int cameraId, android.hardware.Camera camera) {
+ android.hardware.Camera.CameraInfo info =
+ new android.hardware.Camera.CameraInfo();
+ android.hardware.Camera.getCameraInfo(cameraId, info);
+ int rotation = activity.getWindowManager().getDefaultDisplay()
+ .getRotation();
+ int degrees = 0;
+ switch (rotation) {
+ case Surface.ROTATION_0: degrees = 0; break;
+ case Surface.ROTATION_90: degrees = 90; break;
+ case Surface.ROTATION_180: degrees = 180; break;
+ case Surface.ROTATION_270: degrees = 270; break;
+ }
+
+ int result = (info.mOrientation - degrees + 360) % 360;
+ camera.setDisplayOrientation(result);
+ }
}
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index 0fac843..0fc4c43 100644
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -162,6 +162,7 @@ public class VideoCamera extends NoSearchActivity
private int mMaxVideoDurationInMs;
boolean mPausing = false;
+ boolean mSwitching;
boolean mPreviewing = false; // True if preview is started.
private ContentResolver mContentResolver;
@@ -176,6 +177,10 @@ public class VideoCamera extends NoSearchActivity
private final Handler mHandler = new MainHandler();
private Parameters mParameters;
+ // multiple cameras support
+ private int mNumberOfCameras;
+ private int mCameraId;
+
// This Handler is used to post message back onto the main thread of the
// application
private class MainHandler extends Handler {
@@ -269,6 +274,9 @@ public class VideoCamera extends NoSearchActivity
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
CameraSettings.upgradePreferences(mPreferences);
+ mNumberOfCameras = CameraHolder.instance().getNumberOfCameras();
+ mCameraId = CameraSettings.readPreferredCameraId(this);
+
readVideoPreferences();
/*
@@ -371,7 +379,7 @@ public class VideoCamera extends NoSearchActivity
// becomes landscape.
Configuration config = getResources().getConfiguration();
if (config.orientation == Configuration.ORIENTATION_LANDSCAPE
- && !mPausing && mGLRootView == null) {
+ && !mPausing && !mSwitching && mGLRootView == null) {
attachHeadUpDisplay();
} else if (mGLRootView != null) {
detachHeadUpDisplay();
@@ -626,7 +634,8 @@ public class VideoCamera extends NoSearchActivity
if (mCameraDevice == null) {
// If the activity is paused and resumed, camera device has been
// released and we need to open the camera.
- mCameraDevice = CameraHolder.instance().open();
+ mCameraDevice = CameraHolder.instance().open(mCameraId);
+ Util.setCameraDisplayOrientation(this, mCameraId, mCameraDevice);
}
mCameraDevice.lock();
@@ -1053,6 +1062,57 @@ public class VideoCamera extends NoSearchActivity
});
gallery.setIcon(android.R.drawable.ic_menu_gallery);
mGalleryItems.add(gallery);
+
+ if (mNumberOfCameras > 1) {
+ menu.add(Menu.NONE, Menu.NONE,
+ MenuHelper.POSITION_SWITCH_CAMERA_ID,
+ R.string.switch_camera_id)
+ .setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ switchCameraId();
+ return true;
+ }
+ }).setIcon(android.R.drawable.ic_menu_camera);
+ }
+ }
+
+ private void switchCameraId() {
+ mSwitching = true;
+
+ int nextId = (mCameraId + 1) % mNumberOfCameras;
+ CameraSettings.writePreferredCameraId(this, nextId);
+
+ changeHeadUpDisplayState();
+
+ // This is similar to what mShutterButton.performClick() does,
+ // but not quite the same.
+ if (mMediaRecorderRecording) {
+ if (mIsVideoCaptureIntent) {
+ stopVideoRecording();
+ showAlert();
+ } else {
+ stopVideoRecordingAndGetThumbnail();
+ }
+ } else {
+ stopVideoRecording();
+ }
+ closeCamera();
+ mHandler.removeMessages(INIT_RECORDER);
+
+ // Restart preview
+ try {
+ startPreview();
+ } catch (CameraHardwareException e) {
+ showCameraBusyAndFinish();
+ return;
+ }
+
+ if (mSurfaceHolder != null) {
+ mHandler.sendEmptyMessage(INIT_RECORDER);
+ }
+
+ mSwitching = false;
+ changeHeadUpDisplayState();
}
private PreferenceGroup filterPreferenceScreenByIntent(