summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSenpo Hu <senpo@google.com>2015-01-11 15:04:31 -0800
committerSenpo Hu <senpo@google.com>2015-01-16 12:01:24 -0800
commitfb0496133a0b4b526dc70f6447bd4b97d95de95f (patch)
tree99f7a50373819633ca21a07009f40b837ad9b5fb /src
parent3d9639a1b93ee245c53bc7948ec12be4119ff08c (diff)
downloadandroid_packages_apps_Camera2-fb0496133a0b4b526dc70f6447bd4b97d95de95f.tar.gz
android_packages_apps_Camera2-fb0496133a0b4b526dc70f6447bd4b97d95de95f.tar.bz2
android_packages_apps_Camera2-fb0496133a0b4b526dc70f6447bd4b97d95de95f.zip
Move FirstRunDialog to app layer.
The first run logic should live in CameraActivity. This refactoring could clean up CaptureModule and PhotoModule. * Introduce ResolutionSetting class. * Introduce OneCameraManagerImpl for camera API 1. Tested and verified this works on K / L devices. Change-Id: I11a968a9346b520dee23fc4591a73bb483c43246
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/CameraActivity.java75
-rw-r--r--src/com/android/camera/CaptureModule.java78
-rw-r--r--src/com/android/camera/PhotoModule.java159
-rw-r--r--src/com/android/camera/PhotoUI.java120
-rw-r--r--src/com/android/camera/app/AppController.java8
-rw-r--r--src/com/android/camera/app/FirstRunDialog.java191
-rw-r--r--src/com/android/camera/one/OneCameraManager.java46
-rw-r--r--src/com/android/camera/one/v1/OneCameraCharacteristicsImpl.java94
-rw-r--r--src/com/android/camera/one/v1/OneCameraManagerImpl.java108
-rw-r--r--src/com/android/camera/one/v2/OneCameraManagerImpl.java27
-rw-r--r--src/com/android/camera/settings/Keys.java53
-rw-r--r--src/com/android/camera/settings/ResolutionSetting.java108
-rw-r--r--src/com/android/camera/settings/ResolutionUtil.java15
-rw-r--r--src/com/android/camera/settings/SettingsUtil.java20
-rw-r--r--src/com/android/camera/util/ApiHelper.java4
15 files changed, 523 insertions, 583 deletions
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 70fd52d8d..82ce47401 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -71,6 +71,7 @@ import com.android.camera.app.CameraAppUI;
import com.android.camera.app.CameraController;
import com.android.camera.app.CameraProvider;
import com.android.camera.app.CameraServices;
+import com.android.camera.app.FirstRunDialog;
import com.android.camera.app.LocationManager;
import com.android.camera.app.MemoryManager;
import com.android.camera.app.MemoryQuery;
@@ -111,6 +112,8 @@ import com.android.camera.session.CaptureSessionManager.SessionListener;
import com.android.camera.settings.AppUpgrader;
import com.android.camera.settings.CameraSettingsActivity;
import com.android.camera.settings.Keys;
+import com.android.camera.settings.ResolutionSetting;
+import com.android.camera.settings.ResolutionUtil;
import com.android.camera.settings.SettingsManager;
import com.android.camera.settings.SettingsUtil;
import com.android.camera.tinyplanet.TinyPlanetFragment;
@@ -205,6 +208,7 @@ public class CameraActivity extends QuickActivity
private OneCameraManager mCameraManager;
private SettingsManager mSettingsManager;
+ private ResolutionSetting mResolutionSetting;
private ModeListView mModeListView;
private boolean mModeListVisible = false;
private int mCurrentModeIndex;
@@ -269,6 +273,9 @@ public class CameraActivity extends QuickActivity
private MemoryManager mMemoryManager;
private MotionManager mMotionManager;
+ /** First run dialog */
+ private FirstRunDialog mFirstRunDialog;
+
@Override
public CameraAppUI getCameraAppUI() {
return mCameraAppUI;
@@ -1414,11 +1421,12 @@ public class CameraActivity extends QuickActivity
mSoundPlayer = new SoundPlayer(mAppContext);
try {
- mCameraManager = OneCameraManager.get(this);
+ mCameraManager = OneCameraManager.get(this, ResolutionUtil.getDisplayMetrics(this));
} catch (OneCameraException e) {
// Log error and continue. Modules requiring OneCamera should check
// and handle if null by showing error dialog or other treatment.
- Log.w(TAG, "Creating camera manager failed.", e);
+ Log.e(TAG, "Creating camera manager failed.", e);
+ CameraUtil.showErrorAndFinish(this, R.string.cannot_connect_camera);
}
// TODO: Try to move all the resources allocation to happen as soon as
@@ -1431,6 +1439,7 @@ public class CameraActivity extends QuickActivity
AppUpgrader appUpgrader = new AppUpgrader(this);
appUpgrader.upgrade(mSettingsManager);
Keys.setDefaults(mSettingsManager, mAppContext);
+ mResolutionSetting = new ResolutionSetting(mSettingsManager, mCameraManager);
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
// We suppress this flag via theme when drawing the system preview
@@ -1609,6 +1618,19 @@ public class CameraActivity extends QuickActivity
}
});
mMotionManager = getServices().getMotionManager();
+
+ mFirstRunDialog = new FirstRunDialog(this, new FirstRunDialog.FirstRunDialogListener() {
+ @Override
+ public void onFirstRunStateReady() {
+ // Run normal resume tasks.
+ resume();
+ }
+
+ @Override
+ public void onCameraAccessException() {
+ CameraUtil.showErrorAndFinish(CameraActivity.this, R.string.cannot_connect_camera);
+ }
+ });
}
/**
@@ -1737,10 +1759,13 @@ public class CameraActivity extends QuickActivity
}
mPaused = true;
- mPeekAnimationHandler = null;
- mPeekAnimationThread.quitSafely();
- mPeekAnimationThread = null;
+ if (mPeekAnimationHandler != null) {
+ mPeekAnimationHandler = null;
+ mPeekAnimationThread.quitSafely();
+ mPeekAnimationThread = null;
+ }
mCameraAppUI.hideCaptureIndicator();
+ mFirstRunDialog.dismiss();
// Delete photos that are pending deletion
performDeletion();
@@ -1776,10 +1801,17 @@ public class CameraActivity extends QuickActivity
@Override
public void onResumeTasks() {
+ mPaused = false;
+
+ // Show the dialog if necessary. The rest resume logic will be invoked
+ // at the onFirstRunStateReady() callback.
+ mFirstRunDialog.showIfNecessary();
+ }
+
+ private void resume() {
CameraPerformanceTracker.onEvent(CameraPerformanceTracker.ACTIVITY_RESUME);
Log.v(TAG, "Build info: " + Build.DISPLAY);
- mPaused = false;
updateStorageSpaceAndHint(null);
mLastLayoutOrientation = getResources().getConfiguration().orientation;
@@ -1912,8 +1944,11 @@ public class CameraActivity extends QuickActivity
mPanoramaViewHelper.onResume();
ReleaseHelper.showReleaseInfoDialogOnStart(this, mSettingsManager);
- // Record location if the setting is active
- Keys.syncLocationManager(mSettingsManager, mLocationManager);
+
+ // Enable location recording if the setting is on.
+ final boolean locationRecordingEnabled =
+ mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL, Keys.KEY_RECORD_LOCATION);
+ mLocationManager.recordLocation(locationRecordingEnabled);
final int previewVisibility = getPreviewVisibility();
updatePreviewRendering(previewVisibility);
@@ -2303,6 +2338,11 @@ public class CameraActivity extends QuickActivity
}
@Override
+ public ResolutionSetting getResolutionSetting() {
+ return mResolutionSetting;
+ }
+
+ @Override
public CameraServices getServices() {
return (CameraServices) getApplication();
}
@@ -2334,25 +2374,6 @@ public class CameraActivity extends QuickActivity
}
/**
- * Creates an AlertDialog appropriate for choosing whether to enable
- * location on the first run of the app.
- */
- public AlertDialog getFirstTimeLocationAlert() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder = SettingsUtil.getFirstTimeLocationAlertBuilder(builder, new Callback<Boolean>() {
- @Override
- public void onCallback(Boolean locationOn) {
- Keys.setLocation(mSettingsManager, locationOn, mLocationManager);
- }
- });
- if (builder != null) {
- return builder.create();
- } else {
- return null;
- }
- }
-
- /**
* Launches an ACTION_EDIT intent for the given local data item. If
* 'withTinyPlanet' is set, this will show a disambig dialog first to let
* the user start either the tiny planet editor or another photo editor.
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 0226b636a..a3b97929f 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -39,7 +39,6 @@ import android.view.View;
import com.android.camera.app.AppController;
import com.android.camera.app.CameraAppUI;
import com.android.camera.app.CameraAppUI.BottomBarUISpec;
-import com.android.camera.app.FirstRunDialog;
import com.android.camera.app.LocationManager;
import com.android.camera.async.MainThreadExecutor;
import com.android.camera.burst.BurstFacade;
@@ -48,7 +47,6 @@ import com.android.camera.burst.BurstReadyStateChangeListener;
import com.android.camera.debug.DebugPropertyHelper;
import com.android.camera.debug.Log;
import com.android.camera.debug.Log.Tag;
-import com.android.camera.exif.Rational;
import com.android.camera.hardware.HardwareSpec;
import com.android.camera.hardware.HeadingSensor;
import com.android.camera.module.ModuleController;
@@ -73,7 +71,6 @@ import com.android.camera.remote.RemoteCameraModule;
import com.android.camera.session.CaptureSession;
import com.android.camera.settings.Keys;
import com.android.camera.settings.SettingsManager;
-import com.android.camera.settings.SettingsUtil;
import com.android.camera.ui.CountDownView;
import com.android.camera.ui.PreviewStatusListener;
import com.android.camera.ui.TouchCoordinate;
@@ -135,16 +132,16 @@ public class CaptureModule extends CameraModule implements
private final Context mContext;
/** Module UI. */
private CaptureModuleUI mUI;
- /** First run dialog */
- private FirstRunDialog mFirstRunDialog;
/** The camera manager used to open cameras. */
private OneCameraManager mCameraManager;
/** The currently opened camera device, or null if the camera is closed. */
private OneCamera mCamera;
+ /** The selected picture size. */
+ private Size mPictureSize;
/** Held when opening or closing the camera. */
private final Semaphore mCameraOpenCloseLock = new Semaphore(1);
/** The direction the currently opened camera is facing to. */
- private Facing mCameraFacing = Facing.BACK;
+ private Facing mCameraFacing;
/** Whether HDR is currently enabled. */
private boolean mHdrEnabled = false;
@@ -335,6 +332,7 @@ public class CaptureModule extends CameraModule implements
/** Constructs a new capture module. */
public CaptureModule(AppController appController, boolean stickyHdr) {
super(appController);
+ mPaused = true;
mAppController = appController;
mContext = mAppController.getAndroidContext();
mSettingsManager = mAppController.getSettingsManager();
@@ -362,9 +360,8 @@ public class CaptureModule extends CameraModule implements
mCameraHandler = new Handler(thread.getLooper());
mCameraManager = mAppController.getCameraManager();
mDisplayRotation = CameraUtil.getDisplayRotation(mContext);
- mCameraFacing = getFacingFromCameraId(mSettingsManager.getInteger(
- mAppController.getModuleScope(),
- Keys.KEY_CAMERA_ID));
+ mCameraFacing = getFacingFromCameraId(
+ mSettingsManager.getInteger(mAppController.getModuleScope(), Keys.KEY_CAMERA_ID));
mUI = new CaptureModuleUI(activity, mAppController.getModuleLayoutRoot(), mUIListener);
mAppController.setPreviewStatusListener(mPreviewStatusListener);
@@ -389,7 +386,6 @@ public class CaptureModule extends CameraModule implements
}
});
- mFirstRunDialog = new FirstRunDialog(mAppController, mCameraManager);
mMediaActionSound.load(MediaActionSound.SHUTTER_CLICK);
}
@@ -528,12 +524,11 @@ public class CaptureModule extends CameraModule implements
}
private void reopenCamera() {
- // Don't open camera until the aspect ratio preference is set on devices
- // that require us to show it.
- if (!mFirstRunDialog.shouldShow()) {
- closeCamera();
- openCameraAndStartPreview();
+ if (mPaused) {
+ return;
}
+ closeCamera();
+ openCameraAndStartPreview();
}
private SurfaceTexture getPreviewSurfaceTexture() {
@@ -584,28 +579,6 @@ public class CaptureModule extends CameraModule implements
mSoundPlayer.loadSound(R.raw.timer_increment);
mHeadingSensor.activate();
-
- if (mFirstRunDialog.shouldShow()) {
- mFirstRunDialog.setListener(new FirstRunDialog.FirstRunDialogListener() {
- @Override
- public void onLocationPreferenceConfirmed(boolean locationRecordingEnabled) {
- // If this device doesn't need to show the aspect ratio
- // dialog, start the preview right away since
- // onAspectRatioPreferenceConfirmed will never be called.
- if (!mFirstRunDialog.shouldShow()) {
- openCameraAndStartPreview();
- }
- }
-
- @Override
- public void onAspectRatioPreferenceConfirmed(Rational chosenAspectRatio) {
- // Open the camera. This dialog will be dismissed in
- // onPreviewStarted() after preview is started.
- openCameraAndStartPreview();
- }
- });
- mFirstRunDialog.show();
- }
}
@Override
@@ -1036,9 +1009,6 @@ public class CaptureModule extends CameraModule implements
mState = ModuleState.UPDATE_TRANSFORM_ON_NEXT_SURFACE_TEXTURE_UPDATE;
}
- // Dismiss the aspect ratio preference dialog.
- mFirstRunDialog.dismiss();
-
mAppController.onPreviewStarted();
onReadyStateChanged(true);
}
@@ -1160,8 +1130,7 @@ public class CaptureModule extends CameraModule implements
return;
}
- Size pictureSize = getPictureSizeFromSettings();
- Size previewBufferSize = mCamera.pickPreviewSize(pictureSize, mContext);
+ Size previewBufferSize = mCamera.pickPreviewSize(mPictureSize, mContext);
mPreviewBufferWidth = previewBufferSize.getWidth();
mPreviewBufferHeight = previewBufferSize.getHeight();
updateFrameDistributorBufferSize();
@@ -1185,9 +1154,9 @@ public class CaptureModule extends CameraModule implements
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while waiting to acquire camera-open lock.", e);
}
- OneCameraCharacteristics oneCameraCharacteristics;
+ OneCameraCharacteristics cameraCharacteristics;
try {
- oneCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraFacing);
+ cameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraFacing);
} catch (OneCameraAccessException ocae) {
mAppController.showErrorAndFinish(R.string.cannot_connect_camera);
return;
@@ -1210,15 +1179,23 @@ public class CaptureModule extends CameraModule implements
// for taking the image.
MainThreadExecutor mainThreadExecutor = MainThreadExecutor.create();
ImageRotationCalculator imageRotationCalculator = ImageRotationCalculatorImpl
- .from(oneCameraCharacteristics);
+ .from(cameraCharacteristics);
ImageBackend imageBackend = ProcessingServiceManager.getImageBackendInstance();
ImageSaver.Builder imageSaverBuilder = new YuvImageBackendImageSaver(
mainThreadExecutor, imageRotationCalculator, imageBackend);
// Only enable HDR on the back camera
boolean useHdr = mHdrEnabled && mCameraFacing == Facing.BACK;
- Size pictureSize = getPictureSizeFromSettings();
- mCameraManager.open(mCameraFacing, useHdr, pictureSize, imageSaverBuilder,
+
+ // Read the preferred picture size from the setting.
+ try {
+ mPictureSize = mAppController.getResolutionSetting().getPictureSize(mCameraFacing);
+ } catch (OneCameraAccessException ex) {
+ mAppController.showErrorAndFinish(R.string.cannot_connect_camera);
+ return;
+ }
+
+ mCameraManager.open(mCameraFacing, useHdr, mPictureSize, imageSaverBuilder,
new OpenCallback() {
@Override
public void onFailure() {
@@ -1339,13 +1316,6 @@ public class CaptureModule extends CameraModule implements
initSurfaceTextureConsumer();
}
- private Size getPictureSizeFromSettings() {
- String pictureSizeKey = mCameraFacing == Facing.FRONT ? Keys.KEY_PICTURE_SIZE_FRONT
- : Keys.KEY_PICTURE_SIZE_BACK;
- return SettingsUtil.sizeFromSettingString(
- mSettingsManager.getString(SettingsManager.SCOPE_GLOBAL, pictureSizeKey));
- }
-
private int getPreviewOrientation(int deviceOrientationDegrees) {
// Important: Camera2 buffers are already rotated to the natural
// orientation of the device (at least for the back-camera).
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index e4a8a1ca9..ea85a0247 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -24,9 +24,6 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.SurfaceTexture;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.media.CameraProfile;
@@ -59,12 +56,13 @@ import com.android.camera.hardware.HardwareSpec;
import com.android.camera.hardware.HardwareSpecImpl;
import com.android.camera.hardware.HeadingSensor;
import com.android.camera.module.ModuleController;
+import com.android.camera.one.OneCamera;
+import com.android.camera.one.OneCameraAccessException;
import com.android.camera.remote.RemoteCameraModule;
import com.android.camera.settings.CameraPictureSizesCacher;
import com.android.camera.settings.Keys;
import com.android.camera.settings.ResolutionUtil;
import com.android.camera.settings.SettingsManager;
-import com.android.camera.settings.SettingsUtil;
import com.android.camera.ui.CountDownView;
import com.android.camera.ui.TouchCoordinate;
import com.android.camera.util.ApiHelper;
@@ -269,43 +267,6 @@ public class PhotoModule
*/
private String mFlashModeBeforeSceneMode;
- /**
- * This callback gets called when user select whether or not to
- * turn on geo-tagging.
- */
- public interface LocationDialogCallback {
- /**
- * Gets called after user selected/unselected geo-tagging feature.
- *
- * @param selected whether or not geo-tagging feature is selected
- */
- public void onLocationTaggingSelected(boolean selected);
- }
-
- /**
- * This callback defines the text that is shown in the aspect ratio selection
- * dialog, provides the current aspect ratio, and gets notified when user changes
- * aspect ratio selection in the dialog.
- */
- public interface AspectRatioDialogCallback {
- /**
- * Returns current aspect ratio that is being used to set as default.
- */
- public Rational getCurrentAspectRatio();
-
- /**
- * Gets notified when user has made the aspect ratio selection.
- *
- * @param chosenAspectRatio The aspect ratio that user has selected
- * @param dialogHandlingFinishedRunnable runnable to run when the operations
- * needed to handle changes from dialog
- * are finished.
- */
- public void onAspectRatioSelected(
- Rational chosenAspectRatio,
- Runnable dialogHandlingFinishedRunnable);
- }
-
private void checkDisplayRotation() {
// Need to just be a no-op for the quick resume-pause scenario.
if (mPaused) {
@@ -475,95 +436,6 @@ public class PhotoModule
mAppController.setShutterEnabled(true);
setCameraState(IDLE);
startFaceDetection();
- settingsFirstRun();
- }
-
- /**
- * Prompt the user to pick to record location and choose aspect ratio for the
- * very first run of camera only.
- */
- private void settingsFirstRun() {
- final SettingsManager settingsManager = mActivity.getSettingsManager();
-
- if (mActivity.isSecureCamera() || isImageCaptureIntent()) {
- return;
- }
-
- boolean locationPrompt = !settingsManager.isSet(SettingsManager.SCOPE_GLOBAL,
- Keys.KEY_RECORD_LOCATION);
- boolean aspectRatioPrompt = !settingsManager.getBoolean(
- SettingsManager.SCOPE_GLOBAL, Keys.KEY_USER_SELECTED_ASPECT_RATIO);
- if (!locationPrompt && !aspectRatioPrompt) {
- return;
- }
-
- // Check if the back camera exists
- int backCameraId = mAppController.getCameraProvider().getFirstBackCameraId();
- if (backCameraId == -1) {
- // If there is no back camera, do not show the prompt.
- return;
- }
-
- if (locationPrompt) {
- // Show both location and aspect ratio selection dialog.
- mUI.showLocationAndAspectRatioDialog(new LocationDialogCallback(){
- @Override
- public void onLocationTaggingSelected(boolean selected) {
- Keys.setLocation(mActivity.getSettingsManager(), selected,
- mActivity.getLocationManager());
- }
- }, createAspectRatioDialogCallback());
- } else {
- // App upgrade. Only show aspect ratio selection.
- boolean wasShown = mUI.showAspectRatioDialog(createAspectRatioDialogCallback());
- if (!wasShown) {
- // If the dialog was not shown, set this flag to true so that we
- // never have to check for it again. It means that we don't need
- // to show the dialog on this device.
- mActivity.getSettingsManager().set(SettingsManager.SCOPE_GLOBAL,
- Keys.KEY_USER_SELECTED_ASPECT_RATIO, true);
- }
- }
- }
-
- private AspectRatioDialogCallback createAspectRatioDialogCallback() {
- Size currentSize = new Size(mCameraSettings.getCurrentPhotoSize());
- final Rational currentAspectRatio = ResolutionUtil.getAspectRatio(currentSize);
- AspectRatioDialogCallback callback = new AspectRatioDialogCallback() {
- @Override
- public Rational getCurrentAspectRatio() {
- return currentAspectRatio;
- }
-
- @Override
- public void onAspectRatioSelected(
- Rational chosenAspectRatio, Runnable dialogHandlingFinishedRunnable) {
- List<Size> supportedPhotoSizes = Size.convert(mCameraCapabilities.getSupportedPhotoSizes());
- Size largestPictureSize = ResolutionUtil.getLargestPictureSize(
- chosenAspectRatio, supportedPhotoSizes);
- mActivity.getSettingsManager().set(
- SettingsManager.SCOPE_GLOBAL,
- Keys.KEY_PICTURE_SIZE_BACK,
- SettingsUtil.sizeToSettingString(largestPictureSize));
- mActivity.getSettingsManager().set(
- SettingsManager.SCOPE_GLOBAL,
- Keys.KEY_USER_SELECTED_ASPECT_RATIO,
- true);
- String aspectRatio = mActivity.getSettingsManager().getString(
- SettingsManager.SCOPE_GLOBAL,
- Keys.KEY_USER_SELECTED_ASPECT_RATIO);
- Log.e(TAG, "aspect ratio after setting it to true=" + aspectRatio);
- if (chosenAspectRatio != currentAspectRatio) {
- Log.i(TAG, "changing aspect ratio from dialog");
- stopPreview();
- startPreview();
- mUI.setRunnableForNextFrame(dialogHandlingFinishedRunnable);
- } else {
- mHandler.post(dialogHandlingFinishedRunnable);
- }
- }
- };
- return callback;
}
@Override
@@ -2053,21 +1925,22 @@ public class PhotoModule
return;
}
- SettingsManager settingsManager = mActivity.getSettingsManager();
- String pictureSizeKey = isCameraFrontFacing() ? Keys.KEY_PICTURE_SIZE_FRONT
- : Keys.KEY_PICTURE_SIZE_BACK;
- String pictureSize = settingsManager.getString(SettingsManager.SCOPE_GLOBAL,
- pictureSizeKey);
-
- List<com.android.camera.util.Size> supported =
- com.android.camera.util.Size.convert(mCameraCapabilities.getSupportedPhotoSizes());
+ List<Size> supported = Size.convert(mCameraCapabilities.getSupportedPhotoSizes());
CameraPictureSizesCacher.updateSizesForCamera(mAppController.getAndroidContext(),
mCameraDevice.getCameraId(), supported);
- SettingsUtil.setCameraPictureSize(pictureSize, supported, mCameraSettings,
- mCameraDevice.getCameraId());
- Size size = SettingsUtil.getPhotoSize(pictureSize, supported,
- mCameraDevice.getCameraId());
+ OneCamera.Facing cameraFacing =
+ isCameraFrontFacing() ? OneCamera.Facing.FRONT : OneCamera.Facing.BACK;
+ Size pictureSize;
+ try {
+ pictureSize = mAppController.getResolutionSetting().getPictureSize(cameraFacing);
+ } catch (OneCameraAccessException ex) {
+ mAppController.showErrorAndFinish(R.string.cannot_connect_camera);
+ return;
+ }
+
+ mCameraSettings.setPhotoSize(pictureSize.toPortabilitySize());
+
if (ApiHelper.IS_NEXUS_5) {
if (ResolutionUtil.NEXUS_5_LARGE_16_BY_9.equals(pictureSize)) {
mShouldResizeTo16x9 = true;
@@ -2080,7 +1953,7 @@ public class PhotoModule
// the right aspect ratio.
List<Size> sizes = Size.convert(mCameraCapabilities.getSupportedPreviewSizes());
Size optimalSize = CameraUtil.getOptimalPreviewSize(mActivity, sizes,
- (double) size.width() / size.height());
+ (double) pictureSize.width() / pictureSize.height());
Size original = new Size(mCameraSettings.getCurrentPreviewSize());
if (!optimalSize.equals(original)) {
Log.v(TAG, "setting preview size. optimal: " + optimalSize + "original: " + original);
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 02f98d848..d2e5c093f 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -33,17 +33,12 @@ import android.widget.ImageView;
import com.android.camera.debug.DebugPropertyHelper;
import com.android.camera.debug.Log;
-import com.android.camera.exif.Rational;
import com.android.camera.ui.CountDownView;
import com.android.camera.ui.FaceView;
import com.android.camera.ui.PreviewOverlay;
import com.android.camera.ui.PreviewStatusListener;
import com.android.camera.ui.focus.FocusRing;
-import com.android.camera.util.ApiHelper;
import com.android.camera.util.CameraUtil;
-import com.android.camera.util.GservicesHelper;
-import com.android.camera.widget.AspectRatioDialogLayout;
-import com.android.camera.widget.LocationDialogLayout;
import com.android.camera2.R;
import com.android.ex.camera2.portability.CameraAgent;
import com.android.ex.camera2.portability.CameraCapabilities;
@@ -91,7 +86,6 @@ public class PhotoUI implements PreviewStatusListener,
mDialog = null;
}
};
- private Runnable mRunnableForNextFrame = null;
private final CountDownView mCountdownView;
@Override
@@ -126,13 +120,6 @@ public class PhotoUI implements PreviewStatusListener,
}
/**
- * Sets the runnable to run when the next frame comes in.
- */
- public void setRunnableForNextFrame(Runnable runnable) {
- mRunnableForNextFrame = runnable;
- }
-
- /**
* Starts the countdown timer.
*
* @param sec seconds to countdown
@@ -314,14 +301,6 @@ public class PhotoUI implements PreviewStatusListener,
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- if (mRunnableForNextFrame != null) {
- mRootView.post(mRunnableForNextFrame);
- mRunnableForNextFrame = null;
- }
- }
-
- public View getRootView() {
- return mRootView;
}
private void initIndicators() {
@@ -351,105 +330,6 @@ public class PhotoUI implements PreviewStatusListener,
}
}
- public void showLocationAndAspectRatioDialog(
- final PhotoModule.LocationDialogCallback locationCallback,
- final PhotoModule.AspectRatioDialogCallback aspectRatioDialogCallback) {
- setDialog(new Dialog(mActivity,
- android.R.style.Theme_Black_NoTitleBar_Fullscreen));
- final LocationDialogLayout locationDialogLayout = new LocationDialogLayout(
- mActivity, true);
- locationDialogLayout.setListener(new LocationDialogLayout.LocationDialogListener() {
- @Override
- public void onConfirm(boolean selected) {
- // Update setting.
- locationCallback.onLocationTaggingSelected(selected);
-
- if (showAspectRatioDialogOnThisDevice()) {
- // Go to next page.
- showAspectRatioDialog(aspectRatioDialogCallback, mDialog);
- } else {
- // If we don't want to show the aspect ratio dialog,
- // dismiss the dialog right after the user chose the
- // location setting.
- if (mDialog != null) {
- mDialog.dismiss();
- }
- }
- }
- });
- mDialog.setContentView(locationDialogLayout, new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
- mDialog.show();
- }
-
- /**
- * Dismisses previous dialog if any, sets current dialog to the given dialog,
- * and set the on dismiss listener for the given dialog.
- * @param dialog dialog to show
- */
- private void setDialog(Dialog dialog) {
- if (mDialog != null) {
- mDialog.setOnDismissListener(null);
- mDialog.dismiss();
- }
- mDialog = dialog;
- if (mDialog != null) {
- mDialog.setOnDismissListener(mOnDismissListener);
- }
- }
-
- /**
- * @return Whether the dialog was shown.
- */
- public boolean showAspectRatioDialog(final PhotoModule.AspectRatioDialogCallback callback) {
- if (showAspectRatioDialogOnThisDevice()) {
- setDialog(new Dialog(mActivity, android.R.style.Theme_Black_NoTitleBar_Fullscreen));
- showAspectRatioDialog(callback, mDialog);
- return true;
- } else {
- return false;
- }
- }
-
- private boolean showAspectRatioDialog(final PhotoModule.AspectRatioDialogCallback callback,
- final Dialog aspectRatioDialog) {
- if (aspectRatioDialog == null) {
- Log.e(TAG, "Dialog for aspect ratio is null.");
- return false;
- }
- final AspectRatioDialogLayout aspectRatioDialogLayout = new AspectRatioDialogLayout(
- mActivity, callback.getCurrentAspectRatio());
- aspectRatioDialogLayout.setListener(
- new AspectRatioDialogLayout.AspectRatioDialogListener() {
- @Override
- public void onConfirm(Rational chosenAspectRatio) {
- callback.onAspectRatioSelected(chosenAspectRatio, new Runnable() {
- @Override
- public void run() {
- if (mDialog != null) {
- mDialog.dismiss();
- }
- }
- });
- }
- });
- aspectRatioDialog.setContentView(aspectRatioDialogLayout, new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
- aspectRatioDialog.show();
- return true;
- }
-
- /**
- * @return Whether this is a device that we should show the aspect ratio
- * intro dialog on.
- */
- private boolean showAspectRatioDialogOnThisDevice() {
- // We only want to show that dialog on N4/N5/N6
- // Don't show if using API2 portability, b/17462976
- return !GservicesHelper.useCamera2ApiThroughPortabilityLayer(mActivity) &&
- (ApiHelper.IS_NEXUS_4 || ApiHelper.IS_NEXUS_5 || ApiHelper.IS_NEXUS_6);
- }
-
public void initializeZoom(CameraCapabilities capabilities, CameraSettings settings) {
if ((capabilities == null) || settings == null ||
!capabilities.supports(CameraCapabilities.Feature.ZOOM)) {
diff --git a/src/com/android/camera/app/AppController.java b/src/com/android/camera/app/AppController.java
index 1ec233236..3ebfcac40 100644
--- a/src/com/android/camera/app/AppController.java
+++ b/src/com/android/camera/app/AppController.java
@@ -32,6 +32,7 @@ import com.android.camera.ButtonManager;
import com.android.camera.SoundPlayer;
import com.android.camera.module.ModuleController;
import com.android.camera.one.OneCameraManager;
+import com.android.camera.settings.ResolutionSetting;
import com.android.camera.settings.SettingsManager;
import com.android.camera.ui.AbstractTutorialOverlay;
import com.android.camera.ui.PreviewStatusListener;
@@ -365,6 +366,13 @@ public interface AppController {
public SettingsManager getSettingsManager();
/**
+ * Returns the {@link com.android.camera.settings.ResolutionSetting}.
+ *
+ * @return the current resolution setting.
+ */
+ public ResolutionSetting getResolutionSetting();
+
+ /**
* @return Common services and functionality to be shared.
*/
public CameraServices getServices();
diff --git a/src/com/android/camera/app/FirstRunDialog.java b/src/com/android/camera/app/FirstRunDialog.java
index 8011e6f21..08c22e77f 100644
--- a/src/com/android/camera/app/FirstRunDialog.java
+++ b/src/com/android/camera/app/FirstRunDialog.java
@@ -17,52 +17,51 @@
package com.android.camera.app;
import android.app.Dialog;
+import android.content.Context;
import android.content.DialogInterface;
-import android.graphics.ImageFormat;
import android.view.ViewGroup;
-import com.android.camera.debug.Log;
import com.android.camera.exif.Rational;
import com.android.camera.one.OneCamera;
import com.android.camera.one.OneCameraAccessException;
-import com.android.camera.one.OneCameraCharacteristics;
-import com.android.camera.one.OneCameraManager;
import com.android.camera.settings.Keys;
+import com.android.camera.settings.ResolutionSetting;
import com.android.camera.settings.ResolutionUtil;
import com.android.camera.settings.SettingsManager;
-import com.android.camera.settings.SettingsUtil;
import com.android.camera.util.ApiHelper;
-import com.android.camera.util.Size;
import com.android.camera.widget.AspectRatioDialogLayout;
import com.android.camera.widget.LocationDialogLayout;
-import java.util.List;
-
/**
* The dialog to show when users open the app for the first time.
*/
public class FirstRunDialog {
public interface FirstRunDialogListener {
-
- public void onLocationPreferenceConfirmed(boolean locationRecordingEnabled);
-
- public void onAspectRatioPreferenceConfirmed(Rational chosenAspectRatio);
+ public void onFirstRunStateReady();
+ public void onCameraAccessException();
}
- private static final Log.Tag TAG = new Log.Tag("FirstRunDialog");
-
/** The default preference of aspect ratio. */
private static final Rational DEFAULT_ASPECT_RATIO = ResolutionUtil.ASPECT_RATIO_4x3;
/** The default preference of whether enabling location recording. */
private static final boolean DEFAULT_LOCATION_RECORDING_ENABLED = true;
+ /** Listener to receive events. */
+ private final FirstRunDialogListener mListener;
+
/** The app controller. */
private final AppController mAppController;
- /** The camera manager used to query camera characteristics. */
- private final OneCameraManager mCameraManager;
+ /** The app context. */
+ private final Context mContext;
+
+ /** The resolution settings. */
+ private final ResolutionSetting mResolutionSetting;
+
+ /** The settings manager. */
+ private final SettingsManager mSettingsManager;
/** Aspect ratio preference dialog */
private Dialog mAspectRatioPreferenceDialog;
@@ -70,55 +69,30 @@ public class FirstRunDialog {
/** Location preference dialog */
private Dialog mLocationPreferenceDialog;
- /** Listener to receive events. */
- private FirstRunDialogListener mListener;
-
/**
* Constructs a first run dialog.
*
* @param appController The app controller.
- * @param cameraManager The camera manager used to query supported aspect
- * ratio by camera devices.
*/
- public FirstRunDialog(AppController appController, OneCameraManager cameraManager) {
- mAppController = appController;
- mCameraManager = cameraManager;
- }
-
- /**
- * Set a dialog listener.
- *
- * @param listener The dialog listener to be set.
- */
- public void setListener(FirstRunDialogListener listener) {
+ public FirstRunDialog(AppController appController, FirstRunDialogListener listener) {
mListener = listener;
- }
-
- /**
- * Whether first run dialogs should be presented to the user.
- *
- * @return Whether first run dialogs should be presented to the user.
- */
- public boolean shouldShow() {
- return shouldShowAspectRatioPreferenceDialog() || shouldShowLocationPreferenceDialog();
+ mAppController = appController;
+ mContext = mAppController.getAndroidContext();
+ mResolutionSetting = mAppController.getResolutionSetting();
+ mSettingsManager = mAppController.getSettingsManager();
}
/**
* Shows first run dialogs if necessary.
- *
- * @return Whether first run dialogs are shown.
*/
- public boolean show() {
- // When people open the app for the first time, prompt two dialogs to
- // ask preferences about
- // location and aspect ratio.
- if (promptLocationPreferenceDialog()) {
- return true;
+ public void showIfNecessary() {
+ if (shouldShow()) {
+ // When people open the app for the first time, prompt two dialogs to
+ // ask preferences about location and aspect ratio. The first dialog is
+ // location reference.
+ promptLocationPreferenceDialog();
} else {
- // This should be a rare case because location and aspect ratio
- // preferences usually got
- // set at the same time when people open the app for the first time.
- return promptAspectRatioPreferenceDialog();
+ mListener.onFirstRunStateReady();
}
}
@@ -135,76 +109,54 @@ public class FirstRunDialog {
}
/**
- * Whether a aspect ratio dialog should be presented to the user.
+ * Whether first run dialogs should be presented to the user.
*
- * @return Whether a aspect ratio dialog should be presented to the user.
+ * @return Whether first run dialogs should be presented to the user.
*/
- private boolean shouldShowAspectRatioPreferenceDialog() {
- final SettingsManager settingsManager = mAppController.getSettingsManager();
- final boolean isAspectRatioPreferenceSet = settingsManager.getBoolean(
+ private boolean shouldShow() {
+ final boolean isAspectRatioPreferenceSet = mSettingsManager.getBoolean(
SettingsManager.SCOPE_GLOBAL, Keys.KEY_USER_SELECTED_ASPECT_RATIO);
- return ApiHelper.shouldShowAspectRatioDialog() && !isAspectRatioPreferenceSet;
+ final boolean isAspectRatioDevice =
+ ApiHelper.IS_NEXUS_4 || ApiHelper.IS_NEXUS_5 || ApiHelper.IS_NEXUS_6;
+ final boolean shouldShowAspectRatioDialog =
+ isAspectRatioDevice && !isAspectRatioPreferenceSet;
+ final boolean shouldShowLocationDialog =
+ !mSettingsManager.isSet(SettingsManager.SCOPE_GLOBAL, Keys.KEY_RECORD_LOCATION);
+ return shouldShowAspectRatioDialog || shouldShowLocationDialog;
}
/**
* Prompts a dialog to allow people to choose aspect ratio preference when
* people open the app for the first time. If the preference has been set,
* this will return false.
- *
- * @return Whether the dialog will be prompted or not.
*/
- private boolean promptAspectRatioPreferenceDialog() {
- // Do nothing if the preference is already set.
- if (!shouldShowAspectRatioPreferenceDialog()) {
- return false;
- }
-
+ private void promptAspectRatioPreferenceDialog() {
// Create a content view for the dialog.
final AspectRatioDialogLayout dialogLayout = new AspectRatioDialogLayout(
- mAppController.getAndroidContext(), DEFAULT_ASPECT_RATIO);
+ mContext, DEFAULT_ASPECT_RATIO);
dialogLayout.setListener(new AspectRatioDialogLayout.AspectRatioDialogListener() {
@Override
public void onConfirm(Rational aspectRatio) {
+ // Change resolution setting based on the chosen aspect ratio.
try {
- final SettingsManager settingsManager =
- mAppController.getSettingsManager();
-
- // Save the picture size setting for back camera.
- OneCameraCharacteristics backCameraChars =
- mCameraManager.getCameraCharacteristics(OneCamera.Facing.BACK);
- List<Size> backCameraPictureSizes =
- backCameraChars.getSupportedPictureSizes(ImageFormat.JPEG);
- Size backCameraChosenPictureSize =
- ResolutionUtil.getLargestPictureSize(
- aspectRatio, backCameraPictureSizes);
- settingsManager.set(
- SettingsManager.SCOPE_GLOBAL,
- Keys.KEY_PICTURE_SIZE_BACK,
- SettingsUtil.sizeToSettingString(backCameraChosenPictureSize));
-
- // Save the picture size setting for front camera.
- OneCameraCharacteristics frontCameraChars =
- mCameraManager.getCameraCharacteristics(OneCamera.Facing.FRONT);
- List<Size> frontCameraPictureSizes =
- frontCameraChars.getSupportedPictureSizes(ImageFormat.JPEG);
- Size frontCameraChosenPictureSize =
- ResolutionUtil.getLargestPictureSize(
- aspectRatio, frontCameraPictureSizes);
- settingsManager.set(
- SettingsManager.SCOPE_GLOBAL,
- Keys.KEY_PICTURE_SIZE_FRONT,
- SettingsUtil.sizeToSettingString(frontCameraChosenPictureSize));
-
- // Indicate the aspect ratio is selected.
- settingsManager.set(
- SettingsManager.SCOPE_GLOBAL,
- Keys.KEY_USER_SELECTED_ASPECT_RATIO,
- true);
+ mResolutionSetting.setPictureAspectRatio(OneCamera.Facing.BACK, aspectRatio);
+ mResolutionSetting.setPictureAspectRatio(OneCamera.Facing.FRONT, aspectRatio);
} catch (OneCameraAccessException ex) {
- throw new RuntimeException(ex);
+ mListener.onCameraAccessException();
+ return;
}
- mListener.onAspectRatioPreferenceConfirmed(aspectRatio);
+ // Mark that user has made the choice.
+ mSettingsManager.set(
+ SettingsManager.SCOPE_GLOBAL,
+ Keys.KEY_USER_SELECTED_ASPECT_RATIO,
+ true);
+
+ // Dismiss all dialogs.
+ dismiss();
+
+ // Notify that the app is ready to go.
+ mListener.onFirstRunStateReady();
}
});
@@ -221,47 +173,27 @@ public class FirstRunDialog {
// Show the dialog.
mAspectRatioPreferenceDialog.show();
- return true;
- }
-
- /**
- * Whether a location dialog should be presented to the user.
- *
- * @return Whether a location dialog should be presented to the user.
- */
- private boolean shouldShowLocationPreferenceDialog() {
- final SettingsManager settingsManager = mAppController.getSettingsManager();
- return !settingsManager.isSet(SettingsManager.SCOPE_GLOBAL, Keys.KEY_RECORD_LOCATION);
}
/**
* Prompts a dialog to allow people to choose location preference when
* people open the app for the first time. If the preference has been set,
* this will return false.
- *
- * @return Whether the dialog will be prompted or not.
*/
- private boolean promptLocationPreferenceDialog() {
- // Do nothing if the preference is already set.
- if (!shouldShowLocationPreferenceDialog()) {
- return false;
- }
-
+ private void promptLocationPreferenceDialog() {
// Create a content view for the dialog.
final LocationDialogLayout dialogLayout = new LocationDialogLayout(
- mAppController.getAndroidContext(), DEFAULT_LOCATION_RECORDING_ENABLED);
+ mContext, DEFAULT_LOCATION_RECORDING_ENABLED);
dialogLayout.setListener(new LocationDialogLayout.LocationDialogListener() {
@Override
public void onConfirm(boolean locationRecordingEnabled) {
- mAppController.getSettingsManager().set(
+ // Change the location preference setting.
+ mSettingsManager.set(
SettingsManager.SCOPE_GLOBAL,
Keys.KEY_RECORD_LOCATION,
locationRecordingEnabled);
- mAppController.getLocationManager().recordLocation(
- locationRecordingEnabled);
-
- mListener.onLocationPreferenceConfirmed(locationRecordingEnabled);
+ // Prompt the second dialog about aspect ratio preference.
promptAspectRatioPreferenceDialog();
}
});
@@ -279,6 +211,5 @@ public class FirstRunDialog {
// Show the dialog.
mLocationPreferenceDialog.show();
- return true;
}
}
diff --git a/src/com/android/camera/one/OneCameraManager.java b/src/com/android/camera/one/OneCameraManager.java
index 686e74bde..9a4fe0c65 100644
--- a/src/com/android/camera/one/OneCameraManager.java
+++ b/src/com/android/camera/one/OneCameraManager.java
@@ -16,19 +16,16 @@
package com.android.camera.one;
-import android.content.Context;
-import android.hardware.camera2.CameraManager;
+import com.google.common.base.Optional;
+
import android.os.Handler;
import android.util.DisplayMetrics;
-import android.view.WindowManager;
import com.android.camera.CameraActivity;
-import com.android.camera.debug.Log;
import com.android.camera.debug.Log.Tag;
import com.android.camera.one.OneCamera.Facing;
import com.android.camera.one.OneCamera.OpenCallback;
import com.android.camera.one.v2.imagesaver.ImageSaver;
-import com.android.camera.util.ApiHelper;
import com.android.camera.util.Size;
/**
@@ -83,8 +80,9 @@ public abstract class OneCameraManager {
* @throws OneCameraException Thrown if an error occurred while trying to
* access the camera.
*/
- public static OneCameraManager get(CameraActivity activity) throws OneCameraException {
- return create(activity);
+ public static OneCameraManager get(CameraActivity activity, DisplayMetrics displayMetrics)
+ throws OneCameraException {
+ return create(activity, displayMetrics);
}
/**
@@ -93,32 +91,16 @@ public abstract class OneCameraManager {
* @throws OneCameraException Thrown if an error occurred while trying to
* access the camera.
*/
- private static OneCameraManager create(CameraActivity activity) throws OneCameraException {
- DisplayMetrics displayMetrics = getDisplayMetrics(activity);
- CameraManager cameraManager = null;
-
- try {
- cameraManager = ApiHelper.HAS_CAMERA_2_API ? (CameraManager) activity
- .getSystemService(Context.CAMERA_SERVICE) : null;
- } catch (IllegalStateException ex) {
- cameraManager = null;
- Log.e(TAG, "Could not get camera service v2", ex);
+ private static OneCameraManager create(CameraActivity activity, DisplayMetrics displayMetrics)
+ throws OneCameraException {
+ Optional<OneCameraManager> manager =
+ com.android.camera.one.v2.OneCameraManagerImpl.create(activity, displayMetrics);
+ if (!manager.isPresent()) {
+ manager = com.android.camera.one.v1.OneCameraManagerImpl.create(activity);
}
- int maxMemoryMB = activity.getServices().getMemoryManager()
- .getMaxAllowedNativeMemoryAllocation();
- return new com.android.camera.one.v2.OneCameraManagerImpl(
- activity, cameraManager, maxMemoryMB,
- displayMetrics, activity.getSoundPlayer());
- }
-
- private static DisplayMetrics getDisplayMetrics(Context context) {
- DisplayMetrics displayMetrics = new DisplayMetrics();
- WindowManager wm = (WindowManager)
- context.getSystemService(Context.WINDOW_SERVICE);
- if (wm != null) {
- displayMetrics = new DisplayMetrics();
- wm.getDefaultDisplay().getMetrics(displayMetrics);
+ if (!manager.isPresent()) {
+ throw new OneCameraException("No camera manager is available.");
}
- return displayMetrics;
+ return manager.get();
}
}
diff --git a/src/com/android/camera/one/v1/OneCameraCharacteristicsImpl.java b/src/com/android/camera/one/v1/OneCameraCharacteristicsImpl.java
new file mode 100644
index 000000000..fc4bc95fc
--- /dev/null
+++ b/src/com/android/camera/one/v1/OneCameraCharacteristicsImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 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.one.v1;
+
+import android.graphics.Rect;
+import android.hardware.Camera;
+
+import com.android.camera.one.OneCamera;
+import com.android.camera.one.OneCameraCharacteristics;
+import com.android.camera.util.Size;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Describes a OneCamera device which is on top of camera1 API.
+ */
+public class OneCameraCharacteristicsImpl implements OneCameraCharacteristics {
+ private final Camera.CameraInfo mCameraInfo;
+
+ /** The supported picture sizes. */
+ private final ArrayList<Size> mSupportedPictureSizes = new ArrayList<>();
+
+ /** The supported preview sizes. */
+ private final ArrayList<Size> mSupportedPreviewSizes = new ArrayList<>();
+
+ public OneCameraCharacteristicsImpl(
+ Camera.CameraInfo cameraInfo, Camera.Parameters cameraParameters) {
+ mCameraInfo = cameraInfo;
+
+ List<Camera.Size> supportedPictureSizes = cameraParameters.getSupportedPictureSizes();
+ if (supportedPictureSizes != null) {
+ for (Camera.Size pictureSize : supportedPictureSizes) {
+ mSupportedPictureSizes.add(new Size(pictureSize));
+ }
+ }
+
+ List<Camera.Size> supportedPreviewSizes = cameraParameters.getSupportedPreviewSizes();
+ if (supportedPreviewSizes != null) {
+ for (Camera.Size previewSize : supportedPreviewSizes) {
+ mSupportedPreviewSizes.add(new Size(previewSize));
+ }
+ }
+ }
+
+ @Override
+ public List<Size> getSupportedPictureSizes(int imageFormat) {
+ return mSupportedPictureSizes;
+ }
+
+ @Override
+ public List<Size> getSupportedPreviewSizes() {
+ return mSupportedPreviewSizes;
+ }
+
+ @Override
+ public int getSensorOrientation() {
+ return mCameraInfo.orientation;
+ }
+
+ @Override
+ public OneCamera.Facing getCameraDirection() {
+ int direction = mCameraInfo.facing;
+ if (direction == Camera.CameraInfo.CAMERA_FACING_BACK) {
+ return OneCamera.Facing.BACK;
+ } else {
+ return OneCamera.Facing.FRONT;
+ }
+ }
+
+ @Override
+ public Rect getSensorInfoActiveArraySize() {
+ throw new RuntimeException("Not implemented yet.");
+ }
+
+ @Override
+ public float getAvailableMaxDigitalZoom() {
+ throw new RuntimeException("Not implemented yet.");
+ }
+}
diff --git a/src/com/android/camera/one/v1/OneCameraManagerImpl.java b/src/com/android/camera/one/v1/OneCameraManagerImpl.java
index 54076dcb4..87b541905 100644
--- a/src/com/android/camera/one/v1/OneCameraManagerImpl.java
+++ b/src/com/android/camera/one/v1/OneCameraManagerImpl.java
@@ -16,20 +16,80 @@
package com.android.camera.one.v1;
+import com.google.common.base.Optional;
+
+import android.hardware.Camera;
import android.os.Handler;
+import com.android.camera.CameraActivity;
+import com.android.camera.debug.Log;
import com.android.camera.one.OneCamera.Facing;
import com.android.camera.one.OneCamera.OpenCallback;
+import com.android.camera.one.OneCameraAccessException;
import com.android.camera.one.OneCameraCharacteristics;
import com.android.camera.one.OneCameraManager;
import com.android.camera.one.v2.imagesaver.ImageSaver;
import com.android.camera.util.Size;
/**
- * The {@link OneCameraManager} implementation on top of the Camera 1 API
- * portability layer.
+ * The {@link OneCameraManager} implementation on top of the Camera API 1.
*/
public class OneCameraManagerImpl extends OneCameraManager {
+ private static final Log.Tag TAG = new Log.Tag("OneCameraMgrImpl1");
+
+ private static final int NO_DEVICE = -1;
+
+ private final int mFirstBackCameraId;
+ private final int mFirstFrontCameraId;
+ private final Camera.CameraInfo[] mCameraInfos;
+
+ OneCameraCharacteristics mBackCameraCharacteristics;
+ OneCameraCharacteristics mFrontCameraCharacteristics;
+
+ public static Optional<OneCameraManager> create(CameraActivity activity) {
+ int numberOfCameras;
+ Camera.CameraInfo[] cameraInfos;
+ try {
+ numberOfCameras = Camera.getNumberOfCameras();
+ cameraInfos = new Camera.CameraInfo[numberOfCameras];
+ for (int i = 0; i < numberOfCameras; i++) {
+ cameraInfos[i] = new Camera.CameraInfo();
+ Camera.getCameraInfo(i, cameraInfos[i]);
+ }
+ } catch (RuntimeException ex) {
+ Log.e(TAG, "Exception while creating CameraDeviceInfo", ex);
+ return Optional.absent();
+ }
+
+ int firstFront = NO_DEVICE;
+ int firstBack = NO_DEVICE;
+ // Get the first (smallest) back and first front camera id.
+ for (int i = numberOfCameras - 1; i >= 0; i--) {
+ if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
+ firstBack = i;
+ } else {
+ if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+ firstFront = i;
+ }
+ }
+ }
+
+ OneCameraManager cameraManager =
+ new OneCameraManagerImpl(firstBack, firstFront, cameraInfos);
+ return Optional.of(cameraManager);
+ }
+
+ /**
+ * Instantiates a new {@link OneCameraManager} for Camera1 API.
+ */
+ public OneCameraManagerImpl(
+ int firstBackCameraId,
+ int firstFrontCameraId,
+ Camera.CameraInfo[] info) {
+ mFirstBackCameraId = firstBackCameraId;
+ mFirstFrontCameraId = firstFrontCameraId;
+ mCameraInfos = info;
+ }
@Override
public void open(Facing facing, boolean enableHdr, Size pictureSize,
@@ -39,11 +99,49 @@ public class OneCameraManagerImpl extends OneCameraManager {
@Override
public boolean hasCameraFacing(Facing facing) {
- throw new RuntimeException("Not implemented yet.");
+ if (facing == Facing.BACK) {
+ return mFirstBackCameraId != NO_DEVICE;
+ } else if (facing == Facing.FRONT) {
+ return mFirstFrontCameraId != NO_DEVICE;
+ }
+ return false;
}
@Override
- public OneCameraCharacteristics getCameraCharacteristics(Facing facing) {
- throw new RuntimeException("Not implemented yet.");
+ public OneCameraCharacteristics getCameraCharacteristics(Facing facing)
+ throws OneCameraAccessException {
+ // Returns the cached object if there exists one.
+ if (facing == Facing.BACK && mBackCameraCharacteristics != null) {
+ return mBackCameraCharacteristics;
+ } else if (facing == Facing.FRONT && mFrontCameraCharacteristics != null) {
+ return mFrontCameraCharacteristics;
+ }
+
+ int cameraId = NO_DEVICE;
+ if (facing == Facing.BACK) {
+ cameraId = mFirstBackCameraId;
+ } else if (facing == Facing.FRONT) {
+ cameraId = mFirstFrontCameraId;
+ }
+ if (cameraId == NO_DEVICE) {
+ throw new OneCameraAccessException(
+ "Unable to get camera characteristics (no camera id.)");
+ }
+
+ OneCameraCharacteristics characteristics;
+ Camera camera = null;
+ try {
+ camera = Camera.open(cameraId);
+ Camera.Parameters cameraParameters = camera.getParameters();
+ if (cameraParameters == null) {
+ Log.e(TAG, "Camera object returned null parameters!");
+ throw new OneCameraAccessException("API1 Camera.getParameters() returned null");
+ }
+ characteristics = new OneCameraCharacteristicsImpl(
+ mCameraInfos[cameraId], cameraParameters);
+ } finally {
+ camera.release();
+ }
+ return characteristics;
}
} \ No newline at end of file
diff --git a/src/com/android/camera/one/v2/OneCameraManagerImpl.java b/src/com/android/camera/one/v2/OneCameraManagerImpl.java
index 3cc2e4bbb..100e3bea5 100644
--- a/src/com/android/camera/one/v2/OneCameraManagerImpl.java
+++ b/src/com/android/camera/one/v2/OneCameraManagerImpl.java
@@ -16,13 +16,17 @@
package com.android.camera.one.v2;
+import android.annotation.TargetApi;
+import android.content.Context;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
+import android.os.Build;
import android.os.Handler;
import android.util.DisplayMetrics;
+import com.android.camera.CameraActivity;
import com.android.camera.SoundPlayer;
import com.android.camera.app.AppController;
import com.android.camera.debug.Log;
@@ -34,11 +38,15 @@ import com.android.camera.one.OneCameraAccessException;
import com.android.camera.one.OneCameraCharacteristics;
import com.android.camera.one.OneCameraManager;
import com.android.camera.one.v2.imagesaver.ImageSaver;
+import com.android.camera.util.ApiHelper;
import com.android.camera.util.Size;
+import com.google.common.base.Optional;
+
/**
* The {@link OneCameraManager} implementation on top of Camera2 API.
*/
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class OneCameraManagerImpl extends OneCameraManager {
private static final Tag TAG = new Tag("OneCameraMgrImpl2");
@@ -48,6 +56,25 @@ public class OneCameraManagerImpl extends OneCameraManager {
private final DisplayMetrics mDisplayMetrics;
private final SoundPlayer mSoundPlayer;
+ public static Optional<OneCameraManager> create(CameraActivity activity, DisplayMetrics displayMetrics) {
+ if (!ApiHelper.HAS_CAMERA_2_API) {
+ return Optional.absent();
+ }
+ CameraManager cameraManager;
+ try {
+ cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+ } catch (IllegalStateException ex) {
+ Log.e(TAG, "camera2.CameraManager is not available.");
+ return Optional.absent();
+ }
+ final int maxMemoryMB = activity.getServices().getMemoryManager()
+ .getMaxAllowedNativeMemoryAllocation();
+ final SoundPlayer soundPlayer = activity.getSoundPlayer();
+ OneCameraManager oneCameraManager = new OneCameraManagerImpl(
+ activity, cameraManager, maxMemoryMB, displayMetrics, soundPlayer);
+ return Optional.of(oneCameraManager);
+ }
+
/**
* Instantiates a new {@link OneCameraManager} for Camera2 API.
*
diff --git a/src/com/android/camera/settings/Keys.java b/src/com/android/camera/settings/Keys.java
index 35d0aca81..6b3ce5b20 100644
--- a/src/com/android/camera/settings/Keys.java
+++ b/src/com/android/camera/settings/Keys.java
@@ -68,7 +68,12 @@ public class Keys {
"pref_should_show_refocus_viewer_cling";
public static final String KEY_EXPOSURE_COMPENSATION_ENABLED =
"pref_camera_exposure_compensation_key";
+
+ /**
+ * Whether the user has chosen an aspect ratio on the first run dialog.
+ */
public static final String KEY_USER_SELECTED_ASPECT_RATIO = "pref_user_selected_aspect_ratio";
+
public static final String KEY_COUNTDOWN_DURATION = "pref_camera_countdown_duration_key";
public static final String KEY_HDR_PLUS_FLASH_MODE = "pref_hdr_plus_flash_mode";
public static final String KEY_SHOULD_SHOW_SETTINGS_BUTTON_CLING =
@@ -211,53 +216,5 @@ public class Keys {
return settingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL,
KEY_CAMERA_GRID_LINES);
}
-
- /**
- * Returns whether pano orientation is horizontal.
- */
- public static boolean isPanoOrientationHorizontal(SettingsManager settingsManager) {
- return settingsManager.isDefault(SettingsManager.SCOPE_GLOBAL,
- KEY_CAMERA_PANO_ORIENTATION);
- }
-
- /**
- * Sets the settings for whether location recording should be enabled or
- * not. Also makes sure to pass on the change to the location manager.
- */
- public static void setLocation(SettingsManager settingsManager, boolean on,
- LocationManager locationManager) {
- settingsManager.set(SettingsManager.SCOPE_GLOBAL, KEY_RECORD_LOCATION, on);
- locationManager.recordLocation(on);
- }
-
- /**
- * Sets the user selected aspect ratio setting to selected.
- */
- public static void setAspectRatioSelected(SettingsManager settingsManager) {
- settingsManager.set(SettingsManager.SCOPE_GLOBAL,
- KEY_USER_SELECTED_ASPECT_RATIO, true);
- }
-
- /**
- * Sets the manual exposure compensation enabled setting
- * to on/off based on the given argument.
- */
- public static void setManualExposureCompensation(SettingsManager settingsManager,
- boolean on) {
- settingsManager.set(SettingsManager.SCOPE_GLOBAL,
- KEY_EXPOSURE_COMPENSATION_ENABLED, on);
- }
-
- /**
- * Reads the current location recording settings and passes it on to the
- * given location manager.
- */
- public static void syncLocationManager(SettingsManager settingsManager,
- LocationManager locationManager) {
- boolean value = settingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL,
- KEY_RECORD_LOCATION);
- locationManager.recordLocation(value);
- }
-
}
diff --git a/src/com/android/camera/settings/ResolutionSetting.java b/src/com/android/camera/settings/ResolutionSetting.java
new file mode 100644
index 000000000..d5d91f57f
--- /dev/null
+++ b/src/com/android/camera/settings/ResolutionSetting.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015 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.settings;
+
+import com.android.camera.debug.Log;
+import com.android.camera.exif.Rational;
+import com.android.camera.one.OneCamera;
+import com.android.camera.one.OneCameraAccessException;
+import com.android.camera.one.OneCameraCharacteristics;
+import com.android.camera.one.OneCameraManager;
+import com.android.camera.util.Size;
+
+import android.graphics.ImageFormat;
+
+import java.util.List;
+
+/**
+ * Handles the picture resolution setting stored in SharedPreferences keyed by
+ * Keys.KEY_PICTURE_SIZE_BACK and Keys.KEY_PICTURE_SIZE_FRONT.
+ */
+public class ResolutionSetting {
+ private static final Log.Tag TAG = new Log.Tag("ResolutionSettings");
+
+ private final SettingsManager mSettingsManager;
+
+ private final OneCameraManager mOneCameraManager;
+
+ public ResolutionSetting(SettingsManager settingsManager, OneCameraManager oneCameraManager) {
+ mSettingsManager = settingsManager;
+ mOneCameraManager = oneCameraManager;
+ }
+
+ /**
+ * Changes the picture size settings for the cameras with specified facing.
+ * Pick the largest picture size with the specified aspect ratio.
+ *
+ * @param cameraFacing The specified direction that the camera is facing.
+ * @param aspectRatio The chosen aspect ratio.
+ */
+ public void setPictureAspectRatio(OneCamera.Facing cameraFacing, Rational aspectRatio)
+ throws OneCameraAccessException {
+ OneCameraCharacteristics cameraCharacteristics =
+ mOneCameraManager.getCameraCharacteristics(cameraFacing);
+
+ // Pick the largest picture size with the selected aspect ratio and save the choice for front camera.
+ final String pictureSizeSettingKey = cameraFacing == OneCamera.Facing.FRONT ?
+ Keys.KEY_PICTURE_SIZE_FRONT : Keys.KEY_PICTURE_SIZE_BACK;
+ final List<Size> supportedPictureSizes =
+ cameraCharacteristics.getSupportedPictureSizes(ImageFormat.JPEG);
+ final Size chosenPictureSize =
+ ResolutionUtil.getLargestPictureSize(aspectRatio, supportedPictureSizes);
+ mSettingsManager.set(
+ SettingsManager.SCOPE_GLOBAL,
+ pictureSizeSettingKey,
+ SettingsUtil.sizeToSettingString(chosenPictureSize));
+ }
+
+ /**
+ * Reads the picture size setting for the cameras with specified facing.
+ *
+ * @param cameraFacing The specified direction that the camera is facing.
+ * @return The preferred picture size.
+ */
+ public Size getPictureSize(OneCamera.Facing cameraFacing) throws OneCameraAccessException {
+ final String pictureSizeSettingKey = cameraFacing == OneCamera.Facing.FRONT ?
+ Keys.KEY_PICTURE_SIZE_FRONT : Keys.KEY_PICTURE_SIZE_BACK;
+
+ /**
+ * If there is no saved reference, pick a largest size with 4:3 aspect
+ * ratio as a fallback.
+ */
+ final boolean isPictureSizeSettingSet =
+ mSettingsManager.isSet(SettingsManager.SCOPE_GLOBAL, pictureSizeSettingKey);
+ if (!isPictureSizeSettingSet) {
+ final Rational aspectRatio = ResolutionUtil.ASPECT_RATIO_4x3;
+
+ final OneCameraCharacteristics cameraCharacteristics =
+ mOneCameraManager.getCameraCharacteristics(cameraFacing);
+ final List<Size> supportedPictureSizes =
+ cameraCharacteristics.getSupportedPictureSizes(ImageFormat.JPEG);
+ final Size fallbackPictureSize =
+ ResolutionUtil.getLargestPictureSize(aspectRatio, supportedPictureSizes);
+ mSettingsManager.set(
+ SettingsManager.SCOPE_GLOBAL,
+ pictureSizeSettingKey,
+ SettingsUtil.sizeToSettingString(fallbackPictureSize));
+ Log.e(TAG, "Picture size setting is not set. Choose " + fallbackPictureSize);
+ }
+
+ /** Reads picture size setting from SettingsManager. */
+ return SettingsUtil.sizeFromSettingString(
+ mSettingsManager.getString(SettingsManager.SCOPE_GLOBAL, pictureSizeSettingKey));
+ }
+} \ No newline at end of file
diff --git a/src/com/android/camera/settings/ResolutionUtil.java b/src/com/android/camera/settings/ResolutionUtil.java
index 40ee4ee5a..913a0f640 100644
--- a/src/com/android/camera/settings/ResolutionUtil.java
+++ b/src/com/android/camera/settings/ResolutionUtil.java
@@ -20,6 +20,10 @@ import com.android.camera.exif.Rational;
import com.android.camera.util.ApiHelper;
import com.android.camera.util.Size;
+import android.content.Context;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
@@ -370,4 +374,15 @@ public class ResolutionUtil {
}
return maxSize;
}
+
+ public static DisplayMetrics getDisplayMetrics(Context context) {
+ DisplayMetrics displayMetrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager)
+ context.getSystemService(Context.WINDOW_SERVICE);
+ if (wm != null) {
+ wm.getDefaultDisplay().getMetrics(displayMetrics);
+ }
+ return displayMetrics;
+ }
+
}
diff --git a/src/com/android/camera/settings/SettingsUtil.java b/src/com/android/camera/settings/SettingsUtil.java
index 732a834a0..728e7a920 100644
--- a/src/com/android/camera/settings/SettingsUtil.java
+++ b/src/com/android/camera/settings/SettingsUtil.java
@@ -148,26 +148,6 @@ public class SettingsUtil {
new SparseArray<SelectedVideoQualities>(2);
/**
- * Based on the selected size, this method selects the matching concrete
- * resolution and sets it as the picture size.
- *
- * @param sizeSetting The setting selected by the user. One of "large",
- * "medium, "small" or two integers separated by "x".
- * @param supported The list of supported resolutions.
- * @param settings The Camera settings to set the selected picture
- * resolution on.
- * @param cameraId This is used for caching the results for finding the
- * different sizes.
- */
- public static void setCameraPictureSize(String sizeSetting, List<Size> supported,
- CameraSettings settings, int cameraId) {
- Size selectedSize = getCameraPictureSize(sizeSetting, supported, cameraId);
- Log.d(TAG, "Selected " + sizeSetting + " resolution: " + selectedSize.getWidth() + "x" +
- selectedSize.getHeight());
- settings.setPhotoSize(selectedSize.toPortabilitySize());
- }
-
- /**
* Based on the selected size, this method returns the matching concrete
* resolution.
*
diff --git a/src/com/android/camera/util/ApiHelper.java b/src/com/android/camera/util/ApiHelper.java
index 046a9f9b4..67a67a8c7 100644
--- a/src/com/android/camera/util/ApiHelper.java
+++ b/src/com/android/camera/util/ApiHelper.java
@@ -99,8 +99,4 @@ public class ApiHelper {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|| "L".equals(Build.VERSION.CODENAME);
}
-
- public static boolean shouldShowAspectRatioDialog() {
- return IS_NEXUS_4 || IS_NEXUS_5 || IS_NEXUS_6;
- }
}