Major refactor: Make resources access through app.
1. Make the camera device avaiability a callback event so the process can be
event-driven.
2. Add ModuleManager interface and implementation.
3. Make AndroidCameraManagerImpl implementation package private.
This CL is the refactoring work on Gallery2 side. The other part is
http://ag/389297/
Known issue: only work for normal photo mode and video mode for now.
Change-Id: Ib0a89ca56c00f6a7294192e9737a70dec5143ee3
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index b1d6957..82a82c2 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -55,7 +55,6 @@
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
-import android.view.OrientationEventListener;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
@@ -67,12 +66,17 @@
import com.android.camera.app.AppController;
import com.android.camera.app.AppManagerFactory;
+import com.android.camera.app.CameraController;
+import com.android.camera.app.CameraManager;
+import com.android.camera.app.CameraManagerFactory;
+import com.android.camera.app.CameraProvider;
import com.android.camera.app.ImageTaskManager;
import com.android.camera.app.MediaSaver;
+import com.android.camera.app.ModuleManagerImpl;
import com.android.camera.app.OrientationManager;
import com.android.camera.app.OrientationManagerImpl;
-import com.android.camera.app.PlaceholderManager;
import com.android.camera.app.PanoramaStitchingManager;
+import com.android.camera.app.PlaceholderManager;
import com.android.camera.crop.CropActivity;
import com.android.camera.data.CameraDataAdapter;
import com.android.camera.data.CameraPreviewData;
@@ -87,6 +91,7 @@
import com.android.camera.filmstrip.FilmstripController;
import com.android.camera.filmstrip.FilmstripImageData;
import com.android.camera.filmstrip.FilmstripListener;
+import com.android.camera.module.ModuleController;
import com.android.camera.tinyplanet.TinyPlanetFragment;
import com.android.camera.ui.DetailsDialog;
import com.android.camera.ui.FilmstripView;
@@ -99,13 +104,12 @@
import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
import com.android.camera.util.RefocusHelper;
import com.android.camera.util.UsageStatistics;
-
import com.android.camera2.R;
import java.io.File;
public class CameraActivity extends Activity
- implements AppController, ModeListView.ModeSwitchListener,
+ implements AppController, ModeListView.ModeSwitchListener, CameraManager.CameraOpenCallback,
ActionBar.OnMenuVisibilityListener, ShareActionProvider.OnShareTargetSelectedListener,
OrientationManager.OnOrientationChangeListener {
@@ -126,8 +130,8 @@
public static final String SECURE_CAMERA_EXTRA = "secure_camera";
/**
- * Request code from an activity we started that indicated that we do not
- * want to reset the view to the preview in onResume.
+ * Request code from an activity we started that indicated that we do not want
+ * to reset the view to the preview in onResume.
*/
public static final int REQ_CODE_DONT_SWITCH_TO_PREVIEW = 142;
@@ -136,7 +140,9 @@
private static final int HIDE_ACTION_BAR = 1;
private static final long SHOW_ACTION_BAR_TIMEOUT_MS = 3000;
- /** Whether onResume should reset the view to the preview. */
+ /**
+ * Whether onResume should reset the view to the preview.
+ */
private boolean mResetToPreviewOnResume = true;
// Supported operations at FilmStripView. Different data has different
@@ -153,15 +159,21 @@
private static final int SUPPORT_SHOW_ON_MAP = 1 << 9;
private static final int SUPPORT_ALL = 0xffffffff;
- /** This data adapter is used by FilmStripView. */
+ /**
+ * This data adapter is used by FilmStripView.
+ */
private LocalDataAdapter mDataAdapter;
- /** This data adapter represents the real local camera data. */
+ /**
+ * This data adapter represents the real local camera data.
+ */
private LocalDataAdapter mWrappedDataAdapter;
private PanoramaStitchingManager mPanoramaManager;
private PlaceholderManager mPlaceholderManager;
private int mCurrentModuleIndex;
private CameraModule mCurrentModule;
+ private ModuleController mCurrentModule2;
+ private ModuleManagerImpl mModuleManager;
private FrameLayout mAboveFilmstripControlLayout;
private FrameLayout mCameraModuleRootView;
private FilmstripController mFilmstripController;
@@ -202,6 +214,8 @@
private Intent mVideoShareIntent;
private Intent mImageShareIntent;
+ private CameraController mCameraController;
+
private MediaSaver mMediaSaver;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
@@ -219,40 +233,6 @@
}
};
- private CameraManager.CameraOpenCallback mCameraOpenCallback =
- new CameraManager.CameraOpenCallback() {
- @Override
- public void onCameraOpened(CameraManager.CameraProxy camera) {
- // TODO: implement this.
- }
-
- @Override
- public void onCameraDisabled(int cameraId) {
- UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
- UsageStatistics.ACTION_OPEN_FAIL, "security");
-
- CameraUtil.showErrorAndFinish(CameraActivity.this,
- R.string.camera_disabled);
- }
-
- @Override
- public void onDeviceOpenFailure(int cameraId) {
- UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
- UsageStatistics.ACTION_OPEN_FAIL, "open");
-
- CameraUtil.showErrorAndFinish(CameraActivity.this,
- R.string.cannot_connect_camera);
- }
-
- @Override
- public void onReconnectionFailure(CameraManager mgr) {
- UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
- UsageStatistics.ACTION_OPEN_FAIL, "reconnect");
-
- CameraUtil.showErrorAndFinish(CameraActivity.this,
- R.string.cannot_connect_camera);
- }
- };
// close activity when screen turns off
private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
@@ -264,6 +244,43 @@
private static BroadcastReceiver sScreenOffReceiver;
+ @Override
+ public void onCameraOpened(CameraManager.CameraProxy camera) {
+ if (!mModuleManager.getModuleAgent(mCurrentModuleIndex).requestAppForCamera()) {
+ // We shouldn't be here. Just close the camera and leave.
+ camera.release(false);
+ throw new IllegalStateException("Camera opened but the module shouldn't be " +
+ "requesting");
+ }
+ if (mCurrentModule2 != null) {
+ mCurrentModule2.onCameraAvailable(camera);
+ }
+ }
+
+ @Override
+ public void onCameraDisabled(int cameraId) {
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA, UsageStatistics.ACTION_OPEN_FAIL,
+ "security");
+
+ CameraUtil.showErrorAndFinish(this, R.string.camera_disabled);
+ }
+
+ @Override
+ public void onDeviceOpenFailure(int cameraId) {
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
+ UsageStatistics.ACTION_OPEN_FAIL, "open");
+
+ CameraUtil.showErrorAndFinish(this, R.string.cannot_connect_camera);
+ }
+
+ @Override
+ public void onReconnectionFailure(CameraManager mgr) {
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
+ UsageStatistics.ACTION_OPEN_FAIL, "reconnect");
+
+ CameraUtil.showErrorAndFinish(this, R.string.cannot_connect_camera);
+ }
+
private static class ScreenOffReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -373,7 +390,7 @@
return;
}
- if(!arePreviewControlsVisible()) {
+ if (!arePreviewControlsVisible()) {
setPreviewControlsVisibility(true);
CameraActivity.this.setSystemBarsVisibility(false);
}
@@ -437,8 +454,7 @@
hidePanoStitchingProgress();
return;
}
- int panoStitchingProgress = mPanoramaManager.getTaskProgress(
- contentUri);
+ int panoStitchingProgress = mPanoramaManager.getTaskProgress(contentUri);
if (panoStitchingProgress < 0) {
hidePanoStitchingProgress();
return;
@@ -731,8 +747,9 @@
private void setMenuItemVisible(Menu menu, int itemId, boolean visible) {
MenuItem item = menu.findItem(itemId);
- if (item != null)
+ if (item != null) {
item.setVisible(visible);
+ }
}
private ImageTaskManager.TaskListener mPlaceholderListener =
@@ -768,7 +785,7 @@
public void onTaskProgress(String filePath, Uri imageUri, int progress) {
// Do nothing
}
- };
+ };
private ImageTaskManager.TaskListener mStitchingListener =
new ImageTaskManager.TaskListener() {
@@ -886,12 +903,6 @@
}
@Override
- public CameraManager.CameraProxy getCameraProxy() {
- // TODO: implement this
- return null;
- }
-
- @Override
public MediaSaver getMediaSaver() {
return mMediaSaver;
}
@@ -937,6 +948,11 @@
}
}
+ @Override
+ public CameraProvider getCameraProvider() {
+ return mCameraController;
+ }
+
private void removeData(int dataID) {
mDataAdapter.removeData(CameraActivity.this, dataID);
if (mDataAdapter.getTotalNumber() > 1) {
@@ -1102,6 +1118,14 @@
setContentView(R.layout.activity_main);
mActionBar = getActionBar();
mActionBar.addOnMenuVisibilityListener(this);
+ mMainHandler = new MainHandler(getMainLooper());
+ mCameraController =
+ new CameraController(this, this, mMainHandler,
+ CameraManagerFactory.getAndroidCameraManager());
+ // TODO: Try to move all the resources allocation to happen as soon as
+ // possible so we can call module.init() at the earliest time.
+ mModuleManager = new ModuleManagerImpl();
+ setupModules();
ModeListView modeListView = (ModeListView) findViewById(R.id.mode_list_layout);
if (modeListView != null) {
@@ -1114,7 +1138,6 @@
setRotationAnimation();
}
- mMainHandler = new MainHandler(getMainLooper());
// Check if this is in the secure camera mode.
Intent intent = getIntent();
String action = intent.getAction();
@@ -1283,7 +1306,7 @@
// users can click the undo button to bring back the image that they
// chose to delete.
if (mPendingDeletion && !mIsUndoingDeletion) {
- performDeletion();
+ performDeletion();
}
}
return result;
@@ -1293,8 +1316,12 @@
public void onPause() {
// Delete photos that are pending deletion
performDeletion();
+ // TODO: call mCurrentModule.pause() instead after all the modules
+ // support pause().
mCurrentModule.onPauseBeforeSuper();
mOrientationManager.pause();
+ // Close the camera and wait for the operation done.
+ mCameraController.closeCamera();
super.onPause();
mCurrentModule.onPauseAfterSuper();
@@ -1328,6 +1355,8 @@
UsageStatistics.ACTION_FOREGROUNDED, this.getClass().getSimpleName());
mOrientationManager.resume();
+ // TODO: call mCurrentModule.resume() instead after all the modules
+ // support resume().
mCurrentModule.onResumeBeforeSuper();
super.onResume();
mCurrentModule.onResumeAfterSuper();
@@ -1492,7 +1521,6 @@
return;
}
- CameraHolder.instance().keep();
closeModule(mCurrentModule);
setModuleFromIndex(moduleIndex);
@@ -1513,37 +1541,16 @@
* index an sets it as mCurrentModule.
*/
private void setModuleFromIndex(int moduleIndex) {
- mCurrentModuleIndex = moduleIndex;
- switch (moduleIndex) {
- case ModeListView.MODE_VIDEO:
- mCurrentModule = new VideoModule();
- break;
-
- case ModeListView.MODE_PHOTO:
- mCurrentModule = new PhotoModule();
- break;
-
- case ModeListView.MODE_WIDEANGLE:
- mCurrentModule = new WideAnglePanoramaModule();
- break;
-
- case ModeListView.MODE_PHOTOSPHERE:
- mCurrentModule = PhotoSphereHelper.createPanoramaModule();
- break;
- case ModeListView.MODE_GCAM:
- // Force immediate release of Camera instance
- CameraHolder.instance().strongRelease();
- mCurrentModule = GcamHelper.createGcamModule();
- break;
- case ModeListView.MODE_CRAFT:
- mCurrentModule = RefocusHelper.createRefocusModule();
- break;
- default:
- // Fall back to photo mode.
- mCurrentModule = new PhotoModule();
- mCurrentModuleIndex = ModeListView.MODE_PHOTO;
- break;
+ ModuleManagerImpl.ModuleAgent agent = mModuleManager.getModuleAgent(moduleIndex);
+ if (agent == null) {
+ return;
}
+ if (!agent.requestAppForCamera()) {
+ mCameraController.closeCamera();
+ }
+ mCurrentModuleIndex = agent.getModuleId();
+ mCurrentModule2 = agent.createModule();
+ mCurrentModule = (CameraModule) mCurrentModule2;
}
/**
@@ -1564,9 +1571,9 @@
/**
* Launch the tiny planet editor.
*
- * @param data the data must be a 360 degree stereographically mapped
- * panoramic image. It will not be modified, instead a new item
- * with the result will be added to the filmstrip.
+ * @param data The data must be a 360 degree stereographically mapped
+ * panoramic image. It will not be modified, instead a new item
+ * with the result will be added to the filmstrip.
*/
public void launchTinyPlanetEditor(LocalData data) {
TinyPlanetFragment fragment = new TinyPlanetFragment();
@@ -1579,11 +1586,15 @@
private void openModule(CameraModule module) {
module.init(this, mCameraModuleRootView);
+ // TODO: call mCurrentModule.resume() instead after all the modules
+ // support resume().
module.onResumeBeforeSuper();
module.onResumeAfterSuper();
}
private void closeModule(CameraModule module) {
+ // TODO: call mCurrentModule.pause() instead after all the modules
+ // support pause().
module.onPauseBeforeSuper();
module.onPauseAfterSuper();
((ViewGroup) mCameraModuleRootView).removeAllViews();
@@ -1608,8 +1619,8 @@
Log.v(TAG, "showing undo bar");
mPendingDeletion = true;
if (mUndoDeletionBar == null) {
- ViewGroup v = (ViewGroup) getLayoutInflater().inflate(
- R.layout.undo_bar, mAboveFilmstripControlLayout, true);
+ ViewGroup v = (ViewGroup) getLayoutInflater().inflate(R.layout.undo_bar,
+ mAboveFilmstripControlLayout, true);
mUndoDeletionBar = (ViewGroup) v.findViewById(R.id.camera_undo_deletion_bar);
View button = mUndoDeletionBar.findViewById(R.id.camera_undo_deletion_button);
button.setOnClickListener(new View.OnClickListener() {
@@ -1630,7 +1641,7 @@
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
mIsUndoingDeletion = true;
} else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
- mIsUndoingDeletion =false;
+ mIsUndoingDeletion = false;
}
return false;
}
@@ -1646,9 +1657,7 @@
mPendingDeletion = false;
if (mUndoDeletionBar != null) {
if (withAnimation) {
- mUndoDeletionBar.animate()
- .setDuration(200)
- .alpha(0f)
+ mUndoDeletionBar.animate().setDuration(200).alpha(0f)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
@@ -1669,8 +1678,7 @@
public void onAnimationRepeat(Animator animation) {
// Do nothing.
}
- })
- .start();
+ }).start();
} else {
mUndoDeletionBar.setVisibility(View.GONE);
}
@@ -1762,11 +1770,131 @@
}
public CameraManager.CameraOpenCallback getCameraOpenErrorCallback() {
- return mCameraOpenCallback;
+ return mCameraController;
}
// For debugging purposes only.
public CameraModule getCurrentModule() {
return mCurrentModule;
}
+
+ private void setupModules() {
+ // PhotoModule, the default module.
+ mModuleManager.registerModule(new ModuleManagerImpl.ModuleAgent() {
+ @Override
+ public int getModuleId() {
+ return ModeListView.MODE_PHOTO;
+ }
+
+ @Override
+ public boolean requestAppForCamera() {
+ return true;
+ }
+
+ @Override
+ public ModuleController createModule() {
+ return new PhotoModule();
+ }
+ });
+ mModuleManager.setDefaultModuleIndex(ModeListView.MODE_PHOTO);
+
+ // VideoModule.
+ mModuleManager.registerModule(new ModuleManagerImpl.ModuleAgent() {
+ @Override
+ public int getModuleId() {
+ return ModeListView.MODE_VIDEO;
+ }
+
+ @Override
+ public boolean requestAppForCamera() {
+ return true;
+ }
+
+ @Override
+ public ModuleController createModule() {
+ return new VideoModule();
+ }
+ });
+
+ // WideAngle.
+ mModuleManager.registerModule(new ModuleManagerImpl.ModuleAgent() {
+ @Override
+ public int getModuleId() {
+ return ModeListView.MODE_WIDEANGLE;
+ }
+
+ @Override
+ public boolean requestAppForCamera() {
+ return false;
+ }
+
+ @Override
+ public ModuleController createModule() {
+ // TODO: remove the type casting.
+ return new WideAnglePanoramaModule();
+ }
+ });
+
+ // PhotoSphere.
+ if (PhotoSphereHelper.hasLightCycleCapture(this)) {
+ mModuleManager.registerModule(new ModuleManagerImpl.ModuleAgent() {
+ @Override
+ public int getModuleId() {
+ return ModeListView.MODE_PHOTOSPHERE;
+ }
+
+ @Override
+ public boolean requestAppForCamera() {
+ return false;
+ }
+
+ @Override
+ public ModuleController createModule() {
+ // TODO: remove the type casting.
+ return (ModuleController) PhotoSphereHelper.createPanoramaModule();
+ }
+ });
+ }
+
+ // Refocus.
+ if (RefocusHelper.hasRefocusCapture(this)) {
+ mModuleManager.registerModule(new ModuleManagerImpl.ModuleAgent() {
+ @Override
+ public int getModuleId() {
+ return ModeListView.MODE_CRAFT;
+ }
+
+ @Override
+ public boolean requestAppForCamera() {
+ return false;
+ }
+
+ @Override
+ public ModuleController createModule() {
+ // TODO: remove the type casting.
+ return (ModuleController) RefocusHelper.createRefocusModule();
+ }
+ });
+ }
+
+ // Gcam for HDR+.
+ if (GcamHelper.hasGcamCapture()) {
+ mModuleManager.registerModule(new ModuleManagerImpl.ModuleAgent() {
+ @Override
+ public int getModuleId() {
+ return ModeListView.MODE_GCAM;
+ }
+
+ @Override
+ public boolean requestAppForCamera() {
+ return false;
+ }
+
+ @Override
+ public ModuleController createModule() {
+ return (ModuleController) GcamHelper.createGcamModule();
+ }
+ });
+ }
+ }
}
diff --git a/src/com/android/camera/CameraHolder.java b/src/com/android/camera/CameraHolder.java
index 64b18ea..4603dd8 100644
--- a/src/com/android/camera/CameraHolder.java
+++ b/src/com/android/camera/CameraHolder.java
@@ -16,8 +16,6 @@
package com.android.camera;
-import static com.android.camera.util.CameraUtil.Assert;
-
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.os.Handler;
@@ -26,12 +24,16 @@
import android.os.Message;
import android.util.Log;
-import com.android.camera.CameraManager.CameraProxy;
+import com.android.camera.app.CameraManager;
+import com.android.camera.app.CameraManager.CameraProxy;
+import com.android.camera.app.CameraManagerFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
+import static com.android.camera.util.CameraUtil.Assert;
+
/**
* The class is used to hold an {@code android.hardware.Camera} instance.
*
@@ -198,7 +200,7 @@
}
Assert(!mCameraOpened);
if (mCameraDevice != null && mCameraId != cameraId) {
- mCameraDevice.release();
+ mCameraDevice.release(true);
mCameraDevice = null;
mCameraId = -1;
}
@@ -206,7 +208,7 @@
Log.v(TAG, "open camera " + cameraId);
if (mMockCameraInfo == null) {
mCameraDevice = CameraManagerFactory
- .getAndroidCameraManager().cameraOpen(handler, cameraId, cb);
+ .getAndroidCameraManager().cameraOpenOld(handler, cameraId, cb);
} else {
if (mMockCamera != null) {
mCameraDevice = mMockCamera[cameraId];
@@ -222,7 +224,7 @@
mCameraId = cameraId;
mParameters = mCameraDevice.getParameters();
} else {
- if (!mCameraDevice.reconnect(handler, cb)) {
+ if (!mCameraDevice.reconnectOld(handler, cb)) {
Log.e(TAG, "fail to reconnect Camera:" + mCameraId + ", aborting.");
return null;
}
@@ -250,16 +252,6 @@
if (mCameraDevice == null) return;
- long now = System.currentTimeMillis();
- if (now < mKeepBeforeTime) {
- if (mCameraOpened) {
- mCameraOpened = false;
- mCameraDevice.stopPreview();
- }
- mHandler.sendEmptyMessageDelayed(RELEASE_CAMERA,
- mKeepBeforeTime - now);
- return;
- }
strongRelease();
}
@@ -267,7 +259,7 @@
if (mCameraDevice == null) return;
mCameraOpened = false;
- mCameraDevice.release();
+ mCameraDevice.release(true);
mCameraDevice = null;
// We must set this to null because it has a reference to Camera.
// Camera has references to the listeners.
diff --git a/src/com/android/camera/CameraModule.java b/src/com/android/camera/CameraModule.java
index b6fb0e6..340fea1 100644
--- a/src/com/android/camera/CameraModule.java
+++ b/src/com/android/camera/CameraModule.java
@@ -23,6 +23,7 @@
import com.android.camera.app.MediaSaver;
+@Deprecated
public interface CameraModule {
public void init(CameraActivity activity, View frame);
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index a2d7566..67bd698 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -51,16 +51,18 @@
import android.view.View;
import android.view.WindowManager;
-import com.android.camera.CameraManager.CameraAFCallback;
-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.app.CameraManager.CameraAFCallback;
+import com.android.camera.app.CameraManager.CameraAFMoveCallback;
+import com.android.camera.app.CameraManager.CameraPictureCallback;
+import com.android.camera.app.CameraManager.CameraProxy;
+import com.android.camera.app.CameraManager.CameraShutterCallback;
import com.android.camera.PhotoModule.NamedImages.NamedEntity;
+import com.android.camera.app.AppController;
import com.android.camera.app.MediaSaver;
import com.android.camera.exif.ExifInterface;
import com.android.camera.exif.ExifTag;
import com.android.camera.exif.Rational;
+import com.android.camera.module.ModuleController;
import com.android.camera.ui.CountDownView.OnCountDownFinishedListener;
import com.android.camera.ui.ModeListView;
import com.android.camera.ui.RotateTextToast;
@@ -79,13 +81,9 @@
import java.util.Vector;
public class PhotoModule
- implements CameraModule,
- PhotoController,
- FocusOverlayManager.Listener,
- CameraPreference.OnPreferenceChangedListener,
- ShutterButton.OnShutterButtonListener, MediaSaver.QueueListener,
- OnCountDownFinishedListener,
- SensorEventListener {
+ implements CameraModule, ModuleController, PhotoController, FocusOverlayManager.Listener,
+ CameraPreference.OnPreferenceChangedListener, ShutterButton.OnShutterButtonListener,
+ MediaSaver.QueueListener, OnCountDownFinishedListener, SensorEventListener {
private static final String TAG = "CAM_PhotoModule";
@@ -372,6 +370,9 @@
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
+
+ mActivity.getCameraProvider().requestCamera(mCameraId);
+
// we need to reset exposure for the preview
resetExposureCompensation();
@@ -456,9 +457,8 @@
mCameraId = mPendingSwitchCameraId;
mPendingSwitchCameraId = -1;
setCameraId(mCameraId);
+ mActivity.getCameraProvider().requestCamera(mCameraId);
- // from onPause
- closeCamera();
mUI.collapseCameraControls();
mUI.clearFaces();
if (mFocusManager != null) mFocusManager.removeMessages();
@@ -466,26 +466,9 @@
// Restart the camera and initialize the UI. From onCreate.
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
- mCameraDevice = CameraUtil.openCamera(
- mActivity, mCameraId, mHandler,
- mActivity.getCameraOpenErrorCallback());
-
- if (mCameraDevice == null) {
- Log.e(TAG, "Failed to open camera:" + mCameraId + ", aborting.");
- return;
- }
- mParameters = mCameraDevice.getParameters();
- initializeCapabilities();
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ CameraInfo info = mActivity.getCameraProvider().getCameraInfo()[mCameraId];
mMirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
mFocusManager.setMirror(mMirror);
- mFocusManager.setParameters(mInitialParams);
- setupPreview();
-
- // reset zoom value index
- mZoomValue = 0;
- openCameraCommon();
-
// Start switch camera animation. Post a message because
// onFrameAvailable from the old camera may already exist.
mHandler.sendEmptyMessage(SWITCH_CAMERA_START_ANIMATION);
@@ -507,8 +490,6 @@
}
updateSceneMode();
showTapToFocusToastIfNeeded();
-
-
}
@Override
@@ -897,7 +878,7 @@
} else {
orientation = mOrientation;
}
- mJpegRotation = CameraUtil.getJpegRotation(mCameraId, orientation);
+ mJpegRotation = CameraUtil.getJpegRotation(mActivity, mCameraId, orientation);
mParameters.setRotation(mJpegRotation);
Location loc = mLocationManager.getCurrentLocation();
CameraUtil.setGpsParameters(mParameters, loc);
@@ -978,6 +959,30 @@
}
@Override
+ public void onCameraAvailable(CameraProxy cameraProxy) {
+ if (mPaused) {
+ return;
+ }
+ mCameraDevice = cameraProxy;
+
+ initializeCapabilities();
+
+ // Reset zoom value index.
+ mZoomValue = 0;
+ if (mFocusManager == null) {
+ initializeFocusManager();
+ }
+ mFocusManager.setParameters(mInitialParams);
+
+ mParameters = mCameraDevice.getParameters();
+ setCameraParameters(UPDATE_PARAM_ALL);
+ mCameraPreviewParamsReady = true;
+ startPreview();
+
+ onCameraOpened();
+ }
+
+ @Override
public void onStop() {
if (mMediaProviderClient != null) {
mMediaProviderClient.release();
@@ -1166,41 +1171,19 @@
mPaused = false;
}
- 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;
+ mActivity.getCameraProvider().requestCamera(mCameraId);
+
mJpegPictureCallbackTime = 0;
mZoomValue = 0;
resetExposureCompensation();
- if (!prepareCamera()) {
- // Camera failure.
- return;
- }
+
+ mOnResumeTime = SystemClock.uptimeMillis();
+ checkDisplayRotation();
// If first time initialization is not finished, put it in the
// message queue.
@@ -1227,7 +1210,12 @@
}
@Override
+ public void onPauseAfterSuper() {
+ }
+
+ @Override
public void onPauseBeforeSuper() {
+ Log.v(TAG, "On pause.");
mPaused = true;
Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (gsensor != null) {
@@ -1238,11 +1226,6 @@
if (msensor != null) {
mSensorManager.unregisterListener(this, msensor);
}
- }
-
- @Override
- public void onPauseAfterSuper() {
- Log.v(TAG, "On pause.");
mUI.showPreviewCover();
// When camera is started from secure lock screen for the first time
// after screen on, the activity gets onCreate->onResume->onPause->onResume.
@@ -1313,6 +1296,33 @@
}
@Override
+ public void init(AppController app, boolean isSecureCamera, boolean isCaptureIntent) {
+ init((CameraActivity) app.getAndroidContext(), app.getModuleLayoutRoot());
+ }
+
+ @Override
+ public void resume() {
+ onResumeBeforeSuper();
+ onResumeAfterSuper();
+ }
+
+ @Override
+ public void pause() {
+ onPauseBeforeSuper();
+ onPauseAfterSuper();
+ }
+
+ @Override
+ public void destroy() {
+ // TODO: implement this.
+ }
+
+ @Override
+ public void onPreviewSizeChanged(int width, int height) {
+ // TODO: implement this.
+ }
+
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
Log.v(TAG, "onConfigurationChanged");
setDisplayOrientation();
@@ -1444,14 +1454,8 @@
mCameraDevice.setFaceDetectionCallback(null, null);
mCameraDevice.setErrorCallback(null);
- if (mActivity.isSecureCamera() && !CameraActivity.isFirstStartAfterScreenOn()) {
- // Blocks until camera is actually released.
- CameraHolder.instance().strongRelease();
- } else {
- CameraHolder.instance().release();
- }
-
mFaceDetectionStarted = false;
+ mActivity.getCameraProvider().releaseCamera(mCameraDevice.getCameraId());
mCameraDevice = null;
setCameraState(PREVIEW_STOPPED);
mFocusManager.onCameraReleased();
@@ -1478,24 +1482,40 @@
startPreview();
}
- /** This can run on a background thread, post any view updates to MainHandler. */
- private void startPreview() {
- if (mPaused || mCameraDevice == null) {
- return;
+ /**
+ * Returns whether we can/should start the preview or not.
+ */
+ private boolean checkPreviewPreconditions() {
+ if (mPaused) {
+ return false;
}
- // Any decisions we make based on the surface texture state
- // need to be protected.
+ if (mCameraDevice == null) {
+ Log.w(TAG, "startPreview: camera device not ready yet.");
+ return false;
+ }
+
SurfaceTexture st = mUI.getSurfaceTexture();
if (st == null) {
Log.w(TAG, "startPreview: surfaceTexture is not ready.");
- return;
+ return false;
}
if (!mCameraPreviewParamsReady) {
Log.w(TAG, "startPreview: parameters for preview is not ready.");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * The start/stop preview should only run on the UI thread.
+ */
+ private void startPreview() {
+ if (!checkPreviewPreconditions()) {
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
@@ -1516,10 +1536,11 @@
}
setCameraParameters(UPDATE_PARAM_ALL);
// Let UI set its expected aspect ratio
- mCameraDevice.setPreviewTexture(st);
+ mCameraDevice.setPreviewTexture(mUI.getSurfaceTexture());
Log.v(TAG, "startPreview");
mCameraDevice.startPreview();
+
mFocusManager.onPreviewStarted();
onPreviewStarted();
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 7820a93..4686d60 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -43,6 +43,7 @@
import com.android.camera.CameraPreference.OnPreferenceChangedListener;
import com.android.camera.FocusOverlayManager.FocusUI;
+import com.android.camera.app.CameraManager;
import com.android.camera.ui.AbstractSettingPopup;
import com.android.camera.ui.CameraControls;
import com.android.camera.ui.CameraRootView;
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index f765b9c..678520b 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -53,12 +53,12 @@
import android.view.WindowManager;
import android.widget.Toast;
-import com.android.camera.CameraManager.CameraPictureCallback;
-import com.android.camera.CameraManager.CameraProxy;
+import com.android.camera.app.CameraManager.CameraPictureCallback;
+import com.android.camera.app.CameraManager.CameraProxy;
+import com.android.camera.app.AppController;
import com.android.camera.app.MediaSaver;
-import com.android.camera.app.OrientationManager;
-import com.android.camera.app.OrientationManagerImpl;
import com.android.camera.exif.ExifInterface;
+import com.android.camera.module.ModuleController;
import com.android.camera.ui.RotateTextToast;
import com.android.camera.util.AccessibilityUtils;
import com.android.camera.util.ApiHelper;
@@ -73,12 +73,9 @@
import java.util.Iterator;
import java.util.List;
-public class VideoModule implements CameraModule,
- VideoController,
- CameraPreference.OnPreferenceChangedListener,
- ShutterButton.OnShutterButtonListener,
- MediaRecorder.OnErrorListener,
- MediaRecorder.OnInfoListener {
+public class VideoModule implements CameraModule, ModuleController, VideoController,
+ CameraPreference.OnPreferenceChangedListener, ShutterButton.OnShutterButtonListener,
+ MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener {
private static final String TAG = "CAM_VideoModule";
@@ -196,14 +193,6 @@
}
};
-
- protected class CameraOpenThread extends Thread {
- @Override
- public void run() {
- openCamera();
- }
- }
-
private void openCamera() {
if (mCameraDevice == null) {
mCameraDevice = CameraUtil.openCamera(
@@ -336,8 +325,7 @@
* To reduce startup time, we start the preview in another thread.
* We make sure the preview is started at the end of onCreate.
*/
- CameraOpenThread cameraOpenThread = new CameraOpenThread();
- cameraOpenThread.start();
+ requestCamera(mCameraId);
mContentResolver = mActivity.getContentResolver();
@@ -346,17 +334,6 @@
mIsVideoCaptureIntent = isVideoCaptureIntent();
initializeSurfaceView();
- // Make sure camera device is opened.
- try {
- cameraOpenThread.join();
- if (mCameraDevice == null) {
- return;
- }
- } catch (InterruptedException ex) {
- // ignore
- }
-
- readVideoPreferences();
mUI.setPrefChangedListener(this);
mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false);
@@ -366,10 +343,6 @@
setDisplayOrientation();
mUI.showTimeLapseUI(mCaptureTimeLapse);
- initializeVideoSnapshot();
- resizeForPreviewAspectRatio();
-
- initializeVideoControl();
mPendingSwitchCameraId = -1;
}
@@ -392,7 +365,7 @@
}
// Set rotation and gps data.
- int rotation = CameraUtil.getJpegRotation(mCameraId, mOrientation);
+ int rotation = CameraUtil.getJpegRotation(mActivity, mCameraId, mOrientation);
mParameters.setRotation(rotation);
Location loc = mLocationManager.getCurrentLocation();
CameraUtil.setGpsParameters(mParameters, loc);
@@ -413,7 +386,7 @@
private void loadCameraPreferences() {
CameraSettings settings = new CameraSettings(mActivity, mParameters,
- mCameraId, CameraHolder.instance().getCameraInfo());
+ mCameraId, mActivity.getCameraProvider().getCameraInfo());
// Remove the video quality preference setting when the quality is given in the intent.
mPreferenceGroup = filterPreferenceScreenByIntent(
settings.getPreferenceGroup(R.xml.video_preferences));
@@ -443,6 +416,17 @@
}
}
+ @Override
+ public void onCameraAvailable(CameraProxy cameraProxy) {
+ mCameraDevice = cameraProxy;
+ readVideoPreferences();
+ resizeForPreviewAspectRatio();
+ startPreview();
+ initializeVideoSnapshot();
+ initializeVideoControl();
+ mUI.initializeZoom(mParameters);
+ }
+
private void startPlayVideoActivity() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(mCurrentVideoUri, convertOutputFormatToMimeType(mProfile.fileFormat));
@@ -654,21 +638,13 @@
showVideoSnapshotUI(false);
if (!mPreviewing) {
- openCamera();
- if (mCameraDevice == null) {
- return;
- }
- readVideoPreferences();
- resizeForPreviewAspectRatio();
- startPreview();
+ requestCamera(mCameraId);
} else {
// preview already started
mUI.enableShutter(true);
}
mUI.initDisplayChangeListener();
- // Initializing it here after the preview is started.
- mUI.initializeZoom(mParameters);
keepScreenOnAwhile();
@@ -765,7 +741,7 @@
}
mCameraDevice.setZoomChangeListener(null);
mCameraDevice.setErrorCallback(null);
- CameraHolder.instance().release();
+ mActivity.getCameraProvider().releaseCamera(mCameraDevice.getCameraId());
mCameraDevice = null;
mPreviewing = false;
mSnapshotInProgress = false;
@@ -786,6 +762,7 @@
// Camera will be released in onStopVideoRecording.
onStopVideoRecording();
} else {
+ stopPreview();
closeCamera();
releaseMediaRecorder();
}
@@ -1011,7 +988,7 @@
// which is the orientation the graphics need to rotate in order to render correctly.
int rotation = 0;
if (mOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
- CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
+ CameraInfo info = mActivity.getCameraProvider().getCameraInfo()[mCameraId];
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - mOrientation + 360) % 360;
} else { // back-facing camera
@@ -1111,8 +1088,7 @@
PreferenceGroup screen) {
Intent intent = mActivity.getIntent();
if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) {
- CameraSettings.removePreferenceFromScreen(screen,
- CameraSettings.KEY_VIDEO_QUALITY);
+ CameraSettings.removePreferenceFromScreen(screen, CameraSettings.KEY_VIDEO_QUALITY);
}
if (intent.hasExtra(MediaStore.EXTRA_DURATION_LIMIT)) {
@@ -1244,7 +1220,7 @@
if (bitmap != null) {
// MetadataRetriever already rotates the thumbnail. We should rotate
// it to match the UI orientation (and mirror if it is front-facing camera).
- CameraInfo[] info = CameraHolder.instance().getCameraInfo();
+ CameraInfo[] info = mActivity.getCameraProvider().getCameraInfo();
boolean mirror = (info[mCameraId].facing == CameraInfo.CAMERA_FACING_FRONT);
bitmap = CameraUtil.rotateAndMirror(bitmap, 0, mirror);
}
@@ -1535,6 +1511,33 @@
}
@Override
+ public void init(AppController app, boolean isSecureCamera, boolean isCaptureIntent) {
+ init((CameraActivity) app.getAndroidContext(), app.getModuleLayoutRoot());
+ }
+
+ @Override
+ public void resume() {
+ onResumeBeforeSuper();
+ onResumeAfterSuper();
+ }
+
+ @Override
+ public void pause() {
+ onPauseBeforeSuper();
+ onPauseAfterSuper();
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+
+ @Override
+ public void onPreviewSizeChanged(int width, int height) {
+ // TODO: implement this
+ }
+
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
Log.v(TAG, "onConfigurationChanged");
setDisplayOrientation();
@@ -1597,20 +1600,14 @@
setCameraId(mCameraId);
closeCamera();
+ requestCamera(mCameraId);
mUI.collapseCameraControls();
// Restart the camera and initialize the UI. From onCreate.
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
- openCamera();
- readVideoPreferences();
- startPreview();
- initializeVideoSnapshot();
- resizeForPreviewAspectRatio();
- initializeVideoControl();
// From onResume
mZoomValue = 0;
- mUI.initializeZoom(mParameters);
mUI.setOrientationIndicator(0, false);
// Start switch camera animation. Post a message because
@@ -1776,9 +1773,7 @@
mPendingSwitchCameraId = cameraId;
Log.d(TAG, "Start to copy texture.");
- // We need to keep a preview frame for the animation before
- // releasing the camera. This will trigger onPreviewTextureCopied.
- // TODO: ((CameraScreenNail) mActivity.mCameraScreenNail).copyTexture();
+
// Disable all camera controls.
mSwitchingCamera = true;
switchCamera();
@@ -1804,4 +1799,8 @@
public void onPreviewUIDestroyed() {
stopPreview();
}
+
+ private void requestCamera(int id) {
+ mActivity.getCameraProvider().requestCamera(id);
+ }
}
diff --git a/src/com/android/camera/WideAnglePanoramaModule.java b/src/com/android/camera/WideAnglePanoramaModule.java
index 47f8ad4..bc0a582 100644
--- a/src/com/android/camera/WideAnglePanoramaModule.java
+++ b/src/com/android/camera/WideAnglePanoramaModule.java
@@ -44,12 +44,12 @@
import android.view.ViewGroup;
import android.view.WindowManager;
-import com.android.camera.CameraManager.CameraProxy;
+import com.android.camera.app.CameraManager.CameraProxy;
+import com.android.camera.app.AppController;
import com.android.camera.app.MediaSaver;
-import com.android.camera.app.OrientationManager;
-import com.android.camera.app.OrientationManagerImpl;
import com.android.camera.data.LocalData;
import com.android.camera.exif.ExifInterface;
+import com.android.camera.module.ModuleController;
import com.android.camera.util.CameraUtil;
import com.android.camera.util.UsageStatistics;
import com.android.camera2.R;
@@ -64,7 +64,7 @@
* Activity to handle panorama capturing.
*/
public class WideAnglePanoramaModule
- implements CameraModule, WideAnglePanoramaController,
+ implements CameraModule, ModuleController, WideAnglePanoramaController,
SurfaceTexture.OnFrameAvailableListener {
public static final int DEFAULT_SWEEP_ANGLE = 160;
@@ -844,6 +844,36 @@
}
@Override
+ public void init(AppController app, boolean isSecureCamera, boolean isCaptureIntent) {
+ // TODO: implement this.
+ init((CameraActivity) app.getAndroidContext(), app.getModuleLayoutRoot());
+ }
+
+ @Override
+ public void resume() {
+ // TODO: implement this.
+ onResumeBeforeSuper();
+ onResumeAfterSuper();
+ }
+
+ @Override
+ public void pause() {
+ // TODO: implement this.
+ onPauseBeforeSuper();
+ onPauseAfterSuper();
+ }
+
+ @Override
+ public void destroy() {
+ // TODO: implement this.
+ }
+
+ @Override
+ public void onPreviewSizeChanged(int width, int height) {
+ // TODO: implement this.
+ }
+
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
mUI.onConfigurationChanged(newConfig, mThreadRunning);
}
@@ -853,6 +883,11 @@
}
@Override
+ public void onCameraAvailable(CameraProxy cameraProxy) {
+ // TODO: implement this.
+ }
+
+ @Override
public void onResumeBeforeSuper() {
mPaused = false;
}
diff --git a/src/com/android/camera/AndroidCameraManagerImpl.java b/src/com/android/camera/app/AndroidCameraManagerImpl.java
similarity index 85%
rename from src/com/android/camera/AndroidCameraManagerImpl.java
rename to src/com/android/camera/app/AndroidCameraManagerImpl.java
index 308633c..cc4facb 100644
--- a/src/com/android/camera/AndroidCameraManagerImpl.java
+++ b/src/com/android/camera/app/AndroidCameraManagerImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.camera;
+package com.android.camera.app;
import static com.android.camera.util.CameraUtil.Assert;
@@ -58,6 +58,10 @@
private static final int RECONNECT = 3;
private static final int UNLOCK = 4;
private static final int LOCK = 5;
+ @Deprecated
+ private static final int OPEN_CAMERA_OLD = 6; // TODO: remove this.
+ @Deprecated
+ private static final int RECONNECT_OLD = 7; // TODO: remove this.
// Preview
private static final int SET_PREVIEW_TEXTURE_ASYNC = 101;
private static final int START_PREVIEW_ASYNC = 102;
@@ -188,7 +192,30 @@
public void handleMessage(final Message msg) {
try {
switch (msg.what) {
- case OPEN_CAMERA:
+ case OPEN_CAMERA: {
+ final CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
+ final int cameraId = msg.arg1;
+ mCamera = android.hardware.Camera.open(cameraId);
+ if (mCamera != null) {
+ mParametersIsDirty = true;
+
+ // Get a instance of Camera.Parameters for later use.
+ if (mParamsToSet == null) {
+ mParamsToSet = mCamera.getParameters();
+ }
+
+ if (openCallback != null) {
+ openCallback.onCameraOpened(new AndroidCameraProxyImpl(cameraId));
+ }
+ } else {
+ if (openCallback != null) {
+ openCallback.onDeviceOpenFailure(cameraId);
+ }
+ }
+ return;
+ }
+
+ case OPEN_CAMERA_OLD: {
mCamera = android.hardware.Camera.open(msg.arg1);
if (mCamera != null) {
mParametersIsDirty = true;
@@ -203,13 +230,34 @@
}
}
return;
+ }
- case RELEASE:
+ case RELEASE: {
mCamera.release();
mCamera = null;
return;
+ }
- case RECONNECT:
+ case RECONNECT: {
+ final CameraOpenCallbackForward cbForward =
+ (CameraOpenCallbackForward) msg.obj;
+ final int cameraId = msg.arg1;
+ try {
+ mCamera.reconnect();
+ } catch (IOException ex) {
+ if (cbForward != null) {
+ cbForward.onReconnectionFailure(AndroidCameraManagerImpl.this);
+ }
+ return;
+ }
+
+ if (cbForward != null) {
+ cbForward.onCameraOpened(new AndroidCameraProxyImpl(cameraId));
+ }
+ return;
+ }
+
+ case RECONNECT_OLD: {
mReconnectIOException = null;
try {
mCamera.reconnect();
@@ -217,108 +265,132 @@
mReconnectIOException = ex;
}
return;
+ }
- case UNLOCK:
+ case UNLOCK: {
mCamera.unlock();
return;
+ }
- case LOCK:
+ case LOCK: {
mCamera.lock();
return;
+ }
- case SET_PREVIEW_TEXTURE_ASYNC:
+ case SET_PREVIEW_TEXTURE_ASYNC: {
setPreviewTexture(msg.obj);
return;
+ }
- case SET_PREVIEW_DISPLAY_ASYNC:
+ case SET_PREVIEW_DISPLAY_ASYNC: {
try {
mCamera.setPreviewDisplay((SurfaceHolder) msg.obj);
} catch (IOException e) {
throw new RuntimeException(e);
}
return;
+ }
- case START_PREVIEW_ASYNC:
+ case START_PREVIEW_ASYNC: {
mCamera.startPreview();
return;
+ }
- case STOP_PREVIEW:
+ case STOP_PREVIEW: {
mCamera.stopPreview();
return;
+ }
- case SET_PREVIEW_CALLBACK_WITH_BUFFER:
+ case SET_PREVIEW_CALLBACK_WITH_BUFFER: {
mCamera.setPreviewCallbackWithBuffer(
(PreviewCallback) msg.obj);
return;
+ }
- case ADD_CALLBACK_BUFFER:
+ case ADD_CALLBACK_BUFFER: {
mCamera.addCallbackBuffer((byte[]) msg.obj);
return;
+ }
- case AUTO_FOCUS:
+ case AUTO_FOCUS: {
mCamera.autoFocus((AutoFocusCallback) msg.obj);
return;
+ }
- case CANCEL_AUTO_FOCUS:
+ case CANCEL_AUTO_FOCUS: {
mCamera.cancelAutoFocus();
return;
+ }
- case SET_AUTO_FOCUS_MOVE_CALLBACK:
+ case SET_AUTO_FOCUS_MOVE_CALLBACK: {
setAutoFocusMoveCallback(mCamera, msg.obj);
return;
+ }
- case SET_DISPLAY_ORIENTATION:
+ case SET_DISPLAY_ORIENTATION: {
mCamera.setDisplayOrientation(msg.arg1);
return;
+ }
- case SET_ZOOM_CHANGE_LISTENER:
+ case SET_ZOOM_CHANGE_LISTENER: {
mCamera.setZoomChangeListener(
(OnZoomChangeListener) msg.obj);
return;
+ }
- case SET_FACE_DETECTION_LISTENER:
+ case SET_FACE_DETECTION_LISTENER: {
setFaceDetectionListener((FaceDetectionListener) msg.obj);
return;
+ }
- case START_FACE_DETECTION:
+ case START_FACE_DETECTION: {
startFaceDetection();
return;
+ }
- case STOP_FACE_DETECTION:
+ case STOP_FACE_DETECTION: {
stopFaceDetection();
return;
+ }
- case SET_ERROR_CALLBACK:
+ case SET_ERROR_CALLBACK: {
mCamera.setErrorCallback((ErrorCallback) msg.obj);
return;
+ }
- case SET_PARAMETERS:
+ case SET_PARAMETERS: {
mParametersIsDirty = true;
mParamsToSet.unflatten((String) msg.obj);
mCamera.setParameters(mParamsToSet);
return;
+ }
- case GET_PARAMETERS:
+ case GET_PARAMETERS: {
if (mParametersIsDirty) {
mParameters = mCamera.getParameters();
mParametersIsDirty = false;
}
return;
+ }
- case SET_PREVIEW_CALLBACK:
+ case SET_PREVIEW_CALLBACK: {
mCamera.setPreviewCallback((PreviewCallback) msg.obj);
return;
+ }
- case ENABLE_SHUTTER_SOUND:
+ case ENABLE_SHUTTER_SOUND: {
enableShutterSound((msg.arg1 == 1) ? true : false);
return;
+ }
- case REFRESH_PARAMETERS:
+ case REFRESH_PARAMETERS: {
mParametersIsDirty = true;
return;
+ }
- default:
+ default: {
throw new RuntimeException("Invalid CameraProxy message=" + msg.what);
+ }
}
} catch (RuntimeException e) {
if (msg.what != RELEASE && mCamera != null) {
@@ -344,13 +416,18 @@
}
@Override
- public CameraManager.CameraProxy cameraOpen(
- Handler handler, int cameraId, CameraOpenCallback callback) {
+ public void cameraOpen(Handler handler, int cameraId, CameraOpenCallback callback) {
mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0,
CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
+ }
+
+ @Override
+ public CameraProxy cameraOpenOld(Handler handler, int cameraId, CameraOpenCallback callback) {
+ mCameraHandler.obtainMessage(OPEN_CAMERA_OLD, cameraId, 0,
+ CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
mCameraHandler.waitDone();
if (mCamera != null) {
- return new AndroidCameraProxyImpl();
+ return new AndroidCameraProxyImpl(cameraId);
} else {
return null;
}
@@ -363,9 +440,11 @@
* handler multiple times.
*/
public class AndroidCameraProxyImpl implements CameraManager.CameraProxy {
+ private final int mCameraId;
- private AndroidCameraProxyImpl() {
+ private AndroidCameraProxyImpl(int cameraId) {
Assert(mCamera != null);
+ mCameraId = cameraId;
}
@Override
@@ -374,25 +453,39 @@
}
@Override
- public void release() {
- // release() must be synchronous so we know exactly when the camera
- // is released and can continue on.
+ public int getCameraId() {
+ return mCameraId;
+ }
+
+ // TODO: Make this package private.
+ @Override
+ public void release(boolean sync) {
+ Log.v("DEBUG", "camera manager release");
+ mCameraHandler.removeCallbacksAndMessages(null);
mCameraHandler.sendEmptyMessage(RELEASE);
- mCameraHandler.waitDone();
+ if (sync) {
+ mCameraHandler.waitDone();
+ }
}
@Override
- public boolean reconnect(Handler handler, CameraOpenCallback cb) {
- mCameraHandler.sendEmptyMessage(RECONNECT);
+ public void reconnect(Handler handler, CameraOpenCallback cb) {
+ mCameraHandler.obtainMessage(RECONNECT, mCameraId, 0,
+ CameraOpenCallbackForward.getNewInstance(handler, cb)).sendToTarget();
+ }
+
+ @Override
+ public boolean reconnectOld(Handler handler, CameraOpenCallback cb) {
+ mCameraHandler.sendEmptyMessage(RECONNECT_OLD);
mCameraHandler.waitDone();
CameraOpenCallback cbforward =
CameraOpenCallbackForward.getNewInstance(handler, cb);
if (mReconnectIOException != null) {
if (cbforward != null) {
cbforward.onReconnectionFailure(AndroidCameraManagerImpl.this);
- }
+ }
return false;
- }
+ }
return true;
}
diff --git a/src/com/android/camera/app/AppController.java b/src/com/android/camera/app/AppController.java
index a08a115..1b25397 100644
--- a/src/com/android/camera/app/AppController.java
+++ b/src/com/android/camera/app/AppController.java
@@ -22,7 +22,6 @@
import android.net.Uri;
import android.widget.FrameLayout;
-import com.android.camera.CameraManager;
import com.android.camera.LocationManager;
/**
@@ -142,11 +141,9 @@
/********************** App-level resources **********************/
/**
- * Returns the camera device proxy.
- *
- * @return {@code null} if not available yet.
+ * Returns the {@link com.android.camera.app.CameraProvider}.
*/
- public CameraManager.CameraProxy getCameraProxy();
+ public CameraProvider getCameraProvider();
/**
* Returns the {@link com.android.camera.app.MediaSaver}.
diff --git a/src/com/android/camera/app/CameraController.java b/src/com/android/camera/app/CameraController.java
new file mode 100644
index 0000000..acd2cce
--- /dev/null
+++ b/src/com/android/camera/app/CameraController.java
@@ -0,0 +1,186 @@
+/*
+ * 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.app;
+
+import android.content.Context;
+import android.hardware.Camera;
+import android.os.Handler;
+import android.util.Log;
+
+import com.android.camera.CameraDisabledException;
+import com.android.camera.util.CameraUtil;
+
+/**
+ * A class which implements {@link com.android.camera.app.CameraProvider} used
+ * by {@link com.android.camera.CameraActivity}.
+ * TODO: Make this class package private.
+ */
+public class CameraController implements CameraManager.CameraOpenCallback, CameraProvider {
+ private final String TAG = "CameraController";
+ private Context mContext;
+ private CameraManager.CameraOpenCallback mCallbackReceiver;
+ private Handler mCallbackHandler;
+ private final CameraManager mCameraManager;
+ private final Camera.CameraInfo[] mCameraInfos;
+ private final int mNumberOfCameras;
+ private final int mFirstBackCameraId;
+ private final int mFirstFrontCameraId;
+
+ private CameraManager.CameraProxy mCameraProxy;
+ private int mRequestingCameraId = -1;
+
+ /**
+ * Constructor.
+ *
+ * @param context The {@link android.content.Context} used to check if the
+ * camera is disabled.
+ * @param handler The {@link android.os.Handler} to post the camera
+ * callbacks to.
+ * @param cameraManager Used for camera open/close.
+ */
+ public CameraController(Context context, CameraManager.CameraOpenCallback callbackReceiver,
+ Handler handler, CameraManager cameraManager) {
+ mContext = context;
+ mCallbackReceiver = callbackReceiver;
+ mCallbackHandler = handler;
+ mCameraManager = cameraManager;
+ mNumberOfCameras = Camera.getNumberOfCameras();
+ mCameraInfos = new Camera.CameraInfo[mNumberOfCameras];
+ for (int i = 0; i < mNumberOfCameras; i++) {
+ mCameraInfos[i] = new Camera.CameraInfo();
+ Camera.getCameraInfo(i, mCameraInfos[i]);
+ }
+
+ int firstFront = -1;
+ int firstBack = -1;
+ // Get the first (smallest) back and first front camera id.
+ for (int i = 0; i < mNumberOfCameras; i++) {
+ if (mCameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
+ firstBack = i;
+ } else {
+ if (mCameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+ firstFront = i;
+ }
+ }
+ }
+ mFirstBackCameraId = firstBack;
+ mFirstFrontCameraId = firstFront;
+ }
+
+ @Override
+ public Camera.CameraInfo[] getCameraInfo() {
+ return mCameraInfos;
+ }
+
+ @Override
+ public int getNumberOfCameras() {
+ return mNumberOfCameras;
+ }
+
+ @Override
+ public int getFirstBackCameraId() {
+ return mFirstBackCameraId;
+ }
+
+ @Override
+ public int getFirstFrontCameraId() {
+ return mFirstFrontCameraId;
+ }
+
+ @Override
+ public void onCameraOpened(CameraManager.CameraProxy camera) {
+ mRequestingCameraId = -1;
+ mCameraProxy = camera;
+ mCallbackReceiver.onCameraOpened(camera);
+ }
+
+ @Override
+ public void onCameraDisabled(int cameraId) {
+ mCallbackReceiver.onCameraDisabled(cameraId);
+ }
+
+ @Override
+ public void onDeviceOpenFailure(int cameraId) {
+ mCallbackReceiver.onDeviceOpenFailure(cameraId);
+ }
+
+ @Override
+ public void onReconnectionFailure(CameraManager mgr) {
+ mCallbackReceiver.onReconnectionFailure(mgr);
+ }
+
+ @Override
+ public void requestCamera(int id) {
+ // Double open is avoided.
+ if (mRequestingCameraId == id) {
+ return;
+ }
+ mRequestingCameraId = id;
+ if (mCameraProxy == null) {
+ // No camera yet.
+ checkAndOpenCamera(mContext, mCameraManager, id, mCallbackHandler, this);
+ } else if (mCameraProxy.getCameraId() != id) {
+ // Already has another camera opened.
+ mCameraProxy.release(false);
+ mCameraProxy = null;
+ checkAndOpenCamera(mContext, mCameraManager, id, mCallbackHandler, this);
+ } else {
+ // The same camera, just do a reconnect.
+ mCameraProxy.reconnect(mCallbackHandler, this);
+ mCameraProxy = null;
+ }
+ }
+
+ @Override
+ public void releaseCamera(int id) {
+ if (mCameraProxy.getCameraId() != id) {
+ throw new IllegalStateException("Trying to release an unopened camera.");
+ }
+ if (mRequestingCameraId != -1) {
+ mRequestingCameraId = -1;
+ }
+ }
+
+ /**
+ * Closes the opened camera device.
+ * TODO: Make this method package private.
+ */
+ public void closeCamera() {
+ Log.v(TAG, "closing camera");
+ if (mCameraProxy == null) {
+ return;
+ }
+ mCameraProxy.release(true);
+ mCameraProxy = null;
+ mRequestingCameraId = -1;
+ }
+
+ private static void checkAndOpenCamera(Context context, CameraManager cameraManager,
+ final int cameraId, Handler handler, final CameraManager.CameraOpenCallback cb) {
+ try {
+ CameraUtil.throwIfCameraDisabled(context);
+ cameraManager.cameraOpen(handler, cameraId, cb);
+ } catch (CameraDisabledException ex) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ cb.onCameraDisabled(cameraId);
+ }
+ });
+ }
+ }
+}
diff --git a/src/com/android/camera/CameraManager.java b/src/com/android/camera/app/CameraManager.java
similarity index 88%
rename from src/com/android/camera/CameraManager.java
rename to src/com/android/camera/app/CameraManager.java
index 131045a..532c970 100644
--- a/src/com/android/camera/CameraManager.java
+++ b/src/com/android/camera/app/CameraManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.camera;
+package com.android.camera.app;
import android.annotation.TargetApi;
import android.graphics.SurfaceTexture;
@@ -129,23 +129,28 @@
* Callback when {@link java.io.IOException} is caught during
* {@link android.hardware.Camera#reconnect()}.
*
- * @param mgr The {@link com.android.camera.CameraManager}
+ * @param mgr The {@link CameraManager}
* with the reconnect failure.
*/
public void onReconnectionFailure(CameraManager mgr);
}
/**
- * Opens the camera of the specified ID synchronously.
+ * Opens the camera of the specified ID asynchronously. The camera device
+ * will be opened in the camera handler thread and will be returned through
+ * the {@link CameraManager.CameraOpenCallback#
+ * onCameraOpened(com.android.camera.app.CameraManager.CameraProxy)}.
*
* @param handler The {@link android.os.Handler} in which the callback
* was handled.
* @param callback The callback when any error happens.
* @param cameraId The camera ID to open.
- * @return An instance of {@link CameraProxy} on success. null on failure.
*/
- public CameraProxy cameraOpen(
- Handler handler, int cameraId, CameraOpenCallback callback);
+ public void cameraOpen(Handler handler, int cameraId, CameraOpenCallback callback);
+
+ // TODO: remove this after every module supports onCameraAvailable().
+ @Deprecated
+ public CameraProxy cameraOpenOld(Handler handler, int cameraId, CameraOpenCallback callback);
/**
* An interface that takes camera operation requests and post messages to the
@@ -163,22 +168,38 @@
public android.hardware.Camera getCamera();
/**
+ * Returns the camera ID associated to by this
+ * {@link CameraManager.CameraProxy}.
+ * @return
+ */
+ public int getCameraId();
+
+ /**
* Releases the camera device synchronously.
* This function must be synchronous so the caller knows exactly when the camera
* is released and can continue on.
+ * TODO: make this package-private after this interface is refactored under app.
+ *
+ * @param synchronous Whether this call should be synchronous.
*/
- public void release();
+ public void release(boolean synchronous);
/**
- * Reconnects to the camera device.
+ * Reconnects to the camera device. On success, the camera device will
+ * be returned through {@link CameraManager
+ * .CameraOpenCallback#onCameraOpened(com.android.camera.app.CameraManager
+ * .CameraProxy)}.
* @see android.hardware.Camera#reconnect()
*
* @param handler The {@link android.os.Handler} in which the callback
* was handled.
* @param cb The callback when any error happens.
- * @return {@code false} on errors.
*/
- public boolean reconnect(Handler handler, CameraOpenCallback cb);
+ public void reconnect(Handler handler, CameraOpenCallback cb);
+
+ // TODO: remove this.
+ @Deprecated
+ public boolean reconnectOld(Handler handler, CameraOpenCallback cb);
/**
* Unlocks the camera device.
diff --git a/src/com/android/camera/CameraManagerFactory.java b/src/com/android/camera/app/CameraManagerFactory.java
similarity index 82%
rename from src/com/android/camera/CameraManagerFactory.java
rename to src/com/android/camera/app/CameraManagerFactory.java
index 914ebb2..38f6c6d 100644
--- a/src/com/android/camera/CameraManagerFactory.java
+++ b/src/com/android/camera/app/CameraManagerFactory.java
@@ -14,7 +14,10 @@
* limitations under the License.
*/
-package com.android.camera;
+package com.android.camera.app;
+
+import com.android.camera.app.AndroidCameraManagerImpl;
+import com.android.camera.app.CameraManager;
/**
* A factory class for {@link CameraManager}.
@@ -24,7 +27,7 @@
private static AndroidCameraManagerImpl sAndroidCameraManager;
/**
- * Returns the android camera implementation of {@link CameraManager}.
+ * Returns the android camera implementation of {@link com.android.camera.app.CameraManager}.
*
* @return The {@link CameraManager} to control the camera device.
*/
diff --git a/src/com/android/camera/app/CameraProvider.java b/src/com/android/camera/app/CameraProvider.java
new file mode 100644
index 0000000..7c81557
--- /dev/null
+++ b/src/com/android/camera/app/CameraProvider.java
@@ -0,0 +1,62 @@
+/*
+ * 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.app;
+
+import android.hardware.Camera;
+
+/**
+ * An interface which defines the camera provider.
+ */
+public interface CameraProvider {
+
+ /**
+ * Requests the camera device. If the camera device of the same ID is
+ * already requested, then no-op here.
+ *
+ * @param id The ID of the requested camera device.
+ */
+ public void requestCamera(int id);
+
+ /**
+ * Releases the camera device.
+ *
+ * @param id The camera ID.
+ */
+ public void releaseCamera(int id);
+
+ /**
+ * Get the {@link android.hardware.Camera.CameraInfo} of all the cameras.
+ *
+ * @return An array of the {@link android.hardware.Camera.CameraInfo}.
+ */
+ public Camera.CameraInfo[] getCameraInfo();
+
+ /**
+ * Returns the total number of cameras available on the device.
+ */
+ public int getNumberOfCameras();
+
+ /**
+ * Returns the lowest ID of the back camera.
+ */
+ public int getFirstBackCameraId();
+
+ /**
+ * Returns the lowest ID of the front camera.
+ */
+ public int getFirstFrontCameraId();
+}
diff --git a/src/com/android/camera/app/ModuleManager.java b/src/com/android/camera/app/ModuleManager.java
new file mode 100644
index 0000000..2c08e14
--- /dev/null
+++ b/src/com/android/camera/app/ModuleManager.java
@@ -0,0 +1,93 @@
+/*
+ * 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.app;
+
+import com.android.camera.module.ModuleController;
+
+/**
+ * The module manager which maintains the
+ * {@link ModuleManagerImpl.ModuleAgent}.
+ */
+public interface ModuleManager {
+ public static int MODULE_INDEX_NONE = -1;
+
+ /**
+ * The module agent which is responsible for maintaining the static
+ * characteristics and the creation of the module.
+ */
+ public static interface ModuleAgent {
+
+ /**
+ * @return The module ID.
+ */
+ public int getModuleId();
+
+ /**
+ * @return Whether the module will request the app for the camera.
+ */
+ public boolean requestAppForCamera();
+
+ /**
+ * Creates the module.
+ * @return The module.
+ */
+ public ModuleController createModule();
+ }
+
+ /**
+ * Registers a module. A module will be available only if its agent is
+ * registered. The registration might fail.
+ *
+ * @param agent The {@link com.android.camera.app.ModuleManager.ModuleAgent}
+ * of the module.
+ * @throws java.lang.NullPointerException if the {@code agent} is null.
+ * @throws java.lang.IllegalArgumentException if the module ID is
+ * {@code MODULE_INDEX} or another module with the sameID is registered
+ * already.
+ */
+ void registerModule(ModuleAgent agent);
+
+ /**
+ * Unregister a module.
+ *
+ * @param moduleId The module ID.
+ * @return Whether the un-registration succeeds.
+ */
+ boolean unregisterModule(int moduleId);
+
+ /**
+ * Sets the default module index. No-op if the module index does not exist.
+ *
+ * @param moduleId The ID of the default module.
+ * @return Whether the {@code moduleId} exists.
+ */
+ boolean setDefaultModuleIndex(int moduleId);
+
+ /**
+ * @return The default module index. {@code MODULE_INDEX_NONE} if not set.
+ */
+ int getDefaultModuleIndex();
+
+ /**
+ * Returns the {@link com.android.camera.app.ModuleManager.ModuleAgent} by
+ * the module ID.
+ *
+ * @param moduleId The module ID.
+ * @return The agent.
+ */
+ ModuleAgent getModuleAgent(int moduleId);
+}
diff --git a/src/com/android/camera/app/ModuleManagerImpl.java b/src/com/android/camera/app/ModuleManagerImpl.java
new file mode 100644
index 0000000..7087520
--- /dev/null
+++ b/src/com/android/camera/app/ModuleManagerImpl.java
@@ -0,0 +1,84 @@
+/*
+ * 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.app;
+
+import android.util.SparseArray;
+
+/**
+ * A class which implements {@link com.android.camera.app.ModuleManager}.
+ */
+public class ModuleManagerImpl implements ModuleManager {
+ private static final String TAG = "ModuleManagerImpl";
+
+ private SparseArray<ModuleAgent> mRegisteredModuleAgents = new
+ SparseArray<ModuleAgent>(2);
+ private int mDefaultModuleId = MODULE_INDEX_NONE;
+
+ public ModuleManagerImpl() {
+ }
+
+ @Override
+ public void registerModule(ModuleAgent agent) {
+ if (agent == null) {
+ throw new NullPointerException("Registering a null ModuleAgent.");
+ }
+ final int moduleId = agent.getModuleId();
+ if (moduleId == MODULE_INDEX_NONE) {
+ throw new IllegalArgumentException(
+ "ModuleManager: The module ID can not be " + "MODULE_INDEX_NONE");
+ }
+ if (mRegisteredModuleAgents.get(moduleId) != null) {
+ throw new IllegalArgumentException("Module ID is registered already:" + moduleId);
+ }
+ mRegisteredModuleAgents.put(moduleId, agent);
+ }
+
+ @Override
+ public boolean unregisterModule(int moduleId) {
+ if (mRegisteredModuleAgents.get(moduleId) == null) {
+ return false;
+ }
+ mRegisteredModuleAgents.delete(moduleId);
+ if (moduleId == mDefaultModuleId) {
+ mDefaultModuleId = -1;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean setDefaultModuleIndex(int moduleId) {
+ if (mRegisteredModuleAgents.get(moduleId) != null) {
+ mDefaultModuleId = moduleId;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getDefaultModuleIndex() {
+ return mDefaultModuleId;
+ }
+
+ @Override
+ public ModuleAgent getModuleAgent(int moduleId) {
+ ModuleAgent agent = mRegisteredModuleAgents.get(moduleId);
+ if (agent == null) {
+ return mRegisteredModuleAgents.get(mDefaultModuleId);
+ }
+ return mRegisteredModuleAgents.get(moduleId);
+ }
+}
diff --git a/src/com/android/camera/module/ModuleController.java b/src/com/android/camera/module/ModuleController.java
index 63f2a8d..a0aedbf 100644
--- a/src/com/android/camera/module/ModuleController.java
+++ b/src/com/android/camera/module/ModuleController.java
@@ -18,7 +18,9 @@
import android.content.res.Configuration;
+import com.android.camera.app.CameraManager;
import com.android.camera.app.AppController;
+import com.android.camera.app.MediaSaver;
/**
* The controller at app level.
@@ -52,7 +54,7 @@
* Destroys the module. Always call this method to release the resources used
* by this module.
*/
- public void destory();
+ public void destroy();
/********************** UI / Camera preview **********************/
@@ -83,12 +85,16 @@
/**
* Called by the app when the camera is available. The module should use
* {@link com.android.camera.app.AppController#}
+ *
+ * @param cameraProxy The camera device proxy.
*/
- public void onCameraAvailable();
+ public void onCameraAvailable(CameraManager.CameraProxy cameraProxy);
/**
* Called by the app when the {@link com.android.camera.app.MediaSaver} is
* available.
+ *
+ * @param mediaSaver The {@link com.android.camera.app.MediaSaver} to use.
*/
- public void onMediaSaverAvailable();
+ public void onMediaSaverAvailable(MediaSaver mediaSaver);
}
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index f90a1a5..0ed6b59 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -55,7 +55,8 @@
import com.android.camera.CameraActivity;
import com.android.camera.CameraDisabledException;
import com.android.camera.CameraHolder;
-import com.android.camera.CameraManager;
+import com.android.camera.app.CameraManager;
+import com.android.camera.app.CameraManagerFactory;
import com.android.camera2.R;
import java.io.Closeable;
@@ -608,13 +609,15 @@
if (isFrontCameraIntent(intentCameraId)) {
// Check if the front camera exist
- int frontCameraId = CameraHolder.instance().getFrontCameraId();
+ int frontCameraId = ((CameraActivity) currentActivity).getCameraProvider()
+ .getFirstFrontCameraId();
if (frontCameraId != -1) {
cameraId = frontCameraId;
}
} else if (isBackCameraIntent(intentCameraId)) {
// Check if the back camera exist
- int backCameraId = CameraHolder.instance().getBackCameraId();
+ int backCameraId = ((CameraActivity) currentActivity).getCameraProvider()
+ .getFirstBackCameraId();
if (backCameraId != -1) {
cameraId = backCameraId;
}
@@ -754,12 +757,12 @@
view.setVisibility(View.GONE);
}
- public static int getJpegRotation(int cameraId, int orientation) {
+ public static int getJpegRotation(CameraActivity activity, int cameraId, int orientation) {
// See android.hardware.Camera.Parameters.setRotation for
// documentation.
int rotation = 0;
if (orientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
- CameraInfo info = CameraHolder.instance().getCameraInfo()[cameraId];
+ CameraInfo info = activity.getCameraProvider().getCameraInfo()[cameraId];
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - orientation + 360) % 360;
} else { // back-facing camera
@@ -881,6 +884,15 @@
return new int[0];
}
+ public static void throwIfCameraDisabled(Context context) throws CameraDisabledException {
+ // Check if device policy has disabled the camera.
+ DevicePolicyManager dpm =
+ (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ if (dpm.getCameraDisabled(null)) {
+ throw new CameraDisabledException();
+ }
+ }
+
private static class ImageFileNamer {
private final SimpleDateFormat mFormat;
diff --git a/src_pd/com/android/camera/util/SmartCameraHelper.java b/src_pd/com/android/camera/util/SmartCameraHelper.java
index 2b48388..e5942f4 100644
--- a/src_pd/com/android/camera/util/SmartCameraHelper.java
+++ b/src_pd/com/android/camera/util/SmartCameraHelper.java
@@ -20,8 +20,7 @@
import android.app.Activity;
import android.hardware.Camera;
-import com.android.camera.CameraManager.CameraPreviewDataCallback;
-import com.android.camera.CameraManager.CameraProxy;
+import com.android.camera.app.CameraManager.CameraProxy;
public class SmartCameraHelper {
public static void register(CameraProxy camera, Camera.Size previewSize, Activity activity) {}
diff --git a/tests_camera/src/com/android/camera/activity/CameraTestCase.java b/tests_camera/src/com/android/camera/activity/CameraTestCase.java
index 4aae6b4..339f005 100644
--- a/tests_camera/src/com/android/camera/activity/CameraTestCase.java
+++ b/tests_camera/src/com/android/camera/activity/CameraTestCase.java
@@ -30,7 +30,7 @@
import android.view.View;
import com.android.camera.CameraHolder;
-import com.android.camera.CameraManager.CameraProxy;
+import com.android.camera.app.CameraManager.CameraProxy;
import com.android.camera.util.CameraUtil;
import com.android.gallery3d.R;